nc_test_slave.c
来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 779 行 · 第 1/2 页
C
779 行
//==========================================================================//// tests/nc_test_slave.c//// Network characterizations test (slave portion)////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-01-10// Purpose: // Description: // ////####DESCRIPTIONEND####////==========================================================================// Network characterization test code - slave portion#include "nc_test_framework.h"#include <math.h>#ifdef __ECOS#ifndef CYGPKG_LIBC_STDIO#define perror(s) diag_printf(#s ": %s\n", strerror(errno))#endif#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)#define MAX_LOAD_THREAD_LEVEL 20#define MIN_LOAD_THREAD_LEVEL 0#define NUM_LOAD_THREADS 10#define IDLE_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY+3#define LOAD_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-1#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-2#define DESIRED_BACKGROUND_LOAD 20static char main_thread_stack[CYGHWR_NET_DRIVERS][STACK_SIZE];static cyg_thread main_thread_data[CYGHWR_NET_DRIVERS];static cyg_handle_t main_thread_handle[CYGHWR_NET_DRIVERS];static char idle_thread_stack[STACK_SIZE];static cyg_thread idle_thread_data;static cyg_handle_t idle_thread_handle;static cyg_sem_t idle_thread_sem;volatile static long long idle_thread_count;static cyg_tick_count_t idle_thread_start_time;static cyg_tick_count_t idle_thread_stop_time;static char load_thread_stack[NUM_LOAD_THREADS][STACK_SIZE];static cyg_thread load_thread_data[NUM_LOAD_THREADS];static cyg_handle_t load_thread_handle[NUM_LOAD_THREADS];static cyg_sem_t load_thread_sem[NUM_LOAD_THREADS];static long load_thread_level;static void calibrate_load(int load);static void start_load(int load);static void do_some_random_computation(int p);#define abs(n) ((n) < 0 ? -(n) : (n))#endif#ifdef __ECOS#define test_param_t cyg_addrword_t#ifdef CYGDBG_NET_TIMING_STATSextern void show_net_times(void);#endif#else#define test_param_t int#endif#define MAX_BUF 8192static unsigned char in_buf[MAX_BUF], out_buf[MAX_BUF];#ifdef __ECOSextern voidcyg_test_exit(void);#elsevoidcyg_test_exit(void){ test_printf("... Done\n"); exit(1);}static voidshow_net_times(void){}#endif#ifdef __ECOSstatic voidtest_delay(int ticks){ cyg_thread_delay(ticks);}#elsestatic voidtest_delay(int ticks){ usleep(ticks * 10000);}#endifvoidpexit(char *s){ perror(s);#ifdef CYGDBG_NET_TIMING_STATS show_net_times();#endif cyg_test_exit();}//// Generic UDP test//static voiddo_udp_test(int s1, struct nc_request *req, struct sockaddr_in *master){ int i, s, td_len, seq, seq_errors, lost; struct sockaddr_in test_chan_slave, test_chan_master; fd_set fds; struct timeval timeout; struct nc_test_results results; struct nc_test_data *tdp; int nsent, nrecvd; int need_recv, need_send; need_recv = true; need_send = true; switch (ntohl(req->type)) { case NC_REQUEST_UDP_SEND: need_recv = false; need_send = true; break; case NC_REQUEST_UDP_RECV: need_recv = true; need_send = false; break; case NC_REQUEST_UDP_ECHO: break; } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { pexit("datagram socket"); } memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave)); test_chan_slave.sin_family = AF_INET;#ifdef __ECOS test_chan_slave.sin_len = sizeof(test_chan_slave);#endif test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY); test_chan_slave.sin_port = htons(ntohl(req->slave_port)); if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) { perror("bind"); close(s); } memcpy(&test_chan_master, master, sizeof(*master)); test_chan_master.sin_port = htons(ntohl(req->master_port)); nsent = 0; nrecvd = 0; seq = 0; seq_errors = 0; lost = 0; for (i = 0; i < ntohl(req->nbufs); i++) { if (need_recv) { FD_ZERO(&fds); FD_SET(s, &fds); timeout.tv_sec = NC_TEST_TIMEOUT; timeout.tv_usec = 0; if (select(s+1, &fds, 0, 0, &timeout) <= 0) { test_printf("recvfrom timeout, expecting seq #%d\n", seq); if (++lost > MAX_ERRORS) { test_printf("... giving up\n"); break; } } else { nrecvd++; tdp = (struct nc_test_data *)in_buf; td_len = ntohl(req->buflen) + sizeof(struct nc_test_data); if (recvfrom(s, tdp, td_len, 0, 0, 0) < 0) { perror("recvfrom"); close(s); return; } if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) && (ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) { if (ntohl(tdp->seq) != seq) { test_printf("Packets out of sequence - recvd: %d, expected: %d\n", ntohl(tdp->seq), seq); seq = ntohl(tdp->seq); seq_errors++; } } else { test_printf("Bad data packet - key: %x/%x, seq: %d\n", ntohl(tdp->key1), ntohl(tdp->key2), ntohl(tdp->seq)); } } } if (need_send) { int retries = 10; bool sent = false; int res; tdp = (struct nc_test_data *)out_buf; tdp->key1 = htonl(NC_TEST_DATA_KEY1); tdp->key2 = htonl(NC_TEST_DATA_KEY2); tdp->seq = htonl(seq); td_len = ntohl(req->buflen) + sizeof(struct nc_test_data); tdp->len = htonl(td_len); while (!sent && (--retries >= 0)) { res = sendto(s, tdp, td_len, 0, (struct sockaddr *)&test_chan_master, sizeof(test_chan_master)); if (res > 0) { sent = true; break; } if (errno == ENOBUFS) { // Saturated the system test_delay(1); // Time for 200 500 byte 10-baseT packets } else { // What else to do? close(s); return; } } if (sent) { nsent++; } else { perror("sendto"); } } seq++; } results.key1 = htonl(NC_TEST_RESULT_KEY1); results.key2 = htonl(NC_TEST_RESULT_KEY2); results.seq = req->seq; results.nsent = htonl(nsent); results.nrecvd = htonl(nrecvd); if (sendto(s, &results, sizeof(results), 0, (struct sockaddr *)&test_chan_master, sizeof(test_chan_master)) < 0) { perror("sendto results"); } close(s);}//// Read data from a stream, accounting for the fact that packet 'boundaries'// are not preserved. This can also timeout (which would probably wreck the// data boundaries).//intdo_read(int fd, void *buf, int buflen){ char *p = (char *)buf; int len = buflen; int res; while (len) { res = read(fd, p, len); if (res < 0) { perror("read"); } else { len -= res; p += res; if (res == 0) { break; } } } return (buflen - len);}//// Generic TCP test//static voiddo_tcp_test(int s1, struct nc_request *req, struct sockaddr_in *master){ int i, s, len, td_len, seq, seq_errors, lost, test_chan, res; struct sockaddr_in test_chan_slave, test_chan_master; struct nc_test_results results; struct nc_test_data *tdp; int nsent, nrecvd; int need_recv, need_send; int one = 1; static int slave_tcp_port = -1; need_recv = true; need_send = true; switch (ntohl(req->type)) { case NC_REQUEST_TCP_SEND: need_recv = false; need_send = true; break; case NC_REQUEST_TCP_RECV: need_recv = true; need_send = false; break; case NC_REQUEST_TCP_ECHO: break; } if (slave_tcp_port < 0) { s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { pexit("datagram socket"); } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { perror("setsockopt SO_REUSEADDR"); return; }#ifdef SO_REUSEPORT if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) { perror("setsockopt SO_REUSEPORT"); return; }#endif memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave)); test_chan_slave.sin_family = AF_INET;#ifdef __ECOS test_chan_slave.sin_len = sizeof(test_chan_slave);#endif test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY); test_chan_slave.sin_port = htons(ntohl(req->slave_port)); if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) { perror("bind"); close(s); } listen(s, SOMAXCONN); slave_tcp_port = s; } s = slave_tcp_port; len = sizeof(test_chan_master); if ((test_chan = accept(s, (struct sockaddr *)&test_chan_master, &len)) < 0) { pexit("accept"); } len = sizeof(test_chan_master); getpeername(test_chan, (struct sockaddr *)&test_chan_master, &len); test_printf("connection from %s.%d\n", inet_ntoa(test_chan_master.sin_addr), ntohs(test_chan_master.sin_port)); nsent = 0; nrecvd = 0; seq = 0; seq_errors = 0; lost = 0; for (i = 0; i < ntohl(req->nbufs); i++) { if (need_recv) { tdp = (struct nc_test_data *)in_buf; td_len = ntohl(req->buflen) + sizeof(struct nc_test_data); res = do_read(test_chan, tdp, td_len); if (res != td_len) { test_printf("recvfrom timeout, expecting seq #%d\n", seq); if (++lost > MAX_ERRORS) { test_printf("... giving up\n"); break; } } else { nrecvd++; if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) && (ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) { if (ntohl(tdp->seq) != seq) { test_printf("Packets out of sequence - recvd: %d, expected: %d\n", ntohl(tdp->seq), seq); seq = ntohl(tdp->seq); seq_errors++; } } else { test_printf("Bad data packet - key: %x/%x, seq: %d\n", ntohl(tdp->key1), ntohl(tdp->key2), ntohl(tdp->seq)); } } } if (need_send) { tdp = (struct nc_test_data *)out_buf; tdp->key1 = htonl(NC_TEST_DATA_KEY1); tdp->key2 = htonl(NC_TEST_DATA_KEY2);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?