summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorQiuwen Lu <[email protected]>2016-09-21 14:31:36 +0800
committerQiuwen Lu <[email protected]>2016-09-21 14:31:36 +0800
commitde850016375d367637d1f9ab610de596a8a92ac7 (patch)
treec76a4eb1879fb9147ce72a6dc9702bc08ede7500 /examples
parent2678cdce677a3e82294d5c307cc1120b36281f5a (diff)
引入pag系列测试样例文件。
Diffstat (limited to 'examples')
-rw-r--r--examples/pag/rx_sample.c584
-rw-r--r--examples/pag/tx_sample.c757
-rw-r--r--examples/pag/tx_sample_mq.c263
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;
+}