Adding net_test_bench application, scripts to set irq smp affinity, setup scripts...
[keystone-rtos/netapi.git] / ti / runtime / netapi / test / net_test_bench.c
1 /******************************************\r
2  * File: nt_bench.c   \r
3  * Purpose:  benchmarks for NT.\r
4  **************************************************************\r
5  * FILE:  nt_bench.c\r
6  * \r
7  * DESCRIPTION:  netapi user space transport\r
8  *               library  test application : benchmarks\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 #include <signal.h>\r
49 #include <pthread.h>\r
50 #include <sched.h>\r
51 \r
52 #include "trie.h"\r
53 #include "string.h"\r
54 #include "netapi.h"\r
55 #include "pktio.h"\r
56 #include "net_test.h"\r
57 #include <ti/drv/sa/salld.h>\r
58 \r
59 #define netapi_timing_start hplib_mUtilGetPmuCCNT\r
60 \r
61 static int scnt=0;\r
62 static int QUIT=0;\r
63 static int XMIT=0;\r
64 __thread int our_core;\r
65 \r
66 void benchmarks1(void);\r
67 void benchmarks2(Pktlib_HeapHandle h , int n_trials);\r
68 void benchmarks3(Pktlib_HeapHandle h , int n_trials);\r
69 \r
70 //sig handler\r
71 void netTest_utilMySig(int x)\r
72 {\r
73   QUIT=1;\r
74   scnt+=1;\r
75   printf(">ifdma-test: recv'd signal %d cnt=%d\n",x,scnt);\r
76   if (scnt > 10) {printf(">ifdma-test: WARNING EXITING WITH PROPER SHUTDOWN, LUTS LEFT ACTIVE\n");exit(1);}\r
77 \r
78 }\r
79 void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
80                          PKTIO_METADATA_T meta[], int n_pkts,\r
81                          uint64_t ts );\r
82 \r
83 \r
84 /*************debug********************/\r
85 void netTest_utilDumpDescr(unsigned long *p, int n)\r
86 {\r
87    printf("--------dump of descriptor %d %x\n", n, (int) p);\r
88    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
89    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
90    printf("-----------------------------\n");\r
91 }\r
92 void netTest_utilDumpHeader(unsigned long *p, int n, int a, int r)\r
93 {\r
94    printf("--------dump of header %d %x appID=%x flag1=%x\n", n, (int) p,a,r);\r
95    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
96    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
97    printf("> %x %x %x %x %x %x %x %x\n",p[16],p[17],p[18],p[19],p[20],p[21],p[22],p[23]);\r
98    printf("> %x %x %x %x %x %x %x %x\n",p[24],p[25],p[26],p[27],p[28],p[29],p[30],p[31]);\r
99    printf("-----------------------------\n");\r
100 }\r
101 /*****************************************/\r
102 \r
103 \r
104 \r
105 \r
106 \r
107 \r
108 \r
109 /*******************************************\r
110  *************NETAPI OBJECTS***************\r
111  *****************************************/\r
112 static NETAPI_CFG_T our_netapi_default_cfg=\r
113 {\r
114 TUNE_NETAPI_PERM_MEM_SZ,\r
115 128,  //start of packet offset for hw to place data on rx for default flow\r
116 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system\r
117 TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use\r
118 TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap\r
119 64, //#descriptors w/o buffers in default heap\r
120 TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap\r
121 128   ,  //tail room\r
122 256      //extra room \r
123 };\r
124 \r
125 Pktlib_HeapHandle OurHeap;     //default heap, used by producer\r
126 PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};\r
127 PKTIO_HANDLE_T * netcp_rx_chan;\r
128 NETAPI_T netapi_handle;\r
129 \r
130 PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};\r
131 \r
132 NETCP_CFG_ROUTE_T  test_route=\r
133 {\r
134 NULL, NULL  //* to be filled in\r
135 };\r
136 \r
137 \r
138 /*************************END NETAPI OBJECTS***********************/\r
139 \r
140 static unsigned char all_mac[]={0,0,0,0,0,0};\r
141 \r
142 \r
143 \r
144 //stats\r
145 int pkt_rx=0; \r
146 int pkt_tx=0; \r
147 unsigned long long pkt_rx_cycles=0;\r
148 unsigned long long pkt_tx_cycles=0;\r
149 unsigned long long pkt_cb_cycles=0;\r
150 \r
151 \r
152 //**********************************\r
153 //producer thread\r
154 //*********************************\r
155 void producer_thread(int coreid)\r
156 {\r
157 int err;\r
158 int i;\r
159 Ti_Pkt * tip;\r
160 unsigned char * pData;\r
161 int len;\r
162 PKTIO_METADATA_T meta = {PKTIO_META_IFDMA_TX,{0},0};\r
163 int np;\r
164 cpu_set_t cpu_set;\r
165 unsigned long t1;\r
166 unsigned long t2;\r
167 \r
168     CPU_ZERO( &cpu_set);\r
169     CPU_SET( 2, &cpu_set);\r
170     hplib_utilSetupThread(2, &cpu_set);\r
171 \r
172      //DAL we poll the default pktio channel for pkts from net\r
173       for(i=0;!((volatile) QUIT);i++)\r
174       {\r
175         t1 = netapi_timing_start();\r
176         np = netapi_pktioPoll(netcp_rx_chan,NULL,&err);\r
177         t2 = netapi_timing_start();\r
178         pkt_rx+=np;\r
179         if (np) \r
180         {\r
181            pkt_rx_cycles += (t2-t1);\r
182         }\r
183       }\r
184       printf("nt-bench: recevier  DONE %d pkts rx,  pkt poll cycles=% u; pkt rx cycle=%u pkt tx cycles=%u \n", pkt_rx,\r
185              (unsigned)  (pkt_rx ?  (pkt_rx_cycles - pkt_cb_cycles)/pkt_rx : 0),\r
186              (unsigned)  (pkt_rx ?  (pkt_rx_cycles) /pkt_rx : 0),\r
187              (unsigned)  (pkt_tx ?  (pkt_tx_cycles) /pkt_tx : 0)\r
188             );\r
189 }\r
190 \r
191 \r
192 //******************************\r
193 //  main program\r
194 //*****************************\r
195 int main(int argc, char **argv)\r
196 {\r
197     int err,i;\r
198     int32_t             errCode;\r
199     Pktlib_HeapIfTable*  pPktifTable;\r
200     Pktlib_HeapCfg heapCfg;\r
201     long t1, t2 ;\r
202     cpu_set_t cpu_set;\r
203 \r
204 \r
205      //install signal handler for ^c\r
206     signal(SIGINT,netTest_utilMySig);\r
207     CPU_ZERO( &cpu_set);\r
208     CPU_SET( 0, &cpu_set);\r
209     hplib_utilSetupThread(2, &cpu_set);\r
210 \r
211 \r
212     /*******************************************/\r
213     /*************NETAPI STARTUP****************/\r
214     /*******************************************/\r
215 \r
216     /* create netapi */\r
217     netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);\r
218     netapi_netcpCfgExceptions(netapi_handle, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_DISCARD, (NETCP_CFG_ROUTE_HANDLE_T) NULL);\r
219 \r
220     /* open the main heap */\r
221     OurHeap = Pktlib_findHeapByName("netapi");\r
222     if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}\r
223 \r
224     //if we want to relay network packets, we create a handle to the \r
225     //default netcp receive queue here\r
226     netcp_rx_chan= netapi_pktioOpen(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_net, &netcp_rx_cfg,  &err);\r
227     if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}\r
228 \r
229 /*********************************************/\r
230 /*****************end NETAPI STARTUP**********/\r
231 /*********************************************/\r
232 \r
233 /*************************************************\r
234 ********************some basic benchmarks*********\r
235 **************************************************/\r
236 printf("\n\n*******STARTING MEM ACCESS BENCHMARK*********\n\n");\r
237 benchmarks1();\r
238 printf("\n\n*******STARTING RAW BENCHMARK2*********\n\n");\r
239 benchmarks2(OurHeap, 20);\r
240 printf("\n\n*******STARTING RAW BENCHMARK3*********\n\n");\r
241 benchmarks3(OurHeap, 20);\r
242 printf("\n\n******STARTING RECV BENCHMARK (q to quit)*****\n\n");\r
243 \r
244 \r
245 //now creaate a simple netcp rule\r
246 //to get a lot of packets\r
247 netapi_netcpCfgCreateMacInterface(\r
248                   netapi_handle,\r
249                   &all_mac[0],\r
250                   0,0,\r
251                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
252                   (NETCP_CFG_VLAN_T ) NULL ,  //future\r
253                   1,\r
254                   &err);\r
255 \r
256 //**************************************\r
257 //Create a worked thread\r
258 //***************************************\r
259 {\r
260     pthread_t *thrs;\r
261     int procs =1; \r
262     char c;\r
263     thrs = malloc( sizeof( pthread_t ) * procs );\r
264     if (thrs == NULL)\r
265     {\r
266         perror( "malloc" );\r
267         return -1;\r
268     }\r
269     printf( "benchmark-test: Starting %d threads...\n", procs );\r
270 \r
271     if (pthread_create( &thrs[0], NULL, (void*)producer_thread,\r
272                       (void *)0 ))\r
273     {\r
274         perror( "pthread_create" );\r
275         exit(1);\r
276     }\r
277     //this thread of execution (main) now just waits on user input\r
278     for(;;)\r
279     {\r
280         printf(">");\r
281         c=getchar();\r
282         if (c=='q') {QUIT=1;break;}\r
283         if (c=='t') {XMIT=!XMIT; printf("XMIT= %d\n", XMIT); }\r
284         else if (c=='s') printf(">IFDMA-TEST STATS:    %d received   %d xmitted \n", pkt_rx,pkt_tx);\r
285         else if (c=='h') printf("> 'q' to quit,  's' for stats, 't' to toggle transmit  'h' for help\n");\r
286     }\r
287 \r
288     //wait for completion \r
289     printf("main task now pending on thread completion\n");\r
290     for (i = 0; i < procs; i++)\r
291         pthread_join( thrs[i], NULL );\r
292 \r
293     free( thrs );\r
294 }\r
295 \r
296 /*************************************************\r
297  ************CLEAN UP****************************\r
298  ************************************************/\r
299 //get rid of rule, in the case that we are relaying packets\r
300 //also close our netcp rx channel\r
301 netapi_netcpCfgDelMac(netapi_handle,0,&err);\r
302 netapi_pktioClose(netcp_rx_chan,&err);\r
303 \r
304 \r
305 //done\r
306 netapi_shutdown(netapi_handle);\r
307 \r
308 \r
309 //!finished!\r
310 }\r
311 \r
312 \r
313 //receive callback for packets from net (for consumer)\r
314 void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
315                          PKTIO_METADATA_T meta[], int n_pkts,\r
316                          uint64_t ts )\r
317 {\r
318 int i;\r
319 Ti_Pkt * tip;\r
320 int len;\r
321 unsigned long t1;\r
322 unsigned long t2;\r
323 unsigned long t3;\r
324 unsigned long t4;\r
325 \r
326 t1= netapi_timing_start();\r
327 for(i=0;i<n_pkts;i++)\r
328 {\r
329     tip = p_recv[i];\r
330     len = Pktlib_getPacketLen(tip);\r
331     if (XMIT)\r
332     {\r
333        t3= netapi_timing_start();\r
334        //sendit(tip);\r
335        pkt_tx+=1;\r
336        t4= netapi_timing_start();\r
337        pkt_tx_cycles += (t4-t3);\r
338     }\r
339     else\r
340       Pktlib_freePacket((Ti_Pkt*)tip);\r
341 }\r
342 t2 = netapi_timing_start();\r
343 pkt_cb_cycles += (t2-t1);\r
344 }\r
345 \r
346 \r
347 \r
348 \r
349 //SOME BENCHMARKS\r
350 //sonme benchmarks\r
351 void benchmarks1(void)\r
352 {\r
353 int i,j;\r
354 unsigned long v1pop;\r
355 unsigned long v2pop;\r
356 unsigned long v1push;\r
357 unsigned long v2push;\r
358 unsigned long v1read;\r
359 unsigned long v2read;\r
360 unsigned long v1write;\r
361 unsigned long v2write;\r
362 unsigned long v1read2;\r
363 unsigned long v2read2;\r
364 #define N 100\r
365 Ti_Pkt  pkts[N];\r
366 unsigned char * p_pkt;\r
367 int len;\r
368 int sum=0;\r
369 int sum2=0;\r
370 char *p=(char *) malloc(1000);\r
371 //alloc\r
372 v1pop=netapi_timing_start();\r
373 for(i=0;i<N;i++)   pkts[i]= Pktlib_allocPacket(OurHeap,1000);\r
374 v2pop = netapi_timing_start();\r
375 \r
376 //write access\r
377 Pktlib_getDataBuffer(pkts[0],(uint8_t**)&p_pkt,&len);\r
378 v1write=netapi_timing_start();\r
379 for(i=0;i<1000;i++) p_pkt[i]=i;\r
380 v2write=netapi_timing_start();\r
381 \r
382 //read access\r
383 v1read=netapi_timing_start();\r
384 for(j=0;j<10;j++)\r
385 for(i=0;i<1000;i++) sum+=p_pkt[i];\r
386 v2read=netapi_timing_start();\r
387 \r
388 // access (from malloc)\r
389 v1read2=netapi_timing_start();\r
390 for(i=0;i<1000;i++) sum2+=p[i];\r
391 v2read2=netapi_timing_start();\r
392 \r
393 //free packet\r
394 v1push=netapi_timing_start();\r
395 for(i=0;i<N;i++)   Pktlib_freePacket(pkts[i]);\r
396 v2push = netapi_timing_start();\r
397 \r
398 //resutls\r
399 printf("allocs= %d  free=%d   write=%d  read=%d read-malloc=%d (sum=%d %d)\n",\r
400         (v2pop-v1pop)/N, (v2push-v1push)/N,  (v2write-v1write)/1000, (v2read-v1read)/10000,\r
401         (v2read2-v1read2)/1000,sum,sum2);\r
402 \r
403 \r
404 };\r
405 \r
406 \r
407 //raw queue benchmark\r
408 #include "ti/drv/nwal/nwal_util.h"\r
409 \r
410 #define NTOPOP 150\r
411 volatile unsigned long t1;\r
412 volatile unsigned long t2;\r
413 volatile unsigned long t3;\r
414 volatile unsigned long t4;\r
415 volatile unsigned long t5;\r
416 volatile unsigned long t6;\r
417 volatile unsigned long sum1=0;\r
418 volatile unsigned long sum2=0;\r
419 volatile unsigned long sum3=0;\r
420 volatile unsigned long sum4=0;\r
421 volatile Ti_Pkt * pHd[NTOPOP];\r
422 \r
423 void * pop_raw(int n)\r
424 {\r
425 \r
426 }\r
427 void * p2v (void* in)\r
428 {\r
429 \r
430 \r
431 }\r
432 void * v2p(void * in)\r
433 {\r
434 \r
435 }\r
436 void push_raw(void *pkt, int n)\r
437 {\r
438 \r
439 }\r
440 \r
441 void benchmarks2(Pktlib_HeapHandle h , int ntrials)\r
442 {\r
443 int i,j;\r
444 int k;\r
445 int abort=0;\r
446 Qmss_QueueHnd freeQ=Pktlib_getInternalHeapQueue(h);\r
447 \r
448 //n_trials of NTOPOP actions\r
449 for(i=0;i<ntrials;i++)\r
450 {\r
451     abort=0;\r
452     sum1=sum2=sum3=sum4=0;\r
453     //raw pop\r
454     t1= netapi_timing_start();\r
455     for(j=0;j<NTOPOP;j++)\r
456     {\r
457        pHd[j] = (Ti_Pkt *)QMSS_DESC_PTR(pktio_mQmssQueuePopRaw (freeQ));\r
458        if (!pHd[j]) \r
459        {\r
460          printf("abort test. out of descriptors\n"); abort=1;\r
461          break;\r
462        }\r
463     }\r
464     t2= netapi_timing_start();\r
465     k=j;\r
466     for(j=0;j<k;j++)\r
467     {\r
468        pHd[j]  =  Osal_qmssConvertDescPhyToVirt(pHd[j]);\r
469     }\r
470     t3= netapi_timing_start();\r
471     sum1 += (t2-t1);\r
472     sum2 += (t3-t2);\r
473     //raw push\r
474     t4= netapi_timing_start();\r
475     for(j=0;j<k;j++)\r
476     {\r
477        if (!pHd[j]) continue;\r
478        pHd[j]= Osal_qmssConvertDescVirtToPhy(pHd[j]);\r
479     }\r
480     t5= netapi_timing_start();\r
481     for(j=0;j<k;j++)\r
482     {\r
483       pktio_mQmssQueuePushDescSizeRaw(freeQ,\r
484                                              (void *) pHd[j],\r
485                                              128);\r
486     }\r
487     t6= netapi_timing_start();\r
488     sum3 += (t5-t4);\r
489     sum4 += (t6-t5);\r
490 \r
491     if (!abort)\r
492     printf("nt=%d raw pop=%d  p2v=%d v2p=%d raw push=%d\n", i,\r
493              sum1/k,  sum2/k, sum3/k, sum4/k);\r
494     sleep(1);\r
495 }\r
496 return;\r
497 }\r
498 \r
499 //full queue push/pops\r
500 void benchmarks3(Pktlib_HeapHandle h , int ntrials)\r
501 {\r
502 int i,j;\r
503 int k;\r
504 int abort=0;\r
505 Qmss_QueueHnd freeQ=Pktlib_getInternalHeapQueue(h);\r
506 \r
507 //n_trials of NTOPOP actions\r
508 for(i=0;i<ntrials;i++)\r
509 {\r
510     abort=0;\r
511     sum2=sum4=0;\r
512     //raw pop\r
513     t1= netapi_timing_start();\r
514     for(j=0;j<NTOPOP;j++)\r
515     {\r
516        pHd[j] = (Ti_Pkt *)QMSS_DESC_PTR(Qmss_queuePop(freeQ));\r
517        if (!pHd[j])\r
518        {\r
519          printf("abort test. out of descriptors\n"); abort=1;\r
520          break;\r
521        }\r
522     }\r
523     t3= netapi_timing_start();\r
524     sum2 += (t3-t1);\r
525     k=j;\r
526     //raw push\r
527     t5= netapi_timing_start();\r
528     for(j=0;j<k;j++)\r
529     {\r
530        if (!pHd[j]) continue;\r
531        Qmss_queuePushDescSize(freeQ, pHd[j], 128);\r
532     }\r
533     t6= netapi_timing_start();\r
534     sum4 += (t6-t5);\r
535     if (!abort)\r
536     printf("nt=%d pop=%d  push=%d\n", i,\r
537               sum2/k, sum4/k);\r
538     sleep(1);\r
539 }\r
540 return;\r
541 }\r
542 \r