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