SDOCM00113322: kernel RX UDP/TCP checksum offload to NETCP breaks user space tranport...
[keystone-rtos/netapi.git] / ti / runtime / netapi / test / nt_bridge.c
1 /******************************************
2  * File: nt_bridge.c   
3  * Purpose:  netcp bridge offload prototypes.
4  **************************************************************
5  * FILE:  nt_bench.c
6  * 
7  * DESCRIPTION:  netapi user space transport
8  *               library  test application : benchmarks
9  * 
10  * REVISION HISTORY:  rev 0.0.1 
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2013-2014
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>
50 #include <sched.h>
52 #include "trie.h"
53 #include "string.h"
54 #include "netapi.h"
55 #include "pktio.h"
56 #include <ti/drv/sa/salld.h>
57 #include "net_test_sa_utils.h"
58 #include "net_test_utils.h"
59 #include "net_test_thread_utils.h"
60 #include "fdb.h"
62 #if defined(DEVICE_K2H)
63 #include <ti/drv/qmss/device/k2h/src/qmss_device.c>
64 #include <ti/drv/cppi/device/k2h/src/cppi_device.c>
65 #elif defined (DEVICE_K2K)
66 #include <ti/drv/qmss/device/k2k/src/qmss_device.c>
67 #include <ti/drv/cppi/device/k2k/src/cppi_device.c>
68 #elif defined (DEVICE_K2L)
69 #include <ti/drv/qmss/device/k2l/src/qmss_device.c>
70 #include <ti/drv/cppi/device/k2l/src/cppi_device.c>
71 #elif defined (DEVICE_K2E)
72 #include <ti/drv/qmss/device/k2e/src/qmss_device.c>
73 #include <ti/drv/cppi/device/k2e/src/cppi_device.c>
74 #else /*Default */
75 #include <ti/drv/qmss/device/k2h/src/qmss_device.c>
76 #include <ti/drv/cppi/device/k2h/src/cppi_device.c>
77 #endif /* Device */
79 #define netapi_timing_start hplib_mUtilGetPmuCCNT
81 extern Rm_ServiceHandle   *rmClientServiceHandle;
83 static int scnt=0;
84 static int QUIT=0;
85 static int XMIT=0;
86 static int CAP=0;
87 volatile int RESET=0; //to reset stats
88 volatile int MAC=0;
89 volatile int FAST=1;
91 uint16_t num_learned_macs = 0;
93 uint16_t num_configured_interfaces = 0;
95 static ntBridgeCfgFile_T config_file[MAX_INTERFACES];
97 NETCP_CFG_ROUTE_T test_route[MAX_INTERFACES];
99 static ntBridgeAleCfgFile_T ale_config_file;
100 FDB_ENTRY_T                 ale_cfg[32];
103 //*********************for checksum test
104 unsigned short checksum(unsigned short *p, int len)
106     unsigned short s=0;
107     int i;
108     for(i=0;i<len/2;i++) s+=p[i];
109     if (len&0x1) s+=(p[len/2+1]<<8);
110     return s;
113 #define NCSUM 1600
114 unsigned long csum_val[NCSUM];
115 unsigned long csum_num[NCSUM];
116 unsigned long long csum_tim[NCSUM];
117 //***********************************************
119 #define CHECK_SET_PARAM(ARG1, ARG2)     \
120     do { \
121         if(strcmp(key, ARG1) == 0) { \
122         if(d1)strncpy(ARG2,d1,netTest_CONFIG_STRING_LEN); \
123         continue; \
124         } \
125     } while(0)
127 #define CHECK_SET_PARAM2(ARG1, ARG2,  ARG3)     \
128     do { \
129         if(strcmp(key, ARG1) == 0) { \
130         if(d1) strncpy(ARG2,d1,netTest_CONFIG_STRING_LEN); \
131         if(d2) strncpy(ARG3,d2,netTest_CONFIG_STRING_LEN); \
132         continue; \
133         } \
134     } while(0)
137 void parse_simple_param_u8(char* input_str, uint8_t *val)
139     if (strlen(input_str))
140     {
141         *val = (uint8_t)strtol(input_str, NULL, 0);
142     }
145 void parse_simple_param_u16(char* input_str, uint16_t *val)
147     if (strlen(input_str))
148     {
149         *val = (uint16_t)strtol(input_str, NULL, 0);
150     }
153 void parse_simple_param_u32(char* input_str, uint32_t *val)
155     if (strlen(input_str))
156     {
157         *val = (uint32_t)strtol(input_str, NULL, 0);
158     }
160 void parse_dscp_entry_default(char* input_str_queue,
161                               char* input_str_flow,
162                               paEQosModeConfig_t* pQosShapperCfg)
164     int i;
165     if (strlen(input_str_queue) && strlen(input_str_flow))
166     {
167         for(i=0;i<MAX_DSCP_ENTRIES;i++)
168         {
169                 pQosShapperCfg->dscpMap[i].flowOffset =(uint16_t)strtol(input_str_flow, NULL, 0);
170                 pQosShapperCfg->dscpMap[i].queueOffset = (uint16_t)strtol(input_str_queue, NULL, 0);
171         }
172     }
174 void parse_dscp_entry(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg)
176     int i;
178     for(i=0;i<MAX_DSCP_ENTRIES;i++)
179     {
180         if ((pConfig->dscpMapF[i][0]) && (pConfig->dscpMapQ[i][0]))
181         {
182             pQosShapperCfg->dscpMap[i].flowOffset =atoi(&pConfig->dscpMapF[i][0]);
183             pQosShapperCfg->dscpMap[i].queueOffset = atoi(&pConfig->dscpMapQ[i][0]);
184             printf("parse_dsp_entry[%d]: flowOffset: %d, queueOffset: %d\n",
185                 i,
186                 pQosShapperCfg->dscpMap[i].flowOffset,
187                 pQosShapperCfg->dscpMap[i].queueOffset);
188         }
189         else
190         {
191             pQosShapperCfg->dscpMap[i].flowOffset =0;
192             pQosShapperCfg->dscpMap[i].queueOffset = 0;
193         }
194     }
197 unsigned char ntUtilHex2Dec(char *p_s)
199     int val;
200     sscanf(p_s,"%x",&val); 
201     return val&0xff;
204 void parse_pbit_entry_default(char* input_str_queue,
205                               char* input_str_flow,
206                               paEQosModeConfig_t* pQosShapperCfg)
208     int i;
209     if (strlen(input_str_queue) && strlen(input_str_flow))
210     {
211         for(i=0;i<MAX_PBIT_ENTRIES;i++)
212         {
213                 pQosShapperCfg->pbitMap[i].flowOffset =(uint16_t)strtol(input_str_flow, NULL, 0);
214                 pQosShapperCfg->pbitMap[i].queueOffset = (uint16_t)strtol(input_str_queue, NULL, 0);
215         }
216     }
219 void parse_pbit_entry(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg)
221     int i;
223     for(i=0;i<MAX_PBIT_ENTRIES;i++)
224     {
225         if ((pConfig->pbitMapF[i][0]) && (pConfig->pbitMapQ[i][0]))
226         {
227             pQosShapperCfg->pbitMap[i].flowOffset =atoi(&pConfig->pbitMapF[i][0]);
228             pQosShapperCfg->pbitMap[i].queueOffset = atoi(&pConfig->pbitMapQ[i][0]);
229             printf("parse_pbit_entry[%d]: flowOffset: %d, queueOffset: %d\n",
230                     i,
231                     pQosShapperCfg->pbitMap[i].flowOffset,
232                     pQosShapperCfg->pbitMap[i].queueOffset);
233         }
234         else
235         {
236             pQosShapperCfg->pbitMap[i].flowOffset =0;
237             pQosShapperCfg->pbitMap[i].queueOffset = 0;
238         }
239     }
241 void parseOneMac(char * p_mac_str, uint8_t *p_mac)
243     int index = 0;
244     int i;
245     if (strlen(&p_mac_str[0]))
246     {
247         char *pch = strtok (&(p_mac_str[0]),":");
249         while (pch != NULL)
250         {
251             p_mac[index] = ntUtilHex2Dec(pch);
252             index++;
253             pch = strtok (NULL,":");
254         }
255         //printf("parseOneMac: 0x%x: 0x%x: 0x%x: 0x%x: 0x%x:0x%x\n",
256         //p_mac[0],p_mac[1],p_mac[2],p_mac[3],p_mac[4],p_mac[5]);
257     }
262 void parseMac(ntBridgeAleCfgFile_T *pConfig, FDB_ENTRY_T *pAleCfg)
264     int i;
265     int port = 0;
266     FDB_ENTRY_T *tmp = pAleCfg;
267     for(i=0;i<32;i++)
268     {
269         if (strlen(&pConfig->mac[i][0]))
270         {
271             parseOneMac((char*)&pConfig->mac[i][0], (uint8_t*)&tmp->mac_addr);
272             sscanf(&pConfig->switch_port[i][0],"swp%d",&tmp->switch_port);
273             tmp++;
274             num_learned_macs++;
275             /* check port to be 1 or 2 */
276             //printf("parseMac: port: %d\n", tmp->switch_port);
277         }
283 void parseMode(ntBridgeCfgFile_T *pConfig, paEQosModeConfig_t* pQosShapperCfg)
286     if (strlen(&pConfig->ctrlBitMap[0]))
287     {
288         printf("parseMode: mode: %s\n", &pConfig->ctrlBitMap[0]);
289         if (strcmp(pConfig->ctrlBitMap, "dscp") == 0)
290         {
291             pQosShapperCfg->ctrlBitMap = 0; pa_IF_EQoS_ROUTE_DP_BIT_MODE;
292             
293         }
294         else if (strcmp(pConfig->ctrlBitMap, "pbit") == 0)
295         {
296             pQosShapperCfg->ctrlBitMap = pa_IF_EQoS_ROUTE_DP_BIT_MODE;
297         }
298         else
299         {
300             netapi_Log("parseMode(), invalid QOS Mode in config file \n");
301         }
302     }
307 paEQosModeConfig_t netTestQosShapperCfg[MAX_INTERFACES];
310 /* Default Qos Shapper configuration for eth0 and eth1 */
311 paEQosModeConfig_t netTestQosShapperCfg1 = 
313     pa_IF_EQoS_ROUTE_DP_BIT_MODE,
314     {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7},
315     {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7},
316     1,
317     0,
318     0,
319     0,
320     0
321 };
322 paEQosModeConfig_t netTestQosShapperCfg2 = 
324     pa_IF_EQoS_ROUTE_DP_BIT_MODE,
325     {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7},
326     {0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7},
327     2,
328     0,
329     0,
330     0,
331     0
332 };
334 void ntBrideProcessCfgFile(FILE * fpr, ntBridgeCfgFile_T *pConfig)
336     char line[MAX_LINE_LENGTH + 1];
337     int i;
338     static int sa_count = 0;
339  
340     char *key, *ep;
341     char * d1, *d2, *d3;
342     char tokens[] = " :=;\n";
343     char temp_str[TEMP_STR_LEN];
344     memset(line, 0, MAX_LINE_LENGTH + 1);
345     //memset(pConfig, 0, sizeof(netTestConfigFile_t));
346     while (fgets(line, MAX_LINE_LENGTH + 1, fpr))
347     {
348         if(line[0]=='#')
349             continue; //skip comment
350         key  = (char *)strtok(line, tokens);
352         d1 = (char *)strtok(NULL, tokens);
353         if (!key)
354             continue;
355         if (!d1) 
356             continue;
358         if(strlen(d1) == 0) 
359         {
360             continue;
361         }
363         d2 = (char *)strtok(NULL, tokens);
365         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_FLOW_BASE,&(pConfig->flowBase[0]));
367         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_QUEUE_BASE,&(pConfig->queueBase[0]));
369         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_VLAN_ID,&(pConfig->vlanId[0]));
371         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_PORT,&(pConfig->port[0]));
372         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_INGRESS_DEF_PRI,&(pConfig->ingressDefPri[0]));
374         CHECK_SET_PARAM(ntBridge_INIT_CONFIG_QOS_MODE,&(pConfig->ctrlBitMap[0]));
375         CHECK_SET_PARAM2(ntBridge_INIT_CONFIG_DSCP_MAP_DEFAULT,&pConfig->dscpMapFDefault[0],&pConfig->dscpMapQDefault[0]);
376         CHECK_SET_PARAM2(ntBridge_INIT_CONFIG_PBIT_MAP_DEFAULT,&pConfig->pbitMapFDefault[0],&pConfig->pbitMapQDefault[0]);
379         for(i=0;i<MAX_DSCP_ENTRIES;i++)
380         {
381             snprintf(temp_str,TEMP_STR_LEN-1,"dscp_map_%d",i);
383             CHECK_SET_PARAM2(temp_str,&pConfig->dscpMapF[i][0],&pConfig->dscpMapQ[i][0]);
384         }
386         for(i=0;i< MAX_PBIT_ENTRIES;i++)
387         {
388             snprintf(temp_str,TEMP_STR_LEN-1,"pbit_map_%d",i);
389             CHECK_SET_PARAM2(temp_str,&pConfig->pbitMapF[i][0],&pConfig->pbitMapQ[i][0]);
390         }
391     }
393 void ntBrideProcessAleCfgFile(FILE * fpr, ntBridgeAleCfgFile_T *pConfig)
395     char line[MAX_LINE_LENGTH + 1];
396     int i;
397     static int sa_count = 0;
398  
399     char *key, *ep;
400     char * d1, *d2, *d3;
401     char tokens[] = " =;\n";
402     char temp_str[TEMP_STR_LEN];
403     memset(line, 0, MAX_LINE_LENGTH + 1);
404     //memset(pConfig, 0, sizeof(netTestConfigFile_t));
405     while (fgets(line, MAX_LINE_LENGTH + 1, fpr))
406     {
407         if(line[0]=='#')
408             continue; //skip comment
409         key  = (char *)strtok(line, tokens);
411         d1 = (char *)strtok(NULL, tokens);
412         if (!key)
413             continue;
414         if (!d1) 
415             continue;
417         if(strlen(d1) == 0) 
418         {
419             continue;
420         }
422         d2 = (char *)strtok(NULL, tokens);
424         
425         for(i=0;i< 32;i++)
426         {
427             snprintf(temp_str,TEMP_STR_LEN-1,"mac%d",i);
428             CHECK_SET_PARAM2(temp_str,&pConfig->mac[i][0],&pConfig->switch_port[i][0]);
429         }
430     }
433 //sig handler
434 void netTest_utilMySig(int x)
436     QUIT=1;
437     scnt+=1;
438     printf(">ifdma-test: recv'd signal %d cnt=%d\n",x,scnt);
439     if (scnt > 10) {printf(">ifdma-test: WARNING EXITING WITH PROPER SHUTDOWN, LUTS LEFT ACTIVE\n");exit(1);}
441 void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
442                          PKTIO_METADATA_T meta[], int n_pkts,
443                          uint64_t ts );
446 /*************debug********************/
447 void netTest_utilDumpDescr(unsigned long *p, int n)
449     printf("--------dump of descriptor %d %x\n", n, (int) p);
450     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]);
451     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]);
452     printf("-----------------------------\n");
454 void netTest_utilDumpHeader(unsigned long *p, int n, int a, int r)
456     printf("--------dump of header %d %x appID=%x flag1=%x\n", n, (int) p,a,r);
457     printf("> %0x %0x %0x %0x %0x %0x %0x %0x\n",
458           ntohl(p[0]),ntohl(p[1]),ntohl(p[2]),ntohl(p[3]),
459           ntohl(p[4]),ntohl(p[5]),ntohl(p[6]),ntohl(p[7]) );
461     printf("-----------------------------\n");
463 /*****************************************/
466 unsigned long long CALIB=0;
467 unsigned long long calibrate_idle(void)
469     volatile unsigned long long  at1;
470     volatile unsigned long long  at2;
471     volatile unsigned long pt1;
472     volatile unsigned long pt2;
473     unsigned long long calib;
474     at1 = hplib_mUtilGetTimestamp();
475     pt1=netapi_timing_start();
476     for(;;)
477     {
478        pt2=netapi_timing_start()   ;
479        if ((pt2-pt1) >= 100000) break;
480     }
481     at2 = hplib_mUtilGetTimestamp();
482     
483     calib = ((unsigned long long) (pt2-pt1))/(at2-at1);
484     printf("calibrate:   arm time=%lld  -> arm cycles=%d calib=%lld\n", at2-at1, pt2-pt1, calib);
485     
486     return calib;
489 /*******************************************
490  *************NETAPI OBJECTS***************
491  *****************************************/
492 static NETAPI_CFG_T our_netapi_default_cfg=
494 TUNE_NETAPI_PERM_MEM_SZ,
495 128,  //start of packet offset for hw to place data on rx for default flow
496 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
497 TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
498 TUNE_NETAPI_DEFAULT_NUM_BUFFERS*2,   //#descriptors+buffers in default heap
499 64, //#descriptors w/o buffers in default heap
500 TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap
501 128,       //tail room
502 256,      //extra room,
503 0,
504 NULL,
505 18,
506 0x2000
507 };
509 Pktlib_HeapHandle OurHeap;     //default heap, used by producer
510 PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};
511 PKTIO_CFG_T netcp_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 12};
512 PKTIO_HANDLE_T * netcp_rx_chan;
513 PKTIO_HANDLE_T * netcp_tx_chan;
514 NETAPI_T netapi_handle;
516 PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};
517 PKTIO_CONTROL_T poll_cannel_control={PKTIO_SET_POLL_FLAGS, NULL, nwal_POLL_DEFAULT_GLOB_PKT_Q};
519 //template for fast path
520 nwalTxPktInfo_t txPktInfoNoCrypto =
522     NULL,                                                       /* p_pkt */
523     NWAL_TX_FLAG1_META_DATA_VALID,                              /* txFlags */
524     0,                                                          /* lpbackPass */
525     0,                                                          /* enetport */
526     0,                                                          /* msuSize */
527     0,                                                          /* startOffset */
528     0,                                                          /* saOffBytes */
529     0,                                                          /* saPayLoadLen */
530     0,                                                          /* saAhIcvOffBytes */
531     0,                                                          /* saAhMacSize */
532     0,                                                          /* etherLenOffBytes */
533     netTest_MAC_HEADER_LEN,                                     /* ipOffBytes */
534     netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN,              /* l4OffBytes */
535     netTest_UDP_HEADER_LEN,                                     /* l4HdrLen */
536     0,                                                          /* pseudoHdrChecksum */
537     0                                                           /* pLoadLen */
538 };
542 NETCP_CFG_ROUTE_T  test_route1 =
544 0,
545 NULL,
546 NULL,
547 0,
548 1,
549 0,
551 };
552 NETCP_CFG_ROUTE_T  test_route2 =
554 0,
555 NULL,
556 NULL,
557 0,
558 2,
559 0,
561 };
564 //#define WITH_QOS
565 #ifdef WITH_QOS  //send to qos input queue, set in device tree (6409)
566 //#define QOSQ 6410   /* for wrr */
567 #define QOSQ 6409  /* for SP */
568 PKTIO_CFG_T direct_to_cpsw_cfg={PKTIO_TX, PKTIO_GLOBAL, QOSQ, 8};
569 #else  //send direct to 648, the CPSW input queue
570 PKTIO_CFG_T direct_to_cpsw_cfg={PKTIO_TX, PKTIO_GLOBAL, 648, 8};
571 #endif
573 PKTIO_HANDLE_T * cpsw_tx_chan[MAX_INTERFACES];
575 //NETCP_CFG_FLOW_T flow;
578 /*************************END NETAPI OBJECTS***********************/
580 static unsigned char all_mac[]={0,0,0,0,0,0};
581 static unsigned char test_mac0[]={0,0,0,0,0,0xf};
582 static unsigned char test_mac1[]={0,0,0,0,0,0xff};
583 static unsigned char test_mac2[]={0xd4,0xbe,0xd9,0,0xd3,0x7e};
584 static unsigned char test_mac3[]={0,0x15,0x60,0xa1,0xf7,0xbe};
585 static unsigned char test_mac4[]={0xff,0xff,0xff,0x00,0x00,0x00};
586 //static unsigned char test_mac0[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e};
587 int test_port0 = 1;
588 //static unsigned char test_mac1[]={0x00,0x15,0x60,0xa1,0xf7,0xbe};
589 int test_port1 = 2;
591 static unsigned long last_header[32/sizeof(unsigned long)];
594 //stats
595 int pkt_rx=0; 
596 int pkt_tx=0; 
597 unsigned long long pkt_rx_cycles=0L;
598 unsigned long long pkt_tx_cycles=0L;
599 unsigned long long pkt_cb_cycles=0L;
600 unsigned long long idle_cycles=0L;
601 volatile unsigned long long start_time;
602 unsigned long long end_time;
604 paSysStats_t netcp_stats;
608 void netTest_utilStatsCbMt(NETAPI_T h, paSysStats_t* pPaStats)
610     if(pPaStats)
611     {
612         memcpy(&netcp_stats,pPaStats, sizeof(paSysStats_t));
613     }
615 void netTest_utilsStatsCb(NETAPI_T h, paSysStats_t* pPaStats)
617     if(pPaStats)
618     {
619        printf("C1 number of packets:           %d\n", pPaStats->classify1.nPackets);
620        printf("C1 number IPv4 packets:         %d\n", pPaStats->classify1.nIpv4Packets);
621        printf("C1 number IPv6 packets:        %d\n", pPaStats->classify1.nIpv6Packets);
622        printf("C1 number Custom packets:        %d\n", pPaStats->classify1.nCustomPackets);
623        printf("C1 number SRIO packets:        %d\n", pPaStats->classify1.nSrioPackets);
624        printf("C1 number LLC/SNAP Fail packets:        %d\n", pPaStats->classify1.nLlcSnapFail);
625        printf("C1 number table matched:        %d\n", pPaStats->classify1.nTableMatch);
626        printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);
627        printf("C1 number IP Fragmented packets: %d\n", pPaStats->classify1.nIpFrag);
628        printf("C1 number IP Depth Overflow: %d\n", pPaStats->classify1.nIpDepthOverflow);
629        printf("C1 number VLAN Depth Overflow: %d\n", pPaStats->classify1.nVlanDepthOverflow);
630        printf("C1 number GRE Depth Overflow: %d\n", pPaStats->classify1.nGreDepthOverflow);
631        printf("C1 number MPLS Packets: %d\n", pPaStats->classify1.nMplsPackets);
632        printf ("C1 number of parse fail:        %d\n",pPaStats->classify1.nParseFail);
633        printf("C1 number of Invalid IPv6 Opt:  %d\n", pPaStats->classify1.nInvalidIPv6Opt);
634        printf("C1 number of TX IP Fragments:  %d\n", pPaStats->classify1.nTxIpFrag);
635        printf ("C1 number of silent discard:    %d\n",pPaStats->classify1.nSilentDiscard);
636        printf("C1 number of invalid control:   %d\n", pPaStats->classify1.nInvalidControl);
637        printf ("C1 number of invalid states:    %d\n",pPaStats->classify1.nInvalidState);
638        printf ("C1 number of system fails:      %d\n",pPaStats->classify1.nSystemFail);
639        printf ("C2 number Packets  :           %d\n",pPaStats->classify2.nPackets);
640        printf ("C2 number udp           :      %d\n",pPaStats->classify2.nUdp);
641        printf ("C2 number tcp           :      %d\n",pPaStats->classify2.nTcp);
642        printf ("C2 number Custom       :      %d\n",pPaStats->classify2.nCustom);
643        printf ("C2 number silent drop   :      %d\n",pPaStats->classify2.nSilentDiscard);
644        printf ("C2 number invalid cntrl :      %d\n\n",pPaStats->classify2.nInvalidControl);
645        printf ("C2 number Modify Stats Cmd Fail :      %d\n\n",pPaStats->modify.nCommandFail);
646     }
650 //**********************************
651 //producer thread
652 //*********************************
653 void producer_thread(int coreid)
655 int err;
656 int i;
657 Ti_Pkt * tip;
658 unsigned char * pData;
659 int len;
660 PKTIO_METADATA_T meta = {PKTIO_META_IFDMA_TX,{0},0};
661 int np;
662 cpu_set_t cpu_set;
663 unsigned long t1;
664 unsigned long t2;
666     CPU_ZERO( &cpu_set);
667     CPU_SET( coreid, &cpu_set);
668     hplib_utilSetupThread(coreid,
669                           &cpu_set,
670                           hplib_spinLock_Type_LOL);
671     start_time = hplib_mUtilGetTimestamp();
673     /* Poll the default pktio channel for pkts from network */
674     for(i=0;!((volatile int) QUIT);i++)
675     {
676         if (FAST)
677         {
678             //netapi_netcpCfgReqStats(netapi_handle, netTest_utilStatsCbMt, 0,&err); 
679             sleep(2);
680             continue;
681         }
682         t1 = netapi_timing_start();
683         np = netapi_pktioPoll(netcp_rx_chan,NULL,&err);
684         t2 = netapi_timing_start();
685         pkt_rx+=np;
686         if (np) 
687         {
688             pkt_rx_cycles += (t2-t1);
689         }
690         else
691         {
692             idle_cycles += (t2-t1);
693         }
694         if (RESET)
695         {
696             idle_cycles=0LL;
697             start_time = hplib_mUtilGetTimestamp();
698             pkt_rx=pkt_tx=0;
699             pkt_rx_cycles=pkt_tx_cycles=0LL;
700             pkt_cb_cycles=0LL;
701             RESET=0;
702         }
703     }
704     end_time = hplib_mUtilGetTimestamp();
705     printf("nt-bench: receiver  DONE %d pkts rx,  pkt poll cycles=% u; pkt rx cycle=%u pkt tx cycles=%u idle cycles=%lld duration=%lld ticks idle pct= %lld\n",
706             pkt_rx,
707             (unsigned)(pkt_rx ?  (pkt_rx_cycles - pkt_cb_cycles)/pkt_rx : 0),
708             (unsigned)  (pkt_rx ?  (pkt_rx_cycles) /pkt_rx : 0),
709             (unsigned)  (pkt_tx ?  (pkt_tx_cycles) /pkt_tx : 0),
710             idle_cycles, (end_time-start_time), 
711             (idle_cycles*100) /( CALIB* (end_time-start_time))
712      );
713      printf("Leaving producer_thread\n");
717 void nt_setupQosShapper(NETAPI_T h, paEQosModeConfig_t *pqosCfg)
719     int i;
720     paEmacPortConfig_t ctrl;
721     nwalLocCxtInfo_t info;
722     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
723     
724     memset(&info, 0, sizeof(nwalLocCxtInfo_t));
726     memset(&ctrl, 0, sizeof(paEmacPortConfig_t));
728     ctrl.cfgType = pa_EMAC_PORT_CFG_EQoS_MODE;
729     ctrl.numEntries = 1;
731     ctrl.u.eQoSModeCfg = pqosCfg;
733     if(pqosCfg->flowBase)
734     {
735         printf("nt_setupQosShapper: flowBase from config file: %d\n", pqosCfg->flowBase);
736         ctrl.u.eQoSModeCfg->flowBase = pqosCfg->flowBase;
737     }
738     else
739     {
740         nwal_getLocCxtInfo(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &info);
741         printf("nt_setupQosShapper: flowBase from nwal: %d\n", info.rxPktFlowId);
742         ctrl.u.eQoSModeCfg->flowBase = info.rxPktFlowId;
743     }
744     nwal_emacPortCfg(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &ctrl);
749 //******************************
750 //  main program
751 //*****************************
752 int main(int argc, char **argv)
754     int err,i;
755     int32_t             errCode;
756     Pktlib_HeapIfTable*  pPktifTable;
757     Pktlib_HeapCfg heapCfg;
758     long t1, t2 ;
759     cpu_set_t cpu_set;
760     FILE* fpr[MAX_INTERFACES];
762      //install signal handler for ^c
763     signal(SIGINT,netTest_utilMySig);
765      for(i=0; i < MAX_INTERFACES; i++)
766      {
767          fpr[i] = NULL;
768      }
770     memset(&config_file[0], 0, sizeof(ntBridgeCfgFile_T)*MAX_INTERFACES);
771     memset(&netTestQosShapperCfg[0], 0, sizeof(paEQosModeConfig_t)*MAX_INTERFACES);
772     memset(&ale_cfg, 0, sizeof(ntBridgeAleCfg_T));
773     memset(&ale_cfg, 0, sizeof(FDB_ENTRY_T)*32);
775     /* USE defautl Qos Shapper Configuration for 2 ports unless config files provided */
776     memcpy(&netTestQosShapperCfg[0], &netTestQosShapperCfg1, sizeof(paEQosModeConfig_t));
777     memcpy(&netTestQosShapperCfg[1], &netTestQosShapperCfg2, sizeof(paEQosModeConfig_t));
779     if (argc == 2)
780     {
781         fpr[0] = fopen(argv[1], "r");
782         num_configured_interfaces = 1;
783     }
784     else if (argc == 3)
785     {
786         fpr[0] = fopen(argv[1], "r");
787         fpr[1] = fopen(argv[2], "r");
788         num_configured_interfaces = 2;
789         
790     }
791     else
792     {
793         printf("No qos shapper input files, using default settings\n");
794         num_configured_interfaces = 2;
795     }
797     for (i=0;i< num_configured_interfaces;i++)
798     {
799         if (fpr[i])
800         {
801             ntBrideProcessCfgFile(fpr[i], &config_file[i]);
803             parse_dscp_entry_default((char*)&config_file[i].dscpMapQDefault,
804                                      (char*)&config_file[i].dscpMapFDefault,
805                                      &netTestQosShapperCfg[i]);
806             parse_pbit_entry_default((char*)&config_file[i].pbitMapQDefault,
807                                      (char*)&config_file[i].pbitMapFDefault,
808                                      &netTestQosShapperCfg[i]);
809             
810             parse_simple_param_u16((char*)&config_file[i].queueBase, &netTestQosShapperCfg[i].queueBase);
811              printf("main: netTestQos Cfg: queueBase: %d\n",netTestQosShapperCfg[i].queueBase);
813             parse_simple_param_u8((char*)&config_file[i].flowBase, &netTestQosShapperCfg[i].flowBase);
814             printf("main: netTestQos Cfg: flowBase: %d\n",netTestQosShapperCfg[i].flowBase);
816             parse_simple_param_u16((char*)&config_file[i].vlanId, &netTestQosShapperCfg[i].vlanId);
817             printf("main: netTestQos Cfg: vlanId: %d\n",netTestQosShapperCfg[i].vlanId);
819             parse_simple_param_u8((char*)&config_file[i].port, &netTestQosShapperCfg[i].port);
820             printf("main: netTestQos Cfg: port: %d\n",netTestQosShapperCfg[i].port);
822             parse_simple_param_u8((char*)&config_file[i].ingressDefPri, &netTestQosShapperCfg[i].ingressDefPri);
823             printf("main: netTestQos Cfg: ingressDefPri: %d\n",netTestQosShapperCfg[i].ingressDefPri);
825             parse_dscp_entry(&config_file[i], &netTestQosShapperCfg[i]);
826             parse_pbit_entry(&config_file[i], &netTestQosShapperCfg[i]);
827             parseMode(&config_file[i], &netTestQosShapperCfg[i]);
829         }
830     }
832 #if 0
833     if (initRm())
834     {
835         printf("main: initRm() returned error\n");
836         exit(1);
837     }
838 #endif
839     CPU_ZERO( &cpu_set);
840     CPU_SET( 0, &cpu_set);
841     hplib_utilSetupThread(0,
842                           &cpu_set,
843                           hplib_spinLock_Type_LOL);
846     /*******************************************/
847     /*************NETAPI STARTUP****************/
848     /*******************************************/
850     /* create netapi */
851     our_netapi_default_cfg.rmHandle = rmClientServiceHandle;
852     netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);
853     if (netapi_handle == NULL)
854     {
855         printf("main: netapi_init failure, exiting\n");
856         exit(1);
857     }
858     
860     /* open the main heap */
861     OurHeap = Pktlib_findHeapByName("netapi");
862     if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}
864     for(i = 0; i < MAX_INTERFACES; i++)
865     {
866         char temp_str[PKTIO_MAX_NAME] = {0};
867         direct_to_cpsw_cfg.qnum = netTestQosShapperCfg[i].queueBase;
868         snprintf(temp_str, PKTIO_MAX_NAME, "cpsw_tx%d",i);
869         cpsw_tx_chan[i]= netapi_pktioCreate(netapi_handle,&temp_str[0],NULL,
870                                      &direct_to_cpsw_cfg, &err); 
871         if (!cpsw_tx_chan[i])
872         {
873             printf("pktio open %s failed err=%d\n", &temp_str[0], err);
874             exit(1);
875         }
876     }
878 #if 0
879     direct_to_cpsw_cfg.qnum = netTestQosShapperCfg2.queueBase;
880     
881     cpsw_tx_chan2= netapi_pktioCreate(netapi_handle,"cpsw_tx2",NULL,
882                                      &direct_to_cpsw_cfg, &err); 
883     if (!cpsw_tx_chan2){printf("pktio open CPSW TX2 failed err=%d\n",err); exit(1);}
884 #endif
887     //if we want to relay network packets, we create a handle to the 
888     //default netcp receive queue here
889     netcp_rx_chan= netapi_pktioOpen(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_net, &netcp_rx_cfg,  &err);
890     if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}
892     netcp_tx_chan= netapi_pktioOpen(netapi_handle, NETCP_TX, (PKTIO_CB) NULL, &netcp_tx_cfg,  &err);
893     if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);}
894     else  //install a fast path template into the NETCP TX channel
895     {
896             PKTIO_CONTROL_T control2;
897             control2.op = PKTIO_UPDATE_FAST_PATH;
898             PKTIO_CFG_T cfg2;
899             cfg2.fast_path_cfg.fp_send_option = PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT;
900             cfg2.fast_path_cfg.txPktInfo= &txPktInfoNoCrypto;
901             netapi_pktioControl(netcp_tx_chan, NULL, &cfg2, &control2, &err);
902     }
904     //build route for cpsw
905     NETCP_CFG_FLOW_T flow;
906     flow.dma_engine = 1;
907     for (i = 0; i < MAX_INTERFACES;i++)
908     {
909         if(netTestQosShapperCfg[i].flowBase)
910         {
911             flow.dma_engine = 1;
912             flow.flowid = netTestQosShapperCfg[i].flowBase;
913             test_route[i].p_flow = &flow;
914         }
915         else
916         {
917             test_route[i].p_flow =NETCP_DEFAULT_FLOW;
918         }
919         test_route[i].egress_swith_port = netTestQosShapperCfg[i].port;
920         test_route[i].routeType = NWAL_ROUTE_PKTTYPE_EQOS;
921         test_route[i].valid_params = NETCP_CFG_VALID_PARAM_ROUTE_TYPE;
922         test_route[i].p_dest_q = cpsw_tx_chan[i];
923     }
925 /*********************************************/
926 /*****************end NETAPI STARTUP**********/
927 /*********************************************/
931     //calibrate idle
932     CALIB = calibrate_idle();
933     ntoff_start();
934     ntoff_add_do_perm(&test_mac0[0],test_port0);
935     ntoff_add_do_perm(&test_mac1[0],test_port1);
936     //ntoff_add_do_perm(&test_mac2[0],test_port0);
937     //ntoff_add_do_perm(&test_mac3[0],test_port1);
938     //ntoff_add_do_perm(&test_mac4[0],test_port0);
940 //**************************************
941 //Create a worked thread
942 //***************************************
943     {
944         pthread_t *thrs;
945         int procs =1; 
946         int c;
947         thrs = malloc( sizeof( pthread_t ) * procs );
948         if (thrs == NULL)
949         {
950                 perror( "malloc" );
951                 return -1;
952         }
953         printf( "net_test_bridge: Starting %d threads...\n", procs );
955         if (pthread_create( &thrs[0], NULL, (void*)producer_thread,
956                         (void *)1 ))
957         {
958                         perror( "pthread_create" );
959                         exit(1);
960         }
961         //this thread of execution (main) now just waits on user input
962         for(;;)
963         {
964             printf(">");
965             c=getchar();
966             if (c=='c') {CAP=!CAP; printf("CAPTURE= %d\n", CAP); }
967             else if (c=='t') {XMIT=!XMIT; printf("XMIT= %d\n", XMIT); }
968             else if (c=='l')
969             {
970                 FILE* fprAle = NULL;
971                 system("/etc/transportnetlib/test/parse_ale.sh");
972                 fprAle = fopen("ale_table.txt","r");
973                 if (fprAle)
974                 {
975                     ntBrideProcessAleCfgFile(fprAle, &ale_config_file);
976                     //for(i=0;i<32;i++)
977                         parseMac(&ale_config_file, &ale_cfg[0]);
978                      for(i=0;i<num_learned_macs;i++)
979                      {
980                         printf("parseOneMac[%d]: 0x%x: 0x%x: 0x%x: 0x%x: 0x%x:0x%x, switch port: %d\n",
981                         i,
982                         ale_cfg[i].mac_addr[0],
983                         ale_cfg[i].mac_addr[1],
984                         ale_cfg[i].mac_addr[2],
985                         ale_cfg[i].mac_addr[3],
986                         ale_cfg[i].mac_addr[4],
987                         ale_cfg[i].mac_addr[5],
988                         ale_cfg[i].switch_port);
989                      }
990                      ntoff_learn();
991                      ntoff_show();
992                 }
993             }
994             else if (c=='m') 
995             {
996                 unsigned add1 = netapi_timing_start();
997                 if (!MAC)
998                 {
999                     //add macs
1000                     ntoff_add_macs(netapi_handle,
1001                                    FAST? &test_route1: NULL,
1002                                    FAST );
1004                     add1 = netapi_timing_start()-add1;
1005                     printf("adding  MACs cycles=%d err=%x\n", add1,err);
1006                     MAC=1;
1007                 }
1009                 else
1010                     printf("MAC already offloaded\n");
1011             }
1012     
1013             else if (c=='!') system("sh");
1014             else if (c=='n')
1015             {
1016                 unsigned add2 = netapi_timing_start();
1017                 if (MAC)
1018                 {
1019                     ntoff_del_macs(netapi_handle);
1021                     add2 = netapi_timing_start()-add2;
1022                     printf("removing MAC cycles=%d\n",add2);
1023                     MAC=0;
1024                 } else printf("no mac offloaded\n");
1025            }
1026            else if (c=='f') 
1027            {
1028               FAST=!FAST; printf("bridge offload = %s\n", FAST ? "netcp" : "user space");
1029               if (!FAST) XMIT=1;
1030            }
1031            else if (c=='j')
1032             {
1033                 netapi_netcpCfgReqStats(netapi_handle, netTest_utilStatsCbMt, 0,&err);
1034                 sleep(1);
1035                 netapi_netcpPoll(netapi_handle);
1036                 netTest_utilsStatsCb(netapi_handle, &netcp_stats);
1037                 
1038             }
1039            else if (c=='s') 
1040            {
1041               unsigned long long et= hplib_mUtilGetTimestamp();
1042               printf(">NT_BENCH STATS:    %d received   %d xmitted,   %lld idle cycles,  %lld duration ticks  idle=%lld\n",
1043                        pkt_rx,pkt_tx,
1044                        idle_cycles,
1045                        (et-start_time),
1046                        (idle_cycles*100)/(CALIB*(et-start_time))
1047                     );
1048               Pktlib_HeapStats    pktLibHeapStats;
1049               Pktlib_getHeapStats(OurHeap, &pktLibHeapStats);
1050               printf("main  heap stats>  #free=%d #zb=%d #garbage=%d\n",
1051                                 pktLibHeapStats.numFreeDataPackets,
1052                                 pktLibHeapStats.numZeroBufferPackets,
1053                                 pktLibHeapStats.numPacketsinGarbage);
1054            }
1055            else if (c=='S')
1056            {
1057                 system("/usr/bin/dumpqos.sh");
1058            }
1059            else if (c=='r')
1060            {
1061               RESET=1;
1062            }
1063            else if (c=='h')
1064            {
1065                 printf("> 'q' to quit,           's' for Heap stats,  'S' for QOS stats \n");
1066                 printf("  'c' to toggle capture, 'd' to dump capture, 'r' to reset idle counters\n");
1067                 printf("  'm' to add macs,       'n' to remove macs   'l' to learn macs\n");
1068                 printf("  'f' toggle s/w or netcp offload, '!' shell, 'S' Chksum Stats,  'h' for help\n");
1069            }
1070            else if (c=='d')
1071            {
1072               netTest_utilDumpHeader(&last_header[0], 0,0,0);
1073            }
1074            else if (c == 'z')
1075             {
1076                 nwalCtlInfo_t nwalCtrl;
1077                 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle;
1078                 memset(&nwalCtrl, 0, sizeof(nwalCtlInfo_t));
1079                 nwalCtrl.pktCtl= NWAL_CTRL_CFG_EMAC_IF_EGRESS_EQOS_MODE;
1080                 nwalCtrl.matchAction =  NWAL_MATCH_ACTION_HOST;
1081                 nwalCtrl.appRxPktFlowId = NWAL_FLOW_NOT_SPECIFIED;
1082                 nwalCtrl.appRxPktQueue = NWAL_QUEUE_NOT_SPECIFIED;
1084                 for (i=0; i < MAX_INTERFACES;i++)
1085                 {
1086                     nt_setupQosShapper(netapi_handle,(paEQosModeConfig_t*)&netTestQosShapperCfg[i]);
1087                 }
1088                 nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &nwalCtrl);
1089             }
1090             else if (c=='q')
1091             {
1092                 nwalCtlInfo_t nwalCtrl;
1093                 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle;
1094                 memset(&nwalCtrl, 0, sizeof(nwalCtlInfo_t));
1095                 nwalCtrl.pktCtl = NWAL_CTRL_CFG_EMAC_IF_EGRESS_EQOS_MODE;
1096                 nwalCtrl.matchAction = NWAL_MATCH_ACTION_DISCARD;
1097                 nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &nwalCtrl);
1099                 QUIT=1;
1100                 break;
1101             }
1102         }
1104         //wait for completion 
1105         printf("main task now pending on thread completion\n");
1106         for (i = 0; i < procs; i++)
1107                 pthread_join( thrs[i], NULL );
1109         free( thrs);
1110     }
1112     /*************************************************
1113      ************CLEAN UP****************************
1114      ************************************************/
1115     //get rid of rule, in the case that we are relaying packets
1116     //also close our netcp rx channel
1117     if (MAC) 
1118     {
1119         ntoff_del_macs(netapi_handle);
1120 #if 0
1121        netapi_netcpCfgDelMac(netapi_handle,0,&err);
1122        netapi_netcpCfgDelMac(netapi_handle,1,&err);
1123 #endif
1124     }
1125     ntoff_stop();
1126     netapi_pktioClose(netcp_rx_chan,&err);
1127     netapi_pktioClose(netcp_tx_chan,&err);
1128     for(i=0;i < MAX_INTERFACES; i++)
1129     {
1130         netapi_pktioDelete(cpsw_tx_chan[i],&err);
1131     }
1134     //done
1135     netapi_shutdown(netapi_handle);
1136     //!finished!
1138 static inline void sendit(Ti_Pkt *tip, int len, int out_port)
1140       int err=0;
1141       PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
1142       nwalTxPktInfo_t meta_tx2={0};
1143       if (len<60)
1144       {
1145          unsigned int templen;
1146          char * p_pkt;
1147          len=60;
1148          Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
1149          Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
1150       }
1151       Pktlib_setPacketLen(tip,len);
1152       meta_tx2.txFlag1 = NWAL_TX_FLAG1_META_DATA_VALID ; 
1153       meta_tx2.ploadLen = len ;
1154       meta_tx2.enetPort=out_port;
1155       meta2.u.tx_meta=&meta_tx2;
1156       netapi_pktioSend(netcp_tx_chan,tip,&meta2,&err);
1159 //receive callback for packets from net (for consumer)
1160 void recv_cb_net(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
1161                          PKTIO_METADATA_T meta[], int n_pkts,
1162                          uint64_t ts )
1164     int i;
1165     Ti_Pkt * tip;
1166     int len;
1167     unsigned long t1;
1168     unsigned long t2;
1169     unsigned long t3;
1170     unsigned long t4;
1171     pasahoLongInfo_t* protoInfo; 
1172     int ifno;
1173     int out_port;
1175     t1= netapi_timing_start();
1176     for(i=0;i<n_pkts;i++)
1177     {
1178         tip = p_recv[i];
1179         len = Pktlib_getPacketLen(tip);
1181         if (CAP)
1182         {
1183            unsigned int templen;
1184            char * p_pkt;
1185            unsigned long val;
1186            unsigned long cs1;
1187            unsigned long cs2;
1188            Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
1189            memcpy(last_header,p_pkt,32);
1190            cs1= netapi_timing_start();
1191            val= (unsigned long) checksum((unsigned short *)p_pkt,len);
1192            cs2= netapi_timing_start();
1193            templen = (len >= NCSUM)? NCSUM-1: len;
1194            csum_num[templen]+=1;
1195            csum_val[templen]+=val;
1196            csum_tim[templen]+= (unsigned long long) (cs2-cs1); 
1197         }
1199         if (XMIT)
1200         {
1201             protoInfo=nwal_mGetProtoInfo(tip);
1202             ifno = nwal_mGetRxEmacPort( protoInfo);
1203             //----------------------------------------------------
1204             //very trivial bridging -> just output to other port!
1205             //----------------------------------------------------
1206             if (ifno ==1) out_port=2; else out_port=1;
1207             t3= netapi_timing_start();
1208             sendit(tip,len,out_port);
1209             pkt_tx+=1;
1210             t4= netapi_timing_start();
1211             pkt_tx_cycles += (t4-t3);
1212         }
1213         else
1214         {
1215           Pktlib_freePacket((Ti_Pkt*)tip);
1216         }
1217     }
1218     t2 = netapi_timing_start();
1219     pkt_cb_cycles += (t2-t1);
1220     }