]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blob - ti/runtime/netapi/test/net_test_router.c
NETAPI: This commit addes the following functionality:
[keystone-rtos/netapi.git] / ti / runtime / netapi / test / net_test_router.c
1 /******************************************
2  * File: net_test_router.c
3  * Purpose: net_test_router application
4  **************************************************************
5  * FILE:  net_test_router.c
6  * 
7  * DESCRIPTION:  netapi user space transport
8  *               library  net_test_router application
9  * 
10  * REVISION HISTORY:  rev 0.0.1 
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2013
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 <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <signal.h>
49 #include <pthread.h>
51 #include "net_test.h"
52 #include "trie.h"
53 #include "string.h"
55 #include <sys/resource.h>
57 #include <ti/drv/sa/salld.h>
58 #include <ti/drv/pa/pa.h>
60 #include "net_test_util.h"
62 extern int QUIT;
64 /* Global definitions */
65 #ifdef MULTI_THREAD
66     cpu_set_t cpu_set;
67 #endif
69 netTestConfig_t netTestCfg;
70 static  netTestConfigFile_t config_file;
72 char    input_file_name[] = "net_test_config.txt";
74 nwal_RetValue       nwalRetVal;
75 Pktlib_HeapHandle ourHeap;
76 Pktlib_HeapHandle specialSmall;
77 Pktlib_HeapHandle specialLarge;
79 PKTIO_HANDLE_T *netcp_rx_chan;
80 PKTIO_HANDLE_T *netcp_rx_chan2;
81 PKTIO_HANDLE_T *netcp_tx_chan;
82 PKTIO_HANDLE_T *netcp_sb_tx_chan;
83 PKTIO_HANDLE_T *netcp_sb_rx_chan;
84 PKTIO_CFG_T our_chan_cfg={PKTIO_RX_TX, PKTIO_LOCAL, PKTIO_Q_ANY, 8};
85 PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};
86 PKTIO_CFG_T netcp_rx_cfg2={PKTIO_RX, (PKTIO_GLOBAL|PKTIO_PKT), PKTIO_Q_ANY, 8};
87 PKTIO_CFG_T netcp_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 8};
88 PKTIO_CFG_T netcp_sb_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};
89 PKTIO_CFG_T netcp_sb_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 8};
91 NETCP_CFG_EXCEPTION_PKT_T expPkt_appid;
92 static hplib_spinLock_T stats_lock;
94 Trie * P_trie;
95 Trie *p_trie_sa_rx;
96 Trie *p_trie_sa_tx;
99 #include "router.c"
100 extern Trie * our_router;
101 extern OUR_ROUTE_T routes[];
103 unsigned int ip[MAX_ROUTES]={BE(0x0a0100c8),BE(0x0a00000a),BE(0x0a02000a),BE(0xc0a8010a),BE(0x9eda6719)};
105 void recv_cb_router(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
106                          PKTIO_METADATA_T meta[], int n_pkts,
107                          uint64_t ts );
110 extern STATS_T stats[TUNE_NETAPI_NUM_CORES];
111 extern paSysStats_t netcp_stats;
113 /*******************************************
114  *************NETAPI OBJECTS***************
115  *****************************************/
116 static NETAPI_CFG_T our_netapi_default_cfg=
118 TUNE_NETAPI_PERM_MEM_SZ,
119 128,  //start of packet offset for hw to place data on rx for default flow
120 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
121 TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
122 TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
123 64, //#descriptors w/o buffers in default heap
124 TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap
125 128   ,  //tail room
126 256      //extra room 
127 };
131 void house(NETAPI_SCHED_HANDLE_T *s);
132 NETAPI_T netapi_handle;
133 NETAPI_SCHED_HANDLE_T * our_sched;
134 #ifdef MULTI_THREAD
135 NETAPI_SCHED_HANDLE_T * scheduler[TUNE_NETAPI_NUM_CORES];
136 #endif
137 NETAPI_SCHED_CONFIG_T our_sched_cfg={
138   NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 5000000  //every 5000000 poll loops
139 };
142 NETCP_CFG_IP_T ip_rule0;
143 NETCP_CFG_IP_T ip_rule1;
145 PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};
147 /* security objects. (for loopback mode) */
148 netTestSA_t sa_info[MAX_SEC_INDEX];
151 NETCP_CFG_IPSEC_POLICY_T rx_policy[MAX_SEC_INDEX];
156 /*************************END NETAPI OBJECTS***********************/
158 void update_header(HEAD_T * p_head, int len)
160    unsigned char *p = (unsigned char *) &p_head->udp[1];
161    len -= (20+14);
162    /* update ip checksum */
163    /* update udp checksum */
164    /* update length */
165    *p= (len&0xff00)>>8;
166    *(p+1) = len&0xff;
169 #ifdef MULTI_THREAD
170 NETAPI_T worker_nh[TUNE_NETAPI_NUM_CORES];
171 void slow_path_thread(int coreid)
173     int err;
174     PKTIO_HANDLE_T *rx_chan;
175     PKTIO_HANDLE_T *tx_chan;
176     PKTIO_HANDLE_T *sb_tx_chan;
177     PKTIO_HANDLE_T *sb_rx_chan;
179     
182     CPU_ZERO( &cpu_set);
183 #ifdef CORTEX_A15
184     CPU_SET( coreid, &cpu_set);
185     hplib_utilSetupCore(coreid, &cpu_set);
186 #else
187       CPU_SET( 0, &cpu_set);
188     hplib_utilSetupCore(coreid+1, &cpu_set);
189 #endif
190     worker_nh[coreid]=netapi_init(NETAPI_CORE_MASTER,NULL);
192     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) worker_nh[coreid];
194    /* open netcp default tx, rx queues */
195     tx_chan = pktio_open(worker_nh[coreid], NETCP_TX, NULL, &netcp_tx_cfg,  &err);
197     rx_chan = pktio_open(worker_nh[coreid], NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg,  &err);
201     netapi_setCookie(worker_nh[coreid],(void*)coreid);
202       
203     scheduler[coreid] =netapi_schedOpen(worker_nh[coreid],&our_sched_cfg, &err);
204     if (!scheduler[coreid]) 
205     {
206         Debug_printf("sched create failed for core%d\n",coreid); 
207         exit(1);
208     }
209       scheduler[coreid]->config.yield = FALSE;
210        scheduler[coreid]->config.pollGarbageQ = TRUE;
211         scheduler[coreid]->config.pollCtrlQ = TRUE;
212             /*********************************************/
213     /**************Entry point into scheduler ****/
214     /*********************************************/
215     netapi_schedRun(scheduler[coreid], &err);
216     Debug_printf(">net_test: core %d worker thread done\n",coreid);
218     pktio_close(tx_chan, &err);
219     pktio_close(rx_chan, &err);
220     netapi_shutdown(worker_nh[coreid]);
223 void fast_path_thread(int coreid)
225     int err;
226     PKTIO_HANDLE_T *rx_chan;
227     PKTIO_HANDLE_T *tx_chan;
228     PKTIO_HANDLE_T *sb_tx_chan;
229     PKTIO_HANDLE_T *sb_rx_chan;
231 #ifdef CORTEX_A15
232     CPU_SET( coreid, &cpu_set);
233         hplib_utilSetupCore(coreid, &cpu_set);
234 #else
235       CPU_SET( 0, &cpu_set);
236     hplib_utilSetupCore(coreid + 1, &cpu_set);
237 #endif
238     worker_nh[coreid]=netapi_init(NETAPI_CORE_MASTER,NULL);
240     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) worker_nh[coreid];
242    /* open netcp default tx, rx queues */
243     tx_chan = pktio_open(worker_nh[coreid], NETCP_TX, NULL, &netcp_tx_cfg,  &err);
244     
245     
246     rx_chan = pktio_open(worker_nh[coreid], NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg,  &err);
247     netapi_setCookie(worker_nh[coreid],(void*)coreid);
249     scheduler[coreid] =netapi_schedOpen(worker_nh[coreid],&our_sched_cfg, &err);
250     if (!scheduler[coreid]) 
251         {
252         Debug_printf("sched create failed for core%d\n",coreid); 
253         exit(1);
254     }
256     /*********************************************/
257     /**************Entry point into scheduler ****/
258     /*********************************************/
259     scheduler[coreid]->config.yield = FALSE;
260      scheduler[coreid]->config.pollGarbageQ = FALSE;
261      scheduler[coreid]->config.pollCtrlQ = FALSE;
262      //sleep(100000);
263     netapi_schedRun(scheduler[coreid], &err);
264     Debug_printf(">net_test: core %d worker thread done\n",coreid);
265     pktio_close(tx_chan, &err);
266     pktio_close(rx_chan, &err);
267     netapi_shutdown(worker_nh[coreid]);
268 \r}
270 #endif
272 /***************************************
273  ********** test driver*****************
274  ***************************************/
275 int main(int argc, char **argv)
277     int err,i;
278     Pktlib_HeapCfg      heapCfg;
279     rlim_t oss,ss = 1024*1024;
280     struct rlimit rl;
281     int32_t             errCode;
282     Pktlib_HeapIfTable*  pPktifTable;
283 /* Local Per Process default resourcese maintained at NWAL */
284     nwalLocCxtInfo_t    nwalLocCxt;
286     FILE * fpr = NULL;
289     err= getrlimit(RLIMIT_STACK,&rl);
290     if (!err) Debug_printf(" stack limit = %d\n",rl.rlim_cur); else Debug_printf("getrlimit failed\n");
292      /* install signal handler for ^c */
293     signal(SIGINT,mysig);
295     fpr = fopen(input_file_name, "r");
296     if (fpr == NULL) 
297     {
298         Debug_printf("Error in opening %s input file\n", input_file_name);
299         exit(1);
300     }
301     else
302     {
303         memset(&config_file, 0, sizeof(netTestConfigFile_t));
304         memset(&netTestCfg, 0, sizeof(netTestConfig_t));
305         parse_config_file(fpr,&config_file);
306     }
308     memset(&sa_info, 0, sizeof(sa_info));
310 #ifdef MULTI_THREAD
311     /* assign main net_test thread to run on core 0 */
312     CPU_ZERO( &cpu_set);
313     CPU_SET( 0, &cpu_set);
314     hplib_utilSetupCore(0, &cpu_set);
315 #endif
316     /* create netapi */
317     netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);
319     netcp_cfgExceptions(netapi_handle, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_DISCARD, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
320     expPkt_appid = netcp_cfgExceptions(netapi_handle, 7, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
322     /* open the main heap */
323     ourHeap = Pktlib_findHeapByName("netapi");
324     if (!ourHeap)
325     {
326         Debug_printf("Pktlib_findHeapByName()  fail\n");
327         exit(1);
328     }
330     /* create two secondary heaps */
331     /* Initialize the heap configuration. */
332     memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));
334     pPktifTable = netapi_getPktlibIfTable();
335     /* Populate the heap configuration */
336     heapCfg.name                = "netapi-small";
337     heapCfg.memRegion           = NETAPI_GLOBAL_REGION;
338     heapCfg.sharedHeap          = 1;
339     heapCfg.useStarvationQueue  = 0;
340     heapCfg.dataBufferSize      = 512;
341     heapCfg.numPkts             = 64;
342     heapCfg.numZeroBufferPackets= 0;
343     heapCfg.heapInterfaceTable.data_malloc  = pPktifTable->data_malloc;
344     heapCfg.heapInterfaceTable.data_free    = pPktifTable->data_free;
345     heapCfg.dataBufferPktThreshold   = 0;
346     heapCfg.zeroBufferPktThreshold   = 0;
348     specialSmall = Pktlib_createHeap(&heapCfg, &errCode);
349     heapCfg.name                = "netapi-big";
350     heapCfg.dataBufferSize      = 1600;
351     specialLarge = Pktlib_createHeap(&heapCfg, &errCode);
352     //register these heaps so poll routine will include their garbage queues.
353     netapi_registerHeap(netapi_handle, specialSmall);
354     netapi_registerHeap(netapi_handle, specialLarge);
356     /* open netcp default tx, rx queues */
357     netcp_tx_chan= pktio_open(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg,  &err);
358     if (!netcp_tx_chan)
359     {
360         Debug_printf("pktio open TX failed err=%d\n",err);
361         exit(1);
362     }
363     netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg,  &err);
364     if (!netcp_rx_chan)
365     {
366         Debug_printf("pktio open RX failed err=%d\n",err);
367         exit(1);
368     }
370     Debug_printf("net_test> %d bytes left in our CMA area\n", netapi_getBufMemRemainder());
371     /* create scheduler instance */
372     our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);
373     if (!our_sched) {Debug_printf("sched create failed\n"); exit(1);}
376     /*create net_test MAC interfaces, attach IP to created MAC interfaces */
377      create_interfaces(&ip_rule0, &ip_rule1);
379     p_trie_sa_rx = trie_new();
380     p_trie_sa_tx = trie_new();
381    if (!p_trie_sa_rx || !p_trie_sa_tx)
382         {Debug_printf("trie alloc for SA  failed\n"); exit(1);}
384     /* Create RX SA's, RX Policy and TX SA's */
385     create_sec_associations(netcp_sb_rx_chan, netcp_sb_tx_chan,netcp_tx_chan);
388 #ifdef MULTI_THREAD
390     char c;
391     /* create and set affinity of slow path and fast path threads to
392     * specific CPU cores as specified in the net_test_config.txt file */
393     create_sp_fp_threads();
396         //this thread of execution (main) now just waits on user input
397         for(;;)
398         {
399            printf(">");
400            c=getchar();
401            if (c=='q') {QUIT=1;break;}
402            else if (c=='s') our_stats_cb(netapi_handle, &netcp_stats);
403            else if (c=='h') Debug_printf("'q' to quit,  's' for stats, 'h' for help\n");
404         }
407 #else
408     /*********************************************/
409     /**************Entry point into scheduler ****/
410     /*********************************************/
411     netapi_schedRun(our_sched, &err);
412 #endif
414 /* done */
415 our_stats_cb(netapi_handle, NULL);
419 /*************************************************
420  ************CLEAN UP****************************
421  ************************************************/
424     delete_sec_associations();
425     delete_interfaces( &ip_rule0, &ip_rule1);
427     //close pktio channels we opened
428     pktio_close(netcp_tx_chan ,&err);
429     pktio_close(netcp_rx_chan ,&err);
430     netapi_shutdown(netapi_handle);
433 static inline void send_it(Ti_Pkt *tip, int len, ROUTE_SEC_T * p_sec, int out_port)
435   unsigned long st1;
436   unsigned long st2;
437   int err=0;
438   PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
439   nwalTxPktInfo_t meta_tx2={0};
440   st1=hplib_mUtilGetPmuCCNT();
441 #ifdef MULTI_THREAD
442     int coreid=Osal_nwalGetProcId();  //who we are(thread local)
443     //int coreid = our_core;
444 #else
445     int coreid=0;
446 #endif
447   if (len<60) 
448   { 
449      unsigned int templen;
450      char * p_pkt;
451      len=60; 
452      Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
453      Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
454      stats[coreid].tx_min+=1;
455   }
456   Pktlib_setPacketLen(tip,len);
457   meta_tx2.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID );
458   meta_tx2.startOffset = 0;
459   meta_tx2.ipOffBytes = 14;
460   meta_tx2.ploadLen = len ;
461   meta_tx2.enetPort=out_port;
462   if(p_sec)
463   {   
464        meta_tx2.txFlag1 |= NWAL_TX_FLAG1_DO_IPSEC_ESP_CRYPTO ;
465        meta2.sa_handle=p_sec->tx_inflow_mode_handle; //this tells netapi that inflow crypto needs to be applied
466        meta_tx2.saOffBytes=14+20;
467        meta_tx2.saPayloadLen=len-14-20;   //don't include tag, mac and outer header
468        stats[coreid].sec_tx+=1;
469   }
470   meta2.u.tx_meta=&meta_tx2;
471   pktio_send(netcp_tx_chan,tip,&meta2,&err);
472   stats[coreid].tx +=1;
473   st2=hplib_mUtilGetPmuCCNT();
474   stats[coreid].send_cycles += (unsigned long long) (st2-st1);  
475
476 void recv_cb_router(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
477                          PKTIO_METADATA_T meta[], int n_pkts,
478                          uint64_t ts )
480     int i;
481     int len;
482     int p;
483     Ti_Pkt * tip;
484     unsigned int templen;
485     char * p_pkt;
486     HEAD_T temp_head;
487     unsigned int appid;
488     IP_HEAD_T th;
489     ROUTE_SEC_T *sec_data=NULL;
490     unsigned long t1;
491     unsigned long t2;
492     unsigned long long ct1;
493     unsigned long long ct2;
494     unsigned short ip_pl;
495     unsigned long long n_c_ops;
496     int ifno;
497     int out_port;
498 #ifdef MULTI_THREAD
499         int coreid=Osal_nwalGetProcId();  //who we are(thread local)
500         //int coreid = our_core;
501 #else
502     int coreid=0;
503 #endif
504     t1=hplib_mUtilGetPmuCCNT();
505     ct1 =Osal_cache_op_measure(&n_c_ops);
506     for(i=0;i<n_pkts;i++)
507     {
508         ifno = ((unsigned int)meta[i].u.rx_meta->appId)&0xff;
509         if(coreid<TUNE_NETAPI_NUM_CORES) stats[coreid].rx+=1;
510         if (ifno < TUNE_NETAPI_MAX_NUM_MAC) stats[coreid].if_rx[ifno]+=1;
511         tip = p_recv[i];
512         Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
513         len = Pktlib_getPacketLen(tip)-4;//real length, subtract mac trailer
514         stats[coreid].rx+=1;
515         appid = ((unsigned int)meta[i].u.rx_meta->appId)&0xff000000;
516         switch(appid)
517         {
518            case(NETAPI_NETCP_MATCH_IPSEC):
519            case(NETAPI_NETCP_MATCH_IPSEC_POLICY):
520            {
521              int tailen=12+2;
522              memcpy(&temp_head,&p_pkt[14],sizeof(HEAD_T));
523              if (!check_header(&temp_head,&meta[i])) {
524                 stats[coreid].n_bad+=1;
525                 Pktlib_freePacket(tip); 
526                 continue;
527              }
528              tailen+=p_pkt[len-12-2]; //padding length  (12)should come from sec_ptr
529              p_pkt = &p_pkt[8+16+20];   //16= iv len, should come from sec_ptr
530              len -= (8+16+20+tailen);  //16= iv len should come from sec ptr
531             
532              //now check inner headder.
533              memcpy(&th,&p_pkt[14],20);
534              if (!check_header(&temp_head,&meta[i])) {
535                 stats[coreid].n_bad+=1;
536                 Pktlib_freePacket(tip);
537                 continue;
538              }
539              Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
540              Pktlib_setPacketLen(tip,len);
541              
542              if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data,&out_port)<0)
543               {
544                 stats[coreid].n_bad+=1;
545                 Pktlib_freePacket(tip);
546              }
547              else
548              {
549                send_it(tip,len,sec_data,out_port);
550              }
551              break;
552            }
553            case(NETAPI_NETCP_MATCH_GENERIC_MAC):
554               if((p_pkt[12]!=0x8)||(p_pkt[13]!=0x00)) 
555               {
556                 stats[coreid].n_new+=1;
557                 Pktlib_freePacket(tip); 
558                 continue;
559               }
560               if (!check_header(&temp_head,&meta[i])) 
561               {
562                 stats[coreid].n_bad+=1;
563                 Pktlib_freePacket(tip);
564                 continue;
565               }
566               memcpy(&th,&p_pkt[14],20);
567               ip_pl= (((unsigned char *)&th.w1)[2]<<8) | ((unsigned char *)&th.w1)[3];
568               if ((ip_pl+14)<60)
569               {
570                 len-= (60-(ip_pl+14));
571                 stats[coreid].rx_min+=1;
572               }
573               Pktlib_setPacketLen(tip,len);
574               if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data,&out_port)<0)
575               {
576                 stats[coreid].n_bad+=1;
577                 Pktlib_freePacket(tip);
578               }
579               else
580               {
581                  send_it(tip,len,sec_data,out_port);
582               }
583               break;
584            case(NETAPI_NETCP_MATCH_GENERIC_IP):
585               Pktlib_freePacket(tip); 
586               stats[coreid].n_new=1;
587               break;
588            default:
589               stats[coreid].n_new+=1;
590               Pktlib_freePacket(tip);
591               break;
592        }
594 t2=hplib_mUtilGetPmuCCNT();
595 ct2 =Osal_cache_op_measure(&n_c_ops);
596 stats[coreid].app_cycles +=  (unsigned long long) (t2-t1);
597 stats[coreid].tx_cache_cycles += (unsigned long long) (ct2-ct1);
598 return;
601 /* STUB functions required for compilation */
602 void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
603                          PKTIO_METADATA_T meta[], int n_pkts,
604                          uint64_t ts )
608 void recv_sb_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
609                          PKTIO_METADATA_T meta[], int n_pkts,
610                          uint64_t ts )