Updates for stats collection across processes
[keystone-rtos/netapi.git] / ti / runtime / netapi / demo / src / netapi_dpi_demo.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 <ti/runtime/netapi/netapi.h>\r
54 #include <ti/runtime/hplib/hplib.h>\r
55 #include "ti/runtime/netapi/pktio.h"\r
56 #include "netapi_dpi_demo.h"\r
57 #include "navl_wrapper.h"\r
58 //#include "ti/runtime/netapi/test/net_test.h"\r
59 #include <ti/drv/sa/salld.h>\r
60 \r
61 #include <ti/drv/qmss/device/k2e/src/qmss_device.c>\r
62 #include <ti/drv/cppi/device/k2e/src/cppi_device.c>\r
63 \r
64 extern Rm_ServiceHandle   *rmClientServiceHandle;\r
65 extern NETCP_CFG_EXCEPTION_PKT_T expPkt_appid;\r
66 \r
67 \r
68 #define netapi_timing_start hplib_mUtilGetPmuCCNT\r
69 \r
70 navl_wrapper_cfg_info_t *pNavlCfg;\r
71 navl_wrapper_pkt_stat_t *pStats1;\r
72 navl_wrapper_pkt_stat_t *pStats2;\r
73 navl_global_dpi_stats *pGlobDpiStats;\r
74 void* pTemp;\r
75 \r
76 \r
77 STATS_T stats;\r
78 paSysStats_t netcp_stats;\r
79 //struct dpi_stats dpis;\r
80 \r
81 #define VDPI\r
82 #ifdef VDPI\r
83 static int DPI=0;  //1 to enable\r
84 static int DUMP_DPI_CONN=0;\r
85 #endif\r
86 \r
87 \r
88 void* pShmBase;\r
89 void *pShmEntry;\r
90 \r
91 \r
92 \r
93 static int scnt=0;\r
94 volatile static int QUIT=0;\r
95 static int XMIT=0;\r
96 static int CAP=0;\r
97 volatile int RESET=0; //to reset stats\r
98 static int NTH=1;\r
99 volatile static int PKTGEN=0;\r
100 int pkt_len=64;\r
101 \r
102 \r
103 \r
104 NETCP_CFG_MACIF_T mac[NUM_PROCS];\r
105 NETCP_CFG_MACIF_T mac0;\r
106 NETCP_CFG_MACIF_T mac1;\r
107 \r
108 hplib_spinLock_T dpi_demo_thread_lock;\r
109 \r
110 \r
111 static char usage[] = "usage: %s -s \n";\r
112 \r
113 \r
114 \r
115 \r
116 //int procs =2; \r
117 \r
118 #define HPLIB_THREADID 0  // for main: HPLIB THREAD INSTANCE\r
119 //__thread int our_core;\r
120 static unsigned char dummy_mac[]={0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x00};\r
121 \r
122 void house(NETAPI_SCHED_HANDLE_T *s);\r
123 void our_stats_cb_mt(NETAPI_T h, paSysStats_t* pPaStats);\r
124 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);\r
125 \r
126 //sig handler\r
127 void netTest_utilMySig(int x)\r
128 {\r
129   QUIT=1;\r
130   scnt+=1;\r
131   printf(">net_test_dpi: recv'd signal %d cnt=%d\n",x,scnt);\r
132   if (scnt > 10) {printf(">dpi-demo: WARNING EXITING WITH PROPER SHUTDOWN LUTS LEFT ACTIVE\n");exit(1);}\r
133 \r
134 }\r
135 \r
136 \r
137 void recv_cb_bridge(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
138                          PKTIO_METADATA_T meta[], int n_pkts,\r
139                          uint64_t ts );\r
140 \r
141 \r
142 /*************debug********************/\r
143 void netTest_utilDumpDescr(unsigned long *p, int n)\r
144 {\r
145    printf("--------dump of descriptor %d %x\n", n, (int) p);\r
146    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
147    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
148    printf("-----------------------------\n");\r
149 }\r
150 void netTest_utilDumpHeader(unsigned long *p, int n, int a, int r)\r
151 {\r
152    printf("--------dump of header %d %x appID=%x flag1=%x\n", n, (int) p,a,r);\r
153    printf("> %0x %0x %0x %0x %0x %0x %0x %0x\n",\r
154           ntohl(p[0]),ntohl(p[1]),ntohl(p[2]),ntohl(p[3]),\r
155           ntohl(p[4]),ntohl(p[5]),ntohl(p[6]),ntohl(p[7]) );\r
156 #if 0\r
157    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
158    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
159    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
160 #endif\r
161    printf("-----------------------------\n");\r
162 }\r
163 /*****************************************/\r
164 \r
165 void house(NETAPI_SCHED_HANDLE_T * s)\r
166 {\r
167     int err;\r
168     NETAPI_SCHED_SHUTDOWN_T sched_shutdown;\r
169     int coreid;  //who we are\r
170     NETAPI_T nh= netapi_schedGetHandle(s);\r
171     coreid=(int) netapi_getCookie(nh);\r
172     \r
173     if (QUIT)\r
174     {\r
175         sched_shutdown.shutdown_type = NETAPI_SCHED_SHUTDOWN_NOW;\r
176         netapi_schedClose(s,&sched_shutdown,&err); \r
177         return;\r
178     }\r
179 \r
180 \r
181 #ifdef VDPI\r
182     if (DUMP_DPI_CONN )\r
183         navl_dump_conn_info();\r
184 #endif\r
185 \r
186 \r
187     /* only slow path threads get netcp stats, this needs to be set in cookie\r
188        during slow path thread creation*/\r
189     if (coreid & SP_THREAD_MASK)\r
190     {\r
191         netapi_netcpCfgReqStats(nh, our_stats_cb_mt, 0,&err);\r
192     }\r
193 \r
194 }\r
195 \r
196 unsigned long long CALIB=0;\r
197 unsigned long long calibrate_idle(void)\r
198 {\r
199     volatile unsigned long long  at1;\r
200     volatile unsigned long long  at2;\r
201     volatile unsigned long pt1;\r
202     volatile unsigned long pt2;\r
203     unsigned long long calib;\r
204     at1 = hplib_mUtilGetTimestamp();\r
205     pt1=netapi_timing_start();\r
206     for(;;)\r
207     {\r
208        pt2=netapi_timing_start()   ;\r
209        if ((pt2-pt1) >= 100000) break;\r
210     }\r
211     at2 = hplib_mUtilGetTimestamp();\r
212     \r
213     calib = ((unsigned long long) (pt2-pt1))/(at2-at1);\r
214     printf("calibrate:   arm time=%lld  -> arm cycles=%d calib=%lld\n", at2-at1, pt2-pt1, calib);\r
215     \r
216     return calib;\r
217 }\r
218 \r
219 /*******************************************\r
220  *************NETAPI OBJECTS***************\r
221  *****************************************/\r
222 static NETAPI_CFG_T our_netapi_default_cfg=\r
223 {\r
224 TUNE_NETAPI_PERM_MEM_SZ,\r
225 128,  //start of packet offset for hw to place data on rx for default flow\r
226 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system\r
227 TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use\r
228 TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap\r
229 64, //#descriptors w/o buffers in default heap\r
230 TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap\r
231 128,       //tail room\r
232 256,      //extra room\r
233 0,\r
234 NULL\r
235 };\r
236 \r
237 Pktlib_HeapHandle OurHeap;     //default heap, used by producer\r
238 PKTIO_HANDLE_T * netcp_rx_chan;\r
239 PKTIO_HANDLE_T * netcp_rx_chan2;\r
240 PKTIO_HANDLE_T * netcp_tx_chan;\r
241 \r
242 PKTIO_CFG_T our_chan_cfg={PKTIO_RX_TX, PKTIO_LOCAL, PKTIO_Q_ANY, 8};\r
243 PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};\r
244 PKTIO_CFG_T netcp_rx_cfg2={PKTIO_RX, (PKTIO_GLOBAL|PKTIO_PKT), PKTIO_Q_ANY, 8};\r
245 PKTIO_CFG_T netcp_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 8};\r
246 NETAPI_T netapi_handle;\r
247 NETAPI_SCHED_HANDLE_T * our_sched;\r
248 NETAPI_SCHED_HANDLE_T * scheduler[TUNE_NETAPI_NUM_CORES];\r
249 NETAPI_SCHED_CONFIG_T our_sched_cfg={\r
250   NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 5000000  //every 5000000 poll loops\r
251 };\r
252 \r
253 NETCP_CFG_IP_T ip_rule0;\r
254 NETCP_CFG_IP_T ip_rule1;\r
255 \r
256 \r
257 PKTIO_CFG_T direct_to_cpsw_cfg={PKTIO_TX, PKTIO_GLOBAL, 648, 8};\r
258 PKTIO_HANDLE_T * cpsw_tx_chan;\r
259 \r
260 PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};\r
261 PKTIO_CONTROL_T poll_cannel_control={PKTIO_SET_POLL_FLAGS, NULL, nwal_POLL_DEFAULT_GLOB_PKT_Q};\r
262 \r
263 //template for fast path\r
264 nwalTxPktInfo_t txPktInfoNoCrypto =\r
265 {\r
266     NULL,                                                                                               /* p_pkt */\r
267     NWAL_TX_FLAG1_META_DATA_VALID,      /* txFlags */\r
268     0,                                                                                                  /* lpbackPass */\r
269     0,                                                                                                  /* enetport */\r
270     0,                                                                                                  /* msuSize */\r
271     0,                                                                                                   /* startOffset */\r
272     0,                                                    /* saOffBytes */\r
273     0,                                                                                                  /* saPayLoadLen */\r
274     0               ,                                                                                    /* saAhIcvOffBytes */\r
275     0,                                                                                                 /* saAhMacSize */\r
276     0,                                              /* etherLenOffBytes */\r
277     MAC_HEADER_LEN,         /* ipOffBytes */\r
278     MAC_HEADER_LEN + IP_HEADER_LEN,                                        /* l4OffBytes */\r
279     UDP_HEADER_LEN,                                                             /* l4HdrLen */\r
280     0,                                                                         /* pseudoHdrChecksum */\r
281     0                                                                                                   /* pLoadLen */\r
282 };\r
283 \r
284 \r
285 NETCP_CFG_ROUTE_T  test_route=\r
286 {\r
287 0,\r
288 NULL,\r
289 NULL,\r
290 0//* to be filled in\r
291 };\r
292 \r
293 NETCP_CFG_FLOW_HANDLE_T kernelFlow22;\r
294 NETCP_CFG_FLOW_HANDLE_T kernelFlow23;\r
295 \r
296 /*************************END NETAPI OBJECTS***********************/\r
297 \r
298 static unsigned char all_mac[]={0,0,0,0,0,0};\r
299 nwalIpAddr_t all_ip={0,0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
300 \r
301 \r
302 static unsigned char all_dest[]={0xff,0xff,0xff,0xff,0xff,0xff};\r
303 \r
304 \r
305 \r
306 \r
307 static unsigned long last_header[32/sizeof(unsigned long)];\r
308 static unsigned long last_desc[64/sizeof(unsigned long)];\r
309 \r
310 //stats\r
311 #define MAX_CORE 4\r
312 int pkt_rx[MAX_CORE]; \r
313 int pkt_tx[MAX_CORE]; \r
314 unsigned long long pkt_rx_cycles[MAX_CORE]={0L};\r
315 unsigned long long pkt_tx_cycles[MAX_CORE]={0L};\r
316 unsigned long long pkt_cb_cycles[MAX_CORE]={0L};\r
317 unsigned long long idle_cycles[MAX_CORE]={0L};\r
318 volatile unsigned long long start_time[MAX_CORE];\r
319 unsigned long long end_time[MAX_CORE];\r
320 unsigned long long pkt_stall[MAX_CORE]={0L};\r
321 //*********************************\r
322 // packet generator\r
323 //*********************************\r
324 void gen_pkts(int np, int out_port);\r
325 \r
326 /******************************************************\r
327  * stats callback\r
328  *******************************************************/\r
329 void our_stats_cb_mt(NETAPI_T h, paSysStats_t* pPaStats)\r
330 {\r
331   stats.n_stats_cb +=1;\r
332   if(pPaStats) memcpy(&netcp_stats,pPaStats, sizeof(paSysStats_t));\r
333 }\r
334 \r
335 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats)\r
336 {\r
337     uint32_t numFreeDataPackets;\r
338     uint32_t            numZeroBufferPackets;\r
339     uint32_t            numPacketsinGarbage;\r
340     Pktlib_HeapStats    pktLibHeapStats;\r
341     int i,j;\r
342     unsigned long long bcpp;\r
343     unsigned long long bcpp_noc;\r
344     unsigned long long bcpp_app;\r
345     unsigned long long bcpp_tx;\r
346     unsigned long long npL;\r
347     unsigned long long cyclesL;\r
348     unsigned long long ccyclesL; //cache cycles\r
349     unsigned long long tmp_npL[TUNE_NETAPI_NUM_CORES];\r
350     unsigned long long tmp_cyclesL[TUNE_NETAPI_NUM_CORES];\r
351     unsigned long long tmp_ccyclesL[TUNE_NETAPI_NUM_CORES]; //cache cycles\r
352     NETAPI_SA_STATS_T netapi_sa_stats;\r
353 \r
354     printf(">*****stats @ %lld (#cbs%d) \n", hplib_mUtilGetTimestamp(),stats.n_stats_cb);\r
355     //printf("netcp_tx_handle check %x\n", netcp_tx_chan->back);\r
356     printf(">itx=%d rx=%d tx=%d bad=%d slow=%d \n>rx_class0=%d rx_class1=%d rx_class2=%d  secRx=%d  secPRX=%d sb_rx=%d sb_tx=%d auth_ok=%d sec_tx=%d  min_rx=%d min_tx=%d ip=%d\n",\r
357              stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new, \r
358              stats.n_class0_rx, stats.n_class1_rx, \r
359              stats.n_class2_rx, stats.sec_rx, stats.secp_rx, stats.sb_rx, stats.sb_tx, stats.n_auth_ok,\r
360              stats.sec_tx, stats.rx_min, stats.tx_min, stats.ip);\r
361     printf(">if rx stats:  %d %d %d\n",stats.if_rx[0],stats.if_rx[1],stats.if_rx[2]);\r
362 \r
363 \r
364     printf(">core rx stats:  %d %d %d\n",stats.core_rx[1],stats.core_rx[2],stats.core_rx[3]);\r
365 \r
366 \r
367     for (j= 1;j < NUM_PROCS;j++)\r
368     {\r
369         tmp_npL[j]=0LL; tmp_cyclesL[j]=0LL; tmp_ccyclesL[j]=0LL;\r
370         netapi_schedGetStats(scheduler[j],&tmp_npL[j],&tmp_cyclesL[j],&tmp_ccyclesL[j]);\r
371         npL += tmp_npL[j];\r
372         cyclesL += tmp_cyclesL[j];\r
373         ccyclesL += tmp_ccyclesL[j];\r
374     }\r
375 \r
376     if (npL && stats.rx)\r
377     {\r
378         bcpp = cyclesL/npL; \r
379         bcpp_noc = (cyclesL-ccyclesL)/npL; \r
380         bcpp_app = (stats.app_cycles-stats.tx_cache_cycles)/stats.rx;\r
381     }\r
382     else {bcpp = bcpp_noc=bcpp_app=0L;}\r
383     if (stats.tx)\r
384     {\r
385         bcpp_tx = (stats.send_cycles-stats.tx_cache_cycles)/stats.tx;\r
386     }\r
387     else\r
388     {\r
389         bcpp_tx = 0L;\r
390     }\r
391     printf(">         ++ busy cycles pp=%lld (%lld wo cache ops) (app+tx= %lld) (tx= %lld) ++\n",\r
392          bcpp,bcpp_noc,bcpp_app, bcpp_tx);\r
393 \r
394 \r
395 #ifdef VDPI\r
396     navl_return_stats(\r
397     &pGlobDpiStats->n_ops,\r
398     &pGlobDpiStats->n_class,\r
399     &pGlobDpiStats->min_time,\r
400     &pGlobDpiStats->max_time,\r
401     &pGlobDpiStats->tot,\r
402     &pGlobDpiStats->m_op,\r
403     &pGlobDpiStats->m_bytes,\r
404     &pGlobDpiStats->n_err,\r
405     &pGlobDpiStats->f_op,\r
406     &pGlobDpiStats->m_cycles,\r
407     &pGlobDpiStats->f_cycles);\r
408 \r
409     printf("dpi stats:  nops=%d nclass=%d min cycle=%d max  cycle=%d ave cycle=%lld #mallocs=%d #mbytes=%d n_err=%d fops=%d mCycles=%d fCycles=%d\n",\r
410     pGlobDpiStats->n_ops,\r
411     pGlobDpiStats->n_class,\r
412     pGlobDpiStats->min_time,\r
413     pGlobDpiStats->max_time,\r
414     pGlobDpiStats->n_ops? pGlobDpiStats->tot/pGlobDpiStats->n_ops : 0,\r
415     pGlobDpiStats->m_op,\r
416     pGlobDpiStats->m_bytes,\r
417     pGlobDpiStats->n_err,\r
418     pGlobDpiStats->f_op, pGlobDpiStats->m_cycles, pGlobDpiStats->f_cycles);\r
419     navl_results(1);\r
420     navl_results(2);\r
421 #endif\r
422     if(pPaStats)\r
423     {\r
424         printf("C1 number of packets:           %d\n", pPaStats->classify1.nPackets);\r
425         printf("C1 number IPv4 packets:         %d\n", pPaStats->classify1.nIpv4Packets);\r
426         printf("C1 number IPv6 packets:        %d\n", pPaStats->classify1.nIpv6Packets);\r
427         printf("C1 number Custom packets:        %d\n", pPaStats->classify1.nCustomPackets);\r
428         printf("C1 number SRIO packets:        %d\n", pPaStats->classify1.nSrioPackets);\r
429         printf("C1 number LLC/SNAP Fail packets:        %d\n", pPaStats->classify1.nLlcSnapFail);\r
430         printf("C1 number table matched:        %d\n", pPaStats->classify1.nTableMatch);\r
431         printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);\r
432         printf("C1 number IP Fragmented packets: %d\n", pPaStats->classify1.nIpFrag);\r
433         printf("C1 number IP Depth Overflow: %d\n", pPaStats->classify1.nIpDepthOverflow);\r
434         printf("C1 number VLAN Depth Overflow: %d\n", pPaStats->classify1.nVlanDepthOverflow);\r
435         printf("C1 number GRE Depth Overflow: %d\n", pPaStats->classify1.nGreDepthOverflow);\r
436         printf("C1 number MPLS Packets: %d\n", pPaStats->classify1.nMplsPackets);\r
437         printf ("C1 number of parse fail:        %d\n",pPaStats->classify1.nParseFail);\r
438         printf("C1 number of Invalid IPv6 Opt:  %d\n", pPaStats->classify1.nInvalidIPv6Opt);\r
439         printf("C1 number of TX IP Fragments:  %d\n", pPaStats->classify1.nTxIpFrag);\r
440         printf ("C1 number of silent discard:    %d\n",pPaStats->classify1.nSilentDiscard);\r
441         printf("C1 number of invalid control:   %d\n", pPaStats->classify1.nInvalidControl);\r
442         printf ("C1 number of invalid states:    %d\n",pPaStats->classify1.nInvalidState);\r
443         printf ("C1 number of system fails:      %d\n",pPaStats->classify1.nSystemFail);\r
444         printf ("C2 number Packets  :           %d\n",pPaStats->classify2.nPackets);\r
445         printf ("C2 number udp           :      %d\n",pPaStats->classify2.nUdp);\r
446         printf ("C2 number tcp           :      %d\n",pPaStats->classify2.nTcp);\r
447         printf ("C2 number Custom       :      %d\n",pPaStats->classify2.nCustom);\r
448         printf ("C2 number silent drop   :      %d\n",pPaStats->classify2.nSilentDiscard);\r
449         printf ("C2 number invalid cntrl :      %d\n\n",pPaStats->classify2.nInvalidControl);\r
450         printf ("C2 number Modify Stats Cmd Fail :      %d\n\n",pPaStats->modify.nCommandFail);\r
451     }\r
452     Pktlib_getHeapStats(OurHeap, &pktLibHeapStats);\r
453 \r
454     printf("main heap stats>  #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,\r
455                                 pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);\r
456     printf("               >  #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n", \r
457                         pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,\r
458                         pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);\r
459 }\r
460 \r
461 NETAPI_T worker_nh[MAX_NUM_CORES];\r
462 \r
463 void slow_path_thread(uint32_t index)\r
464 {\r
465     int err, i;;\r
466     uint32_t thread_num;\r
467     cpu_set_t cpu_set;\r
468 \r
469     /* index being passed in is the core we want to run the thread on */\r
470     thread_num = index;\r
471     printf("slow_path_thread, mypid: %d, core_id %d\n", gettid(), thread_num);\r
472 \r
473     CPU_ZERO( &cpu_set);\r
474     for (i = 0; i < 1;i++)\r
475     {\r
476         CPU_SET( i, &cpu_set);\r
477     }\r
478     hplib_utilSetupThread(thread_num, &cpu_set, hplib_spinLock_Type_LOL);\r
479     worker_nh[thread_num] = netapi_init(NETAPI_CORE_MASTER,NULL);\r
480 \r
481     if (worker_nh[thread_num] == NULL)\r
482     {\r
483         printf("slow_path_thread: netapi_init failure, exiting\n");\r
484         exit(1);\r
485     }\r
486     netapi_setCookie(worker_nh[thread_num],(void*)(thread_num | SP_THREAD_MASK));\r
487 \r
488     scheduler[thread_num] =netapi_schedOpen(worker_nh[thread_num],&our_sched_cfg, &err);\r
489     if (!scheduler[thread_num]) \r
490     {\r
491         printf("sched create failed for core%d\n",thread_num);\r
492         goto ERR_slow_path_thread;\r
493     }\r
494     scheduler[thread_num]->config.yield = TRUE;\r
495     scheduler[thread_num]->config.pollGarbageQ = TRUE;\r
496     scheduler[thread_num]->config.pollCtrlQ = TRUE;\r
497     printf("Slow Path thread: %d setup complete, running on ARM CORE: %d\n",\r
498     index,index);\r
499 \r
500 \r
501     netapi_schedRun(scheduler[thread_num], &err);\r
502 \r
503 ERR_slow_path_thread:\r
504     printf("slow_path_thread: calling netapi_shutdown\n");\r
505     netapi_shutdown(worker_nh[thread_num]);\r
506 }\r
507 \r
508 \r
509 void fast_path_thread(uint32_t index)\r
510 {\r
511     int err, i;\r
512     PKTIO_HANDLE_T *rx_chan;\r
513     PKTIO_HANDLE_T *sb_rx_chan;\r
514     uint32_t thread_num;\r
515     int navlHandle;\r
516 \r
517 \r
518     cpu_set_t cpu_set;\r
519 \r
520     CPU_ZERO( &cpu_set);\r
521     thread_num = index;\r
522     printf("fast_path_thread: core %d\n", index);\r
523 \r
524 \r
525     CPU_SET( thread_num, &cpu_set);\r
526     hplib_utilSetupThread(thread_num, &cpu_set, hplib_spinLock_Type_LOL);\r
527 \r
528 \r
529     hplib_mSpinLockLock(&dpi_demo_thread_lock);\r
530     worker_nh[thread_num]=netapi_init(NETAPI_CORE_MASTER,NULL);\r
531     \r
532     if (worker_nh[thread_num] == NULL)\r
533     {\r
534         printf("fast_path_thread: netapi_init failure, exiting\n");\r
535         hplib_mSpinLockUnlock(&dpi_demo_thread_lock);\r
536         exit(1);\r
537     }\r
538     else\r
539     {\r
540 #ifdef VDPI\r
541             navlHandle = navl_per_thread_init(thread_num);\r
542 #endif\r
543     }\r
544     hplib_mSpinLockUnlock(&dpi_demo_thread_lock);\r
545 \r
546 \r
547     if (worker_nh[thread_num] == NULL)\r
548     {\r
549         printf("fast_path_thread: netapi_init failure, exiting\n");\r
550         exit(1);\r
551     }\r
552     \r
553     /* open netcp default RX channels*/\r
554     rx_chan = netapi_pktioOpen(worker_nh[thread_num], NETCP_RX, (PKTIO_CB) recv_cb_bridge, &netcp_rx_cfg,  &err);\r
555 \r
556 \r
557     netapi_setCookie(worker_nh[thread_num],(void*)thread_num);\r
558     \r
559     scheduler[thread_num] =netapi_schedOpen(worker_nh[thread_num],\r
560                                             &our_sched_cfg,\r
561                                             &err);\r
562     if (!scheduler[thread_num]) \r
563         {\r
564         printf("sched create failed for core%d\n",thread_num);\r
565         goto ERR_fast_path_thread;\r
566         //exit(1);\r
567     }\r
568 \r
569  \r
570     scheduler[thread_num]->config.yield = FALSE;\r
571     scheduler[thread_num]->config.pollGarbageQ = FALSE;\r
572     scheduler[thread_num]->config.pollCtrlQ = FALSE;\r
573    /* Entry point to scheduler */\r
574 \r
575 \r
576     printf("Fast Path thread: %d setup complete, running on ARM CORE: %d\n",\r
577     index,index);\r
578     netapi_schedRun(scheduler[thread_num], &err);\r
579 \r
580 ERR_fast_path_thread:\r
581 #ifdef VDPI\r
582         navl_fini(navlHandle);\r
583 #endif\r
584     netapi_pktioClose(rx_chan, &err);\r
585 \r
586     printf("fast_path_thread: calling netapi_shutdown\n");\r
587     netapi_shutdown(worker_nh[thread_num]);\r
588 }\r
589 \r
590 \r
591 /******************************\r
592 * main program\r
593 *****************************/\r
594 int main(int argc, char **argv)\r
595 {\r
596     int err,i;\r
597     int j;\r
598     int32_t             errCode;\r
599     Pktlib_HeapIfTable*  pPktifTable;\r
600     Pktlib_HeapCfg heapCfg;\r
601     long t1, t2 ;\r
602     cpu_set_t cpu_set;\r
603     int c;\r
604     int statsQueryRequest = 0;\r
605     pthread_t *thrs;\r
606     int p;\r
607 \r
608 #if 0\r
609     if (initRm())\r
610     {\r
611         printf("main: initRm() returned error\n");\r
612         exit(1);\r
613     }\r
614 #endif\r
615 \r
616 \r
617 #if 1\r
618 \r
619     if (argc == 2)\r
620     {\r
621         printf("main: argument %s\n", argv[1]);\r
622         if(!(strcmp(argv[1], "stats")))\r
623         {\r
624             statsQueryRequest =1;\r
625             printf("querying for stats\n");\r
626         }\r
627     }\r
628     printf("statsQueryReqeust: %d\n", statsQueryRequest);\r
629 \r
630 \r
631 #endif\r
632 \r
633 \r
634     if (!statsQueryRequest)\r
635     {\r
636         signal(SIGINT,netTest_utilMySig);\r
637         CPU_ZERO( &cpu_set);\r
638         CPU_SET( 0, &cpu_set);\r
639         hplib_utilSetupThread(HPLIB_THREADID, &cpu_set, hplib_spinLock_Type_LOL);\r
640     \r
641         /* create netapi */\r
642         our_netapi_default_cfg.rmHandle = rmClientServiceHandle;\r
643         netapi_handle = netapi_init(NETAPI_SYS_MASTER,\r
644                                     &our_netapi_default_cfg);\r
645         if (netapi_handle == NULL)\r
646         {\r
647             printf("main: netapi_init failure, exiting\n");\r
648             exit(1);\r
649         }\r
650         /* allocate segment for shared memory for packet stats */\r
651         /* allocate packet statistics */\r
652         pShmBase = hplib_shmOpen();\r
653         if (pShmBase)\r
654         {\r
655             if (hplib_shmAddEntry(pShmBase,\r
656                               sizeof(navl_wrapper_pkt_stat_t)\r
657                              * MAX_PROTOCOLS *NUM_FP_PROCS + sizeof(navl_wrapper_cfg_info_t),\r
658                              APP_ENTRY_1) != hplib_OK)\r
659             {\r
660                 printf("main:  hplib_shmAddEntry failure\n");\r
661                 return -1;\r
662             }\r
663             else\r
664             {\r
665                 pShmEntry = hplib_shmGetEntry(pShmBase, APP_ENTRY_1);\r
666                 pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;\r
667                 memset(pNavlCfg,\r
668                        0,\r
669                        sizeof(navl_wrapper_pkt_stat_t) * MAX_PROTOCOLS *NUM_FP_PROCS+ sizeof(navl_wrapper_cfg_info_t));\r
670                 pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;\r
671                 pNavlCfg->enable_dpi = 0; /* disable DPI by default */\r
672             }\r
673             if (hplib_shmAddEntry(pShmBase, sizeof(navl_global_dpi_stats), APP_ENTRY_2) != hplib_OK)\r
674             {\r
675                 printf("main:  hplib_shmAddEntry failure\n");\r
676                 return -1;\r
677             }\r
678             else\r
679             {\r
680                 pShmEntry = hplib_shmGetEntry(pShmBase, APP_ENTRY_2);\r
681                 pGlobDpiStats = (navl_global_dpi_stats*) pShmEntry;\r
682                 memset(pGlobDpiStats, 0, sizeof(navl_global_dpi_stats));\r
683                 pGlobDpiStats->min_time=100000000;\r
684             }\r
685         }\r
686         else\r
687         {\r
688             printf("main: hplib_shmOpen failure, exiting\n");\r
689             exit(1);\r
690         }\r
691             /* open the main heap */\r
692         OurHeap = Pktlib_findHeapByName("netapi");\r
693         if (!OurHeap)\r
694         {\r
695             printf("findheapbyname fail\n");\r
696             exit(1);\r
697         }\r
698 \r
699         //if we want to relay network packets, we create a handle to the \r
700         //default netcp receive queue here\r
701         netcp_rx_chan= netapi_pktioOpen(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_bridge, &netcp_rx_cfg,  &err);\r
702         if (!netcp_rx_chan)\r
703         {\r
704             printf("pktio open RX failed err=%d\n",err);\r
705             exit(1);\r
706         }\r
707 \r
708         netcp_tx_chan= netapi_pktioOpen(netapi_handle, NETCP_TX, (PKTIO_CB) NULL, &netcp_tx_cfg,  &err);\r
709         if (!netcp_tx_chan)\r
710         {\r
711             printf("pktio open TX failed err=%d\n",err);\r
712             exit(1);\r
713         }\r
714         else  //install a fast path template into the NETCP TX channel\r
715         {\r
716             PKTIO_CONTROL_T control2;\r
717             control2.op = PKTIO_UPDATE_FAST_PATH;\r
718             PKTIO_CFG_T cfg2;\r
719             memset(&cfg2, 0, sizeof(PKTIO_CFG_T));\r
720             cfg2.fast_path_cfg.fp_send_option = PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT;\r
721             cfg2.fast_path_cfg.txPktInfo= &txPktInfoNoCrypto;\r
722             netapi_pktioControl(netcp_tx_chan, NULL, &cfg2, &control2, &err);\r
723        }\r
724 \r
725 \r
726         if (navl_setup() < 0)\r
727         {\r
728             printf("main: navl_setup failure, exiting\n");\r
729             exit(1);\r
730         }\r
731 \r
732         /*********************************************/\r
733         /*****************end NETAPI STARTUP**********/\r
734         /*********************************************/\r
735 \r
736         //now creaate a simple netcp rule\r
737         //to get a lot of packets\r
738         mac0 = netapi_netcpCfgCreateMacInterface(\r
739                       netapi_handle,\r
740                       &all_mac[0],\r
741                       NULL,\r
742                       0,\r
743                       1,\r
744                       (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
745                       (NETCP_CFG_VLAN_T ) NULL ,  //future\r
746                       0x0800,\r
747                       1,\r
748                       &err);\r
749         if (err) {printf("addmac0 failed %d\n",err); exit(1); }\r
750         else printf("addmac0 sucess\n");\r
751 \r
752         mac1 = netapi_netcpCfgCreateMacInterface(\r
753                       netapi_handle,\r
754                       &all_mac[0],\r
755                       NULL,\r
756                       1,\r
757                       2,\r
758                       (NETCP_CFG_ROUTE_HANDLE_T)  NULL,\r
759                       (NETCP_CFG_VLAN_T ) NULL ,  //future\r
760                       0x0800,\r
761                       1,\r
762                       &err);\r
763         if (err) {printf("addmac1 failed %d\n",err); exit(1); }\r
764         else printf("addmac1 sucess\n");\r
765 \r
766         //calibrate idle\r
767         CALIB = calibrate_idle();\r
768 \r
769         //**************************************\r
770         //Create a slow path thread\r
771         //***************************************\r
772         thrs = malloc( sizeof( pthread_t ) * NUM_PROCS );\r
773         if (thrs == NULL)\r
774         {\r
775             perror( "malloc" );\r
776             return -1;\r
777         }\r
778         printf( "dpi-demo: Starting slow_path_thread on core 0\n");\r
779 \r
780         if (pthread_create( &thrs[0], NULL, (void*)slow_path_thread,\r
781                           (void *)0 ))  //start at core 0\r
782         {\r
783             perror( "pthread_create" );\r
784             exit(1);\r
785         }\r
786 \r
787 \r
788         for (j= 1;j < NUM_PROCS;j++)\r
789         {\r
790             printf( "dpi-demo: Starting fast_path_thread on core 1\n");\r
791             if (pthread_create( &thrs[j], NULL, (void*)fast_path_thread,\r
792                           (void *)j ))  //start at core 1\r
793             {\r
794                 perror( "pthread_create" );\r
795                 exit(1);\r
796             }\r
797         }\r
798     }\r
799     else\r
800     {\r
801         \r
802         pShmBase = hplib_shmOpen();\r
803         if (pShmBase)\r
804         {\r
805             pTemp = hplib_shmGetEntry(pShmBase, APP_ENTRY_1);\r
806             pNavlCfg =  (navl_wrapper_cfg_info_t*)pTemp;\r
807 \r
808             pStats1 = pTemp + sizeof(navl_wrapper_cfg_info_t);\r
809 \r
810         \r
811             pStats2 = pTemp + sizeof(navl_wrapper_cfg_info_t) +\r
812                     (sizeof(navl_wrapper_pkt_stat_t)*pNavlCfg->num_protocols);\r
813 \r
814 \r
815             pTemp = hplib_shmGetEntry(pShmBase, APP_ENTRY_2);\r
816             pGlobDpiStats = (struct dpi_stats*) pTemp;\r
817                navl_return_stats(\r
818             &pGlobDpiStats->n_ops,\r
819             &pGlobDpiStats->n_class,\r
820             &pGlobDpiStats->min_time,\r
821             &pGlobDpiStats->max_time,\r
822             &pGlobDpiStats->tot,\r
823             &pGlobDpiStats->m_op,\r
824             &pGlobDpiStats->m_bytes,\r
825             &pGlobDpiStats->n_err,\r
826             &pGlobDpiStats->f_op,\r
827             &pGlobDpiStats->m_cycles,\r
828             &pGlobDpiStats->f_cycles);\r
829 \r
830             printf("dpi stats:  nops=%d nclass=%d min cycle=%d max cycle=%d ave cycle=%lld #mallocs=%d #mbytes=%d n_err=%d fops=%d mCycles=%d fCycles=%d\n",\r
831             pGlobDpiStats->n_ops,\r
832             pGlobDpiStats->n_class,\r
833             pGlobDpiStats->min_time,\r
834             pGlobDpiStats->max_time,\r
835             pGlobDpiStats->n_ops? pGlobDpiStats->tot/pGlobDpiStats->n_ops : 0,\r
836             pGlobDpiStats->m_op,\r
837             pGlobDpiStats->m_bytes,\r
838             pGlobDpiStats->n_err,\r
839             pGlobDpiStats->f_op, pGlobDpiStats->m_cycles, pGlobDpiStats->f_cycles);\r
840             navl_results2(1);\r
841             navl_results2(2);\r
842             \r
843             exit(1);\r
844         }\r
845     }\r
846 \r
847 \r
848         //this thread of execution (main) now just waits on user input\r
849         for(;;)\r
850         {\r
851             printf(">");\r
852             c=getchar();\r
853             if (c=='C')\r
854             {\r
855                 CAP=!CAP; \r
856                 printf("CAPTURE= %d\n", CAP);\r
857             }\r
858             else if (c=='q') {QUIT=1;break;}\r
859             else if (c=='s')\r
860                 our_stats_cb(netapi_handle, &netcp_stats);\r
861     #ifdef VDPI\r
862                else if (c=='c') \r
863                 {navl_clear_stats();printf("> Clearing DPI stats\n");}\r
864                else if (c=='v') navl_set_verbose();\r
865                else if (c=='p') \r
866                  {DUMP_DPI_CONN = !DUMP_DPI_CONN;printf(">  **DPI CONN DUMP is %s ** \n", DUMP_DPI_CONN ?"enabled":"disabled");}\r
867                else if (c=='d')\r
868                  {\r
869                     pNavlCfg->enable_dpi = !pNavlCfg->enable_dpi;\r
870                     printf("enable_dpi flag: %d\n", pNavlCfg->enable_dpi);\r
871                     printf(">  **DPI is %s ** \n", pNavlCfg->enable_dpi?"enabled":"disabled");\r
872                  }\r
873     #endif\r
874             else if (c=='!') {system("sh");}\r
875     \r
876             else if ((c=='h')||(c=='?'))\r
877             {\r
878                 printf("> 'q' to quit,  's' for stats,'d' to dump capture\n,> 'h' for help\n ");\r
879             }\r
880     #if 1\r
881             else if (c=='r')\r
882             {\r
883                 netTest_utilDumpHeader(&last_header[0], 0,0,0);\r
884                 netTest_utilDumpDescr(&last_desc[0], 0);\r
885             }\r
886     #endif\r
887         }\r
888 \r
889 \r
890 \r
891 #ifdef VDPI\r
892             navl_done();\r
893 #endif\r
894 \r
895         //wait for completion \r
896         printf("main task now pending on thread completion\n");\r
897         for (i = 0; i < NUM_PROCS; i++)\r
898                 pthread_join( thrs[i], NULL );\r
899 \r
900         free( thrs );\r
901 \r
902         /*************************************************\r
903         ************CLEAN UP****************************\r
904         ************************************************/\r
905         //get rid of rule, in the case that we are relaying packets\r
906         //also close our netcp rx channel\r
907         netapi_netcpCfgDelMac(netapi_handle,0,&err);\r
908         netapi_netcpCfgDelMac(netapi_handle,1,&err);\r
909     \r
910         netapi_pktioClose(netcp_rx_chan,&err);\r
911         netapi_pktioClose(netcp_tx_chan,&err);\r
912 \r
913 \r
914         //done\r
915         netapi_shutdown(netapi_handle);\r
916 \r
917 \r
918 }\r
919 #if 1\r
920 static inline void send_it(Ti_Pkt *tip, int len, int out_port)\r
921 {\r
922   int err=0;\r
923   PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};\r
924   nwalTxPktInfo_t meta_tx2={0};\r
925   int coreid=Osal_nwalGetProcId();\r
926   if (len<60)\r
927   {\r
928      unsigned int templen;\r
929      char * p_pkt;\r
930      len=60;\r
931      Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
932      Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);\r
933   }\r
934   Pktlib_setPacketLen(tip,len);\r
935   meta_tx2.txFlag1 = NWAL_TX_FLAG1_META_DATA_VALID;\r
936   meta_tx2.ploadLen = len ;\r
937   meta_tx2.enetPort=out_port;\r
938   meta2.u.tx_meta=&meta_tx2;\r
939   stats.tx+=1;\r
940   if(coreid<MAX_NUM_CORES)\r
941     pkt_tx[coreid]+=1;\r
942   netapi_pktioSend(netcp_tx_chan,tip,&meta2,&err);\r
943 }\r
944 #endif\r
945 void recv_cb_bridge(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
946                          PKTIO_METADATA_T meta[], int n_pkts,\r
947                          uint64_t ts )\r
948 {\r
949 int i;\r
950 int len;\r
951 int p;\r
952 Ti_Pkt * tip;\r
953 unsigned int appid;\r
954 unsigned int templen;\r
955 char * p_pkt;\r
956 unsigned long t1;\r
957 unsigned long t2;\r
958 unsigned long long ct1;\r
959 unsigned long long ct2;\r
960 unsigned short ip_pl;\r
961 unsigned long long n_c_ops;\r
962 int ifno;\r
963 int out_port;\r
964 \r
965 int coreid=Osal_nwalGetProcId();\r
966 \r
967 \r
968 pasahoLongInfo_t* protoInfo;\r
969 \r
970 t1=netapi_timing_start();\r
971 ct1 =Osal_cache_op_measure(&n_c_ops);\r
972 for(i=0;i<n_pkts;i++)\r
973 {\r
974         \r
975         tip = p_recv[i];\r
976         appid = ((unsigned int)meta[i].u.rx_meta->appId)&0xff000000;\r
977         if (appid == NETAPI_NETCP_MATCH_GENERIC_IP) \r
978         {\r
979            stats.ip+=1;\r
980         }\r
981 \r
982         protoInfo=nwal_mGetProtoInfo(tip);\r
983         ifno = nwal_mGetRxEmacPort( protoInfo);\r
984         if (ifno ==1) out_port=2; else out_port=1;\r
985         if(coreid<MAX_NUM_CORES) stats.core_rx[coreid]+=1;\r
986         if (ifno < MAX_NUM_INTERFACES) stats.if_rx[ifno]+=1;\r
987         Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
988         if (CAP==coreid)\r
989         {\r
990             memcpy((unsigned char *)&last_header[0],p_pkt,32);\r
991             memcpy((unsigned char*)&last_desc[0],tip,64);\r
992         }\r
993         len = Pktlib_getPacketLen(tip)-4;//real length, subtract mac trailer\r
994         stats.rx+=1;\r
995         //printf("recv_cb_bridge: appId: 0x%x, out_port: %d\n", appid, out_port);\r
996         if (appid == NETAPI_NETCP_MATCH_GENERIC_MAC)\r
997         {\r
998 #ifdef VDPI\r
999             {\r
1000                 if (pNavlCfg->enable_dpi)\r
1001                     navl_process_pkt(p_pkt, len);\r
1002             }\r
1003 #endif\r
1004         }\r
1005 \r
1006     \r
1007  //printf("recv_cb_bridge: coreId: %d, outPort %d\n", coreid, out_port);\r
1008         //Pktlib_freePacket(tip);\r
1009         send_it(tip,len+4,out_port);\r
1010 }\r
1011 t2=netapi_timing_start();\r
1012 ct2 =Osal_cache_op_measure(&n_c_ops);\r
1013 stats.app_cycles +=  (unsigned long long) (t2-t1);\r
1014 stats.tx_cache_cycles += (unsigned long long) (ct2-ct1);\r
1015 return;\r
1016 }\r
1017 \r
1018 #define NTOPOP 150\r
1019 volatile Ti_Pkt * pHd[NTOPOP];\r
1020 \r
1021 #define PKTGEN_PKT_LEN pkt_len\r
1022 #define MAXP 4   //max ports \r
1023 void gen_pkts(int np, int out_port)\r
1024 {\r
1025     int i;\r
1026     int p=0;\r
1027     unsigned long * pI ;\r
1028     Ti_Pkt * tip;\r
1029     int len;\r
1030     unsigned char * pData;\r
1031     int cstall=0;\r
1032     int coreid = Osal_nwalGetProcId();\r
1033     for(i=0;i<np;)\r
1034     {\r
1035         //set out output port\r
1036         if (out_port)\r
1037         {\r
1038             p=out_port;\r
1039         }\r
1040         else //flip flop\r
1041         {\r
1042             p+=1;\r
1043             if(p>MAXP) p=1;\r
1044         }\r
1045         //get a packet\r
1046         tip=Pktlib_allocPacket(OurHeap,PKTGEN_PKT_LEN);\r
1047         pI = (unsigned long *) tip;\r
1048         if (!tip)\r
1049         {\r
1050             pkt_stall[coreid]+=1;\r
1051             cstall+=1;\r
1052             if (cstall >= 100000) \r
1053             {\r
1054                 printf("worker core %d, max stall hit,, exiting.\n",coreid); \r
1055                 return;\r
1056             }\r
1057             continue;\r
1058         }\r
1059         cstall=0;\r
1060         Pktlib_getDataBuffer(tip,&pData,&len);\r
1061         memcpy(pData,&dummy_mac,14);\r
1062         Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, pData,PKTGEN_PKT_LEN);\r
1063         Pktlib_setPacketLen(tip,PKTGEN_PKT_LEN);\r
1064         pI[1]=0x80000000;\r
1065         //pI[2] &= 0xfff0ffff ;move to pktio send function\r
1066 \r
1067         //capture packet just in case\r
1068         if (CAP==coreid)\r
1069         {\r
1070             unsigned int templen;\r
1071             char * p_pkt;\r
1072             Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
1073             memcpy((unsigned char *)&last_header[0],p_pkt,32);\r
1074             memcpy((unsigned char*)&last_desc[0],tip,64);\r
1075         }\r
1076 \r
1077         //send  packet\r
1078         send_it(tip, PKTGEN_PKT_LEN, p);\r
1079         pkt_tx[coreid]+=1;\r
1080         i+=1;\r
1081    }\r
1082 \r
1083     return;\r
1084 }\r