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