2073b432e481eda611fe1df6c7d15366fe5b0a35
[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         long n_class0_rx;   //count of pkts classified \r
193         long n_class1_rx;   //count of pkts classified \r
194         long n_t1;\r
195         long n_t2;\r
196         long n_t3;\r
197 } STATS_T;\r
198 \r
199 typedef struct head_t\r
200 {\r
201         long ip[5];\r
202         long udp[2];\r
203 } HEAD_T;\r
204 \r
205 typedef struct key_t\r
206 {\r
207   long src_ip;\r
208   long dst_ip;\r
209   short src_port;\r
210   short dst_port;\r
211 } KEY_T;\r
212 \r
213 unsigned char mac0[]={0x00,0x01,0x02,0x03,0x04,0x05}; //interface 0\r
214 unsigned char mac1[]={0x00,0x01,0x02,0x03,0x04,0x06}; //interface 1\r
215 nwalIpAddr_t OurIp0={ 10, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
216 nwalIpAddr_t OurIp1={ 10, 0, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
217 \r
218 #if 1  //goes with real tx (to laptop) \r
219 unsigned char real_mac_header[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e,\r
220                       0x00,0x01,0x02,0x03,0x04,0x05,\r
221                       0x08,0x00};\r
222 unsigned char real_ip_addr[]={0xa,0x00,0x00,0x64,0xa,0x0,0x0,0xa};\r
223 #endif\r
224 \r
225 #if 0  //goes with loopback\r
226 unsigned char mac_header[]={0x00,0x01,0x02,0x03,0x04,0x05, \r
227                       0x00,0x11,0x22,0x33,0x44,0x55,\r
228                       0x08,0x00};\r
229 #endif\r
230 #define NE 65536 \r
231 HEAD_T *nat;\r
232 \r
233 #define NP 5000\r
234 int n_pkt = NP;\r
235 STATS_T stats;\r
236 \r
237 Trie * P_trie;\r
238 HEAD_T pkts[NP];\r
239 #define PERSLOW  10  //% of pkts that will not be fastpath'd \r
240 int perslow= PERSLOW;\r
241 \r
242 /*******************************************\r
243  *************NETAPI OBJECTS***************\r
244  *****************************************/\r
245 Pktlib_HeapHandle OurHeap;\r
246 PKTIO_HANDLE_T *our_chan;\r
247 PKTIO_HANDLE_T *netcp_rx_chan;\r
248 PKTIO_HANDLE_T *netcp_tx_chan;\r
249 PKTIO_CFG_T our_chan_cfg={PKTIO_RW, PKTIO_LOCAL, PKTIO_Q_ANY, 8};\r
250 PKTIO_CFG_T netcp_rx_cfg={PKTIO_R, PKTIO_NA, PKTIO_NA, 8};\r
251 PKTIO_CFG_T netcp_tx_cfg={PKTIO_W, PKTIO_NA, PKTIO_NA, 8};\r
252 \r
253 void house(NETAPI_SCHED_HANDLE_T *s);\r
254 NETAPI_T netapi_handle;\r
255 NETAPI_SCHED_HANDLE_T * our_sched;\r
256 NETAPI_SCHED_CONFIG_T our_sched_cfg={\r
257   NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 500  //every 500 poll loops\r
258 };\r
259 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);\r
260 NETAPI_TIMER_GROUP_HANDLE_T ourTimerBlock; \r
261 NETAPI_TIMER_T t1;\r
262 NETAPI_TIMER_T t2;\r
263 NETAPI_TIMER_T t3;\r
264 \r
265 void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
266         int n_fired,     //# timers fired\r
267         NETAPI_TIMER_LIST_T fired_list,\r
268         uint64_t currentTime);\r
269 \r
270 NETCP_CFG_IP_T ip_rule0;\r
271 NETCP_CFG_IP_T ip_rule1;\r
272 NETCP_CFG_CLASS_T class_0;\r
273 NETCP_CFG_CLASS_T class_1;\r
274 \r
275 NETCP_CFG_CLASSIFIER_T class_0_cfg=\r
276 {\r
277    NETCP_CFG_CLASS_TYPE_L4,\r
278    {\r
279         {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2500}}\r
280    }\r
281 };\r
282 \r
283 NETCP_CFG_CLASSIFIER_T class_1_cfg=\r
284 {\r
285    NETCP_CFG_CLASS_TYPE_L4,\r
286    {\r
287         {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2502}}\r
288    }\r
289 };\r
290 \r
291 PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};\r
292 \r
293 /*************************END NETAPI OBJECTS***********************/\r
294 \r
295 #define START_SRC_IP 0x0a00000a\r
296 #define DST_IP       0xc0a80001\r
297 #define NEW_START_SRC_IP 0x9eda000a\r
298 #define DST_PORT 0x555 \r
299 #define START_SRC_PORT 0x1234\r
300 #define NEW_START_SRC_PORT 100\r
301 void update_header(HEAD_T * p_head, int len)\r
302 {\r
303    unsigned char *p = (unsigned char *) &p_head->udp[1];\r
304    len -= (20+14);\r
305    /* update ip checksum */\r
306    /* update udp checksum */\r
307    /* update length */\r
308    *p= (len&0xff00)>>8;\r
309    *(p+1) = len&0xff;\r
310 }\r
311 \r
312 #if 0\r
313 void gen_pkts(int np)\r
314 {\r
315 int i;\r
316 int ip = START_SRC_IP &0xff;\r
317 int port= START_SRC_PORT;\r
318 //HEAD_T temp={{0x25000200,0xdead0000,0x80110000,START_SRC_IP,DST_IP},\r
319 //             {START_SRC_PORT<<16|DST_PORT,0x01ec<<16|0x0000}};\r
320 HEAD_T temp;\r
321 memcpy(&temp,&testPkt[0],sizeof(HEAD_T));\r
322 \r
323 for(i=0;(i<np) && (i<NP);i++)\r
324   {\r
325        memcpy(&pkts[i],&temp,sizeof(temp));\r
326        update_header(&pkts[i],512);      /* update checksums etc */\r
327        /* change template for new pkt */\r
328        ip+=1;\r
329        if(ip>254) {(ip=START_SRC_IP&0xff); port+=1; }\r
330        temp.ip[3] = htonl((START_SRC_IP&0xffffff00)| ip);\r
331        temp.udp[0] = htonl( (temp.udp[0]&0xffff0000)| port);\r
332        temp.udp[1] = htonl(temp.udp[1]);\r
333      \r
334   }\r
335   n_pkt=np;\r
336 }\r
337 #endif\r
338 \r
339 void build_table(Trie * p_trie)\r
340 {\r
341 int i;\r
342 int sport=NEW_START_SRC_PORT; \r
343 HEAD_T temp,temp2;\r
344 KEY_T key;\r
345 \r
346 memcpy(&temp,&testPkt[14],sizeof(temp));\r
347 \r
348  //insert entry into trie\r
349 key.src_ip = temp.ip[3];\r
350 key.dst_ip = temp.ip[4];\r
351 key.src_port= (temp.udp[0]&0xffff0000)>>16;\r
352 key.dst_port= (temp.udp[0]&0x0000ffff);\r
353 trie_insert(p_trie,(char *)&key,sizeof(key), (void *) &nat[0]); //asociate with nat entry 0\r
354 \r
355 //build nat table\r
356 for(i=0;i<100;i++)\r
357 {\r
358    memcpy(&temp2,&testPkt[14],sizeof(temp));\r
359    temp2.udp[0] = (temp2.udp[0] & 0xffff0000) |  sport;\r
360    memcpy(&nat[i], &temp2, sizeof(temp2));\r
361    sport+= 1;\r
362 }\r
363 }\r
364 \r
365 //===========stub transmitter==================\r
366 void send_pkt(Ti_Pkt *pkt, int len)\r
367 {\r
368 //just free pkt.  Don't send\r
369 Pktlib_freePacket((Ti_Pkt*)pkt);\r
370         return;\r
371 }\r
372 \r
373 //==========stub slow path============\r
374 void slow_path(Ti_Pkt *pkt, int len)\r
375 {\r
376 // debug: check descriptor for validity by verifying that desciptor link field is null as expected\n");\r
377          {Ti_Pkt * k= Pktlib_getNextPacket(pkt); if(k != 0) {printf(" slowpath, nexpkt != NULL");}}\r
378 //just free pkt\r
379 Pktlib_freePacket((Ti_Pkt*)pkt);\r
380         return;\r
381 }\r
382 /* check header */\r
383 struct LastPktInfo\r
384 {\r
385 int iface;\r
386 int ipcsum;\r
387 int l4csum;\r
388 } ;\r
389 static struct LastPktInfo lpInfo;\r
390 \r
391 int check_header(HEAD_T * p_head, PKTIO_METADATA_T * p_meta)\r
392 {\r
393 if (NWAL_RX_FLAG1_META_DATA_VALID & p_meta->u.rx_meta->rxFlag1)\r
394 {\r
395 lpInfo.iface = ((unsigned int)p_meta->u.rx_meta->appId) &0xff; //last byte is interface num\r
396 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
397 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
398 if ((unsigned int)p_meta->u.rx_meta->appId & NETAPI_NETCP_MATCH_CLASS)\r
399 {\r
400   int c= ((unsigned int)p_meta->u.rx_meta->appId >>8)&0xffff;\r
401   if (c==0) stats.n_class0_rx +=1;\r
402   else if (c==1) stats.n_class1_rx +=1;\r
403   else printf("**NET_TEST RX -unknown class: %x\n",  p_meta->u.rx_meta->appId);\r
404 }\r
405 }\r
406 \r
407  return 1;\r
408 }\r
409 \r
410 #define PKT_LEN 1400\r
411 void test_alloc_free(int n)\r
412 {\r
413 int i;\r
414 Ti_Pkt * b;\r
415 \r
416 for(i=0;i<n;i++)\r
417 {\r
418   b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
419   Pktlib_freePacket(b);\r
420 }\r
421 }\r
422 /*-----------test driver: gen an input pkt------- */\r
423 //char buffer[sizeof(HEAD_T)+PKT_LEN];\r
424 Ti_Pkt * get_pkt(int n, unsigned int *p_len)\r
425 {\r
426    int ind;\r
427    long long temp;\r
428    Ti_Pkt * b;\r
429    char * buffer;\r
430    unsigned int len;\r
431 \r
432   if (pktloopback==0)\r
433   {\r
434         if (n>=4) return NULL;   //just gen pkts to warm swtich, so that it knows\r
435                                 //our mac is valid\r
436   }  \r
437   b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
438   if (!b) \r
439     {printf("net_test: get_pkt() heap empty!! %d pkts gen'd %d \n", n); return NULL;};\r
440 \r
441     //debug - way to validate descriptor\r
442     {Ti_Pkt* k= Pktlib_getNextPacket(b); \r
443          if(k != 0) {printf(" genpkt, nexpkt != NULL");}}\r
444 \r
445 \r
446    //get pointer to buffer area of packet\r
447    Pktlib_getDataBuffer(b,(uint8_t**)&buffer,&len);\r
448 \r
449 #if 0 \r
450 if (pktloopback==0)\r
451 {\r
452    temp = (long long) rand();\r
453    temp *= PKT_LEN;\r
454    temp /= RAND_MAX;\r
455    temp +=2;\r
456    *p_len = (int) temp; \r
457    *p_len = *p_len &0xfffffffe;\r
458    temp = (long long) rand();\r
459    temp *= n_pkt;\r
460    temp /= RAND_MAX;\r
461    ind = (int) temp;\r
462    update_header(&pkts[ind],*p_len);\r
463    //printf("get pkt:%d %d ind=%d len=%d\n",RAND_MAX, rand(),ind, *p_len);\r
464     memcpy(&buffer[0], &mac_header[0],14);\r
465     memcpy(&buffer[14],(char*)&pkts[ind],sizeof(HEAD_T)); \r
466 }\r
467 else\r
468 #endif\r
469 \r
470    //copy test packet into buffer\r
471 {\r
472     memcpy(&buffer[0], &testPkt[0],TEST_PKT_LEN);\r
473     *p_len = TEST_PKT_LEN;\r
474 }\r
475     return b; \r
476 }\r
477 \r
478 \r
479 /******************************************************/\r
480 /******************PKT RECEIVE HANDLER *************************/\r
481 /******************************************************/\r
482 void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
483                          PKTIO_METADATA_T meta[], int n_pkts,\r
484                          uint64_t ts )\r
485 {\r
486 int i;\r
487 int len;\r
488 int p;\r
489 HEAD_T * p_res;\r
490 Ti_Pkt * tip;\r
491 unsigned int templen;\r
492 int err;\r
493 KEY_T key;\r
494 char * p_pkt;\r
495 HEAD_T * p_head;\r
496 HEAD_T temp_head;\r
497 \r
498     p_head=&temp_head;\r
499 \r
500     //debug\r
501 #if 0\r
502     if (n_pkts != TX_BURST) {\r
503       printf("recv_cb, txsofar=%d rxsofar=%d  np = %d, NOT %d\n", \r
504              stats.itx, stats.rx, n_pkts,TX_BURST);\r
505       our_stats_cb(netapi_handle,NULL);\r
506     }\r
507 #endif\r
508     //test_alloc_free(7);\r
509     //printf("recv start\n");\r
510 \r
511    /* loop over received pkts */\r
512    for(i=0;i<n_pkts;i++)\r
513    {\r
514         tip = p_recv[i];\r
515         Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
516         len = Pktlib_getPacketLen(tip);//real length\r
517 \r
518          //debug: validate descriptor */\r
519          if(Pktlib_getNextPacket(tip) != 0) {printf(" rcv_cb, nexpkt != NULL");}\r
520         //debug printf("recv pkt, len=%d %d\n", len, templen);\r
521         stats.rx+=1;\r
522 \r
523 #ifdef DEBUG_DESC\r
524    if (stats.rx<16){printf(">rx dmp.."); dump_descr((long *) tip, stats.rx);}\r
525    else if (stats.rx>99) {printf(">rx dmp.."); dump_descr((long *) tip,stats.rx);}\r
526 #endif\r
527 \r
528 \r
529         /* check header */\r
530         memcpy(p_head,&p_pkt[14],sizeof(HEAD_T));\r
531         if (!check_header(p_head,&meta[i])) { \r
532                 stats.n_bad+=1;Pktlib_freePacket(tip); continue;\r
533         }\r
534 \r
535         /* lookup flow */\r
536         key.src_ip = p_head->ip[3];\r
537         key.dst_ip = p_head->ip[4];\r
538         key.src_port= (p_head->udp[0]&0xffff0000)>>16;\r
539         key.dst_port= (p_head->udp[0]&0x0000ffff);\r
540         p_res= (HEAD_T *) trie_lookup(P_trie, (char *) &key, sizeof(key));\r
541         if (!p_res) { stats.n_new+=1;  slow_path(tip, len); continue;}\r
542 \r
543         /* copy header */\r
544         memcpy((char *) p_head, (char *) p_res, sizeof(HEAD_T));\r
545 \r
546         memcpy(&p_pkt[14],p_head,sizeof(HEAD_T));\r
547         /* update_mac(&p_pkt[0]);  */\r
548 \r
549         /* 'simulate' send pkt */\r
550         send_pkt(tip,len);\r
551         stats.tx+=1;\r
552     }\r
553     //printf("recv done\n");\r
554 }\r
555 \r
556 //timer callback \r
557 void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
558         int n_fired,     //# timers fired\r
559         NETAPI_TIMER_LIST_T fired_list,\r
560         uint64_t currentTime)\r
561 {\r
562 int i;\r
563 NETAPI_TIMER_T tx;\r
564 int cookie;\r
565 int err;\r
566 unsigned long long et;\r
567 //DEBUGprintf("TIMER CALLBACK @ %lld %d timers\n", currentTime, n_fired);\r
568 tx = netapi_TimerGetFirst(fired_list);\r
569 for(i=0;i<n_fired;i++)\r
570 {\r
571   cookie = (int) netapi_TimerGetCookie(tx);\r
572   et =  netapi_TimerGetTs(tx); //debug\r
573   //DEBUGprintf("   timer %d - cookie = %d expected ts=%lld (delta=%lld)\n", i, cookie, et, currentTime-et);\r
574   if (cookie ==1)\r
575   {  \r
576      stats.n_t1+=1;\r
577      t1 = netapi_TimerGroupStartTimer(\r
578         th,\r
579         (void *) 1,\r
580         100LL,  //timer group tics\r
581         &err);\r
582   }\r
583   else if (cookie ==2)\r
584   {\r
585       stats.n_t2+=1;\r
586       t2 = netapi_TimerGroupStartTimer(\r
587         th,\r
588         (void *) 2,\r
589         200LL,  //timer group ticks\r
590         &err);\r
591   }\r
592   else\r
593   {\r
594     stats.n_t3+=1;\r
595     t3 = netapi_TimerGroupStartTimer(\r
596         th,\r
597         (void *) 3,\r
598         300LL,  //timer group ticks\r
599         &err);\r
600     //cancel 1 and restart 1\r
601    netapi_TimerGroupCancel(th,t1,&err);\r
602    t1 = netapi_TimerGroupStartTimer(\r
603         th,\r
604         (void *) 1,\r
605         100LL,  //timer group ticks\r
606         &err);\r
607  }\r
608   tx = netapi_TimerGetNext(fired_list,tx); \r
609 }\r
610 }\r
611 \r
612 \r
613 static int np2process = NP;\r
614 /******************************************************\r
615  * stats callback\r
616  *******************************************************/\r
617 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats)\r
618 {\r
619 uint32_t numFreeDataPackets;\r
620 uint32_t numZeroBufferPackets;\r
621 uint32_t numPacketsinGarbage;\r
622 \r
623 printf("stats @ %lld\n", netapi_getTimestamp());\r
624 printf("netcp_tx_handle check %x\n", netcp_tx_chan->back);\r
625 printf("itx=%d rx=%d tx=%d bad=%d slow=%d rx_class0=%d rx_class1=%d n_t1=%d n_t2=%d n_t3=%d\n",stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new,stats.n_class0_rx, stats.n_class1_rx, stats.n_t1, stats.n_t2,stats.n_t3);\r
626 \r
627 if(pPaStats)\r
628 {\r
629        printf("C1 number of packets:           %d\n", pPaStats->classify1.nPackets);\r
630        printf("C1 number IPv4 packets:         %d\n", pPaStats->classify1.nIpv4Packets);\r
631        //printf("C1 number llc/snap fail:        %d\n", pPaStats->classify1.nLlcSnapFail);\r
632        printf("C1 number table matched:        %d\n", pPaStats->classify1.nTableMatch);\r
633        printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);\r
634        printf ("C1 number of parse fail:        %d\n",pPaStats->classify1.nParseFail);\r
635        printf("C1 number of command failures:  %d\n", pPaStats->classify1.nCommandFail);\r
636        printf("C1 number invalid reply dests:  %d\n", pPaStats->classify1.nInvalidComReplyDest);\r
637        printf ("C1 number of silent discard:    %d\n",pPaStats->classify1.nSilentDiscard);\r
638        printf("C1 number of invalid control:   %d\n", pPaStats->classify1.nInvalidControl);\r
639        printf ("C1 number of invalid states:    %d\n",pPaStats->classify1.nInvalidState);\r
640        printf ("C1 number of system fails:      %d\n",pPaStats->classify1.nSystemFail);\r
641        printf ("C2 number parse failed  :      %d\n",pPaStats->classify2.nParseFail);\r
642        printf ("C2 number Invld Header  :      %d\n",pPaStats->classify2.nInvldHdr);\r
643        printf ("C2 number udp           :      %d\n",pPaStats->classify2.nUdp);\r
644        printf ("C2 number tcp           :      %d\n",pPaStats->classify2.nTcp);\r
645        printf ("C2 number cmd fail      :      %d\n",pPaStats->classify2.nCommandFail);\r
646        printf ("C2 number silent drop   :      %d\n",pPaStats->classify2.nSilentDiscard);\r
647        printf ("C2 number invalid cntrl :      %d\n\n",pPaStats->classify2.nInvalidControl);\r
648 }\r
649 Pktlib_getHeapStats(OurHeap, &numFreeDataPackets,\r
650                              &numZeroBufferPackets, &numPacketsinGarbage);\r
651 printf("heap stats>  #free=%d #zb=%d #garbage=%d\n", numFreeDataPackets,\r
652                                 numZeroBufferPackets, numPacketsinGarbage);\r
653 //debug = dump timer polling stats\r
654 dump_poll_stats();\r
655 \r
656 \r
657 }\r
658 \r
659 //******************************************************\r
660 //use scheduling housekeeping callback to generate pkts\r
661 //******************************************************\r
662 void house(NETAPI_SCHED_HANDLE_T * s)\r
663 {\r
664 Ti_Pkt * tip;\r
665 unsigned int len;\r
666 nwalTxPktInfo_t meta_tx={0};\r
667 PKTIO_METADATA_T meta = {PKTIO_META_TX,0};\r
668 int err;\r
669 static int house_pkts_gened=0;\r
670 int p;\r
671 unsigned char * pIpHdr,* pData;\r
672 unsigned int vv1,vv2,vv3;\r
673 \r
674 for(p=0;p<TX_BURST;p++) {  \r
675 //reguest stats \r
676 if ((house_pkts_gened>0) && (! (house_pkts_gened%400)) )\r
677 {\r
678    printf("net_test> request stats at n=%d \n",house_pkts_gened);\r
679    netcp_cfgReqStats(netapi_handle, our_stats_cb, 0,&err); \r
680    if (err!=0) {printf("stats req failed\n");}\r
681 }\r
682 \r
683 \r
684   if (house_pkts_gened >= np2process+ 100)\r
685   {\r
686      //shutdown\r
687      netapi_schedShutdown(s,NULL,&err);\r
688      continue;\r
689   }\r
690 \r
691   else if (house_pkts_gened >= np2process) { house_pkts_gened+=1;  continue;}\r
692   \r
693 \r
694 /* manufacture a pkt to transmit */\r
695    tip = get_pkt(house_pkts_gened, &len);\r
696    if(!tip) { house_pkts_gened +=1; continue; }\r
697 \r
698 \r
699    /* set the pkt length */\r
700    vv1 = netapi_timing_start();\r
701    Pktlib_setPacketLen(tip, len);\r
702 \r
703    /* set up meta data */\r
704     meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM | NWAL_TX_FLAG1_DO_UDP_CHKSUM);\r
705     meta_tx.startOffset = 0;\r
706     meta_tx.pktLen = len;\r
707     meta_tx.ipOffBytes = TEST_PKT_IP_OFFSET_BYTES;\r
708     meta_tx.l4OffBytes = TEST_PKT_UDP_OFFSET_BYTES;\r
709     meta_tx.l4HdrLen = TEST_PKT_UDP_HDR_LEN;\r
710     meta_tx.ploadOffBytes = TEST_PKT_PLOAD_OFFSET_BYTES;\r
711     meta_tx.ploadLen = TEST_PAYLOAD_LEN;\r
712 \r
713     Pktlib_getDataBuffer(tip,&pData,&len);\r
714     pIpHdr = pData + meta_tx.ipOffBytes;\r
715     meta_tx.pseudoHdrChecksum =\r
716         test_utilGetIpv4PsudoChkSum(pIpHdr,(TEST_PAYLOAD_LEN+TEST_PKT_UDP_HDR_LEN));\r
717 \r
718    /* post it to netcp tx channel*/\r
719    meta.u.tx_meta=&meta_tx;\r
720 #ifdef DEBUG_DESC\r
721    if (house_pkts_gened<16) dump_descr((long *) tip, house_pkts_gened);\r
722    else if (house_pkts_gened>99) dump_descr((long *) tip,house_pkts_gened);\r
723 #endif\r
724    vv2= netapi_timing_stop();\r
725    pktio_send(netcp_tx_chan,tip,&meta,&err);\r
726    vv3= netapi_timing_stop();\r
727    printf("pktio send. full=%d metadata=%d pktio_send=%d\n", vv3-vv1,  vv2-vv1,  vv3-vv2);\r
728    if (err == 0) stats.itx +=1;\r
729 \r
730    house_pkts_gened +=1;\r
731  }\r
732 }\r
733 \r
734 \r
735 /***************************************\r
736  ********** test driver*****************\r
737  ***************************************/\r
738 int main(int argc, char **argv)\r
739 {\r
740 int err;\r
741 rlim_t oss,ss = 1024*1024;\r
742 struct rlimit rl;\r
743 \r
744 err= getrlimit(RLIMIT_STACK,&rl);\r
745 if (!err) printf(" stack limit = %d\n",rl.rlim_cur); else printf("getrlimit failed\n");\r
746 #if 0\r
747 rl.rlim_cur = ss;\r
748 err=setrlimit(RLIMIT_STACK,&rl);\r
749 if (!err) printf("set stack to %d\n",rl.rlim_cur); else printf("setrlimit failed\n");\r
750 #endif\r
751 \r
752 if (argc>=2)  np2process = atoi(argv[1]);\r
753 if (np2process<0) np2process = NP; /* default */\r
754 if (argc==3)  perslow = atoi(argv[2]);\r
755 if ((perslow<0)||(perslow>100)) perslow=PERSLOW;//default\r
756 if (argc>3) {printf("net_test  <no of pkts to process> <percent slow path>\n"); exit(1);}\r
757 \r
758 \r
759 //real mode, so update our test packet mac header and ip header\r
760 if (pktloopback==0)\r
761 {\r
762 memcpy(&testPkt,&real_mac_header[0],14); //overwrite test pkt mac address\r
763 memcpy(&testPkt[26],&real_ip_addr[0],8);//overrite test pkt ip addresses\r
764 }\r
765 \r
766 /*******************************************/\r
767 /*************NETAPI STARTUP****************/\r
768 /*******************************************/\r
769 \r
770 /* create netapi */\r
771 netapi_handle = netapi_init(NETAPI_SYS_MASTER);\r
772 \r
773 /* open the main heap */\r
774 OurHeap = Pktlib_findHeapByName("netapi");\r
775 if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}\r
776 \r
777 /* create a pktio channel */\r
778 our_chan=pktio_create(netapi_handle,"our1stq",(PKTIO_CB) recv_cb, &our_chan_cfg,&err);\r
779 if (!our_chan) {printf("pktio create failed err=%d\n",err); exit(1);}\r
780 \r
781 /* open netcp default tx, rx queues */\r
782 netcp_tx_chan= pktio_open(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg,  &err);\r
783 if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);}\r
784 netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb, &netcp_rx_cfg,  &err);\r
785 if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}\r
786 \r
787 \r
788 /* create scheduler instance */\r
789 our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);\r
790 if (!our_sched) {printf("sched create failed\n"); exit(1);}\r
791 \r
792 /* add mac intefaces */\r
793 netcp_cfgCreateMacInterface(\r
794                   netapi_handle,\r
795                   &mac0[0],\r
796                   0,0,\r
797                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
798                   (NETCP_CFG_VLAN_T ) NULL ,  //future\r
799                   1, \r
800                   &err);\r
801 if (err) {printf("addmac0 failed %d\n",err); exit(1); } \r
802 \r
803 //attach an IP to this interface\r
804 ip_rule0=netcp_addIp(\r
805                   netapi_handle,\r
806                   0,\r
807                   nwal_IPV4,\r
808                   &OurIp0,\r
809                   NULL,  //all IP\r
810                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
811                   &err\r
812                   );\r
813 if (err) {printf("addip0 failed %d\n",err); exit(1); } \r
814 #if 1\r
815 //create a 2nd mac instance\r
816 netcp_cfgCreateMacInterface(\r
817                   netapi_handle,\r
818                   &mac1[0],\r
819                   1,1,\r
820                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
821                   (NETCP_CFG_VLAN_T ) NULL ,  //future\r
822                   1,\r
823                   &err);\r
824 if (err) {printf("addmac1 failed %d\n",err); exit(1); }\r
825 \r
826 //attach an IP to this interface\r
827 ip_rule1=netcp_addIp(\r
828                   netapi_handle,\r
829                   1,\r
830                   nwal_IPV4,\r
831                   &OurIp1,\r
832                   NULL,  //all IP\r
833                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
834                   &err\r
835                   );\r
836 if (err) {printf("addip1 failed %d\n",err); exit(1); }\r
837 \r
838 //attach 2 classifiers to iface 0, ip0\r
839 class_0_cfg.u.c_l4.ip = ip_rule0;\r
840 class_0 =  netcp_cfgAddClass(netapi_handle,\r
841                              &class_0_cfg,\r
842                              NULL,\r
843                              NETCP_CFG_ACTION_TO_SW,\r
844                              &err);\r
845 if (err) {printf("addclass0 failed %d\n",err); exit(1);}\r
846 \r
847 class_1_cfg.u.c_l4.ip = ip_rule0;\r
848 class_1 =  netcp_cfgAddClass(netapi_handle,\r
849                              &class_1_cfg,\r
850                              NULL,\r
851                              NETCP_CFG_ACTION_TO_SW,\r
852                              &err);\r
853 if (err) {printf("addclass1 failed %d\n",err); exit(1);}\r
854 \r
855 \r
856 #endif\r
857 \r
858  ourTimerBlock = netapi_TimerGroupCreate(\r
859         netapi_handle,\r
860         "our1sttimer",\r
861         our_timer_cb,\r
862         0,    //1 if timers local to thread\r
863         0,    //1 if expect to cancel\r
864         netapi_getTicksPerSec()/1000,  /* 1 msc resolution for these timers */\r
865         netapi_getTicksPerSec()/5000, /* would like .5 msc tolerence */\r
866         10,  //small # of timers to test garbage collection\r
867         &err);\r
868 if (err) {printf("timergroupcreate failed %d\n",err); exit(1);}\r
869 \r
870 //start a couple of timers \r
871 t1 = netapi_TimerGroupStartTimer(\r
872         ourTimerBlock,\r
873         (void *) 1,\r
874         100LL,  //timer group ticks\r
875         &err);\r
876 if (err) {printf("timerstart failed %d\n");}\r
877 t2 = netapi_TimerGroupStartTimer(\r
878         ourTimerBlock,\r
879         (void *) 2,\r
880         200LL,  //timer group ticks\r
881         &err);\r
882 if (err) {printf("timerstart failed %d\n");}\r
883 t3 = netapi_TimerGroupStartTimer(\r
884         ourTimerBlock,\r
885         (void *) 3,\r
886         300LL,  //timer group ticks\r
887         &err);\r
888 if (err) {printf("timerstart failed %d\n");}\r
889 \r
890 \r
891 /*********************************************/\r
892 /*****************end NETAPI STARTUP**********/\r
893 /*********************************************/\r
894 \r
895 \r
896 /********************************************\r
897 * Basic pkt loopback test\r
898 *********************************************/\r
899 \r
900 \r
901 /* create TRIE */\r
902 P_trie = trie_new();\r
903 if (!P_trie) {printf("trie alloc failed\n"); exit(1);}\r
904 \r
905 nat = (HEAD_T *) malloc(NE * sizeof(HEAD_T));\r
906 if (!nat) {printf("malloc of nat table failed\n"); exit(1);}\r
907 \r
908 //gen_pkts(np2process<NP ? np2process:NP);\r
909 n_pkt= np2process;\r
910 \r
911 /* build table */\r
912 build_table(P_trie);\r
913 \r
914 \r
915 /* processing loop: get pkt, check it, look up in table, copy new header,\r
916    send packet */\r
917 srand((unsigned) np2process);\r
918 \r
919 \r
920 /*********************************************/\r
921 /**************Entry point into scheduler ****/\r
922 /*********************************************/\r
923 netapi_schedWaitForEvents(our_sched, &err);\r
924 \r
925 /* done */\r
926 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
927 our_stats_cb(netapi_handle, NULL);\r
928 \r
929 //delete Classifiers\r
930 netcp_cfgDelClass(netapi_handle, class_0, &err); \r
931 netcp_cfgDelClass(netapi_handle, class_1, &err); \r
932 \r
933 //delete IPs and MAC Interfacess\r
934 netcp_cfgDelIp(netapi_handle, 0, 0, NULL, NULL, ip_rule0, &err);\r
935 netcp_cfgDelIp(netapi_handle, 1, 0, NULL, NULL, ip_rule1, &err);\r
936 netcp_cfgDelMac(netapi_handle,0,&err);\r
937 netcp_cfgDelMac(netapi_handle,1,&err);\r
938 \r
939 //close pktio channels we opened\r
940 pktio_close(netcp_tx_chan ,&err);\r
941 pktio_close(netcp_rx_chan ,&err);\r
942 \r
943 //clear pktio channel we created\r
944 pktio_control(our_chan, (PKTIO_CB) NULL, (PKTIO_CFG_T *) NULL, &zap_channel_control, &err);\r
945 //delete pktio channels we created\r
946 pktio_delete(our_chan, &err);\r
947 \r
948 netapi_shutdown(netapi_handle);\r
949 \r
950 }\r