diff options
| author | Qiuwen Lu <[email protected]> | 2016-09-21 14:31:36 +0800 |
|---|---|---|
| committer | Qiuwen Lu <[email protected]> | 2016-09-21 14:31:36 +0800 |
| commit | de850016375d367637d1f9ab610de596a8a92ac7 (patch) | |
| tree | c76a4eb1879fb9147ce72a6dc9702bc08ede7500 /examples | |
| parent | 2678cdce677a3e82294d5c307cc1120b36281f5a (diff) | |
引入pag系列测试样例文件。
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/pag/rx_sample.c | 584 | ||||
| -rw-r--r-- | examples/pag/tx_sample.c | 757 | ||||
| -rw-r--r-- | examples/pag/tx_sample_mq.c | 263 |
3 files changed, 1604 insertions, 0 deletions
diff --git a/examples/pag/rx_sample.c b/examples/pag/rx_sample.c new file mode 100644 index 0000000..51e1ced --- /dev/null +++ b/examples/pag/rx_sample.c @@ -0,0 +1,584 @@ +//////////////////////////////////////// +///@file rx_sample.c +/// +///@brief pag接口收包示例代码,收包线程可以指定收包个数和打印报文内容 +/// +///修改记录: +/// +///@author [email protected] +///@date 2013-10-13 +/// +///修改内容:建立文档 +//////////////////////////////////////// + +//系统路径下头文件 +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> //getopt +#include <string.h> +#include <pthread.h> +#include <signal.h> +#include <sys/time.h> +#include <linux/types.h> +#include <netinet/ip.h> //struct ip +#include <netinet/ip6.h> +#include <linux/tcp.h> +#include <net/ethernet.h> //struct ether_header + +#include <libpag.h> + +///// 宏定义 /////// + +#define DEF_THREADS_NUM 16 ///<默认线程数 +#define MAX_THREADS_NUM 64 ///<系统支持的最大线程数 + +#define TCPDUMP_MAGIC 0xa1b2c3d4 +#define SNAP_LEN_DEF 96 +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 +#define DLT_EN10MB 1 + +#define rtol(r, n) ((r) << (n) | ((r) >> ((8 * sizeof(r)) - (n)))) + +///// 数据结构定义 /////// + +struct rand_func { + uint32_t x, y, z; +}; + +struct pcap_file_header { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + uint32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + uint32_t linktype; +}; + +struct pcap_timeval { + uint32_t tv_sec; + uint32_t tv_usec; +}; + +struct pcap_pkthdr { + struct pcap_timeval ts; + uint32_t caplen; + uint32_t len; +}; + +////////// 数据 ///////// + +static int glob_loop_flag_main; +static int glob_loop_flag_thread; +static int glob_copy_time; +static int glob_print_pkt_flag; +static int glob_pkts_num; +static int glob_threads_num; +static int glob_pktsend_flag; +static int glob_get_frame; +static int glob_rand_test; +static char *glob_write_pcap = NULL; +static FILE *glob_filep = NULL; + +static struct rand_func randf[MAX_THREADS_NUM]; + +///计数器,每个线程分别计数 +ulong glob_pkts[MAX_THREADS_NUM][16]; +ulong glob_bytes[MAX_THREADS_NUM][16]; + + +pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t pcap_mutex = PTHREAD_MUTEX_INITIALIZER; + +/////// 函数列表 /////////////// + +static inline void my_srand(struct rand_func *f, uint32_t seed) +{ + unsigned n; + + f->x = 6247; + f->y = 3848; + f->z = 0; + + for (n = ((seed >> 22) & 0x3ff) + 20; n > 0; n--) + f->x -= rtol(f->x, 21); + for (n = ((seed >> 11) & 0x7ff) + 20; n > 0; n--) + f->y = rtol(f->y, 11) - f->y; + for (n = ((seed ) & 0x7ff) + 20; n > 0; n--) + f->z = 3286325185u - rtol(f->z, 19); +} + +static inline uint32_t my_rand(struct rand_func *f) +{ +// f->x -= rtol(f->x, 21); +// return f->x; + + f->x -= rtol(f->x, 21); + f->y = rtol(f->y, 11) - f->y; + f->z = 3286325185u - rtol(f->z, 19); + + return f->x ^ f->y ^ f->z; + +// f->x = ~(2911329625u*f->x); +// f->x = rtol(f->x, 17); +// +// f->y = 4031235431u * f->y; +// f->y = rtol(f->y, 15); +// +// f->z = 3286325185u - rtol(f->z, 19); + +// return (f->x + f->y) ^ f->z; +} + +///@brief 输出程序帮助信息 +///@param cmd 程序命令(输入) +void usage(char* cmd) +{ + printf("Usage: %s [-m threads_num][-n pkt_num][-c copy_time][-?]\n", cmd); + printf(" -m threads number, default = %d\n", DEF_THREADS_NUM); + printf(" -n pkts num to rx, default = continously\n"); + printf(" -c copy time of each rx pkt, default = 0\n"); + printf(" -s send rcv pkt\n"); + printf(" -? print usage message\n"); + printf("\n"); +} + +///@brief 打印收包信息的线程,每隔1秒显示一次 +///@param ptr 线程建立时的指针,这里没有使用 +void print_speed_thread(void *ptr) +{ + int i; + ulong old_pkts[MAX_THREADS_NUM]; + ulong old_bytes[MAX_THREADS_NUM]; + + for (i = 0; i < glob_threads_num; i++) + { + old_pkts[i] = 0; + old_bytes[i] = 0; + } + + while (glob_loop_flag_thread) + { + sleep(1); + printf("\nCurrent speed----- "); + printf("\n"); + for (i = 0; i < glob_threads_num; i++) + { + printf("\t Thread[%d]:\t %8lu pps, %8lu M bps\n", i, + glob_pkts[i][0] - old_pkts[i], + (glob_bytes[i][0] - old_bytes[i]) >> 17); + old_pkts[i] = glob_pkts[i][0]; + old_bytes[i] = glob_bytes[i][0]; + } + } +} + +///@brief 拷贝报文(模拟应用处理包的负载) +///@param pkt 指向报文的指针 +///@param len 报文长度 +/* Make sure the gcc not optimization out this function */ +static void copy_pkt(void *pkt, int len) __attribute__((optimize("O0"))); + +static void copy_pkt(void *pkt, int len) +{ + int i; + volatile uint8_t p8_tmp[2000]; + uint8_t *p8 = (uint8_t *)pkt; + + len = (len < 2000) ? len : 2000; + + ///拷贝报文 + for (i = 0; i < len; i++) + { + p8_tmp[i] = p8[i]; + } +} + +///@brief 转发接收到的数据报文 +///@param pkt 指向报文帧头的指针 +static void send_rcvframe(void *pkt, int len, int sid) +{ + void *buff; + int type; + + type = 0; + if (glob_get_frame) { + buff = pag_getsendbuf_eth(sid, 0); + while (!buff) { + usleep(50); + buff = pag_getsendbuf_eth(sid, 0); + } + + memcpy(buff, pkt, len); + pag_send_eth(sid, len, 0); + } else { + buff = pag_getsendbuf(sid); + while (!buff) { + usleep(50); + buff = pag_getsendbuf(sid); + } + + memcpy(buff, pkt, len); + type = (type == 0) ? 1 : 0; + pag_send(type, sid, len); + } +} + +///@brief 打印报文 +///@param pkt 指向报文的指针 +///@param len 报文长度 +static void print_pkt(char *pkt_s, int len) +{ + int i, rc; + int pos = 0; + unsigned char *pkt = (unsigned char *) pkt_s; + + rc = pthread_mutex_lock(&print_mutex); + if (rc) { + fprintf(stderr, "pthread_mutex_lock error\n"); + exit(-1); + } + for (i = 0; i < len;i++) { + if (i % 16 == 0) { + fprintf(stdout, "\n"); + fprintf(stdout, "%08x: ", pos); + fprintf(stdout, "%02x ", pkt[i]); + pos += 16; + } + else + fprintf(stdout, "%02x ", pkt[i]); + } + fprintf(stdout, "\n"); + rc = pthread_mutex_unlock(&print_mutex); + if (rc) { + fprintf(stderr, "pthread_mutex_unlock error\n"); + exit(-1); + } +} + +int get_ip_len(void *pkt) +{ + int len; + unsigned char *p8; + struct iphdr* iph; + + len = 0; + p8 = (unsigned char*)(pkt); + + iph = (struct iphdr *) p8; + if (iph->version == 4) { + len = ntohs((unsigned short)iph->tot_len); + } else if (iph->version == 6) { + struct ip6_hdr *ip6h; + ip6h = (struct ip6_hdr *) p8; + len = ntohs((unsigned short)ip6h->ip6_plen); + } + + return len; +} + +int write_pcap_file(FILE *fp, void *pkt, int len) +{ + struct timeval tv; + static int first = 1; + struct pcap_file_header hdr; + struct pcap_pkthdr pcap_hdr; + int ret; + + gettimeofday(&tv, NULL); + ret = pthread_mutex_lock(&pcap_mutex); + if (ret) { + fprintf(stderr, "pthread_mutex_lock error\n"); + exit(-1); + } + + if (first == 1) { + hdr.magic = TCPDUMP_MAGIC; + hdr.version_major = PCAP_VERSION_MAJOR; + hdr.version_minor = PCAP_VERSION_MINOR; + hdr.thiszone = 0; + hdr.snaplen = 65535; + hdr.sigfigs = 0; + hdr.linktype = DLT_EN10MB; + + ret = fwrite((char *)&hdr, sizeof(struct pcap_file_header), 1, fp); + if (ret != 1) { + fprintf(stderr, "### Error : fwrite pcap_file_header error!\n"); + return -1; + } + first = 0; + } + + pcap_hdr.ts.tv_sec = tv.tv_sec; + pcap_hdr.ts.tv_usec = tv.tv_usec; + pcap_hdr.len = len; + pcap_hdr.caplen = len; + + ret = fwrite((char *)&pcap_hdr, sizeof(struct pcap_pkthdr), 1, fp); + if (ret != 1) { + fprintf(stderr, "### Error : fwrite pcap_pkthdr error!\n"); + return -1; + } + ret = fwrite((char *)pkt, len, 1, fp); + if (ret != 1) { + fprintf(stderr, "### Error : fwrite pcap_pkt error!\n"); + return -1; + } + + ret = pthread_mutex_unlock(&pcap_mutex); + if (ret) { + fprintf(stderr, "pthread_mutex_unlock error\n"); + exit(-1); + } + return 0; +} + +///@brief 接收报文的线程 +///@param ptr 线程建立时的指针,这里指向线程的数据流号 +void rx_thread(void *ptr) +{ + int ret; + int sid, i; + int len; + void *pkt; + void *ip; + uint8_t *p8; + + ///获取缓冲区id + sid = *((int *)ptr); + + my_srand(&randf[sid], time(NULL)); + + ///循环,直到线程循环标志清零 + while (glob_loop_flag_thread) + { + ///--获取一个报文,如果没有报文,则循环等待 + if (glob_get_frame || (glob_filep != NULL)) { + pkt = pag_get_frame(sid); + if (!pkt) { + usleep(500); + continue; + } + len = pag_get_frame_length(sid); + } else { + pkt = pag_get(sid); + if (!pkt) { + usleep(500); + continue; + } + len = get_ip_len(pkt); + } + + if (glob_filep != NULL) { + ret = write_pcap_file(glob_filep, pkt, len); + if (ret != 0) + return ; + fflush(glob_filep); + } + + ///--增加报文计数 + glob_pkts[sid][0]++; + glob_bytes[sid][0] += len; + + ///--根据参数对报文做相应处理 + if (glob_rand_test) { + int n; + n = my_rand(&randf[sid]) & 0xF; + for (i = 0; i < n; i++) + copy_pkt(pkt, len); + if (n & 0x1) + send_rcvframe(pkt, len, sid); + continue; + } else { + for (i = 0; i < glob_copy_time; i++) { + copy_pkt(pkt, len); + } + } + + if (glob_pktsend_flag == 1) { + send_rcvframe(pkt, len, sid); + } + + if (glob_print_pkt_flag) { + print_pkt(pkt, len); + } + } +} + +///@brief 信号响应函数,收到信号后把全局循环标志无效掉 +void stop_loop(int sig) +{ + glob_loop_flag_main = 0; +} + +///@brief 主函数 +///@return 成功返回0,失败返回-1 +int main(int argc, char *argv[]) +{ + int c, i; + struct timeval ts, te; + double sec; + ulong all_pkts, all_bytes; + sigset_t set; + pthread_t rx_tids[MAX_THREADS_NUM], print_tid; + int sids[MAX_THREADS_NUM]; + + ///打印使用信息 + usage(argv[0]); + + ///读取参数 + glob_copy_time = 0; + glob_print_pkt_flag = 0; + glob_pkts_num = 0; + glob_threads_num = DEF_THREADS_NUM; + glob_pktsend_flag = 0; + glob_rand_test = 0; + glob_get_frame = 0; + + while ((c = getopt(argc, argv, "c:n:m:spfrw:?")) != -1) + { + switch (c) + { + case 'c': + glob_copy_time = atoi(optarg); + break; + case 'n': + glob_pkts_num = atoi(optarg); + break; + case 'm': + glob_threads_num = atoi(optarg); + if (glob_threads_num > MAX_THREADS_NUM) + { + printf("\nError: threads num invalid\n"); + return -1; + } + break; + case 's': + glob_pktsend_flag = 1; + break; + case 'p': + glob_print_pkt_flag = 1; + break; + case 'f': + glob_get_frame = 1; + break; + case 'r': + glob_rand_test = 1; + break; + case 'w': + glob_write_pcap = (char *)optarg; + break; + case '?': + default: + usage(argv[0]); + return 0; + } + } + + if (glob_write_pcap != NULL) { + if ((glob_filep = fopen(glob_write_pcap, "w")) == NULL) { + printf("### Error : can not create file %s\n", glob_write_pcap); + return -1; + } + } + + ///打开设备 + if (pag_open() < 0) + { + printf("### Error : can not open device! ###\n"); + return -1; + } + + ///创建线程 + glob_loop_flag_thread = 1; + for (i = 0; i < glob_threads_num; i++) + { + sids[i] = i; + if (pthread_create(&rx_tids[i], NULL, (void *)rx_thread, (void *)&sids[i]) != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + + ///如果不打印报文内容,则打印报文速度 + if (!glob_print_pkt_flag) + { + if (pthread_create(&print_tid, NULL, (void *)print_speed_thread, NULL) != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + + ///等待结束信号,或着收到期望的包数 + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGINT, stop_loop); + + ///记录开始时间 + gettimeofday(&ts, NULL); + + glob_loop_flag_main = 1; + while (glob_loop_flag_main) + { + usleep(10); + + all_pkts = 0; + all_bytes = 0; + for (i = 0; i < glob_threads_num; i++) + { + all_pkts += glob_pkts[i][0]; + } + + if (glob_pkts_num != 0 && glob_pkts_num <= all_pkts) + { + break; + } + } + + ///记录结束时间 + gettimeofday(&te, NULL); + + ///停止线程 + glob_loop_flag_thread = 0; + for (i = 0; i < glob_threads_num; i++) + { + pthread_join(rx_tids[i], NULL); + } + if (!glob_print_pkt_flag) + { + pthread_join(print_tid, NULL); + } + + ///关闭设备 + pag_close(); + + if (glob_filep != NULL) + fclose(glob_filep); + + ///打印总结信息 + printf("\n"); + printf("Pkts recieved in threads: \n"); + + sec = (float)(te.tv_sec - ts.tv_sec) + ((float)(te.tv_usec - ts.tv_usec)) / 1000000.f; + all_pkts = 0; + all_bytes = 0; + for(i = 0; i < glob_threads_num; i++) + { + printf("\t Thread[%d]:\t <%8lu> pkts, <%8lu M> bytes\n", i, + glob_pkts[i][0], glob_bytes[i][0] >> 20); + all_pkts += glob_pkts[i][0]; + all_bytes += glob_bytes[i][0]; + } + + printf("Total : %lu pkts, %lu bytes\n", all_pkts, all_bytes); + printf("Speed : < %u > pps, < %u M > bps\n", + (int)(all_pkts / sec), (int)((all_bytes >> 17) / sec)); + printf("\n"); + + return 0; +} diff --git a/examples/pag/tx_sample.c b/examples/pag/tx_sample.c new file mode 100644 index 0000000..2513b55 --- /dev/null +++ b/examples/pag/tx_sample.c @@ -0,0 +1,757 @@ +//////////////////////////////////////// +///@file tx_sample.c +/// +///@brief pag接口发包示例代码,可以指定发包的长度,类型,源目ip +/// +///修改记录: +/// +///@author [email protected] +///@date 2013-10-13 +/// +///建立文档 +//////////////////////////////////////// + +//系统路径下头文件 +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> //getopt +#include <string.h> +#include <pthread.h> +#include <signal.h> +#include <sys/time.h> +#include <linux/types.h> +#include <net/ethernet.h> +#include <netinet/ip.h> //struct ip +#include <netinet/in.h> //IPPROTO_TCP +#include <netinet/ip6.h> +#include <arpa/inet.h> //inet_addr(); + +#include <libpag.h> + +///// 宏定义 /////// + +#define DEF_THREADS_NUM 16 ///<默认线程数 +#define MAX_THREADS_NUM 64 ///<系统支持的最大线程数 + +#define MIN_TX_PKT_LEN 60 ///<可发送的最小报文长度 +#define MAX_TX_PKT_LEN 2044 ///<可发送的最大报文长度 + +#define rtol(r, n) ((r) << (n) | ((r) >> ((8 * sizeof(r)) - (n)))) + +///// 结构定义 /////// +struct rand_func { + uint32_t x, y, z; +}; + +////////// 数据 ///////// + +static int glob_threads_num; +static int glob_loop_flag_main; +static int glob_loop_flag_thread; +static int glob_pkts_num; +static int glob_inc_len; +static int glob_print_pkt_flag; +static uint32_t glob_pkt_low_len; +static uint32_t glob_pkt_up_len; +static int glob_pkt_proto; +static int glob_ip_version; +static int glob_send_frame; +static uint32_t glob_sip; +static uint32_t glob_dip; +static struct in6_addr glob_ipv6_sip; +static struct in6_addr glob_ipv6_dip; + +static struct rand_func randf[MAX_THREADS_NUM]; + +///计数器,每个线程分别计数 +static ulong glob_pkts[MAX_THREADS_NUM][16]; +static ulong glob_bytes[MAX_THREADS_NUM][16]; + +/////// 函数列表 /////////////// + +///@brief 输出程序帮助信息 +///@param cmd 程序命令(输入) +void usage(char* cmd) +{ + printf("Usage: %s ", cmd); + printf("[-n pkt_num][-m thread_num][-l low_len][-u up_len]\n"); + printf("[-t pkt_type(proto)][-s src_ip][-d dst_ip][-v ip_version][-p] [-?]\n"); + printf(" -n pkts num to tx, default = continously\n"); + printf(" -m send thread number, default = %d\n", DEF_THREADS_NUM); + printf(" -l min pkt lenth, default = %d\n", MIN_TX_PKT_LEN); + printf(" -u max pkt lenth, default = %d\n", MAX_TX_PKT_LEN); + printf(" -t pkt protocol and type, 17 = udp, 6 = tcp, default = random(TCP or UDP)\n"); + printf(" -s src ipv4 of pkt, default = random\n"); + printf(" -S src ipv6 of pkt, default = random\n"); + printf(" -d dst ipv4 of pkt, default = random\n"); + printf(" -D dst ipv6 of pkt, default = random\n"); + printf(" -v ip version, 4 = ipv4, 6 = ipv6, default = ipv4\n"); + printf(" -p print pkts\n"); + printf(" -? print usage message\n"); + printf("\n"); +} + + +///@brief 打印发包信息的线程,每隔1秒显示一次 +///@param ptr 线程建立时的指针,这里没有使用 +void print_thread(void *ptr) +{ + ulong old_pkts[MAX_THREADS_NUM]; + ulong old_bytes[MAX_THREADS_NUM]; + int i; + + for (i = 0; i < MAX_THREADS_NUM; i++) + { + old_pkts[i] = 0; + old_bytes[i] = 0; + } + + while (glob_loop_flag_thread) + { + sleep(1); + printf("\nCurrent speed-----\n"); + for (i = 0; i < glob_threads_num; i++) + { + printf("\t Thread[%d]:\t %8lu pps, %8lu M bps\n", i, + glob_pkts[i][0] - old_pkts[i], + (glob_bytes[i][0] - old_bytes[i]) >> 17); + old_pkts[i] = glob_pkts[i][0]; + old_bytes[i] = glob_bytes[i][0]; + } + } +} + +///@brief 打印报文(检查收包内容) +///@param pkt 指向报文的指针 +///@param len 报文长度 +static void print_pkt(void *pkt, int len) +{ + int i; + uint8_t *p8; + static int pkt_print; + + ///找到报文附加头, 打印长度包括附加头 + pkt_print++; + p8 = (uint8_t *)pkt; + + ///打印报文, 每16字节一行,128字节一段 + printf("\n==== pkt:%d ====\n", pkt_print); + for (i = 0; i < len; i++) + { + if ((i % 128 == 0)) + { + printf("\n"); + } + if ((i % 16 == 0)) + { + printf("\n%03x: ", i / 16 + 1); + } + if (i % 8 == 0) + printf(" "); + printf("%02x ", p8[i]); + } + printf("\n"); +} + +///@brief 构造报文 +///@param pkt 指向报文的指针 +///@param len ip报文长度 +///@param proto 报文类型,17为日志包(udp),6为封堵包(tcp) +inline void build_ipv4_pkt(void *pkt, int len, int proto, uint32_t sip, uint32_t dip) +{ + struct iphdr *iph; + + ///找到报文ip头 + iph = (struct iphdr *)pkt; + + ///修改各字段 + iph->tot_len = htons(len); + iph->protocol = proto; + iph->saddr = sip; + iph->daddr = dip; + if (proto == 17) + { + *((uint16_t *)(pkt + 24)) = htons(len - 20); + } +} + +///@brief 构造ipv6报文 +///@param pkt 指向报文的指针 +///@param len ip报文长度 +///@param proto 报文类型,17为日志包(udp),6为封堵包(tcp) +inline void build_ipv6_pkt(void *pkt, int len, int proto, struct in6_addr sip, struct in6_addr dip) +{ + struct ip6_hdr *iph; + + ///找到报文ip头 + iph = (struct ip6_hdr *)pkt; + + ///修改各字段 + iph->ip6_plen = htons(len - sizeof(struct ip6_hdr)); + iph->ip6_nxt = proto; + iph->ip6_src = sip; + iph->ip6_dst = dip; + if (proto == 17) + { + *((uint16_t *)(pkt + 44)) = htons(len - sizeof(struct ip6_hdr)); + } +} + +static inline void my_srand(struct rand_func *f, uint32_t seed) +{ + unsigned n; + + f->x = 6247; + f->y = 3848; + f->z = 0; + + for (n = ((seed >> 22) & 0x3ff) + 20; n > 0; n--) + f->x -= rtol(f->x, 21); + for (n = ((seed >> 11) & 0x7ff) + 20; n > 0; n--) + f->y = rtol(f->y, 11) - f->y; + for (n = ((seed ) & 0x7ff) + 20; n > 0; n--) + f->z = 3286325185u - rtol(f->z, 19); +// f->x = (seed & 0x001fffffu) + 4027999010u; +// f->y = ((seed>>7) & 0x0007ffffu) + 3993266363u; +// f->z = (seed >> 13) + 3605298456u; +} + +static inline uint32_t my_rand(struct rand_func *f) +{ + f->x -= rtol(f->x, 21); + return f->x; + /* + f->x -= rtol(f->x, 21); + f->y = rtol(f->y, 11) - f->y; + f->z = 3286325185u - rtol(f->z, 19); + + return f->x ^ f->y ^ f->z; + */ + /* + f->x = ~(2911329625u*f->x); + f->x = rtol(f->x, 17); + + f->y = 4031235431u * f->y; + f->y = rtol(f->y, 15); + + f->z = 3286325185u - rtol(f->z, 19); + + return (f->x + f->y) ^ f->z; + */ +} + +///@brief 发送报文的线程 +///@param ptr 线程建立时的指针,这里指向线程的数据流号 +void tx_thread_eth(void *ptr) +{ + int i, sid; + uint32_t len, range, temp = 0; + void *pkt; + uint32_t sip, dip; + struct in6_addr sip6, dip6; + struct in6_addr zero_ip6 = IN6ADDR_ANY_INIT; + uint8_t rand_sip6, rand_dip6; + struct iphdr *iph; + uint8_t p8[MAX_TX_PKT_LEN] = + { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0x08, 0x00, //eth head + 0x45, 0x00, 0x00, 0x92, 0xc7, 0x6b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, //ip head + 0x00, 0x50, 0x07, 0xbb, 0x78, 0x28, 0x73, 0x3e, + 0x43, 0x23, 0x6a, 0x7c, 0x50, 0x12, 0x16, 0x58, + 0x76, 0xd4, 0x00, 0x00//tcp head + }; + uint8_t p8_v6[MAX_TX_PKT_LEN] = + { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0x86, 0xdd, //eth head + 0x60, 0x00, 0x00, 0x00, 0x04, 0xd8, 0x06, 0x40, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, //IPV6报文基本头 + 0xc9, 0x49, 0xe0, 0xf0, 0xce, 0xe0, 0xc4, 0xa0, + 0xe4, 0x76, 0x38, 0x0b, 0x50, 0x10, 0x40, 0x77, + 0x75, 0x2d, 0x00, 0x00 //TCP头 + }; + + ///获取缓冲区id + sid = *((int *)ptr); + + my_srand(&randf[sid], time(NULL)); + + rand_sip6 = memcmp(&glob_ipv6_sip, &zero_ip6, sizeof(zero_ip6)); + rand_dip6 = memcmp(&glob_ipv6_dip, &zero_ip6, sizeof(zero_ip6)); + + + ///把报文的应用数据设置为递增字节 + if (glob_ip_version == 4) + { + for (i = 0; i < MAX_TX_PKT_LEN - 54; i++) + { + p8[54 + i] = (uint8_t)i; + } + } + else + { + for (i = 0; i < MAX_TX_PKT_LEN - 74; i++) + { + p8_v6[74 + i] = (uint8_t)i; + } + } + + ///循环,直到线程循环标志清零 + while (glob_loop_flag_thread) + { + ///--确定报文长度 +// temp = my_rand(&randf[sid]); + range = glob_pkt_up_len - glob_pkt_low_len + 1; + len = temp % range + glob_pkt_low_len; + temp += glob_inc_len; +// glob_pkt_proto = (temp & 0x1) ? IPPROTO_TCP : IPPROTO_UDP; + + ///--发送报文 + ///--如果没有缓冲区,则循环等待 + while (!(pkt = pag_getsendbuf_eth(sid, 0))) { + usleep(5); + } + + ///--把原始报文拷贝到发送缓冲区,根据参数对报文修改报文内容 + if (glob_ip_version == 4) + { +// sip = (glob_sip == 0) ? my_rand(&randf[sid]) : glob_sip; +// dip = (glob_dip == 0) ? my_rand(&randf[sid]) : glob_dip; + sip = my_rand(&randf[sid]); + dip = my_rand(&randf[sid]); + memcpy(pkt, p8, len); +// build_ipv4_pkt(pkt + sizeof(struct ether_header), len - sizeof(struct ether_header), +// glob_pkt_proto, sip, dip); + + ///找到报文ip头 + pkt += sizeof(struct ether_header); + iph = (struct iphdr *)(pkt); + + ///修改各字段 + iph->tot_len = htons(len-sizeof(struct ether_header)); + iph->protocol = glob_pkt_proto; + iph->saddr = sip; + iph->daddr = dip; + if (glob_pkt_proto == 17) { + *((uint16_t *)(pkt + 24)) = htons(len - sizeof(struct ether_header) - 20); + } + } + else + { + if (rand_sip6 == 0) { + sip6.s6_addr32[0] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[1] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[2] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[3] = (uint32_t)my_rand(&randf[sid]); + } + if (rand_dip6 == 0) { + dip6.s6_addr32[0] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[1] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[2] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[3] = (uint32_t)my_rand(&randf[sid]); + } + memcpy(pkt, p8_v6, len); + build_ipv6_pkt(pkt + sizeof(struct ether_header), len - sizeof(struct ether_header), + glob_pkt_proto, sip6, dip6); + } + + ///--发送报文 + if (pag_send_eth(sid, len, 0) == -1) + { + printf("pag_send_eth return -1\n"); + continue; + } + + if (glob_print_pkt_flag) + { + print_pkt(pkt, len); + } + + ///--增加报文计数 + glob_pkts[sid][0]++; + glob_bytes[sid][0] += len; + } +} + +///@brief 发送报文的线程 +///@param ptr 线程建立时的指针,这里指向线程的数据流号 +void tx_thread(void *ptr) +{ + int i, sid; + uint32_t len, range, temp = 0; + void *pkt; + uint32_t sip, dip; + struct in6_addr sip6, dip6; + struct in6_addr zero_ip6 = IN6ADDR_ANY_INIT; + uint8_t rand_sip6, rand_dip6; + struct iphdr *iph; + uint8_t p8[MAX_TX_PKT_LEN-14] = + { + 0x45, 0x00, 0x00, 0x92, 0xc7, 0x6b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, //ip head + 0x00, 0x50, 0x07, 0xbb, 0x78, 0x28, 0x73, 0x3e, + 0x43, 0x23, 0x6a, 0x7c, 0x50, 0x12, 0x16, 0x58, + 0x76, 0xd4, 0x00, 0x00//tcp head + }; + uint8_t p8_v6[MAX_TX_PKT_LEN-14] = + { + 0x60, 0x00, 0x00, 0x00, 0x04, 0xd8, 0x06, 0x40, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, //IPV6报文基本头 + 0xc9, 0x49, 0xe0, 0xf0, 0xce, 0xe0, 0xc4, 0xa0, + 0xe4, 0x76, 0x38, 0x0b, 0x50, 0x10, 0x40, 0x77, + 0x75, 0x2d, 0x00, 0x00 //TCP头 + }; + + ///获取缓冲区id + sid = *((int *)ptr); + + my_srand(&randf[sid], time(NULL)); + + rand_sip6 = memcmp(&glob_ipv6_sip, &zero_ip6, sizeof(zero_ip6)); + rand_dip6 = memcmp(&glob_ipv6_dip, &zero_ip6, sizeof(zero_ip6)); + + + ///把报文的应用数据设置为递增字节 + if (glob_ip_version == 4) + { + for (i = 0; i < MAX_TX_PKT_LEN - 54; i++) + { + p8[40 + i] = (uint8_t)i; + } + } + else + { + for (i = 0; i < MAX_TX_PKT_LEN - 74; i++) + { + p8_v6[60 + i] = (uint8_t)i; + } + } + + ///循环,直到线程循环标志清零 + while (glob_loop_flag_thread) + { + ///--确定报文长度 + temp = my_rand(&randf[sid]); + range = glob_pkt_up_len - glob_pkt_low_len + 1; + len = temp % range + glob_pkt_low_len - sizeof(struct ether_header); +// glob_pkt_proto = (temp & 0x1) ? IPPROTO_TCP : IPPROTO_UDP; + + ///--发送报文 + ///--如果没有缓冲区,则循环等待 + while (!(pkt = pag_getsendbuf(sid))) { + usleep(5); + } + + ///--把原始报文拷贝到发送缓冲区,根据参数对报文修改报文内容 + if (glob_ip_version == 4) + { + sip = (glob_sip == 0) ? my_rand(&randf[sid]) : glob_sip; + dip = (glob_dip == 0) ? my_rand(&randf[sid]) : glob_dip; + memcpy(pkt, p8, len); +// build_ipv4_pkt(pkt, len - sizeof(struct ether_header), +// glob_pkt_proto, sip, dip); + + ///找到报文ip头 +// pkt += sizeof(struct ether_header); + iph = (struct iphdr *)(pkt); + + ///修改各字段 + iph->tot_len = htons(len); + iph->protocol = glob_pkt_proto; + iph->saddr = sip; + iph->daddr = dip; + if (glob_pkt_proto == 17) { + *((uint16_t *)(pkt + 24)) = htons(len - 20); + } + } + else + { + if (rand_sip6 == 0) { + sip6.s6_addr32[0] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[1] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[2] = (uint32_t)my_rand(&randf[sid]); + sip6.s6_addr32[3] = (uint32_t)my_rand(&randf[sid]); + } + if (rand_dip6 == 0) { + dip6.s6_addr32[0] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[1] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[2] = (uint32_t)my_rand(&randf[sid]); + dip6.s6_addr32[3] = (uint32_t)my_rand(&randf[sid]); + } + memcpy(pkt, p8_v6, len); + build_ipv6_pkt(pkt, len, glob_pkt_proto, sip6, dip6); + } + + ///--发送报文 + if (pag_send((glob_pkt_proto == IPPROTO_TCP) ? 1 : 0, sid, len) == -1) + { + printf("pag_send_eth return -1\n"); + continue; + } + + if (glob_print_pkt_flag) + { + print_pkt(pkt, len); + } + + ///--增加报文计数 + glob_pkts[sid][0]++; + glob_bytes[sid][0] += len; + } +} + +///@brief 信号响应函数,收到信号后把全局循环标志无效掉 +void stop_loop(int sig) +{ + glob_loop_flag_main = 0; +} + +void init_rand_func(void) +{ + int i; + + for (i = 0; i < MAX_THREADS_NUM; i++) { + randf[i].x = 0; + randf[i].y = 0; + randf[i].z = 0; + } +} + +///@brief 主函数 +///@return 成功返回0,失败返回-1 +int main(int argc, char *argv[]) +{ + int c, i, ret; + struct timeval ts, te; + double sec; + ulong all_pkts, all_bytes; + sigset_t set; + pthread_t tx_tids[MAX_THREADS_NUM], print_tid; + int sids[MAX_THREADS_NUM]; + + ///打印使用信息 + usage(argv[0]); + + ///产生一个随机数种子 + init_rand_func(); +// srand(time(0)); + + ///初始化参数 + glob_pkts_num = -1; + glob_inc_len = 1; + glob_pkt_low_len = MIN_TX_PKT_LEN; + glob_pkt_up_len = MAX_TX_PKT_LEN; + glob_pkt_proto = (rand() & 0x01) ? IPPROTO_TCP : IPPROTO_UDP; + glob_sip = 0; //(uint32_t)rand(); + glob_dip = 0; //(uint32_t)rand(); + glob_threads_num = DEF_THREADS_NUM; + glob_print_pkt_flag = 0; + glob_send_frame = 0; + glob_ip_version = 4; + for (i = 0; i < 4; i++) + { + glob_ipv6_sip.s6_addr32[i] = 0; //(uint32_t)rand(); + glob_ipv6_dip.s6_addr32[i] = 0; //(uint32_t)rand(); + } + + while ((c = getopt(argc, argv, "n:m:l:u:i:t:s:S:d:D:v:pf?h")) != -1) + { + switch (c) + { + case 'n': + glob_pkts_num = atoi(optarg); + break; + case 'm': + glob_threads_num = atoi(optarg); + if (glob_threads_num > MAX_THREADS_NUM) + { + printf("\nError: threads num invalid\n"); + return -1; + } + break; + case 'l': + glob_pkt_low_len = atoi(optarg); + if (glob_pkt_low_len < MIN_TX_PKT_LEN || glob_pkt_low_len > MAX_TX_PKT_LEN) + { + printf("\nError: min pkt len invalid\n"); + return -1; + } + break; + case 'u': + glob_pkt_up_len = atoi(optarg); + if (glob_pkt_up_len < MIN_TX_PKT_LEN || glob_pkt_up_len > MAX_TX_PKT_LEN) + { + printf("\nError: max pkt len invalid\n"); + return -1; + } + break; + case 'i': + glob_inc_len = atoi(optarg); + break; + case 't': + glob_pkt_proto = atoi(optarg); + break; + case 's': + glob_sip = inet_addr(optarg); + break; + case 'S': + ret = inet_pton(AF_INET6, optarg, &glob_ipv6_sip); + if (ret <= 0) + { + printf("\nError: get ipv6 src address failed\n"); + return -1; + } + break; + case 'd': + glob_dip = inet_addr(optarg); + break; + case 'D': + ret = inet_pton(AF_INET6, optarg, &glob_ipv6_dip); + if (ret <= 0) + { + printf("\nError: get ipv6 dst address failed\n"); + return -1; + } + break; + case 'f': + glob_send_frame = 1; + break; + case 'v': + glob_ip_version = atoi(optarg); + break; + case 'p': + glob_print_pkt_flag = 1; + break; + case '?': + case 'h': + default: + // usage(argv[0]); + return 1; + } + } + + ///输入参数合法性判断 + if (glob_pkt_up_len < glob_pkt_low_len) + { + printf("Warning:send len rang[%d, %d]\n", glob_pkt_low_len, glob_pkt_up_len); + usage(argv[0]); + return -1; + } + + if (glob_ip_version != 4 && glob_ip_version != 6) + { + usage(argv[0]); + return -1; + } + + ///打开设备 + if (pag_open() < 0) + { + printf("### Error : can not open device! ###\n"); + return -1; + } + + ///创建线程 + glob_loop_flag_thread = 1; + for (i = 0; i < glob_threads_num; i++) + { + int ret; + + sids[i] = i; + if (glob_send_frame == 1) + ret = pthread_create(&tx_tids[i], NULL, (void *)tx_thread_eth, (void *)&sids[i]); + else + ret = pthread_create(&tx_tids[i], NULL, (void *)tx_thread, (void *)&sids[i]); + if (ret != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + + ///如果不打印报文内容,则打印报文速度 + if (!glob_print_pkt_flag) + { + if (pthread_create(&print_tid, NULL, (void *)print_thread, NULL) != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + + ///等待结束信号,或着发出期望的包数 + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGINT, stop_loop); + + ///记录开始时间 + gettimeofday(&ts, NULL); + + glob_loop_flag_main = 1; + while (glob_loop_flag_main) + { + usleep(10); + + all_pkts = 0; + all_bytes = 0; + for (i = 0; i < glob_threads_num; i++) + { + all_pkts += glob_pkts[i][0]; + } + + if (glob_pkts_num != 0 && glob_pkts_num <= all_pkts) + { + break; + } + } + + ///记录结束时间 + gettimeofday(&te, NULL); + + ///停止线程 + glob_loop_flag_thread = 0; + for (i = 0; i < glob_threads_num; i++) + { + pthread_join(tx_tids[i], NULL); + } + if (!glob_print_pkt_flag) + { + pthread_join(print_tid, NULL); + } + + ///关闭设备 + pag_close(); + + ///打印总结信息 + printf("\n"); + printf("Pkts sent in threads: \n"); + + sec = (float)(te.tv_sec - ts.tv_sec) + ((float)(te.tv_usec - ts.tv_usec)) / 1000000.f; + all_pkts = 0; + all_bytes = 0; + for (i = 0; i < glob_threads_num; i++) + { + printf("\t Thread[%d]:\t <%8lu> pkts, <%8lu M> bytes\n", i, + glob_pkts[i][0], glob_bytes[i][0] >> 20); + all_pkts += glob_pkts[i][0]; + all_bytes += glob_bytes[i][0]; + } + printf("Total : %lu pkts, %lu bytes\n", all_pkts, all_bytes); + printf("Speed : < %u > pps, < %u M > bps\n", + (int)(all_pkts / sec), (int)((all_bytes >> 17) / sec)); + printf("\n"); + + return 0; +} diff --git a/examples/pag/tx_sample_mq.c b/examples/pag/tx_sample_mq.c new file mode 100644 index 0000000..733abcb --- /dev/null +++ b/examples/pag/tx_sample_mq.c @@ -0,0 +1,263 @@ +/****************************************************************************** +description : sample application +author : dawning +date : 2008.09.30 +******************************************************************************/ +/*Dawning Information Industry(BeiJing) Corp. Ltd. 1995~*. All Rights Reserved.*/ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <signal.h> +#include <time.h> +#include <sys/types.h> +#include <netinet/ip.h> + +#include "libpag.h" + + +#define USAG_MSG "\n *** Usage *** : %s [copynum]\n" + +#define THREAD_NUM 8 +#define SEND_LEN 300 +int COPY_PKT_TIME=0; +int sids[THREAD_NUM]; + +unsigned char sendpkt[4000] = +{ +0x45,0x00,0x00,0x92,0xc7,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0xd0,0x25,0x63,0xc0,0xa8,0x01,0xbb, //ip head +0x00,0x50,0x07,0xbb,0x78,0x28,0x73,0x3e,0x43,0x23,0x6a,0x7c,0x70,0x12,0x16,0x58,0x76,0xd4,0x00,0x00,//tcp head +0x02,0x04,0x05,0x64,0x01,0x01,0x04,0x02 +}; + +ulong pkts[THREAD_NUM][16]; +ulong bytes[THREAD_NUM][16]; +ulong old_pkts[THREAD_NUM]; +ulong old_bytes[THREAD_NUM]; +ulong all_pkts, all_bytes; + +int main_loop_flag = 1; +int thread_loop_flag = 1; + +char dist[8][2000]; + +void print_speed_thread(void *ptr) +{ + int i; + for(i=0; i<THREAD_NUM; i++) + { + old_pkts[i] = 0; + old_bytes[i] = 0; + } + + while(thread_loop_flag) + { + sleep(1); + printf("\nCurrent speed----- "); + printf("\n"); + for(i=0; i<THREAD_NUM; i++) + { + printf("\t Thread[%d]:\t %8lu pps, %8lu M bps\n", i, pkts[i][0] - old_pkts[i], (bytes[i][0] - old_bytes[i]) >> 17); + old_pkts[i] = pkts[i][0]; + old_bytes[i] = bytes[i][0]; + } + + } +} +//copy pkt +inline void process_pkt(int sid, void *pkt) +{ + int i, j, len; + char pkttmp[2000]; + unsigned char *p8,*psend; + struct iphdr* iph; + //printf("process pkt at %p\n",pkt); + pkts[sid][0]++; + p8 = (unsigned char*)(pkt); + //p8+=14; + len=0; + iph=(struct iphdr*)p8; + len = ntohs((unsigned short)iph->tot_len); + //printf("len:%d\n",len); + /* + printf("len:%d\n",len); + for(i=0;i<len;i++) + printf("0x%x ",p8[i]); + printf("\n"); + */ +//for 1.0 or older revison +// len = *(__u16 *)p8 &0xffff; + +//for tag 1.01 +// len = *(__u16 *)p8 &0xfff; + +//for tag 1.1 + //len = p8[1] + ((__u16)(p8[2] & 0x7)<<8); + bytes[sid][0] += len; + //copy pkt data + for(i=0; i<COPY_PKT_TIME; i++) + memcpy(pkttmp,p8,len); + +} + +unsigned long next = 1; +void my_srand(unsigned long seed) +{ + next = seed; +} + +unsigned my_rand(void) +{ + next = next * 1103515245 + 12345; + return((unsigned)(next/65536) % 32768); +} + +void random_ip(char *pkt) +{ + pkt[0] = my_rand() & 0xFF; + pkt[1] = my_rand() & 0xFF; + pkt[2] = my_rand() & 0xFF; + pkt[3] = my_rand() & 0xFF; + pkt[4] = my_rand() & 0xFF; + pkt[5] = my_rand() & 0xFF; + pkt[6] = my_rand() & 0xFF; + pkt[7] = my_rand() & 0xFF; +} + +//threads dealing with packets +void thread(void *ptr) +{ + + int sid; + void *pkt; + + int i; + void* psend; + int sendlen=SEND_LEN; + int pkt_type; + + sid = *((int *)ptr); + + //process pkts + while(thread_loop_flag) + { + do + { + psend = pag_getsendbuf(sid); + //printf("sizeofpsend=%d psend=%p\n",sizeof(psend),psend); + if (psend == NULL) + { + usleep(500); + } + } + while(psend == NULL); + //usleep(1); + //printf("sizeofpsend=%d psend=%p\n",sizeof(psend),psend); + //sleep(1); + memcpy(psend, sendpkt, sendlen); +// random_ip(psend + 26); + + //pkt_type = pkt_type ^ 1; + pag_send(0, sid, sendlen); + //send_count++; + pkts[sid][0]++; + bytes[sid][0] += sendlen; + + } +} + +//signal response function +void stop_loop(int sig) +{ + main_loop_flag = 0; +} + +int main(int argc, char *argv[]) +{ + struct timeval ts, te; + double sec; + ulong all_pkts, all_bytes; + sigset_t set; + pthread_t tids[THREAD_NUM],tx_tids[THREAD_NUM]; + pthread_t tid,tx_tid; + int i; + + if(argc >2) + { + printf(USAG_MSG, argv[0]); + return -1; + } + if(argc ==2) + COPY_PKT_TIME=atoi(argv[1]); + //open a device + //check returned device id + + + if(pag_open() < 0) + { + printf("### Error : can not open device! ###\n"); + return -1; + } + + //create processing threads + + my_srand(time(NULL)); + for(i=0; i<THREAD_NUM; i++) + { + sids[i] = i; + if(pthread_create(&tids[i], NULL, (void *)thread, (void *)&sids[i]) != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + //create printing thread + // if(argc == 1) + { + if(pthread_create(&tid, NULL, (void *)print_speed_thread, NULL) != 0) + { + printf("### Error: Can not creat threads!\n"); + pag_close(); + return -1; + } + } + + + //wait for stop signal + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGINT, stop_loop); + + //loop recieving pkts + gettimeofday(&ts, NULL); + while(main_loop_flag) usleep(10); + gettimeofday(&te, NULL); + + //stop threads + thread_loop_flag = 0; + usleep(200); + + + //close device + pag_close(); + + + sec = (float)(te.tv_sec - ts.tv_sec) + ((float)(te.tv_usec - ts.tv_usec)) / 1000000.f; + printf("\n"); + printf("Pkts recieved in threads: \n"); + all_pkts = 0; + all_bytes = 0; + for(i=0; i<THREAD_NUM; i++) + { + printf("\t Thread[%d]:\t <%8lu> pkts, <%8lu M> bytes\n", i, pkts[i][0], bytes[i][0] >> 20); + all_pkts += pkts[i][0]; + all_bytes += bytes[i][0]; + } + printf("Total : %lu pkts, %lu bytes\n", all_pkts, all_bytes); + printf("Speed : < %lu > pps, < %lu M > bps\n", (ulong)(all_pkts / sec), (ulong)((all_bytes >> 17) / sec)); + printf("\n"); + + return 0; +} |
