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