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