added del_ip, del_mac functions
[keystone-rtos/netapi.git] / ti / runtime / netapi / test / net_test.c
1 /******************************************\r
2  * File: net_test.c\r
3  * Purpose: test app for netapi\r
4  **************************************************************\r
5  * FILE:  net_test.c\r
6  * \r
7  * DESCRIPTION:  netapi user space transport\r
8  *               library  test application\r
9  * \r
10  * REVISION HISTORY:  rev 0.0.1 \r
11  *\r
12  *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
13  * \r
14  *  Redistribution and use in source and binary forms, with or without \r
15  *  modification, are permitted provided that the following conditions \r
16  *  are met:\r
17  *\r
18  *    Redistributions of source code must retain the above copyright \r
19  *    notice, this list of conditions and the following disclaimer.\r
20  *\r
21  *    Redistributions in binary form must reproduce the above copyright\r
22  *    notice, this list of conditions and the following disclaimer in the \r
23  *    documentation and/or other materials provided with the   \r
24  *    distribution.\r
25  *\r
26  *    Neither the name of Texas Instruments Incorporated nor the names of\r
27  *    its contributors may be used to endorse or promote products derived\r
28  *    from this software without specific prior written permission.\r
29  *\r
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
41 \r
42  *****************************************/\r
43 \r
44 #include <stdio.h>\r
45 #include <stdlib.h>\r
46 #include <unistd.h>\r
47 #include <string.h>\r
48 \r
49 \r
50 #include "trie.h"\r
51 #include "string.h"\r
52 #include "netapi.h"\r
53 #include "pktio.h"\r
54 #include <sys/resource.h>\r
55 \r
56 /*************debug********************/\r
57 void dump_descr(unsigned long *p, int n)\r
58 {\r
59    printf("--------dump of descriptor %d %x\n", n, (int) p);\r
60    printf("> %x %x %x %x %x %x %x %x\n",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);\r
61    printf("> %x %x %x %x %x %x %x %x\n",p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);\r
62    printf("-----------------------------\n");\r
63 }\r
64 /*****************************************/\r
65 \r
66 \r
67 //************for multi pkt burst  xfer test in loopback mode\r
68 #define TX_BURST 4\r
69 int pktloopback=TUNE_NETAPI_NWAL_ENABLE_PASS_LOOPBACK;\r
70 \r
71 //this device: 10.0.0.100, mac 0x,01,02,03,04,05  and .. 0x6\r
72 \r
73 //test packet, setup for loopback (so dest is ourself)\r
74 static uint8_t testPkt[] = {\r
75 \r
76   /* MAC header */\r
77   0x00, 0x01, 0x02, 0x03, 0x04, 0x05,\r
78   0x00, 0xe0, 0xa6, 0x66, 0x57, 0x04,\r
79   0x08, 0x00,\r
80 \r
81   /* IP header */\r
82   0x45, 0x00,\r
83   0x00, 0x6c,  /* Length (including this header) */\r
84   0x00, 0x00, 0x00, 0x00, 0x05, 0x11,\r
85   0x00, 0x00,  /* Header checksum */\r
86   0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x64,\r
87 \r
88   /* UDP header */\r
89   0x12, 0x34, 0x05, 0x55,\r
90   0x00, 0x58,  /* Length, including this header */\r
91   0x00, 0x00,  /* Header checksum */\r
92 \r
93  /* Payload */\r
94   0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,\r
95   0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,\r
96   0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,\r
97   0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,\r
98   0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,\r
99   0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,\r
100   0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,\r
101   0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,\r
102   0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,\r
103   0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81\r
104 \r
105 };\r
106 \r
107 #define TEST_PAYLOAD_LEN            80\r
108 \r
109 #define TEST_PKT_IP_OFFSET_BYTES        14\r
110 #define TEST_PKT_UDP_OFFSET_BYTES       34\r
111 #define TEST_PKT_PLOAD_OFFSET_BYTES     42\r
112 #define TEST_PKT_UDP_HDR_LEN            8\r
113 /* Offsets to length fields */\r
114 #define TEST_PKT_OFFSET_IP_LEN      16\r
115 #define TEST_PKT_OFFSET_UDP_LEN     38\r
116 \r
117 #define TEST_PKT_LEN                122\r
118 \r
119 /* The pseudo header checksum of the packet except for the 16 bit length */\r
120 #define TEST_PKT_PSEUDO_HDR_CHKSUM_SANS_LEN  0x0FFC\r
121 \r
122 \r
123 \r
124 #if 1\r
125 //#include "arpa/inet.h"\r
126 long htonl(long x)\r
127 {\r
128         long temp = (x&0xff000000)>>24 | (x&0xff0000)>>8 | (x&0xff00)<<8 |  (x&0xff)<<24 ;\r
129         return temp;\r
130 }\r
131 \r
132 /********************************************************************\r
133  *  FUNCTION PURPOSE: Ones complement addition utility\r
134  ********************************************************************\r
135  ********************************************************************/\r
136 uint16_t test_utilOnesComplementAdd (uint16_t v1, uint16_t v2)\r
137 {\r
138   uint32_t result;\r
139 \r
140   result = (uint32_t)v1 + (uint32_t)v2;\r
141   result = (result >> 16) + (result & 0xffff);\r
142   result = (result >> 16) + (result & 0xffff);\r
143 \r
144   return ((uint16_t)result);\r
145 }\r
146 \r
147 /********************************************************************\r
148  *  FUNCTION PURPOSE: Ones complement checksum utility\r
149  ********************************************************************\r
150  ********************************************************************/\r
151  uint16_t test_utilOnesCompChkSum (uint8_t *p, uint32_t nwords)\r
152 {\r
153   uint16_t chksum = 0;\r
154   uint16_t v;\r
155   uint32_t i;\r
156   uint32_t j;\r
157 \r
158   for (i = j = 0; i < nwords; i++, j+=2)  {\r
159     v = (p[j] << 8) | p[j+1];\r
160     chksum = test_utilOnesComplementAdd (chksum, v);\r
161   }\r
162   return (chksum);\r
163 } /* utilOnesCompChkSum */\r
164 \r
165 /**************************************************************************************\r
166  * FUNCTION PURPOSE: Compute ipv4 psudo checksum\r
167  **************************************************************************************\r
168  * DESCRIPTION: Compute ipv4 psudo checksum\r
169  **************************************************************************************/\r
170 uint16_t test_utilGetIpv4PsudoChkSum (uint8_t *data, uint16_t payloadLen)\r
171 {\r
172   uint16_t psudo_chksum;\r
173 \r
174   psudo_chksum = test_utilOnesCompChkSum (&data[12], 4);\r
175   psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, (uint16_t) data[9]);\r
176   psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, payloadLen);\r
177 \r
178   return (psudo_chksum);\r
179 \r
180 } /* utilGetIpv4PsudoChkSum */\r
181 \r
182 \r
183 \r
184 #endif\r
185 typedef struct stats_t\r
186 {\r
187         long itx;  //initially generated\r
188         long rx;\r
189         long tx;\r
190         long n_bad;\r
191         long n_new;\r
192 } STATS_T;\r
193 \r
194 typedef struct head_t\r
195 {\r
196         long ip[5];\r
197         long udp[2];\r
198 } HEAD_T;\r
199 \r
200 typedef struct key_t\r
201 {\r
202   long src_ip;\r
203   long dst_ip;\r
204   short src_port;\r
205   short dst_port;\r
206 } KEY_T;\r
207 \r
208 unsigned char mac0[]={0x00,0x01,0x02,0x03,0x04,0x05}; //interface 0\r
209 unsigned char mac1[]={0x00,0x01,0x02,0x03,0x04,0x06}; //interface 1\r
210 nwalIpAddr_t OurIp0={ 10, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
211 nwalIpAddr_t OurIp1={ 10, 0, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
212 \r
213 #if 1  //goes with real tx (to laptop) \r
214 unsigned char real_mac_header[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e,\r
215                       0x00,0x01,0x02,0x03,0x04,0x05,\r
216                       0x08,0x00};\r
217 unsigned char real_ip_addr[]={0xa,0x00,0x00,0x64,0xa,0x0,0x0,0xa};\r
218 #endif\r
219 \r
220 #if 0  //goes with loopback\r
221 unsigned char mac_header[]={0x00,0x01,0x02,0x03,0x04,0x05, \r
222                       0x00,0x11,0x22,0x33,0x44,0x55,\r
223                       0x08,0x00};\r
224 #endif\r
225 #define NE 65536 \r
226 HEAD_T *nat;\r
227 \r
228 #define NP 5000\r
229 int n_pkt = NP;\r
230 STATS_T stats;\r
231 \r
232 Trie * P_trie;\r
233 HEAD_T pkts[NP];\r
234 #define PERSLOW  10  //% of pkts that will not be fastpath'd \r
235 int perslow= PERSLOW;\r
236 \r
237 /*******************************************\r
238  *************NETAPI OBJECTS***************\r
239  *****************************************/\r
240 Pktlib_HeapHandle OurHeap;\r
241 PKTIO_HANDLE_T *our_chan;\r
242 PKTIO_HANDLE_T *netcp_rx_chan;\r
243 PKTIO_HANDLE_T *netcp_tx_chan;\r
244 PKTIO_CFG_T our_chan_cfg={PKTIO_RW, PKTIO_LOCAL, PKTIO_Q_ANY, 8};\r
245 PKTIO_CFG_T netcp_rx_cfg={PKTIO_R, PKTIO_NA, PKTIO_NA, 8};\r
246 PKTIO_CFG_T netcp_tx_cfg={PKTIO_W, PKTIO_NA, PKTIO_NA, 8};\r
247 \r
248 void house(NETAPI_SCHED_HANDLE_T *s);\r
249 NETAPI_T netapi_handle;\r
250 NETAPI_SCHED_HANDLE_T * our_sched;\r
251 NETAPI_SCHED_CONFIG_T our_sched_cfg={\r
252   NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 50  //every 50 poll loops\r
253 };\r
254 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);\r
255 NETAPI_TIMER_GROUP_HANDLE_T ourTimerBlock; \r
256 NETAPI_TIMER_T t1;\r
257 NETAPI_TIMER_T t2;\r
258 NETAPI_TIMER_T t3;\r
259 \r
260 void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
261         int n_fired,     //# timers fired\r
262         NETAPI_TIMER_LIST_T fired_list,\r
263         uint64_t currentTime);\r
264 \r
265 NETCP_CFG_IP_T ip_rule0;\r
266 NETCP_CFG_IP_T ip_rule1;\r
267 /*************************END NETAPI OBJECTS***********************/\r
268 \r
269 #define START_SRC_IP 0x0a00000a\r
270 #define DST_IP       0xc0a80001\r
271 #define NEW_START_SRC_IP 0x9eda000a\r
272 #define DST_PORT 0x555 \r
273 #define START_SRC_PORT 0x1234\r
274 #define NEW_START_SRC_PORT 100\r
275 void update_header(HEAD_T * p_head, int len)\r
276 {\r
277    unsigned char *p = (unsigned char *) &p_head->udp[1];\r
278    len -= (20+14);\r
279    /* update ip checksum */\r
280    /* update udp checksum */\r
281    /* update length */\r
282    *p= (len&0xff00)>>8;\r
283    *(p+1) = len&0xff;\r
284 }\r
285 \r
286 #if 0\r
287 void gen_pkts(int np)\r
288 {\r
289 int i;\r
290 int ip = START_SRC_IP &0xff;\r
291 int port= START_SRC_PORT;\r
292 //HEAD_T temp={{0x25000200,0xdead0000,0x80110000,START_SRC_IP,DST_IP},\r
293 //             {START_SRC_PORT<<16|DST_PORT,0x01ec<<16|0x0000}};\r
294 HEAD_T temp;\r
295 memcpy(&temp,&testPkt[0],sizeof(HEAD_T));\r
296 \r
297 for(i=0;(i<np) && (i<NP);i++)\r
298   {\r
299        memcpy(&pkts[i],&temp,sizeof(temp));\r
300        update_header(&pkts[i],512);      /* update checksums etc */\r
301        /* change template for new pkt */\r
302        ip+=1;\r
303        if(ip>254) {(ip=START_SRC_IP&0xff); port+=1; }\r
304        temp.ip[3] = htonl((START_SRC_IP&0xffffff00)| ip);\r
305        temp.udp[0] = htonl( (temp.udp[0]&0xffff0000)| port);\r
306        temp.udp[1] = htonl(temp.udp[1]);\r
307      \r
308   }\r
309   n_pkt=np;\r
310 }\r
311 #endif\r
312 \r
313 void build_table(Trie * p_trie)\r
314 {\r
315 int i;\r
316 int sport=NEW_START_SRC_PORT; \r
317 HEAD_T temp,temp2;\r
318 KEY_T key;\r
319 \r
320 memcpy(&temp,&testPkt[14],sizeof(temp));\r
321 \r
322  //insert entry into trie\r
323 key.src_ip = temp.ip[3];\r
324 key.dst_ip = temp.ip[4];\r
325 key.src_port= (temp.udp[0]&0xffff0000)>>16;\r
326 key.dst_port= (temp.udp[0]&0x0000ffff);\r
327 trie_insert(p_trie,(char *)&key,sizeof(key), (void *) &nat[0]); //asociate with nat entry 0\r
328 \r
329 //build nat table\r
330 for(i=0;i<100;i++)\r
331 {\r
332    memcpy(&temp2,&testPkt[14],sizeof(temp));\r
333    temp2.udp[0] = (temp2.udp[0] & 0xffff0000) |  sport;\r
334    memcpy(&nat[i], &temp2, sizeof(temp2));\r
335    sport+= 1;\r
336 }\r
337 }\r
338 \r
339 //===========stub transmitter==================\r
340 void send_pkt(Ti_Pkt *pkt, int len)\r
341 {\r
342 //just free pkt.  Don't send\r
343 Pktlib_freePacket((Ti_Pkt*)pkt);\r
344         return;\r
345 }\r
346 \r
347 //==========stub slow path============\r
348 void slow_path(Ti_Pkt *pkt, int len)\r
349 {\r
350 // debug: check descriptor for validity by verifying that desciptor link field is null as expected\n");\r
351          {Ti_Pkt * k= Pktlib_getNextPacket(pkt); if(k != 0) {printf(" slowpath, nexpkt != NULL");}}\r
352 //just free pkt\r
353 Pktlib_freePacket((Ti_Pkt*)pkt);\r
354         return;\r
355 }\r
356 /* check header */\r
357 struct LastPktInfo\r
358 {\r
359 int iface;\r
360 int ipcsum;\r
361 int l4csum;\r
362 } ;\r
363 static struct LastPktInfo lpInfo;\r
364 \r
365 int check_header(HEAD_T * p_head, PKTIO_METADATA_T * p_meta)\r
366 {\r
367 if (NWAL_RX_FLAG1_META_DATA_VALID & p_meta->u.rx_meta->rxFlag1)\r
368 {\r
369 lpInfo.iface = ((unsigned int)p_meta->u.rx_meta->appId) &0xff; //last byte is interface num\r
370 lpInfo.ipcsum =(p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_MASK )== NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_ACK ? 1 : 0;\r
371 lpInfo.l4csum = (p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_MASK )== ((NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_ACK) << NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_SHIFT) ? 1 : 0; \r
372 }\r
373  return 1;\r
374 }\r
375 \r
376 #define PKT_LEN 1400\r
377 void test_alloc_free(int n)\r
378 {\r
379 int i;\r
380 Ti_Pkt * b;\r
381 \r
382 for(i=0;i<n;i++)\r
383 {\r
384   b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
385   Pktlib_freePacket(b);\r
386 }\r
387 }\r
388 /*-----------test driver: gen an input pkt------- */\r
389 //char buffer[sizeof(HEAD_T)+PKT_LEN];\r
390 Ti_Pkt * get_pkt(int n, unsigned int *p_len)\r
391 {\r
392    int ind;\r
393    long long temp;\r
394    Ti_Pkt * b;\r
395    char * buffer;\r
396    unsigned int len;\r
397 \r
398   if (pktloopback==0)\r
399   {\r
400         if (n>=4) return NULL;   //just gen pkts to warm swtich, so that it knows\r
401                                 //our mac is valid\r
402   }  \r
403   b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
404   if (!b) \r
405     {printf("net_test: get_pkt() heap empty!! %d pkts gen'd %d \n", n); return NULL;};\r
406 \r
407     //debug - way to validate descriptor\r
408     {Ti_Pkt* k= Pktlib_getNextPacket(b); \r
409          if(k != 0) {printf(" genpkt, nexpkt != NULL");}}\r
410 \r
411 \r
412    //get pointer to buffer area of packet\r
413    Pktlib_getDataBuffer(b,(uint8_t**)&buffer,&len);\r
414 \r
415 #if 0 \r
416 if (pktloopback==0)\r
417 {\r
418    temp = (long long) rand();\r
419    temp *= PKT_LEN;\r
420    temp /= RAND_MAX;\r
421    temp +=2;\r
422    *p_len = (int) temp; \r
423    *p_len = *p_len &0xfffffffe;\r
424    temp = (long long) rand();\r
425    temp *= n_pkt;\r
426    temp /= RAND_MAX;\r
427    ind = (int) temp;\r
428    update_header(&pkts[ind],*p_len);\r
429    //printf("get pkt:%d %d ind=%d len=%d\n",RAND_MAX, rand(),ind, *p_len);\r
430     memcpy(&buffer[0], &mac_header[0],14);\r
431     memcpy(&buffer[14],(char*)&pkts[ind],sizeof(HEAD_T)); \r
432 }\r
433 else\r
434 #endif\r
435 \r
436    //copy test packet into buffer\r
437 {\r
438     memcpy(&buffer[0], &testPkt[0],TEST_PKT_LEN);\r
439     *p_len = TEST_PKT_LEN;\r
440 }\r
441     return b; \r
442 }\r
443 \r
444 \r
445 /******************************************************/\r
446 /******************PKT RECEIVE HANDLER *************************/\r
447 /******************************************************/\r
448 void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
449                          PKTIO_METADATA_T meta[], int n_pkts,\r
450                          uint64_t ts )\r
451 {\r
452 int i;\r
453 int len;\r
454 int p;\r
455 HEAD_T * p_res;\r
456 Ti_Pkt * tip;\r
457 unsigned int templen;\r
458 int err;\r
459 KEY_T key;\r
460 char * p_pkt;\r
461 HEAD_T * p_head;\r
462 HEAD_T temp_head;\r
463 \r
464     p_head=&temp_head;\r
465 \r
466     //debug\r
467 #if 0\r
468     if (n_pkts != TX_BURST) {\r
469       printf("recv_cb, txsofar=%d rxsofar=%d  np = %d, NOT %d\n", \r
470              stats.itx, stats.rx, n_pkts,TX_BURST);\r
471       our_stats_cb(netapi_handle,NULL);\r
472     }\r
473 #endif\r
474     //test_alloc_free(7);\r
475     //printf("recv start\n");\r
476 \r
477    /* loop over received pkts */\r
478    for(i=0;i<n_pkts;i++)\r
479    {\r
480         tip = p_recv[i];\r
481         Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
482         len = Pktlib_getPacketLen(tip);//real length\r
483 \r
484          //debug: validate descriptor */\r
485          if(Pktlib_getNextPacket(tip) != 0) {printf(" rcv_cb, nexpkt != NULL");}\r
486         //debug printf("recv pkt, len=%d %d\n", len, templen);\r
487         stats.rx+=1;\r
488 \r
489 #ifdef DEBUG_DESC\r
490    if (stats.rx<16){printf(">rx dmp.."); dump_descr((long *) tip, stats.rx);}\r
491    else if (stats.rx>99) {printf(">rx dmp.."); dump_descr((long *) tip,stats.rx);}\r
492 #endif\r
493 \r
494 \r
495         /* check header */\r
496         memcpy(p_head,&p_pkt[14],sizeof(HEAD_T));\r
497         if (!check_header(p_head,&meta[i])) { \r
498                 stats.n_bad+=1;Pktlib_freePacket(tip); continue;\r
499         }\r
500 \r
501         /* lookup flow */\r
502         key.src_ip = p_head->ip[3];\r
503         key.dst_ip = p_head->ip[4];\r
504         key.src_port= (p_head->udp[0]&0xffff0000)>>16;\r
505         key.dst_port= (p_head->udp[0]&0x0000ffff);\r
506         p_res= (HEAD_T *) trie_lookup(P_trie, (char *) &key, sizeof(key));\r
507         if (!p_res) { stats.n_new+=1;  slow_path(tip, len); continue;}\r
508 \r
509         /* copy header */\r
510         memcpy((char *) p_head, (char *) p_res, sizeof(HEAD_T));\r
511 \r
512         memcpy(&p_pkt[14],p_head,sizeof(HEAD_T));\r
513         /* update_mac(&p_pkt[0]);  */\r
514 \r
515         /* 'simulate' send pkt */\r
516         send_pkt(tip,len);\r
517         stats.tx+=1;\r
518     }\r
519     //printf("recv done\n");\r
520 }\r
521 \r
522 //timer callback \r
523 void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
524         int n_fired,     //# timers fired\r
525         NETAPI_TIMER_LIST_T fired_list,\r
526         uint64_t currentTime)\r
527 {\r
528 int i;\r
529 NETAPI_TIMER_T tx;\r
530 int cookie;\r
531 int err;\r
532 unsigned long long et;\r
533 printf("TIMER CALLBACK @ %lld %d timers\n", currentTime, n_fired);\r
534 tx = netapi_TimerGetFirst(fired_list);\r
535 for(i=0;i<n_fired;i++)\r
536 {\r
537   cookie = (int) netapi_TimerGetCookie(tx);\r
538   et =  netapi_TimerGetTs(tx); //debug\r
539   printf("   timer %d - cookie = %d expected ts=%lld (delta=%lld)\n", i, cookie, et, currentTime-et);\r
540   if (cookie ==1)\r
541      t1 = netapi_TimerGroupStartTimer(\r
542         th,\r
543         (void *) 1,\r
544         100LL,  //timer group tics\r
545         &err);\r
546   else if (cookie ==2)\r
547       t2 = netapi_TimerGroupStartTimer(\r
548         th,\r
549         (void *) 2,\r
550         200LL,  //timer group ticks\r
551         &err);\r
552   else\r
553   {\r
554     t3 = netapi_TimerGroupStartTimer(\r
555         th,\r
556         (void *) 3,\r
557         300LL,  //timer group ticks\r
558         &err);\r
559     //cancel 1 and restart 1\r
560    netapi_TimerGroupCancel(th,t1,&err);\r
561    t1 = netapi_TimerGroupStartTimer(\r
562         th,\r
563         (void *) 1,\r
564         100LL,  //timer group ticks\r
565         &err);\r
566  }\r
567   tx = netapi_TimerGetNext(fired_list,tx); \r
568 }\r
569 }\r
570 \r
571 \r
572 static int np2process = NP;\r
573 /******************************************************\r
574  * stats callback\r
575  *******************************************************/\r
576 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats)\r
577 {\r
578 uint32_t numFreeDataPackets;\r
579 uint32_t numZeroBufferPackets;\r
580 uint32_t numPacketsinGarbage;\r
581 \r
582 printf("stats @ %lld\n", netapi_getTimestamp());\r
583 if(pPaStats)\r
584 {\r
585        printf("C1 number of packets:           %d\n", pPaStats->classify1.nPackets);\r
586        printf("C1 number IPv4 packets:         %d\n", pPaStats->classify1.nIpv4Packets);\r
587        //printf("C1 number llc/snap fail:        %d\n", pPaStats->classify1.nLlcSnapFail);\r
588        printf("C1 number table matched:        %d\n", pPaStats->classify1.nTableMatch);\r
589        printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);\r
590        printf ("C1 number of parse fail:        %d\n",pPaStats->classify1.nParseFail);\r
591        printf("C1 number of command failures:  %d\n", pPaStats->classify1.nCommandFail);\r
592        printf("C1 number invalid reply dests:  %d\n", pPaStats->classify1.nInvalidComReplyDest);\r
593        printf ("C1 number of silent discard:    %d\n",pPaStats->classify1.nSilentDiscard);\r
594        printf("C1 number of invalid control:   %d\n", pPaStats->classify1.nInvalidControl);\r
595        printf ("C1 number of invalid states:    %d\n",pPaStats->classify1.nInvalidState);\r
596        printf ("C1 number of system fails:      %d\n",pPaStats->classify1.nSystemFail);\r
597        printf ("C2 number parse failed  :      %d\n",pPaStats->classify2.nParseFail);\r
598        printf ("C2 number Invld Header  :      %d\n",pPaStats->classify2.nInvldHdr);\r
599        printf ("C2 number udp           :      %d\n",pPaStats->classify2.nUdp);\r
600        printf ("C2 number tcp           :      %d\n",pPaStats->classify2.nTcp);\r
601        printf ("C2 number cmd fail      :      %d\n",pPaStats->classify2.nCommandFail);\r
602        printf ("C2 number silent drop   :      %d\n",pPaStats->classify2.nSilentDiscard);\r
603        printf ("C2 number invalid cntrl :      %d\n\n",pPaStats->classify2.nInvalidControl);\r
604 }\r
605 Pktlib_getHeapStats(OurHeap, &numFreeDataPackets,\r
606                              &numZeroBufferPackets, &numPacketsinGarbage);\r
607 printf("heap stats>  #free=%d #zb=%d #garbage=%d\n", numFreeDataPackets,\r
608                                 numZeroBufferPackets, numPacketsinGarbage);\r
609 //debug = dump timer polling stats\r
610 dump_poll_stats();\r
611 \r
612 \r
613 }\r
614 \r
615 //******************************************************\r
616 //use scheduling housekeeping callback to generate pkts\r
617 //******************************************************\r
618 void house(NETAPI_SCHED_HANDLE_T * s)\r
619 {\r
620 Ti_Pkt * tip;\r
621 unsigned int len;\r
622 nwalTxPktInfo_t meta_tx={0};\r
623 PKTIO_METADATA_T meta = {PKTIO_META_TX,0};\r
624 int err;\r
625 static int house_pkts_gened=0;\r
626 int p;\r
627 unsigned char * pIpHdr,* pData;\r
628 \r
629 for(p=0;p<TX_BURST;p++) {  \r
630 //reguest stats \r
631 if ((house_pkts_gened>0) && (! (house_pkts_gened%400)) )\r
632 {\r
633    printf("net_test> request stats at n=%d \n",house_pkts_gened);\r
634    netcp_cfgReqStats(netapi_handle, our_stats_cb, 0,&err); \r
635    if (err!=0) {printf("stats req failed\n");}\r
636 }\r
637 \r
638 \r
639   if (house_pkts_gened >= np2process+ 100)\r
640   {\r
641      //shutdown\r
642      netapi_schedShutdown(s,NULL,&err);\r
643      continue;\r
644   }\r
645 \r
646   else if (house_pkts_gened >= np2process) { house_pkts_gened+=1;  continue;}\r
647   \r
648 \r
649 /* manufacture a pkt to transmit */\r
650    tip = get_pkt(house_pkts_gened, &len);\r
651    if(!tip) { house_pkts_gened +=1; continue; }\r
652 \r
653    /* set the pkt length */\r
654    Pktlib_setPacketLen(tip, len);\r
655 \r
656    /* set up meta data */\r
657     meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM | NWAL_TX_FLAG1_DO_UDP_CHKSUM);\r
658     meta_tx.startOffset = 0;\r
659     meta_tx.pktLen = len;\r
660     meta_tx.ipOffBytes = TEST_PKT_IP_OFFSET_BYTES;\r
661     meta_tx.l4OffBytes = TEST_PKT_UDP_OFFSET_BYTES;\r
662     meta_tx.l4HdrLen = TEST_PKT_UDP_HDR_LEN;\r
663     meta_tx.ploadOffBytes = TEST_PKT_PLOAD_OFFSET_BYTES;\r
664     meta_tx.ploadLen = TEST_PAYLOAD_LEN;\r
665 \r
666     Pktlib_getDataBuffer(tip,&pData,&len);\r
667     pIpHdr = pData + meta_tx.ipOffBytes;\r
668     meta_tx.pseudoHdrChecksum =\r
669         test_utilGetIpv4PsudoChkSum(pIpHdr,(TEST_PAYLOAD_LEN+TEST_PKT_UDP_HDR_LEN));\r
670 \r
671    /* post it to netcp tx channel*/\r
672    meta.u.tx_meta=&meta_tx;\r
673 #ifdef DEBUG_DESC\r
674    if (house_pkts_gened<16) dump_descr((long *) tip, house_pkts_gened);\r
675    else if (house_pkts_gened>99) dump_descr((long *) tip,house_pkts_gened);\r
676 #endif\r
677    pktio_send(netcp_tx_chan,tip,&meta,&err);\r
678    if (err == 0) stats.itx +=1;\r
679 \r
680    house_pkts_gened +=1;\r
681  }\r
682 }\r
683 \r
684 \r
685 /***************************************\r
686  ********** test driver*****************\r
687  ***************************************/\r
688 int main(int argc, char **argv)\r
689 {\r
690 int err;\r
691 rlim_t oss,ss = 1024*1024;\r
692 struct rlimit rl;\r
693 \r
694 err= getrlimit(RLIMIT_STACK,&rl);\r
695 if (!err) printf(" stack limit = %d\n",rl.rlim_cur); else printf("getrlimit failed\n");\r
696 #if 0\r
697 rl.rlim_cur = ss;\r
698 err=setrlimit(RLIMIT_STACK,&rl);\r
699 if (!err) printf("set stack to %d\n",rl.rlim_cur); else printf("setrlimit failed\n");\r
700 #endif\r
701 \r
702 if (argc>=2)  np2process = atoi(argv[1]);\r
703 if (np2process<0) np2process = NP; /* default */\r
704 if (argc==3)  perslow = atoi(argv[2]);\r
705 if ((perslow<0)||(perslow>100)) perslow=PERSLOW;//default\r
706 if (argc>3) {printf("net_test  <no of pkts to process> <percent slow path>\n"); exit(1);}\r
707 \r
708 \r
709 //real mode, so update our test packet mac header and ip header\r
710 if (pktloopback==0)\r
711 {\r
712 memcpy(&testPkt,&real_mac_header[0],14); //overwrite test pkt mac address\r
713 memcpy(&testPkt[26],&real_ip_addr[0],8);//overrite test pkt ip addresses\r
714 }\r
715 \r
716 /*******************************************/\r
717 /*************NETAPI STARTUP****************/\r
718 /*******************************************/\r
719 \r
720 /* create netapi */\r
721 netapi_handle = netapi_init(NETAPI_SYS_MASTER);\r
722 \r
723 /* open the main heap */\r
724 OurHeap = Pktlib_findHeapByName("netapi");\r
725 if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}\r
726 \r
727 /* create a pktio channel */\r
728 our_chan=pktio_create(netapi_handle,"our1stq",(PKTIO_CB) recv_cb, &our_chan_cfg,&err);\r
729 if (!our_chan) {printf("pktio create failed err=%d\n",err); exit(1);}\r
730 \r
731 /* open netcp default tx, rx queues */\r
732 netcp_tx_chan= pktio_open(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg,  &err);\r
733 if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);}\r
734 netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb, &netcp_rx_cfg,  &err);\r
735 if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}\r
736 \r
737 \r
738 /* create scheduler instance */\r
739 our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);\r
740 if (!our_sched) {printf("sched create failed\n"); exit(1);}\r
741 \r
742 /* add mac intefaces */\r
743 netcp_cfgCreateMacInterface(\r
744                   netapi_handle,\r
745                   &mac0[0],\r
746                   0,0,\r
747                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
748                   (NETCP_CFG_VLAN_T ) NULL ,  //future\r
749                   1, \r
750                   &err);\r
751 if (err) {printf("addmac0 failed %d\n",err); exit(1); } \r
752 \r
753 //attach an IP to this interface\r
754 ip_rule0=netcp_addIp(\r
755                   netapi_handle,\r
756                   0,\r
757                   nwal_IPV4,\r
758                   &OurIp0,\r
759                   NULL,  //all IP\r
760                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
761                   &err\r
762                   );\r
763 if (err) {printf("addip0 failed %d\n",err); exit(1); } \r
764 #if 1\r
765 //create a 2nd mac instance\r
766 netcp_cfgCreateMacInterface(\r
767                   netapi_handle,\r
768                   &mac1[0],\r
769                   1,1,\r
770                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
771                   (NETCP_CFG_VLAN_T ) NULL ,  //future\r
772                   1,\r
773                   &err);\r
774 if (err) {printf("addmac1 failed %d\n",err); exit(1); }\r
775 \r
776 //attach an IP to this interface\r
777 ip_rule1=netcp_addIp(\r
778                   netapi_handle,\r
779                   1,\r
780                   nwal_IPV4,\r
781                   &OurIp1,\r
782                   NULL,  //all IP\r
783                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
784                   &err\r
785                   );\r
786 if (err) {printf("addip1 failed %d\n",err); exit(1); }\r
787 \r
788 #endif\r
789 \r
790  ourTimerBlock = netapi_TimerGroupCreate(\r
791         netapi_handle,\r
792         "our1sttimer",\r
793         our_timer_cb,\r
794         0,    //1 if timers local to thread\r
795         0,    //1 if expect to cancel\r
796         netapi_getTicksPerSec()/1000,  /* 1 msc resolution for these timers */\r
797         netapi_getTicksPerSec()/5000, /* would like .5 msc tolerence */\r
798         10,  //small # of timers to test garbage collection\r
799         &err);\r
800 if (err) {printf("timergroupcreate failed %d\n",err); exit(1);}\r
801 \r
802 //start a couple of timers \r
803 t1 = netapi_TimerGroupStartTimer(\r
804         ourTimerBlock,\r
805         (void *) 1,\r
806         100LL,  //timer group ticks\r
807         &err);\r
808 if (err) {printf("timerstart failed %d\n");}\r
809 t2 = netapi_TimerGroupStartTimer(\r
810         ourTimerBlock,\r
811         (void *) 2,\r
812         200LL,  //timer group ticks\r
813         &err);\r
814 if (err) {printf("timerstart failed %d\n");}\r
815 t3 = netapi_TimerGroupStartTimer(\r
816         ourTimerBlock,\r
817         (void *) 3,\r
818         300LL,  //timer group ticks\r
819         &err);\r
820 if (err) {printf("timerstart failed %d\n");}\r
821 \r
822 \r
823 /*********************************************/\r
824 /*****************end NETAPI STARTUP**********/\r
825 /*********************************************/\r
826 \r
827 \r
828 /********************************************\r
829 * Basic pkt loopback test\r
830 *********************************************/\r
831 \r
832 \r
833 /* create TRIE */\r
834 P_trie = trie_new();\r
835 if (!P_trie) {printf("trie alloc failed\n"); exit(1);}\r
836 \r
837 nat = (HEAD_T *) malloc(NE * sizeof(HEAD_T));\r
838 if (!nat) {printf("malloc of nat table failed\n"); exit(1);}\r
839 \r
840 //gen_pkts(np2process<NP ? np2process:NP);\r
841 n_pkt= np2process;\r
842 \r
843 /* build table */\r
844 build_table(P_trie);\r
845 \r
846 \r
847 /* processing loop: get pkt, check it, look up in table, copy new header,\r
848    send packet */\r
849 srand((unsigned) np2process);\r
850 \r
851 \r
852 /*********************************************/\r
853 /**************Entry point into scheduler ****/\r
854 /*********************************************/\r
855 netapi_schedWaitForEvents(our_sched, &err);\r
856 \r
857 /* done */\r
858 printf("done: itx=%d rx=%d tx=%d bad=%d slow=%d\n",stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new);\r
859 our_stats_cb(netapi_handle, NULL);\r
860 \r
861 netcp_cfgDelIp(netapi_handle, 0, 0, NULL, NULL, ip_rule0, &err);\r
862 netcp_cfgDelIp(netapi_handle, 1, 0, NULL, NULL, ip_rule1, &err);\r
863 netcp_cfgDelMac(netapi_handle,0,&err);\r
864 netcp_cfgDelMac(netapi_handle,1,&err);\r
865 \r
866 netapi_shutdown(netapi_handle);\r
867 \r
868 }\r