⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nc_test_slave.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================
//
//      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  20
static 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_STATS
extern void show_net_times(void);
#endif
#else
#define test_param_t int
#endif

#define MAX_BUF 8192
static unsigned char in_buf[MAX_BUF], out_buf[MAX_BUF];

#ifdef __ECOS
extern void
cyg_test_exit(void);
#else
void
cyg_test_exit(void)
{
    test_printf("... Done\n");
    exit(1);
}

static void
show_net_times(void)
{
}
#endif

#ifdef __ECOS
static void
test_delay(int ticks)
{
    cyg_thread_delay(ticks);
}

#else

static void
test_delay(int ticks)
{
    usleep(ticks * 10000);
}
#endif

void
pexit(char *s)
{
    perror(s);
#ifdef CYGDBG_NET_TIMING_STATS
    show_net_times();
#endif
    cyg_test_exit();
}

//
// Generic UDP test
//

static void
do_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;
            int 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).
//

int
do_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 void
do_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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -