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 + -
显示快捷键?