nc6_test_slave.c
来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 909 行 · 第 1/2 页
C
909 行
//==========================================================================//// tests/nc6_test_slave.c//// Network characterizations test (slave portion) IPv4+IPv6 aware////==========================================================================//####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#undef __linux#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);#endifextern void cyg_kmem_print_stats(void);#else#define test_param_t int#endif#ifdef __ECOS#ifdef CYGPKG_NET_INET6#define __INET6#endif#else#define __INET6#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#ifdef __ECOS cyg_kmem_print_stats();#endif cyg_test_exit();}static intsa_len(struct sockaddr *sa){ switch (sa->sa_family) { case AF_INET: return sizeof(struct sockaddr_in);#ifdef __INET6 case AF_INET6: return sizeof(struct sockaddr_in6);#endif default: test_printf("Unknown socket type: %d\n", sa->sa_family); return sizeof(struct sockaddr_storage); }}//// Generic UDP test//static voiddo_udp_test(int s1, struct nc_request *req, struct sockaddr *master){ int i, s, td_len, seq, seq_errors, lost; struct sockaddr_storage 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(master->sa_family, SOCK_DGRAM, 0); if (s < 0) { pexit("datagram socket"); } memset((char *)&test_chan_slave, 0, sizeof(test_chan_slave)); memcpy(&test_chan_master, master, sizeof(*master));#ifndef __linux ((struct sockaddr *)&test_chan_slave)->sa_len = master->sa_len;#endif ((struct sockaddr *)&test_chan_slave)->sa_family = master->sa_family; switch (master->sa_family) { case AF_INET: ((struct sockaddr_in *)&test_chan_slave)->sin_addr.s_addr = htonl(INADDR_ANY); ((struct sockaddr_in *)&test_chan_slave)->sin_port = htons(ntohl(req->slave_port)); ((struct sockaddr_in *)&test_chan_master)->sin_port = htons(ntohl(req->master_port)); break;#ifdef __INET6 case AF_INET6: ((struct sockaddr_in6 *)&test_chan_slave)->sin6_addr = in6addr_any; ((struct sockaddr_in6 *)&test_chan_slave)->sin6_port = htons(ntohl(req->slave_port)); ((struct sockaddr_in6 *)&test_chan_master)->sin6_port = htons(ntohl(req->master_port)); break;#endif default: pexit("strange UDP sockaddr"); } if (bind(s, (struct sockaddr *) &test_chan_slave, sa_len((struct sockaddr *)&test_chan_slave)) < 0) { perror("bind UDP slave"); close(s); } 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 UDP data"); 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) { 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); if (sendto(s, tdp, td_len, 0, (struct sockaddr *)&test_chan_master, sa_len(master)) < 0) { perror("sendto UDP data"); if (errno == ENOBUFS) { // Saturated the system test_delay(10); // Time for 200 500 byte 10-baseT packets } else { // What else to do? close(s); return; } } else { nsent++; } } 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, sa_len(master)) < 0) { perror("sendto UDP 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 *master){ int i, s, len, td_len, seq, seq_errors, lost, test_chan, res; struct sockaddr_storage 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; char addr_buf[256]; static int slave_tcp_port[2] = {-1, -1}; int which_port = 0; 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; } switch (master->sa_family) { case AF_INET: which_port = 0; break;#ifdef __INET6 case AF_INET6: which_port = 1; break;#endif default: pexit("unknown TCP family"); } if (slave_tcp_port[which_port] < 0) { test_printf("TCP - listen on %s/%d\n", which_port ? "IPv6" : "IPv4", ntohl(req->slave_port)); s = socket(master->sa_family, 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));#ifndef __linux ((struct sockaddr *)&test_chan_slave)->sa_len = master->sa_len;#endif ((struct sockaddr *)&test_chan_slave)->sa_family = master->sa_family; switch (master->sa_family) { case AF_INET: ((struct sockaddr_in *)&test_chan_slave)->sin_addr.s_addr = htonl(INADDR_ANY); ((struct sockaddr_in *)&test_chan_slave)->sin_port = htons(ntohl(req->slave_port)); break;#ifdef __INET6 case AF_INET6: ((struct sockaddr_in6 *)&test_chan_slave)->sin6_addr = in6addr_any; ((struct sockaddr_in6 *)&test_chan_slave)->sin6_port = htons(ntohl(req->slave_port)); break;#endif default: pexit("strange TCP sockaddr"); } if (bind(s, (struct sockaddr *)&test_chan_slave, sa_len(master)) < 0) { perror("bind"); close(s); } listen(s, SOMAXCONN); slave_tcp_port[which_port] = s; } s = slave_tcp_port[which_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);#ifdef __ECOS _inet_ntop((struct sockaddr *)&test_chan_master, addr_buf, sizeof(addr_buf)); test_printf("connection from %s(%d)\n", addr_buf, _inet_port((struct sockaddr *)&test_chan_master));#endif 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); tdp->seq = htonl(seq); td_len = ntohl(req->buflen) + sizeof(struct nc_test_data);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?