-/******************************************\r
- * File: net_test.c\r
- * Purpose: test app for netapi\r
- **************************************************************\r
- * FILE: net_test.c\r
- * \r
- * DESCRIPTION: netapi user space transport\r
- * library test application\r
- * \r
- * REVISION HISTORY: rev 0.0.1 \r
- *\r
- * Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- * Redistribution and use in source and binary forms, with or without \r
- * modification, are permitted provided that the following conditions \r
- * are met:\r
- *\r
- * Redistributions of source code must retain the above copyright \r
- * notice, this list of conditions and the following disclaimer.\r
- *\r
- * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the \r
- * documentation and/or other materials provided with the \r
- * distribution.\r
- *\r
- * Neither the name of Texas Instruments Incorporated nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- *****************************************/\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <string.h>\r
-\r
-\r
-#include "trie.h"\r
-#include "string.h"\r
-#include "netapi.h"\r
-#include "pktio.h"\r
-#include <sys/resource.h>\r
-\r
-/*************debug********************/\r
-void dump_descr(unsigned long *p, int n)\r
-{\r
- printf("--------dump of descriptor %d %x\n", n, (int) p);\r
- 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
- 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
- printf("-----------------------------\n");\r
-}\r
-/*****************************************/\r
-\r
-\r
-//************for multi pkt burst xfer test in loopback mode\r
-#define TX_BURST 4\r
-int pktloopback=TUNE_NETAPI_NWAL_ENABLE_PASS_LOOPBACK;\r
-\r
-//this device: 10.0.0.100, mac 0x,01,02,03,04,05 and .. 0x6\r
-\r
-//test packet, setup for loopback (so dest is ourself)\r
-static uint8_t testPkt[] = {\r
-\r
- /* MAC header */\r
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,\r
- 0x00, 0xe0, 0xa6, 0x66, 0x57, 0x04,\r
- 0x08, 0x00,\r
-\r
- /* IP header */\r
- 0x45, 0x00,\r
- 0x00, 0x6c, /* Length (including this header) */\r
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x11,\r
- 0x00, 0x00, /* Header checksum */\r
- 0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x64,\r
-\r
- /* UDP header */\r
- 0x12, 0x34, 0x05, 0x55,\r
- 0x00, 0x58, /* Length, including this header */\r
- 0x00, 0x00, /* Header checksum */\r
-\r
- /* Payload */\r
- 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,\r
- 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,\r
- 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,\r
- 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,\r
- 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,\r
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,\r
- 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,\r
- 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,\r
- 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,\r
- 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81\r
-\r
-};\r
-\r
-#define TEST_PAYLOAD_LEN 80\r
-\r
-#define TEST_PKT_IP_OFFSET_BYTES 14\r
-#define TEST_PKT_UDP_OFFSET_BYTES 34\r
-#define TEST_PKT_PLOAD_OFFSET_BYTES 42\r
-#define TEST_PKT_UDP_HDR_LEN 8\r
-/* Offsets to length fields */\r
-#define TEST_PKT_OFFSET_IP_LEN 16\r
-#define TEST_PKT_OFFSET_UDP_LEN 38\r
-\r
-#define TEST_PKT_LEN 122\r
-\r
-/* The pseudo header checksum of the packet except for the 16 bit length */\r
-#define TEST_PKT_PSEUDO_HDR_CHKSUM_SANS_LEN 0x0FFC\r
-\r
-\r
-\r
-#if 1\r
-//#include "arpa/inet.h"\r
-long htonl(long x)\r
-{\r
- long temp = (x&0xff000000)>>24 | (x&0xff0000)>>8 | (x&0xff00)<<8 | (x&0xff)<<24 ;\r
- return temp;\r
-}\r
-\r
-/********************************************************************\r
- * FUNCTION PURPOSE: Ones complement addition utility\r
- ********************************************************************\r
- ********************************************************************/\r
-uint16_t test_utilOnesComplementAdd (uint16_t v1, uint16_t v2)\r
-{\r
- uint32_t result;\r
-\r
- result = (uint32_t)v1 + (uint32_t)v2;\r
- result = (result >> 16) + (result & 0xffff);\r
- result = (result >> 16) + (result & 0xffff);\r
-\r
- return ((uint16_t)result);\r
-}\r
-\r
-/********************************************************************\r
- * FUNCTION PURPOSE: Ones complement checksum utility\r
- ********************************************************************\r
- ********************************************************************/\r
- uint16_t test_utilOnesCompChkSum (uint8_t *p, uint32_t nwords)\r
-{\r
- uint16_t chksum = 0;\r
- uint16_t v;\r
- uint32_t i;\r
- uint32_t j;\r
-\r
- for (i = j = 0; i < nwords; i++, j+=2) {\r
- v = (p[j] << 8) | p[j+1];\r
- chksum = test_utilOnesComplementAdd (chksum, v);\r
- }\r
- return (chksum);\r
-} /* utilOnesCompChkSum */\r
-\r
-/**************************************************************************************\r
- * FUNCTION PURPOSE: Compute ipv4 psudo checksum\r
- **************************************************************************************\r
- * DESCRIPTION: Compute ipv4 psudo checksum\r
- **************************************************************************************/\r
-uint16_t test_utilGetIpv4PsudoChkSum (uint8_t *data, uint16_t payloadLen)\r
-{\r
- uint16_t psudo_chksum;\r
-\r
- psudo_chksum = test_utilOnesCompChkSum (&data[12], 4);\r
- psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, (uint16_t) data[9]);\r
- psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, payloadLen);\r
-\r
- return (psudo_chksum);\r
-\r
-} /* utilGetIpv4PsudoChkSum */\r
-\r
-\r
-\r
-#endif\r
-typedef struct stats_t\r
-{\r
- long itx; //initially generated\r
- long rx;\r
- long tx;\r
- long n_bad;\r
- long n_new;\r
- long n_class0_rx; //count of pkts classified \r
- long n_class1_rx; //count of pkts classified \r
- long n_t1;\r
- long n_t2;\r
- long n_t3;\r
-} STATS_T;\r
-\r
-typedef struct head_t\r
-{\r
- long ip[5];\r
- long udp[2];\r
-} HEAD_T;\r
-\r
-typedef struct key_t\r
-{\r
- long src_ip;\r
- long dst_ip;\r
- short src_port;\r
- short dst_port;\r
-} KEY_T;\r
-\r
-unsigned char mac0[]={0x00,0x01,0x02,0x03,0x04,0x05}; //interface 0\r
-unsigned char mac1[]={0x00,0x01,0x02,0x03,0x04,0x06}; //interface 1\r
-nwalIpAddr_t OurIp0={ 10, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
-nwalIpAddr_t OurIp1={ 10, 0, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
-\r
-#if 1 //goes with real tx (to laptop) \r
-unsigned char real_mac_header[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e,\r
- 0x00,0x01,0x02,0x03,0x04,0x05,\r
- 0x08,0x00};\r
-unsigned char real_ip_addr[]={0xa,0x00,0x00,0x64,0xa,0x0,0x0,0xa};\r
-#endif\r
-\r
-#if 0 //goes with loopback\r
-unsigned char mac_header[]={0x00,0x01,0x02,0x03,0x04,0x05, \r
- 0x00,0x11,0x22,0x33,0x44,0x55,\r
- 0x08,0x00};\r
-#endif\r
-#define NE 65536 \r
-HEAD_T *nat;\r
-\r
-#define NP 5000\r
-int n_pkt = NP;\r
-STATS_T stats;\r
-\r
-Trie * P_trie;\r
-HEAD_T pkts[NP];\r
-#define PERSLOW 10 //% of pkts that will not be fastpath'd \r
-int perslow= PERSLOW;\r
-\r
-/*******************************************\r
- *************NETAPI OBJECTS***************\r
- *****************************************/\r
-Pktlib_HeapHandle OurHeap;\r
-PKTIO_HANDLE_T *our_chan;\r
-PKTIO_HANDLE_T *netcp_rx_chan;\r
-PKTIO_HANDLE_T *netcp_tx_chan;\r
-PKTIO_CFG_T our_chan_cfg={PKTIO_RW, PKTIO_LOCAL, PKTIO_Q_ANY, 8};\r
-PKTIO_CFG_T netcp_rx_cfg={PKTIO_R, PKTIO_NA, PKTIO_NA, 8};\r
-PKTIO_CFG_T netcp_tx_cfg={PKTIO_W, PKTIO_NA, PKTIO_NA, 8};\r
-\r
-void house(NETAPI_SCHED_HANDLE_T *s);\r
-NETAPI_T netapi_handle;\r
-NETAPI_SCHED_HANDLE_T * our_sched;\r
-NETAPI_SCHED_CONFIG_T our_sched_cfg={\r
- NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 500 //every 500 poll loops\r
-};\r
-void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);\r
-NETAPI_TIMER_GROUP_HANDLE_T ourTimerBlock; \r
-NETAPI_TIMER_T t1;\r
-NETAPI_TIMER_T t2;\r
-NETAPI_TIMER_T t3;\r
-\r
-void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
- int n_fired, //# timers fired\r
- NETAPI_TIMER_LIST_T fired_list,\r
- uint64_t currentTime);\r
-\r
-NETCP_CFG_IP_T ip_rule0;\r
-NETCP_CFG_IP_T ip_rule1;\r
-NETCP_CFG_CLASS_T class_0;\r
-NETCP_CFG_CLASS_T class_1;\r
-\r
-NETCP_CFG_CLASSIFIER_T class_0_cfg=\r
-{\r
- NETCP_CFG_CLASS_TYPE_L4,\r
- {\r
- {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2500}}\r
- }\r
-};\r
-\r
-NETCP_CFG_CLASSIFIER_T class_1_cfg=\r
-{\r
- NETCP_CFG_CLASS_TYPE_L4,\r
- {\r
- {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2502}}\r
- }\r
-};\r
-\r
-PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};\r
-\r
-/*************************END NETAPI OBJECTS***********************/\r
-\r
-#define START_SRC_IP 0x0a00000a\r
-#define DST_IP 0xc0a80001\r
-#define NEW_START_SRC_IP 0x9eda000a\r
-#define DST_PORT 0x555 \r
-#define START_SRC_PORT 0x1234\r
-#define NEW_START_SRC_PORT 100\r
-void update_header(HEAD_T * p_head, int len)\r
-{\r
- unsigned char *p = (unsigned char *) &p_head->udp[1];\r
- len -= (20+14);\r
- /* update ip checksum */\r
- /* update udp checksum */\r
- /* update length */\r
- *p= (len&0xff00)>>8;\r
- *(p+1) = len&0xff;\r
-}\r
-\r
-#if 0\r
-void gen_pkts(int np)\r
-{\r
-int i;\r
-int ip = START_SRC_IP &0xff;\r
-int port= START_SRC_PORT;\r
-//HEAD_T temp={{0x25000200,0xdead0000,0x80110000,START_SRC_IP,DST_IP},\r
-// {START_SRC_PORT<<16|DST_PORT,0x01ec<<16|0x0000}};\r
-HEAD_T temp;\r
-memcpy(&temp,&testPkt[0],sizeof(HEAD_T));\r
-\r
-for(i=0;(i<np) && (i<NP);i++)\r
- {\r
- memcpy(&pkts[i],&temp,sizeof(temp));\r
- update_header(&pkts[i],512); /* update checksums etc */\r
- /* change template for new pkt */\r
- ip+=1;\r
- if(ip>254) {(ip=START_SRC_IP&0xff); port+=1; }\r
- temp.ip[3] = htonl((START_SRC_IP&0xffffff00)| ip);\r
- temp.udp[0] = htonl( (temp.udp[0]&0xffff0000)| port);\r
- temp.udp[1] = htonl(temp.udp[1]);\r
- \r
- }\r
- n_pkt=np;\r
-}\r
-#endif\r
-\r
-void build_table(Trie * p_trie)\r
-{\r
-int i;\r
-int sport=NEW_START_SRC_PORT; \r
-HEAD_T temp,temp2;\r
-KEY_T key;\r
-\r
-memcpy(&temp,&testPkt[14],sizeof(temp));\r
-\r
- //insert entry into trie\r
-key.src_ip = temp.ip[3];\r
-key.dst_ip = temp.ip[4];\r
-key.src_port= (temp.udp[0]&0xffff0000)>>16;\r
-key.dst_port= (temp.udp[0]&0x0000ffff);\r
-trie_insert(p_trie,(char *)&key,sizeof(key), (void *) &nat[0]); //asociate with nat entry 0\r
-\r
-//build nat table\r
-for(i=0;i<100;i++)\r
-{\r
- memcpy(&temp2,&testPkt[14],sizeof(temp));\r
- temp2.udp[0] = (temp2.udp[0] & 0xffff0000) | sport;\r
- memcpy(&nat[i], &temp2, sizeof(temp2));\r
- sport+= 1;\r
-}\r
-}\r
-\r
-//===========stub transmitter==================\r
-void send_pkt(Ti_Pkt *pkt, int len)\r
-{\r
-//just free pkt. Don't send\r
-Pktlib_freePacket((Ti_Pkt*)pkt);\r
- return;\r
-}\r
-\r
-//==========stub slow path============\r
-void slow_path(Ti_Pkt *pkt, int len)\r
-{\r
-// debug: check descriptor for validity by verifying that desciptor link field is null as expected\n");\r
- {Ti_Pkt * k= Pktlib_getNextPacket(pkt); if(k != 0) {printf(" slowpath, nexpkt != NULL");}}\r
-//just free pkt\r
-Pktlib_freePacket((Ti_Pkt*)pkt);\r
- return;\r
-}\r
-/* check header */\r
-struct LastPktInfo\r
-{\r
-int iface;\r
-int ipcsum;\r
-int l4csum;\r
-} ;\r
-static struct LastPktInfo lpInfo;\r
-\r
-int check_header(HEAD_T * p_head, PKTIO_METADATA_T * p_meta)\r
-{\r
-if (NWAL_RX_FLAG1_META_DATA_VALID & p_meta->u.rx_meta->rxFlag1)\r
-{\r
-lpInfo.iface = ((unsigned int)p_meta->u.rx_meta->appId) &0xff; //last byte is interface num\r
-lpInfo.ipcsum =(p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_MASK )== NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_ACK ? 1 : 0;\r
-lpInfo.l4csum = (p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_MASK )== ((NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_ACK) << NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_SHIFT) ? 1 : 0; \r
-if ((unsigned int)p_meta->u.rx_meta->appId & NETAPI_NETCP_MATCH_CLASS)\r
-{\r
- int c= ((unsigned int)p_meta->u.rx_meta->appId >>8)&0xffff;\r
- if (c==0) stats.n_class0_rx +=1;\r
- else if (c==1) stats.n_class1_rx +=1;\r
- else printf("**NET_TEST RX -unknown class: %x\n", p_meta->u.rx_meta->appId);\r
-}\r
-}\r
-\r
- return 1;\r
-}\r
-\r
-#define PKT_LEN 1400\r
-void test_alloc_free(int n)\r
-{\r
-int i;\r
-Ti_Pkt * b;\r
-\r
-for(i=0;i<n;i++)\r
-{\r
- b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
- Pktlib_freePacket(b);\r
-}\r
-}\r
-/*-----------test driver: gen an input pkt------- */\r
-//char buffer[sizeof(HEAD_T)+PKT_LEN];\r
-Ti_Pkt * get_pkt(int n, unsigned int *p_len)\r
-{\r
- int ind;\r
- long long temp;\r
- Ti_Pkt * b;\r
- char * buffer;\r
- unsigned int len;\r
-\r
- if (pktloopback==0)\r
- {\r
- if (n>=4) return NULL; //just gen pkts to warm swtich, so that it knows\r
- //our mac is valid\r
- } \r
- b=Pktlib_allocPacket(OurHeap,PKT_LEN);\r
- if (!b) \r
- {printf("net_test: get_pkt() heap empty!! %d pkts gen'd %d \n", n); return NULL;};\r
-\r
- //debug - way to validate descriptor\r
- {Ti_Pkt* k= Pktlib_getNextPacket(b); \r
- if(k != 0) {printf(" genpkt, nexpkt != NULL");}}\r
-\r
-\r
- //get pointer to buffer area of packet\r
- Pktlib_getDataBuffer(b,(uint8_t**)&buffer,&len);\r
-\r
-#if 0 \r
-if (pktloopback==0)\r
-{\r
- temp = (long long) rand();\r
- temp *= PKT_LEN;\r
- temp /= RAND_MAX;\r
- temp +=2;\r
- *p_len = (int) temp; \r
- *p_len = *p_len &0xfffffffe;\r
- temp = (long long) rand();\r
- temp *= n_pkt;\r
- temp /= RAND_MAX;\r
- ind = (int) temp;\r
- update_header(&pkts[ind],*p_len);\r
- //printf("get pkt:%d %d ind=%d len=%d\n",RAND_MAX, rand(),ind, *p_len);\r
- memcpy(&buffer[0], &mac_header[0],14);\r
- memcpy(&buffer[14],(char*)&pkts[ind],sizeof(HEAD_T)); \r
-}\r
-else\r
-#endif\r
-\r
- //copy test packet into buffer\r
-{\r
- memcpy(&buffer[0], &testPkt[0],TEST_PKT_LEN);\r
- *p_len = TEST_PKT_LEN;\r
-}\r
- return b; \r
-}\r
-\r
-\r
-/******************************************************/\r
-/******************PKT RECEIVE HANDLER *************************/\r
-/******************************************************/\r
-void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],\r
- PKTIO_METADATA_T meta[], int n_pkts,\r
- uint64_t ts )\r
-{\r
-int i;\r
-int len;\r
-int p;\r
-HEAD_T * p_res;\r
-Ti_Pkt * tip;\r
-unsigned int templen;\r
-int err;\r
-KEY_T key;\r
-char * p_pkt;\r
-HEAD_T * p_head;\r
-HEAD_T temp_head;\r
-\r
- p_head=&temp_head;\r
-\r
- //debug\r
-#if 0\r
- if (n_pkts != TX_BURST) {\r
- printf("recv_cb, txsofar=%d rxsofar=%d np = %d, NOT %d\n", \r
- stats.itx, stats.rx, n_pkts,TX_BURST);\r
- our_stats_cb(netapi_handle,NULL);\r
- }\r
-#endif\r
- //test_alloc_free(7);\r
- //printf("recv start\n");\r
-\r
- /* loop over received pkts */\r
- for(i=0;i<n_pkts;i++)\r
- {\r
- tip = p_recv[i];\r
- Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen\r
- len = Pktlib_getPacketLen(tip);//real length\r
-\r
- //debug: validate descriptor */\r
- if(Pktlib_getNextPacket(tip) != 0) {printf(" rcv_cb, nexpkt != NULL");}\r
- //debug printf("recv pkt, len=%d %d\n", len, templen);\r
- stats.rx+=1;\r
-\r
-#ifdef DEBUG_DESC\r
- if (stats.rx<16){printf(">rx dmp.."); dump_descr((long *) tip, stats.rx);}\r
- else if (stats.rx>99) {printf(">rx dmp.."); dump_descr((long *) tip,stats.rx);}\r
-#endif\r
-\r
-\r
- /* check header */\r
- memcpy(p_head,&p_pkt[14],sizeof(HEAD_T));\r
- if (!check_header(p_head,&meta[i])) { \r
- stats.n_bad+=1;Pktlib_freePacket(tip); continue;\r
- }\r
-\r
- /* lookup flow */\r
- key.src_ip = p_head->ip[3];\r
- key.dst_ip = p_head->ip[4];\r
- key.src_port= (p_head->udp[0]&0xffff0000)>>16;\r
- key.dst_port= (p_head->udp[0]&0x0000ffff);\r
- p_res= (HEAD_T *) trie_lookup(P_trie, (char *) &key, sizeof(key));\r
- if (!p_res) { stats.n_new+=1; slow_path(tip, len); continue;}\r
-\r
- /* copy header */\r
- memcpy((char *) p_head, (char *) p_res, sizeof(HEAD_T));\r
-\r
- memcpy(&p_pkt[14],p_head,sizeof(HEAD_T));\r
- /* update_mac(&p_pkt[0]); */\r
-\r
- /* 'simulate' send pkt */\r
- send_pkt(tip,len);\r
- stats.tx+=1;\r
- }\r
- //printf("recv done\n");\r
-}\r
-\r
-//timer callback \r
-void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,\r
- int n_fired, //# timers fired\r
- NETAPI_TIMER_LIST_T fired_list,\r
- uint64_t currentTime)\r
-{\r
-int i;\r
-NETAPI_TIMER_T tx;\r
-int cookie;\r
-int err;\r
-unsigned long long et;\r
-//DEBUGprintf("TIMER CALLBACK @ %lld %d timers\n", currentTime, n_fired);\r
-tx = netapi_TimerGetFirst(fired_list);\r
-for(i=0;i<n_fired;i++)\r
-{\r
- cookie = (int) netapi_TimerGetCookie(tx);\r
- et = netapi_TimerGetTs(tx); //debug\r
- //DEBUGprintf(" timer %d - cookie = %d expected ts=%lld (delta=%lld)\n", i, cookie, et, currentTime-et);\r
- if (cookie ==1)\r
- { \r
- stats.n_t1+=1;\r
- t1 = netapi_TimerGroupStartTimer(\r
- th,\r
- (void *) 1,\r
- 100LL, //timer group tics\r
- &err);\r
- }\r
- else if (cookie ==2)\r
- {\r
- stats.n_t2+=1;\r
- t2 = netapi_TimerGroupStartTimer(\r
- th,\r
- (void *) 2,\r
- 200LL, //timer group ticks\r
- &err);\r
- }\r
- else\r
- {\r
- stats.n_t3+=1;\r
- t3 = netapi_TimerGroupStartTimer(\r
- th,\r
- (void *) 3,\r
- 300LL, //timer group ticks\r
- &err);\r
- //cancel 1 and restart 1\r
- netapi_TimerGroupCancel(th,t1,&err);\r
- t1 = netapi_TimerGroupStartTimer(\r
- th,\r
- (void *) 1,\r
- 100LL, //timer group ticks\r
- &err);\r
- }\r
- tx = netapi_TimerGetNext(fired_list,tx); \r
-}\r
-}\r
-\r
-\r
-static int np2process = NP;\r
-/******************************************************\r
- * stats callback\r
- *******************************************************/\r
-void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats)\r
-{\r
-uint32_t numFreeDataPackets;\r
-uint32_t numZeroBufferPackets;\r
-uint32_t numPacketsinGarbage;\r
-\r
-printf("stats @ %lld\n", netapi_getTimestamp());\r
-printf("netcp_tx_handle check %x\n", netcp_tx_chan->back);\r
-printf("itx=%d rx=%d tx=%d bad=%d slow=%d rx_class0=%d rx_class1=%d n_t1=%d n_t2=%d n_t3=%d\n",stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new,stats.n_class0_rx, stats.n_class1_rx, stats.n_t1, stats.n_t2,stats.n_t3);\r
-\r
-if(pPaStats)\r
-{\r
- printf("C1 number of packets: %d\n", pPaStats->classify1.nPackets);\r
- printf("C1 number IPv4 packets: %d\n", pPaStats->classify1.nIpv4Packets);\r
- //printf("C1 number llc/snap fail: %d\n", pPaStats->classify1.nLlcSnapFail);\r
- printf("C1 number table matched: %d\n", pPaStats->classify1.nTableMatch);\r
- printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);\r
- printf ("C1 number of parse fail: %d\n",pPaStats->classify1.nParseFail);\r
- printf("C1 number of command failures: %d\n", pPaStats->classify1.nCommandFail);\r
- printf("C1 number invalid reply dests: %d\n", pPaStats->classify1.nInvalidComReplyDest);\r
- printf ("C1 number of silent discard: %d\n",pPaStats->classify1.nSilentDiscard);\r
- printf("C1 number of invalid control: %d\n", pPaStats->classify1.nInvalidControl);\r
- printf ("C1 number of invalid states: %d\n",pPaStats->classify1.nInvalidState);\r
- printf ("C1 number of system fails: %d\n",pPaStats->classify1.nSystemFail);\r
- printf ("C2 number parse failed : %d\n",pPaStats->classify2.nParseFail);\r
- printf ("C2 number Invld Header : %d\n",pPaStats->classify2.nInvldHdr);\r
- printf ("C2 number udp : %d\n",pPaStats->classify2.nUdp);\r
- printf ("C2 number tcp : %d\n",pPaStats->classify2.nTcp);\r
- printf ("C2 number cmd fail : %d\n",pPaStats->classify2.nCommandFail);\r
- printf ("C2 number silent drop : %d\n",pPaStats->classify2.nSilentDiscard);\r
- printf ("C2 number invalid cntrl : %d\n\n",pPaStats->classify2.nInvalidControl);\r
-}\r
-Pktlib_getHeapStats(OurHeap, &numFreeDataPackets,\r
- &numZeroBufferPackets, &numPacketsinGarbage);\r
-printf("heap stats> #free=%d #zb=%d #garbage=%d\n", numFreeDataPackets,\r
- numZeroBufferPackets, numPacketsinGarbage);\r
-//debug = dump timer polling stats\r
-dump_poll_stats();\r
-\r
-\r
-}\r
-\r
-//******************************************************\r
-//use scheduling housekeeping callback to generate pkts\r
-//******************************************************\r
-void house(NETAPI_SCHED_HANDLE_T * s)\r
-{\r
-Ti_Pkt * tip;\r
-unsigned int len;\r
-nwalTxPktInfo_t meta_tx={0};\r
-PKTIO_METADATA_T meta = {PKTIO_META_TX,0};\r
-int err;\r
-static int house_pkts_gened=0;\r
-int p;\r
-unsigned char * pIpHdr,* pData;\r
-unsigned int vv1,vv2,vv3;\r
-\r
-for(p=0;p<TX_BURST;p++) { \r
-//reguest stats \r
-if ((house_pkts_gened>0) && (! (house_pkts_gened%400)) )\r
-{\r
- printf("net_test> request stats at n=%d \n",house_pkts_gened);\r
- netcp_cfgReqStats(netapi_handle, our_stats_cb, 0,&err); \r
- if (err!=0) {printf("stats req failed\n");}\r
-}\r
-\r
-\r
- if (house_pkts_gened >= np2process+ 100)\r
- {\r
- //shutdown\r
- netapi_schedShutdown(s,NULL,&err);\r
- continue;\r
- }\r
-\r
- else if (house_pkts_gened >= np2process) { house_pkts_gened+=1; continue;}\r
- \r
-\r
-/* manufacture a pkt to transmit */\r
- tip = get_pkt(house_pkts_gened, &len);\r
- if(!tip) { house_pkts_gened +=1; continue; }\r
-\r
-\r
- /* set the pkt length */\r
- vv1 = netapi_timing_start();\r
- Pktlib_setPacketLen(tip, len);\r
-\r
- /* set up meta data */\r
- meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM | NWAL_TX_FLAG1_DO_UDP_CHKSUM);\r
- meta_tx.startOffset = 0;\r
- meta_tx.pktLen = len;\r
- meta_tx.ipOffBytes = TEST_PKT_IP_OFFSET_BYTES;\r
- meta_tx.l4OffBytes = TEST_PKT_UDP_OFFSET_BYTES;\r
- meta_tx.l4HdrLen = TEST_PKT_UDP_HDR_LEN;\r
- meta_tx.ploadOffBytes = TEST_PKT_PLOAD_OFFSET_BYTES;\r
- meta_tx.ploadLen = TEST_PAYLOAD_LEN;\r
-\r
- Pktlib_getDataBuffer(tip,&pData,&len);\r
- pIpHdr = pData + meta_tx.ipOffBytes;\r
- meta_tx.pseudoHdrChecksum =\r
- test_utilGetIpv4PsudoChkSum(pIpHdr,(TEST_PAYLOAD_LEN+TEST_PKT_UDP_HDR_LEN));\r
-\r
- /* post it to netcp tx channel*/\r
- meta.u.tx_meta=&meta_tx;\r
-#ifdef DEBUG_DESC\r
- if (house_pkts_gened<16) dump_descr((long *) tip, house_pkts_gened);\r
- else if (house_pkts_gened>99) dump_descr((long *) tip,house_pkts_gened);\r
-#endif\r
- vv2= netapi_timing_stop();\r
- pktio_send(netcp_tx_chan,tip,&meta,&err);\r
- vv3= netapi_timing_stop();\r
- printf("pktio send. full=%d metadata=%d pktio_send=%d\n", vv3-vv1, vv2-vv1, vv3-vv2);\r
- if (err == 0) stats.itx +=1;\r
-\r
- house_pkts_gened +=1;\r
- }\r
-}\r
-\r
-\r
-/***************************************\r
- ********** test driver*****************\r
- ***************************************/\r
-int main(int argc, char **argv)\r
-{\r
-int err;\r
-rlim_t oss,ss = 1024*1024;\r
-struct rlimit rl;\r
-\r
-err= getrlimit(RLIMIT_STACK,&rl);\r
-if (!err) printf(" stack limit = %d\n",rl.rlim_cur); else printf("getrlimit failed\n");\r
-#if 0\r
-rl.rlim_cur = ss;\r
-err=setrlimit(RLIMIT_STACK,&rl);\r
-if (!err) printf("set stack to %d\n",rl.rlim_cur); else printf("setrlimit failed\n");\r
-#endif\r
-\r
-if (argc>=2) np2process = atoi(argv[1]);\r
-if (np2process<0) np2process = NP; /* default */\r
-if (argc==3) perslow = atoi(argv[2]);\r
-if ((perslow<0)||(perslow>100)) perslow=PERSLOW;//default\r
-if (argc>3) {printf("net_test <no of pkts to process> <percent slow path>\n"); exit(1);}\r
-\r
-\r
-//real mode, so update our test packet mac header and ip header\r
-if (pktloopback==0)\r
-{\r
-memcpy(&testPkt,&real_mac_header[0],14); //overwrite test pkt mac address\r
-memcpy(&testPkt[26],&real_ip_addr[0],8);//overrite test pkt ip addresses\r
-}\r
-\r
-/*******************************************/\r
-/*************NETAPI STARTUP****************/\r
-/*******************************************/\r
-\r
-/* create netapi */\r
-netapi_handle = netapi_init(NETAPI_SYS_MASTER);\r
-\r
-/* open the main heap */\r
-OurHeap = Pktlib_findHeapByName("netapi");\r
-if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}\r
-\r
-/* create a pktio channel */\r
-our_chan=pktio_create(netapi_handle,"our1stq",(PKTIO_CB) recv_cb, &our_chan_cfg,&err);\r
-if (!our_chan) {printf("pktio create failed err=%d\n",err); exit(1);}\r
-\r
-/* open netcp default tx, rx queues */\r
-netcp_tx_chan= pktio_open(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg, &err);\r
-if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);}\r
-netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb, &netcp_rx_cfg, &err);\r
-if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}\r
-\r
-\r
-/* create scheduler instance */\r
-our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);\r
-if (!our_sched) {printf("sched create failed\n"); exit(1);}\r
-\r
-/* add mac intefaces */\r
-netcp_cfgCreateMacInterface(\r
- netapi_handle,\r
- &mac0[0],\r
- 0,0,\r
- (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
- (NETCP_CFG_VLAN_T ) NULL , //future\r
- 1, \r
- &err);\r
-if (err) {printf("addmac0 failed %d\n",err); exit(1); } \r
-\r
-//attach an IP to this interface\r
-ip_rule0=netcp_addIp(\r
- netapi_handle,\r
- 0,\r
- nwal_IPV4,\r
- &OurIp0,\r
- NULL, //all IP\r
- (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
- &err\r
- );\r
-if (err) {printf("addip0 failed %d\n",err); exit(1); } \r
-#if 1\r
-//create a 2nd mac instance\r
-netcp_cfgCreateMacInterface(\r
- netapi_handle,\r
- &mac1[0],\r
- 1,1,\r
- (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
- (NETCP_CFG_VLAN_T ) NULL , //future\r
- 1,\r
- &err);\r
-if (err) {printf("addmac1 failed %d\n",err); exit(1); }\r
-\r
-//attach an IP to this interface\r
-ip_rule1=netcp_addIp(\r
- netapi_handle,\r
- 1,\r
- nwal_IPV4,\r
- &OurIp1,\r
- NULL, //all IP\r
- (NETCP_CFG_ROUTE_HANDLE_T) NULL,\r
- &err\r
- );\r
-if (err) {printf("addip1 failed %d\n",err); exit(1); }\r
-\r
-//attach 2 classifiers to iface 0, ip0\r
-class_0_cfg.u.c_l4.ip = ip_rule0;\r
-class_0 = netcp_cfgAddClass(netapi_handle,\r
- &class_0_cfg,\r
- NULL,\r
- NETCP_CFG_ACTION_TO_SW,\r
- &err);\r
-if (err) {printf("addclass0 failed %d\n",err); exit(1);}\r
-\r
-class_1_cfg.u.c_l4.ip = ip_rule0;\r
-class_1 = netcp_cfgAddClass(netapi_handle,\r
- &class_1_cfg,\r
- NULL,\r
- NETCP_CFG_ACTION_TO_SW,\r
- &err);\r
-if (err) {printf("addclass1 failed %d\n",err); exit(1);}\r
-\r
-\r
-#endif\r
-\r
- ourTimerBlock = netapi_TimerGroupCreate(\r
- netapi_handle,\r
- "our1sttimer",\r
- our_timer_cb,\r
- 0, //1 if timers local to thread\r
- 0, //1 if expect to cancel\r
- netapi_getTicksPerSec()/1000, /* 1 msc resolution for these timers */\r
- netapi_getTicksPerSec()/5000, /* would like .5 msc tolerence */\r
- 10, //small # of timers to test garbage collection\r
- &err);\r
-if (err) {printf("timergroupcreate failed %d\n",err); exit(1);}\r
-\r
-//start a couple of timers \r
-t1 = netapi_TimerGroupStartTimer(\r
- ourTimerBlock,\r
- (void *) 1,\r
- 100LL, //timer group ticks\r
- &err);\r
-if (err) {printf("timerstart failed %d\n");}\r
-t2 = netapi_TimerGroupStartTimer(\r
- ourTimerBlock,\r
- (void *) 2,\r
- 200LL, //timer group ticks\r
- &err);\r
-if (err) {printf("timerstart failed %d\n");}\r
-t3 = netapi_TimerGroupStartTimer(\r
- ourTimerBlock,\r
- (void *) 3,\r
- 300LL, //timer group ticks\r
- &err);\r
-if (err) {printf("timerstart failed %d\n");}\r
-\r
-\r
-/*********************************************/\r
-/*****************end NETAPI STARTUP**********/\r
-/*********************************************/\r
-\r
-\r
-/********************************************\r
-* Basic pkt loopback test\r
-*********************************************/\r
-\r
-\r
-/* create TRIE */\r
-P_trie = trie_new();\r
-if (!P_trie) {printf("trie alloc failed\n"); exit(1);}\r
-\r
-nat = (HEAD_T *) malloc(NE * sizeof(HEAD_T));\r
-if (!nat) {printf("malloc of nat table failed\n"); exit(1);}\r
-\r
-//gen_pkts(np2process<NP ? np2process:NP);\r
-n_pkt= np2process;\r
-\r
-/* build table */\r
-build_table(P_trie);\r
-\r
-\r
-/* processing loop: get pkt, check it, look up in table, copy new header,\r
- send packet */\r
-srand((unsigned) np2process);\r
-\r
-\r
-/*********************************************/\r
-/**************Entry point into scheduler ****/\r
-/*********************************************/\r
-netapi_schedWaitForEvents(our_sched, &err);\r
-\r
-/* done */\r
-printf("done: itx=%d rx=%d tx=%d bad=%d slow=%d\n",stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new);\r
-our_stats_cb(netapi_handle, NULL);\r
-\r
-//delete Classifiers\r
-netcp_cfgDelClass(netapi_handle, class_0, &err); \r
-netcp_cfgDelClass(netapi_handle, class_1, &err); \r
-\r
-//delete IPs and MAC Interfacess\r
-netcp_cfgDelIp(netapi_handle, 0, 0, NULL, NULL, ip_rule0, &err);\r
-netcp_cfgDelIp(netapi_handle, 1, 0, NULL, NULL, ip_rule1, &err);\r
-netcp_cfgDelMac(netapi_handle,0,&err);\r
-netcp_cfgDelMac(netapi_handle,1,&err);\r
-\r
-//close pktio channels we opened\r
-pktio_close(netcp_tx_chan ,&err);\r
-pktio_close(netcp_rx_chan ,&err);\r
-\r
-//clear pktio channel we created\r
-pktio_control(our_chan, (PKTIO_CB) NULL, (PKTIO_CFG_T *) NULL, &zap_channel_control, &err);\r
-//delete pktio channels we created\r
-pktio_delete(our_chan, &err);\r
-\r
-netapi_shutdown(netapi_handle);\r
-\r
-}\r
+/******************************************
+ * File: net_test.c
+ * Purpose: test app for netapi
+ **************************************************************
+ * FILE: net_test.c
+ *
+ * DESCRIPTION: netapi user space transport
+ * library test application
+ *
+ * REVISION HISTORY: rev 0.0.1
+ *
+ * Copyright (c) Texas Instruments Incorporated 2010-2011
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ *****************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+
+#include "trie.h"
+#include "string.h"
+#include "netapi.h"
+#include "pktio.h"
+#include <sys/resource.h>
+
+//IPSEC MODE(only choose one rx and one tx)
+#define IPSEC_MODE_RX_INFLOW
+#define IPSEC_MODE_TX_INFLOW
+//#define IPSEC_MODE_RX_SIDEBAND
+//#define IPSEC_MODE_TX_SIDEBAND
+
+//#define TEST_TIMERS
+
+/*************debug********************/
+void dump_descr(unsigned long *p, int n)
+{
+ printf("--------dump of descriptor %d %x\n", n, (int) p);
+ 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]);
+ 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]);
+ printf("-----------------------------\n");
+}
+void dump_header(unsigned long *p, int n, int a, int r)
+{
+ printf("--------dump of header %d %x appID=%x flag1=%x\n", n, (int) p,a,r);
+ 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]);
+ 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]);
+ 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]);
+ 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]);
+ printf("-----------------------------\n");
+}
+
+/*****************************************/
+
+
+//************for multi pkt burst xfer test in loopback mode
+#define TX_BURST 800
+int pktloopback=TUNE_NETAPI_NWAL_ENABLE_PASS_LOOPBACK;
+nwalTxPSCmdInfo_t flowPSCmdInfo;
+
+//this device: 10.0.0.100, mac 0x,01,02,03,04,05 and .. 0x6
+
+//test packet, setup for loopback (so dest is ourself)
+static uint8_t testPkt[] = {
+
+ /* MAC header */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x00, 0xe0, 0xa6, 0x66, 0x57, 0x04,
+ 0x08, 0x00,
+
+ /* IP header */
+ 0x45, 0x00,
+ 0x00, 0x6c, /* Length (including this header) */
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x11,
+ 0x00, 0x00, /* Header checksum */
+ 0x0a, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x64,
+
+ /* UDP header */
+ 0x12, 0x34, 0x05, 0x55,
+ 0x00, 0x58, /* Length, including this header */
+ 0x00, 0x00, /* Header checksum */
+
+ /* Payload */
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+ 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,
+ 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,
+ 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81
+
+};
+
+#define TEST_PAYLOAD_LEN 80
+
+#define TEST_PKT_IP_OFFSET_BYTES 14
+#define TEST_PKT_UDP_OFFSET_BYTES 34
+#define TEST_PKT_PLOAD_OFFSET_BYTES 42
+#define TEST_PKT_UDP_HDR_LEN 8
+/* Offsets to length fields */
+#define TEST_PKT_OFFSET_IP_LEN 16
+#define TEST_PKT_OFFSET_UDP_LEN 38
+
+#define TEST_PKT_LEN 122
+
+/* The pseudo header checksum of the packet except for the 16 bit length */
+#define TEST_PKT_PSEUDO_HDR_CHKSUM_SANS_LEN 0x0FFC
+
+void example_fast_poll( PKTIO_HANDLE_T * p_pktio);
+
+#if 1
+//#include "arpa/inet.h"
+long htonl(long x)
+{
+ long temp = (x&0xff000000)>>24 | (x&0xff0000)>>8 | (x&0xff00)<<8 | (x&0xff)<<24 ;
+ return temp;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE: Ones complement addition utility
+ ********************************************************************
+ ********************************************************************/
+uint16_t test_utilOnesComplementAdd (uint16_t v1, uint16_t v2)
+{
+ uint32_t result;
+
+ result = (uint32_t)v1 + (uint32_t)v2;
+ result = (result >> 16) + (result & 0xffff);
+ result = (result >> 16) + (result & 0xffff);
+
+ return ((uint16_t)result);
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE: Ones complement checksum utility
+ ********************************************************************
+ ********************************************************************/
+ uint16_t test_utilOnesCompChkSum (uint8_t *p, uint32_t nwords)
+{
+ uint16_t chksum = 0;
+ uint16_t v;
+ uint32_t i;
+ uint32_t j;
+
+ for (i = j = 0; i < nwords; i++, j+=2) {
+ v = (p[j] << 8) | p[j+1];
+ chksum = test_utilOnesComplementAdd (chksum, v);
+ }
+ return (chksum);
+} /* utilOnesCompChkSum */
+
+/**************************************************************************************
+ * FUNCTION PURPOSE: Compute ipv4 psudo checksum
+ **************************************************************************************
+ * DESCRIPTION: Compute ipv4 psudo checksum
+ **************************************************************************************/
+uint16_t test_utilGetIpv4PsudoChkSum (uint8_t *data, uint16_t payloadLen)
+{
+ uint16_t psudo_chksum;
+
+ psudo_chksum = test_utilOnesCompChkSum (&data[12], 4);
+ psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, (uint16_t) data[9]);
+ psudo_chksum = test_utilOnesComplementAdd(psudo_chksum, payloadLen);
+
+ return (psudo_chksum);
+
+} /* utilGetIpv4PsudoChkSum */
+
+
+
+#endif
+typedef struct stats_t
+{
+ long itx; //initially generated
+ long itx2;
+ long rx;
+ long tx;
+ long n_bad;
+ long n_new;
+ long n_class0_rx; //count of pkts classified
+ long n_class1_rx; //count of pkts classified
+ long n_class2_rx; //count of pkts classified
+ long n_t1;
+ long n_t2;
+ long n_t3;
+ long sec_tx;
+ long sec_rx;
+ long sb_tx;
+ long sb_rx;
+ long secp_rx;
+ long n_auth_ok;
+} STATS_T;
+
+typedef struct head_t
+{
+ long ip[5];
+ long udp[2];
+} HEAD_T;
+
+typedef struct key_t
+{
+ long src_ip;
+ long dst_ip;
+ short src_port;
+ short dst_port;
+} KEY_T;
+
+unsigned char mac0[]={0x00,0x01,0x02,0x03,0x04,0x05}; //interface 0
+unsigned char mac1[]={0x00,0x01,0x02,0x03,0x04,0x06}; //interface 1
+nwalIpAddr_t OurIp0={ 10, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+nwalIpAddr_t OurIp1={ 10, 0, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+nwalIpAddr_t OurIp2={ 10, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+nwalIpAddr_t OurIp4IPSEC={ 192,168 , 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+nwalIpAddr_t TheirIp4IPSEC={ 192,168 , 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+
+#if 1 //goes with real tx (to laptop)
+unsigned char real_mac_header[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e,
+ 0x00,0x01,0x02,0x03,0x04,0x05,
+ 0x08,0x00};
+unsigned char real_ip_addr[]={0xa,0x00,0x00,0x64,0xa,0x0,0x0,0xa};
+#endif
+
+#if 0 //goes with loopback
+unsigned char mac_header[]={0x00,0x01,0x02,0x03,0x04,0x05,
+ 0x00,0x11,0x22,0x33,0x44,0x55,
+ 0x08,0x00};
+#endif
+#define NE 65536
+HEAD_T *nat;
+
+#define NP 5000
+int n_pkt = NP;
+STATS_T stats;
+
+Trie * P_trie;
+HEAD_T pkts[NP];
+#define PERSLOW 10 //% of pkts that will not be fastpath'd
+int perslow= PERSLOW;
+
+/*******************************************
+ *************NETAPI OBJECTS***************
+ *****************************************/
+static NETAPI_CFG_T our_netapi_default_cfg=
+{
+TUNE_NETAPI_PERM_MEM_SZ,
+128, //start of packet offset for hw to place data on rx for default flow
+TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
+TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use
+TUNE_NETAPI_DEFAULT_NUM_BUFFERS, //#descriptors+buffers in default heap
+64, //#descriptors w/o buffers in default heap
+TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128, //size of buffers in default heap
+128 , //tail room
+256 //extra room
+};
+
+Pktlib_HeapHandle OurHeap;
+Pktlib_HeapHandle specialSmall;
+Pktlib_HeapHandle specialLarge;
+
+PKTIO_HANDLE_T *our_chan;
+PKTIO_HANDLE_T *netcp_rx_chan;
+PKTIO_HANDLE_T *netcp_rx_chan2;
+PKTIO_HANDLE_T *netcp_tx_chan;
+PKTIO_HANDLE_T *netcp_sb_tx_chan;
+PKTIO_HANDLE_T *netcp_sb_rx_chan;
+PKTIO_CFG_T our_chan_cfg={PKTIO_RW, PKTIO_LOCAL, PKTIO_Q_ANY, 8};
+PKTIO_CFG_T netcp_rx_cfg={PKTIO_R, PKTIO_NA, PKTIO_NA, 8};
+PKTIO_CFG_T netcp_rx_cfg2={PKTIO_R, (PKTIO_GLOBAL|PKTIO_PKT), PKTIO_Q_ANY, 8};
+PKTIO_CFG_T netcp_tx_cfg={PKTIO_W, PKTIO_NA, PKTIO_NA, 8};
+PKTIO_CFG_T netcp_sb_rx_cfg={PKTIO_R, PKTIO_NA, PKTIO_NA, 8};
+PKTIO_CFG_T netcp_sb_tx_cfg={PKTIO_W, PKTIO_NA, PKTIO_NA, 8};
+
+void house(NETAPI_SCHED_HANDLE_T *s);
+NETAPI_T netapi_handle;
+NETAPI_SCHED_HANDLE_T * our_sched;
+NETAPI_SCHED_CONFIG_T our_sched_cfg={
+ NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 50000 //every 5000 poll loops
+};
+void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);
+NETAPI_TIMER_GROUP_HANDLE_T ourTimerBlock;
+NETAPI_TIMER_T t1;
+NETAPI_TIMER_T t2;
+NETAPI_TIMER_T t3;
+
+void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,
+ int n_fired, //# timers fired
+ NETAPI_TIMER_LIST_T fired_list,
+ uint64_t currentTime);
+
+NETCP_CFG_IP_T ip_rule0;
+NETCP_CFG_IP_T ip_rule1;
+NETCP_CFG_CLASS_T class_0;
+NETCP_CFG_CLASS_T class_1;
+NETCP_CFG_CLASS_T class_2;
+NETCP_CFG_FLOW_HANDLE_T specialFlow;
+
+NETCP_CFG_CLASSIFIER_T class_0_cfg=
+{
+ NETCP_CFG_CLASS_TYPE_L4,
+ {
+ {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2500}}
+ }
+};
+
+NETCP_CFG_CLASSIFIER_T class_1_cfg=
+{
+ NETCP_CFG_CLASS_TYPE_L4,
+ {
+ {0,0, NWAL_APP_PLOAD_PROTO_UDP, {2502}}
+ }
+};
+
+NETCP_CFG_ROUTE_T class2_route=
+{
+NULL, NULL //* to be filled in
+};
+NETCP_CFG_CLASSIFIER_T class_2_cfg=
+{
+ NETCP_CFG_CLASS_TYPE_L3_L4,
+ {
+ {0, 4 ,0/*fill in below*/ , NULL, NULL, //L2/L3
+ NWAL_APP_PLOAD_PROTO_UDP, {2504}} //L4
+ }
+};
+
+PKTIO_CONTROL_T zap_channel_control={PKTIO_CLEAR, NULL};
+
+/* security objects. (for loopback mode) */
+NETCP_CFG_SA_T rx_tunnel;
+NETCP_CFG_SA_T tx_tunnel;
+NETCP_CFG_IPSEC_POLICY_T rx_policy;
+void * rx_data_mode_handle;
+void * tx_data_mode_handle;
+void * rx_inflow_mode_handle;
+void * tx_inflow_mode_handle;
+/* rx */
+NETAPI_SEC_SA_INFO_T rx_sa=
+{
+ NWAL_SA_DIR_INBOUND,
+ 0x44444444, //spi
+ nwal_IpSecProtoESP, //ESP mode
+ nwal_SA_MODE_TUNNEL, //tunnel mode
+ nwal_IPV4, //v4
+ { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Src IP (them) -> set below */
+ { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* dst IP (us)-> set below*/
+ 64,/* replayWindow */
+ NWAL_SA_AALG_HMAC_SHA1,
+ NWAL_SA_EALG_AES_CBC,
+ 0,0 //na
+};
+
+/*tx */
+NETAPI_SEC_SA_INFO_T tx_sa=
+{
+ NWAL_SA_DIR_OUTBOUND,
+ 0x44444444, //spi
+ nwal_IpSecProtoESP, //ESP mode
+ nwal_SA_MODE_TUNNEL, //tunnel mode
+ nwal_IPV4, //v4
+ { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Src IP (us) -> set below */
+ { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* dst IP (them) -> set below*/
+ 64, /* NA replayWindow */
+ NWAL_SA_AALG_HMAC_SHA1,
+ NWAL_SA_EALG_AES_CBC,
+ 0,0 //seq no
+};
+
+//since we are doing loopback, the rx key params = tx key params
+static nwalSecKeyParams_t ourTXKeyParams =
+{
+ 16, /* encKeySize: CTR 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_DES_CBC and 0 bytes Salt*/
+ 20, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_MD5 */
+ NULL, //set below
+ NULL, //set below
+};
+
+static nwalSecKeyParams_t ourRXKeyParams ={
+ 16, /* encKeySize: 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_DES_CBC and 0 bytes Salt*/
+ 20, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_MD5 */
+ NULL, //set below
+ NULL, //set below
+};
+
+//keys
+static uint8_t ourAuthKey[36] =
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 };
+static uint8_t ourEncrKey[36] =
+ {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ 0x30, 0x31, 0x32, 0x33 };
+
+
+/*************************END NETAPI OBJECTS***********************/
+
+#define START_SRC_IP 0x0a00000a
+#define DST_IP 0xc0a80001
+#define NEW_START_SRC_IP 0x9eda000a
+#define DST_PORT 0x555
+#define START_SRC_PORT 0x1234
+#define NEW_START_SRC_PORT 100
+void update_header(HEAD_T * p_head, int len)
+{
+ unsigned char *p = (unsigned char *) &p_head->udp[1];
+ len -= (20+14);
+ /* update ip checksum */
+ /* update udp checksum */
+ /* update length */
+ *p= (len&0xff00)>>8;
+ *(p+1) = len&0xff;
+}
+
+#if 0
+void gen_pkts(int np)
+{
+int i;
+int ip = START_SRC_IP &0xff;
+int port= START_SRC_PORT;
+//HEAD_T temp={{0x25000200,0xdead0000,0x80110000,START_SRC_IP,DST_IP},
+// {START_SRC_PORT<<16|DST_PORT,0x01ec<<16|0x0000}};
+HEAD_T temp;
+memcpy(&temp,&testPkt[0],sizeof(HEAD_T));
+
+for(i=0;(i<np) && (i<NP);i++)
+ {
+ memcpy(&pkts[i],&temp,sizeof(temp));
+ update_header(&pkts[i],512); /* update checksums etc */
+ /* change template for new pkt */
+ ip+=1;
+ if(ip>254) {(ip=START_SRC_IP&0xff); port+=1; }
+ temp.ip[3] = htonl((START_SRC_IP&0xffffff00)| ip);
+ temp.udp[0] = htonl( (temp.udp[0]&0xffff0000)| port);
+ temp.udp[1] = htonl(temp.udp[1]);
+
+ }
+ n_pkt=np;
+}
+#endif
+
+void build_table(Trie * p_trie)
+{
+int i;
+int sport=NEW_START_SRC_PORT;
+HEAD_T temp,temp2;
+KEY_T key;
+
+memcpy(&temp,&testPkt[14],sizeof(temp));
+
+ //insert entry into trie
+key.src_ip = temp.ip[3];
+key.dst_ip = temp.ip[4];
+key.src_port= (temp.udp[0]&0xffff0000)>>16;
+key.dst_port= (temp.udp[0]&0x0000ffff);
+trie_insert(p_trie,(char *)&key,sizeof(key), (void *) &nat[0]); //asociate with nat entry 0
+
+//build nat table
+for(i=0;i<100;i++)
+{
+ memcpy(&temp2,&testPkt[14],sizeof(temp));
+ temp2.udp[0] = (temp2.udp[0] & 0xffff0000) | sport;
+ memcpy(&nat[i], &temp2, sizeof(temp2));
+ sport+= 1;
+}
+}
+
+//===========stub transmitter==================
+void send_pkt(Ti_Pkt *pkt, int len)
+{
+//just free pkt. Don't send
+Pktlib_freePacket((Ti_Pkt*)pkt);
+ return;
+}
+
+//==========stub slow path============
+void slow_path(Ti_Pkt *pkt, int len)
+{
+// debug: check descriptor for validity by verifying that desciptor link field is null as expected\n");
+ {Ti_Pkt * k= Pktlib_getNextPacket(pkt); if(k != 0) {printf(" slowpath, nexpkt != NULL");}}
+//just free pkt
+Pktlib_freePacket((Ti_Pkt*)pkt);
+ return;
+}
+/* check header */
+struct LastPktInfo
+{
+int iface;
+int ipcsum;
+int l4csum;
+} ;
+static struct LastPktInfo lpInfo;
+
+int check_header(HEAD_T * p_head, PKTIO_METADATA_T * p_meta)
+{
+if (NWAL_RX_FLAG1_META_DATA_VALID & p_meta->u.rx_meta->rxFlag1)
+{
+lpInfo.iface = ((unsigned int)p_meta->u.rx_meta->appId) &0xff; //last byte is interface num
+lpInfo.ipcsum =(p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_MASK )== NWAL_RX_FLAG1_IPV4_CHKSUM_VERIFY_ACK ? 1 : 0;
+lpInfo.l4csum = (p_meta->u.rx_meta->rxFlag1 & NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_MASK )== ((NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_ACK) << NWAL_RX_FLAG1_L4_CHKSUM_VERIFY_SHIFT) ? 1 : 0;
+if ((unsigned int)p_meta->u.rx_meta->appId & NETAPI_NETCP_MATCH_IPSEC)
+{
+ stats.sec_rx++;
+}
+if ((unsigned int)p_meta->u.rx_meta->appId & NETAPI_NETCP_MATCH_IPSEC_POLICY)
+{
+ stats.secp_rx++;
+}
+
+if ((unsigned int)p_meta->u.rx_meta->appId & NETAPI_NETCP_MATCH_CLASS)
+{
+ int c= ((unsigned int)p_meta->u.rx_meta->appId >>8)&0xffff;
+ if (c==0) stats.n_class0_rx +=1;
+ else if (c==1) stats.n_class1_rx +=1;
+ else if (c==2) stats.n_class2_rx +=1;
+ else printf("**NET_TEST RX -unknown class: %x\n", p_meta->u.rx_meta->appId);
+}
+}
+
+ return 1;
+}
+
+#define PKT_LEN 1400
+void test_alloc_free(int n)
+{
+int i;
+Ti_Pkt * b;
+
+for(i=0;i<n;i++)
+{
+ b=Pktlib_allocPacket(OurHeap,PKT_LEN);
+ Pktlib_freePacket(b);
+}
+}
+
+//measurement test points
+unsigned int vv1;
+unsigned int vv2;
+unsigned int vv3;
+unsigned int vv4;
+unsigned int vv5;
+unsigned int vv6;
+//these are updated by pktio.
+unsigned int vv7p;
+unsigned int vv8p;
+unsigned int vv9p;
+unsigned int vv10p;
+unsigned int vv11p;
+unsigned int vv12p;
+
+unsigned int vv11;
+
+unsigned int vv13p; //rcv path
+unsigned int vv14p;
+unsigned int vv15p;
+
+extern unsigned int nwal_prof1,nwal_prof2,nwal_prof3,nwal_prof4,nwal_prof5,nwal_prof6;
+
+//#define REASSEMBLE_BENCH
+#ifdef REASSEMBLE_BENCH
+#include <ti/drv/pa/example/reassemLib/reassemLib.h>
+/*--------------reassembly benchmark--------------------------------*/
+void our_reassemble_bench(int nfrags)
+{
+paIPReassemblyConfig_t Config={5,128,10000 };
+int i,j;
+int len;
+Ti_Pkt tip;
+char *buffer;
+unsigned long v1;
+unsigned long v2;
+unsigned long sum1=0;
+unsigned long sum2=0;
+paEx_reassemLibInit(&Config);
+for(j=0;j<200/nfrags;j++)
+{
+ for(i=0;i<nfrags;i++)
+ {
+ short temp;
+ tip=Pktlib_allocPacket(OurHeap,PKT_LEN);
+ Pktlib_getDataBuffer(tip,(uint8_t**)&buffer,&len);
+ memcpy(&buffer[0],&testPkt[14],20); //IP header
+ if (i < (nfrags-1)) buffer[6] = 0x20;
+ temp = i*40;
+ buffer[6]|= (temp&0x1f00)>>8;
+ buffer[7]= (temp&0xff);
+ temp = 20+40*8;
+ buffer[2]= (temp&0xff00)>>8;
+ buffer[3]= (temp&0xff);
+ Pktlib_setPacketLen(tip, temp);
+ v1= netapi_timing_stop();
+ paEx_reassemLibProc(tip, 0xffff);
+ v2= netapi_timing_stop();
+ sum1+= v2-v1;
+ }
+ sum2 += v2-v1;
+}
+printf("reasssembly test: %d trials, %d frags/pkt %d cycles/frag %d cycles/last frag\n",j,nfrags, sum1/(j*nfrags), sum2/(j));
+}
+#endif
+
+/*--------------basic pktio send/recv benchmark----------------------*/
+unsigned int timings[10];
+void our_pktio_bench(int ntrials)
+{
+int i;
+#define NBATCH 8
+Ti_Pkt tip;
+unsigned char * pData;
+int len;
+int n;
+int err;
+int sum =0;
+
+ Osal_cache_op_measure_reset();
+ for(i=0;i<10;i++) timings[i]=0;
+ printf("calibration loop .. ");
+ for(i=0;i<1000;i++)
+ {
+ vv1= netapi_timing_stop();
+ vv2= netapi_timing_stop();
+ sum+=(vv2-vv1);
+ }
+ printf(" accuracy = +- %d cycles\n", sum/1000);
+ sleep(1);
+
+PKTIO_METADATA_T meta[10]={0};
+//send single, recv single
+for(i=0;i<ntrials;i++)
+{
+ vv1= netapi_timing_stop();
+ tip=Pktlib_allocPacket(OurHeap,PKT_LEN);
+ vv2= netapi_timing_stop();
+ Pktlib_getDataBuffer(tip,&pData,&len);
+ vv3= netapi_timing_stop();
+ pktio_send(our_chan,tip,&meta[0],&err);
+ vv4= netapi_timing_stop();
+ n=pktio_poll(our_chan,NULL , &err);
+ vv5= netapi_timing_stop();
+ timings[0]+=(vv6-vv4);
+ timings[1]+=(vv5-vv4);
+ timings[2]+=(vv7p-vv4);
+ timings[3]+=(vv4-vv3);
+ timings[4]+=(vv8p-vv3);
+ timings[5]+=(vv3-vv1);
+ timings[6]+=(vv9p-vv8p);
+ timings[7]+=(vv10p-vv7p);
+ timings[8]+=(vv11-vv6);
+}
+ printf("pktio bench. rx=%d (wcb%d) (toqm%d) tx=%d (toqm%d) alloc=%d qpush=%d qpop=%d free=%d\n", timings[0]/ntrials,
+ timings[1]/ntrials, timings[2]/ntrials,timings[3]/ntrials, timings[4]/ntrials,timings[5]/ntrials,
+ timings[6]/ntrials,timings[7]/ntrials, timings[8]/ntrials );
+ printf("raw qpop = %d raw qpush = %d pa2va = %d ", pktio_get_qop_time(),
+ pktio_get_qpush_time(),
+ pktio_get_pa2va_time());
+{
+ unsigned int ccycles;
+ int n_c_ops;
+ ccycles =Osal_cache_op_measure(&n_c_ops);
+ printf("n_c_ops=%d cache_op_time=%d (total) = %d (pp)\n", n_c_ops, ccycles, n_c_ops? (ccycles/(n_c_ops)) : 0);
+}
+
+}
+/*-----------test driver: gen an input pkt------- */
+//char buffer[sizeof(HEAD_T)+PKT_LEN];
+Ti_Pkt * get_pkt(int n, unsigned int *p_len)
+{
+ int ind;
+ long long temp;
+ Ti_Pkt * b;
+ char * buffer;
+ unsigned int len;
+
+ if (pktloopback==0)
+ {
+ if (n>=TX_BURST) return NULL; //just gen pkts to warm swtich, so that it knows
+ //our mac is valid
+ }
+ b=Pktlib_allocPacket(OurHeap,PKT_LEN);
+ if (!b)
+ {printf("net_test: get_pkt() heap empty!! %d pkts gen'd %d \n", n); return NULL;};
+
+ //debug - way to validate descriptor
+ {Ti_Pkt* k= Pktlib_getNextPacket(b);
+ if(k != 0) {printf(" genpkt, nexpkt != NULL");}}
+
+
+ //get pointer to buffer area of packet
+ Pktlib_getDataBuffer(b,(uint8_t**)&buffer,&len);
+ if (!buffer)
+ {printf("net_test: get_pkt() heap returned empty buffer %d \n", n); return NULL;};
+
+#if 0
+if (pktloopback==0)
+{
+ temp = (long long) rand();
+ temp *= PKT_LEN;
+ temp /= RAND_MAX;
+ temp +=2;
+ *p_len = (int) temp;
+ *p_len = *p_len &0xfffffffe;
+ temp = (long long) rand();
+ temp *= n_pkt;
+ temp /= RAND_MAX;
+ ind = (int) temp;
+ update_header(&pkts[ind],*p_len);
+ //printf("get pkt:%d %d ind=%d len=%d\n",RAND_MAX, rand(),ind, *p_len);
+ memcpy(&buffer[0], &mac_header[0],14);
+ memcpy(&buffer[14],(char*)&pkts[ind],sizeof(HEAD_T));
+}
+else
+#endif
+
+ //copy test packet into buffer
+{
+ memcpy(&buffer[0], &testPkt[0],TEST_PKT_LEN);
+ *p_len = TEST_PKT_LEN;
+}
+ return b;
+}
+
+
+/*--------------------------------------------------------------
+ *----------utility to flip a packet and send
+ *--------------------back to source----------------------------
+ * flag=1 => ipsec
+ *--------------------------------------------------------------*/
+void flip_and_send_pkt(Ti_Pkt *tip, unsigned char * p_pkt, int len, int flag)
+{
+unsigned char mac_temp[6];
+unsigned char ip_temp[4];
+unsigned char new_dest_port[2]={0x75,0x30}; // 30000
+uint16_t blah;
+//mac
+memcpy(&mac_temp,&p_pkt[0],6);
+memcpy(&p_pkt[0],&p_pkt[6],6);
+memcpy(&p_pkt[6],&mac_temp,6);
+//memcpy(&p_pkt[0],real_mac_header,6); //for testing to wireshark pc
+
+//ip (outer in case of ipsec)
+memcpy(&ip_temp, &p_pkt[14+12],4);
+memcpy(&p_pkt[14+12],&p_pkt[14+12+4],4);
+memcpy(&p_pkt[14+12+4],&ip_temp,4);
+
+//outer checksum to 0
+if (!flag) memset(&p_pkt[14+10],0,2);
+
+//inner ip &udp for ipsec
+if (flag)
+{
+ //just drop non-udp packet
+ if (p_pkt[14+20+8+16+9]!=0x11)
+ {
+ stats.n_new+=1;Pktlib_freePacket(tip); return;
+ }
+
+//spi
+//memset(&p_pkt[14+20],0x88,4);
+//inner ip
+memcpy(&ip_temp, &p_pkt[14+20+8+16+12],4);
+memcpy(&p_pkt[14+20+8+16+12],&p_pkt[14+20+8+16+12+4],4);
+memcpy(&p_pkt[14+20+8+16+12+4],&ip_temp,4);
+
+//udp
+memcpy(&p_pkt[14+20+8+16+20+2],&new_dest_port[0],2);
+memset(&p_pkt[14+20+8+16+20+6],0,2); //checksum
+
+#ifdef IPSEC_MODE_TX_SIDEBAND
+
+//inner ip checksum : leave alone
+#if 0
+blah=test_utilOnesCompChkSum (&p_pkt[14+20+8+16], 10);
+p_pkt[14+20+8+16+10]= (blah&0xff00)>>8;
+p_pkt[14+20+8+16+11]= blah&0xff;
+#endif
+
+//tbd udp checksum (leave at 0)
+
+//outer ip, set to 0 (we will compute on way out
+memset(&p_pkt[14+10],0,2);
+
+#else //inflow, don't touch outer , clear inner
+memset(&p_pkt[14+20+8+16+10],0,2); //inner checksum, we will compute on way out
+//outer ip checksum : leave alone
+#if 0
+blah = test_utilOnesCompChkSum (&p_pkt[14], 10);
+p_pkt[14+10]= (blah&0xff00)>>8;
+p_pkt[14+11]= blah&0xff;
+#endif
+#endif
+}
+else
+{
+memset(&p_pkt[14+20+6],0,2);//0 udp checksum (we will compute on way out
+memcpy(&p_pkt[14+20+2],&new_dest_port[0],2);
+}
+
+//IPSEC case,
+if (flag)
+{
+#ifdef IPSEC_MODE_TX_SIDEBAND
+ //send to crypto for encryption
+//12 byte auth tag
+ {
+ PKTIO_METADATA_T meta = {PKTIO_META_SB_TX,{0},0};
+ int err;
+ nwalDmTxPayloadInfo_t meta_tx={0};
+ meta.sa_handle=tx_data_mode_handle; //use TX SA context
+ meta_tx.ploadLen = len;
+ meta_tx.encOffset = 14+20+8+16 ;
+ meta_tx.authOffset =14+20 ;
+ meta_tx.encSize=len - 14- 20-8-16-12;
+ meta_tx.authSize= len -14-20-12;
+ meta_tx.encIvSize=16;
+ meta_tx.pEncIV= &p_pkt[14+20+8]; //just use same IV..
+ meta_tx.authIvSize=0;
+ meta_tx.pAuthIV=NULL;
+ meta_tx.aadSize=0;
+ meta_tx.pAad=NULL;
+ /* post it to netcp sb tx channel*/
+ meta.u.tx_sb_meta=&meta_tx;
+ pktio_send(netcp_sb_tx_chan,tip,&meta,&err);
+ }
+
+#else
+ {
+ //inflow tx
+ //send pkt directly, asking for IP and UDP checksum offloads AND IPSEC to be applied
+ PKTIO_METADATA_T meta = {PKTIO_META_TX,{0},0};
+ int err;
+ nwalTxPktInfo_t meta_tx={0};
+ meta.sa_handle=tx_inflow_mode_handle; //this tells netapi that inflow crypto needs to be applied
+ meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM|NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_DO_IPSEC_CRYPTO| NWAL_TX_FLAG1_META_DATA_VALID );
+ meta_tx.saOffBytes=14+20;
+ meta_tx.saPayloadLen=len-14-20; //don't include tag, mac and outer header
+ meta_tx.startOffset = 0;
+ meta_tx.ipOffBytes = 14+20+8+16; //to inner header
+ meta_tx.l4OffBytes = 14+20+8+16+20; //to L4
+ meta_tx.l4HdrLen = 8;
+ meta_tx.ploadLen = (unsigned) ((p_pkt[14+20+8+16+20+4]<<8)|p_pkt[14+20+8+16+20+4+1]) -8 ;
+ meta_tx.pseudoHdrChecksum =
+ test_utilGetIpv4PsudoChkSum(&p_pkt[14+20+8+16],8+ meta_tx.ploadLen);
+
+ /* post it to netcp tx channel*/
+ meta.u.tx_meta=&meta_tx;
+ pktio_send(netcp_tx_chan,tip,&meta,&err);
+ stats.tx +=1;
+ stats.sec_tx +=1;
+ }
+#endif
+
+
+}
+else //non ipsec send pkt directly, asking for IP and UDP checksum ofload
+{
+ PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
+ int err;
+ nwalTxPktInfo_t meta_tx2={0};
+ meta2.sa_handle=nwal_HANDLE_INVALID;
+ meta_tx2.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM|NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID );
+ meta_tx2.startOffset = 0;
+ meta_tx2.ipOffBytes = 14;
+ meta_tx2.l4OffBytes = 14+20;
+ meta_tx2.l4HdrLen = 8;
+ meta_tx2.ploadLen = (unsigned) ((p_pkt[14+20+4]<<8)|p_pkt[14+20+4+1]) -8 ;
+ meta_tx2.pseudoHdrChecksum =
+ test_utilGetIpv4PsudoChkSum(&p_pkt[14],8+ meta_tx2.ploadLen);
+
+ /* post it to netcp tx channel*/
+ meta2.u.tx_meta=&meta_tx2;
+ pktio_send(netcp_tx_chan,tip,&meta2,&err);
+ stats.tx +=1;
+}
+}
+
+
+
+
+/***************************************
+ benchmark receive handler
+****************************************/
+void recv_cb_bench(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
+ PKTIO_METADATA_T meta[], int n_pkts,
+ uint64_t ts )
+{
+ int i;
+ vv6= netapi_timing_stop();
+ for (i=0;i<n_pkts; i++)
+ {
+ Pktlib_freePacket(p_recv[i]);
+ }
+ vv11 = netapi_timing_stop();
+}
+
+/****************************************************************************************/
+/******************SB Accelerator Callback PKT RECEIVE HANDLER *************************/
+/****************** Handles Decrypt and Encrypt operation callbacks ******************/
+/******************************************************************************************/
+void recv_sb_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
+ PKTIO_METADATA_T meta[], int n_pkts,
+ uint64_t ts )
+{
+int i;
+int len;
+int p;
+HEAD_T * p_res;
+Ti_Pkt * tip;
+unsigned int templen;
+int err;
+KEY_T key;
+char * p_pkt;
+HEAD_T * p_head;
+HEAD_T temp_head;
+int tag_cmp=0;
+unsigned int hash[3];
+
+ /* loop over received pkts */
+ for(i=0;i<n_pkts;i++)
+ {
+ tip = p_recv[i];
+ Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
+ len = Pktlib_getPacketLen(tip);//real length
+
+ //is this a decrypt (rx_tunnel) complete
+ if (meta[i].u.rx_sb_meta->appId == rx_tunnel)
+ {
+ stats.sb_rx+=1;
+ //copy hash out of meta data (for some reason it needs endian conversion)
+ hash[0]= htonl( meta[i].u.rx_sb_meta->pAuthTag[0]);
+ hash[1]= htonl( meta[i].u.rx_sb_meta->pAuthTag[1]);
+ hash[2]= htonl( meta[i].u.rx_sb_meta->pAuthTag[2]);
+
+ if(stats.sb_rx<=16)
+ {
+ char *tp = (char *) &hash[0];
+ dump_header((long*)p_pkt, stats.sb_rx, meta[i].u.rx_sb_meta->appId,0);
+ printf("tag in pkt=%x %x %x %x %x %x %x %x %x %x %x %x\n",
+ p_pkt[len-12],p_pkt[len-11],p_pkt[len-10],p_pkt[len-9], p_pkt[len-8],
+ p_pkt[len-7],p_pkt[len-6],
+ p_pkt[len-5],p_pkt[len-4],p_pkt[len-3],p_pkt[len-2],p_pkt[len-1]);
+ printf("tag from SA=%x %x %x %x %x %x %x %x %x %x %x %x\n",
+ tp[0],tp[1],tp[2],tp[3],tp[4],tp[5],
+ tp[6],tp[7],tp[8],tp[9],tp[10],tp[11]);
+ }
+ //check tag
+ tag_cmp = memcmp(&p_pkt[len-12],(char*) &hash[0],12); //todo, really use meta->authTagLen
+ stats.n_auth_ok += !(tag_cmp);
+ flip_and_send_pkt(tip, p_pkt, len,1); //flip packet to echo back and send
+ }
+ //this is an encrypt (tx tunnel) complete
+ else if(meta[i].u.rx_sb_meta->appId== tx_tunnel )
+ {
+ hash[0]= htonl( meta[i].u.rx_sb_meta->pAuthTag[0]);
+ hash[1]= htonl( meta[i].u.rx_sb_meta->pAuthTag[1]);
+ hash[2]= htonl( meta[i].u.rx_sb_meta->pAuthTag[2]);
+ stats.sb_tx+=1;
+ if(stats.sb_tx<=16)
+ {
+ char *tp1 = (char *) &hash[0];
+ dump_header((long*)p_pkt, stats.sb_tx, meta[i].u.rx_sb_meta->appId,0);
+ printf("tag in original rx pkt=%x %x %x %x %x %x %x %x %x %x %x %x\n",
+ p_pkt[len-12],p_pkt[len-11],p_pkt[len-10],p_pkt[len-9], p_pkt[len-8],
+ p_pkt[len-7],p_pkt[len-6],
+ p_pkt[len-5],p_pkt[len-4],p_pkt[len-3],p_pkt[len-2],p_pkt[len-1]);
+
+ printf("tag from SA=%x %x %x %x %x %x %x %x %x %x %x %x\n",
+ tp1[0],tp1[1],tp1[2],tp1[3],tp1[4],tp1[5],
+ tp1[6],tp1[7],tp1[8],tp1[9],tp1[10],tp1[11]);
+ }
+ //put the computed tag in the packet
+ memcpy(&p_pkt[len-12],(char*)&hash[0],12); //todo, really use meta->authTagLen
+ {
+ PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
+ nwalTxPktInfo_t meta_tx={0};
+ // now send directly
+ meta2.sa_handle=nwal_HANDLE_INVALID;
+ meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID);//only outer IP header checksum. no udp checksum possible since pkt is already encrypted
+ meta_tx.startOffset = 0;
+ meta_tx.ipOffBytes = 14;
+ //not used
+ meta_tx.l4OffBytes = 0;
+ meta_tx.l4HdrLen = 0;
+ meta_tx.ploadLen = 0;
+
+ /* post it to netcp tx channel*/
+ meta2.u.tx_meta=&meta_tx;
+ pktio_send(netcp_tx_chan,tip,&meta2,&err);
+ stats.tx +=1;
+ }
+ }
+ else printf("netapi recv_sb_cb: unknown appiD %x \n",meta[i].u.rx_sb_meta->appId );
+ }
+}
+
+/******************************************************/
+/******************PKT RECEIVE HANDLER *************************/
+/******************************************************/
+void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
+ PKTIO_METADATA_T meta[], int n_pkts,
+ uint64_t ts )
+{
+int i;
+int len;
+int p;
+HEAD_T * p_res;
+Ti_Pkt * tip;
+unsigned int templen;
+int err;
+KEY_T key;
+char * p_pkt;
+HEAD_T * p_head;
+HEAD_T temp_head;
+
+ p_head=&temp_head;
+
+ //debug
+#if 0
+ if (n_pkts != TX_BURST) {
+ printf("recv_cb, txsofar=%d rxsofar=%d np = %d, NOT %d\n",
+ stats.itx, stats.rx, n_pkts,TX_BURST);
+ our_stats_cb(netapi_handle,NULL);
+ }
+#endif
+ //test_alloc_free(7);
+ //printf("recv start\n");
+
+ /* loop over received pkts */
+ for(i=0;i<n_pkts;i++)
+ {
+ tip = p_recv[i];
+ Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
+ len = Pktlib_getPacketLen(tip)-4;//real length, subtract mac trailer
+
+ //debug: validate descriptor */
+ if(Pktlib_getNextPacket(tip) != 0) {printf(" rcv_cb, nexpkt != NULL");}
+ //debug printf("recv pkt, len=%d %d\n", len, templen);
+ stats.rx+=1;
+
+#ifdef DEBUG_DESC
+ if (stats.rx<16){printf(">rx dmp.."); dump_descr((long *) tip, stats.rx);}
+ else if (stats.rx>99) {printf(">rx dmp.."); dump_descr((long *) tip,stats.rx);}
+#endif
+ if(stats.rx<=16)
+ {
+ dump_header((long*)p_pkt, stats.rx, meta[i].u.rx_meta->appId,meta[i].u.rx_meta->rxFlag1);
+ }
+ /* check header */
+ memcpy(p_head,&p_pkt[14],sizeof(HEAD_T));
+
+ if ((p_head->ip[2]&0x0000ff00)==0x00003200)
+ {
+ if (!check_header(p_head,&meta[i])) {
+ stats.n_bad+=1;Pktlib_freePacket(tip); continue;
+ }
+
+ //process IP SEC PACKET
+#ifdef IPSEC_MODE_RX_SIDEBAND
+ {
+ //ship to crypto for decrypt!!
+ //12 byte auth tag
+ PKTIO_METADATA_T meta2 = {PKTIO_META_SB_TX,{0},0};
+ nwalDmTxPayloadInfo_t meta_tx={0};
+ meta2.sa_handle=rx_data_mode_handle;
+ meta_tx.ploadLen = len;
+ meta_tx.encOffset = 14+20+8+16 ;
+ meta_tx.authOffset =14+20 ;
+ meta_tx.encSize=len - 14- 20-8-16-12;
+ meta_tx.authSize= len -14-20-12;
+ meta_tx.encIvSize=16;
+ meta_tx.pEncIV= &p_pkt[14+20+8];
+ meta_tx.authIvSize=0;
+ meta_tx.pAuthIV=NULL;
+ meta_tx.aadSize=0;
+ meta_tx.pAad=NULL;
+ /* post it to netcp sb tx channel*/
+ meta2.u.tx_sb_meta=&meta_tx;
+ pktio_send(netcp_sb_tx_chan,tip,&meta2,&err);
+ continue;
+ }
+#else
+ //inflow mode. flip and send
+ flip_and_send_pkt(tip,p_pkt,len,1);
+#endif
+ }
+ else if ((p_head->ip[2]&0x0000ff00)!=0x00001100)
+ {
+ stats.n_new+=1;Pktlib_freePacket(tip); continue;
+ }
+ else //non ipsec
+ {
+ if (!check_header(p_head,&meta[i])) {
+ stats.n_bad+=1;Pktlib_freePacket(tip); continue;
+ }
+
+#if 0
+ /* lookup flow */
+ key.src_ip = p_head->ip[3];
+ key.dst_ip = p_head->ip[4];
+ key.src_port= (p_head->udp[0]&0xffff0000)>>16;
+ key.dst_port= (p_head->udp[0]&0x0000ffff);
+ p_res= (HEAD_T *) trie_lookup(P_trie, (char *) &key, sizeof(key));
+ if (!p_res) { stats.n_new+=1; slow_path(tip, len); continue;}
+
+ /* copy header */
+ memcpy((char *) p_head, (char *) p_res, sizeof(HEAD_T));
+
+ memcpy(&p_pkt[14],p_head,sizeof(HEAD_T));
+ /* update_mac(&p_pkt[0]); */
+
+ /* 'simulate' send pkt */
+ send_pkt(tip,len);
+#endif
+ //just flip and send
+ flip_and_send_pkt(tip,p_pkt,len,0);
+ }
+ }
+ //printf("recv done\n");
+}
+
+//timer callback
+void our_timer_cb( NETAPI_TIMER_GROUP_HANDLE_T th,
+ int n_fired, //# timers fired
+ NETAPI_TIMER_LIST_T fired_list,
+ uint64_t currentTime)
+{
+int i;
+NETAPI_TIMER_T tx;
+int cookie;
+int err;
+unsigned long long et;
+//DEBUGprintf("TIMER CALLBACK @ %lld %d timers\n", currentTime, n_fired);
+tx = netapi_TimerGetFirst(fired_list);
+for(i=0;i<n_fired;i++)
+{
+ cookie = (int) netapi_TimerGetCookie(tx);
+ et = netapi_TimerGetTs(tx); //debug
+ //DEBUGprintf(" timer %d - cookie = %d expected ts=%lld (delta=%lld)\n", i, cookie, et, currentTime-et);
+ if (cookie ==1)
+ {
+ stats.n_t1+=1;
+ t1 = netapi_TimerGroupStartTimer(
+ th,
+ (void *) 1,
+ 100LL, //timer group tics
+ &err);
+ }
+ else if (cookie ==2)
+ {
+ stats.n_t2+=1;
+ t2 = netapi_TimerGroupStartTimer(
+ th,
+ (void *) 2,
+ 200LL, //timer group ticks
+ &err);
+ }
+ else
+ {
+ stats.n_t3+=1;
+ t3 = netapi_TimerGroupStartTimer(
+ th,
+ (void *) 3,
+ 300LL, //timer group ticks
+ &err);
+ //cancel 1 and restart 1
+ netapi_TimerGroupCancel(th,t1,&err);
+ t1 = netapi_TimerGroupStartTimer(
+ th,
+ (void *) 1,
+ 100LL, //timer group ticks
+ &err);
+ }
+ tx = netapi_TimerGetNext(fired_list,tx);
+}
+}
+
+
+static int np2process = NP;
+/******************************************************
+ * stats callback
+ *******************************************************/
+void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats)
+{
+uint32_t numFreeDataPackets;
+uint32_t numZeroBufferPackets;
+uint32_t numPacketsinGarbage;
+Pktlib_HeapStats pktLibHeapStats;
+
+printf(">*****stats @ %lld\n", netapi_getTimestamp());
+//printf("netcp_tx_handle check %x\n", netcp_tx_chan->back);
+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\n n_t1=%d n_t2=%d n_t3=%d\n",stats.itx, stats.rx, stats.tx, stats.n_bad, stats.n_new,
+ stats.n_class0_rx, stats.n_class1_rx,
+ stats.n_class2_rx, stats.sec_rx, stats.secp_rx, stats.sb_rx, stats.sb_tx, stats.n_auth_ok,
+ stats.n_t1, stats.n_t2,stats.n_t3);
+
+if(pPaStats)
+{
+ printf("C1 number of packets: %d\n", pPaStats->classify1.nPackets);
+ printf("C1 number IPv4 packets: %d\n", pPaStats->classify1.nIpv4Packets);
+ //printf("C1 number llc/snap fail: %d\n", pPaStats->classify1.nLlcSnapFail);
+ printf("C1 number table matched: %d\n", pPaStats->classify1.nTableMatch);
+ printf("C1 number failed table matched: %d\n", pPaStats->classify1.nNoTableMatch);
+ printf ("C1 number of parse fail: %d\n",pPaStats->classify1.nParseFail);
+ printf("C1 number of command failures: %d\n", pPaStats->classify1.nCommandFail);
+ printf("C1 number invalid reply dests: %d\n", pPaStats->classify1.nInvalidComReplyDest);
+ printf ("C1 number of silent discard: %d\n",pPaStats->classify1.nSilentDiscard);
+ printf("C1 number of invalid control: %d\n", pPaStats->classify1.nInvalidControl);
+ printf ("C1 number of invalid states: %d\n",pPaStats->classify1.nInvalidState);
+ printf ("C1 number of system fails: %d\n",pPaStats->classify1.nSystemFail);
+ printf ("C2 number parse failed : %d\n",pPaStats->classify2.nParseFail);
+ printf ("C2 number Invld Header : %d\n",pPaStats->classify2.nInvldHdr);
+ printf ("C2 number udp : %d\n",pPaStats->classify2.nUdp);
+ printf ("C2 number tcp : %d\n",pPaStats->classify2.nTcp);
+ printf ("C2 number cmd fail : %d\n",pPaStats->classify2.nCommandFail);
+ printf ("C2 number silent drop : %d\n",pPaStats->classify2.nSilentDiscard);
+ printf ("C2 number invalid cntrl : %d\n\n",pPaStats->classify2.nInvalidControl);
+}
+Pktlib_getHeapStats(OurHeap, &pktLibHeapStats);
+printf("main heap stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
+ pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
+printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
+ pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
+ pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
+
+Pktlib_getHeapStats(specialSmall, &pktLibHeapStats);
+printf("specialSmall heap stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
+ pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
+printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
+ pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
+ pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
+
+
+Pktlib_getHeapStats(specialLarge, &pktLibHeapStats);
+printf("specialLarge heap stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
+ pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
+printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
+ pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
+ pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
+
+
+//debug = dump timer polling stats
+dump_poll_stats();
+
+
+}
+
+//******************************************************
+//use scheduling housekeeping callback to generate pkts
+//******************************************************
+void house(NETAPI_SCHED_HANDLE_T * s)
+{
+Ti_Pkt * tip;
+unsigned int len;
+nwalTxPktInfo_t meta_tx;
+PKTIO_METADATA_T meta = {PKTIO_META_TX,{0},0};
+int err;
+static int house_pkts_gened=0;
+int p;
+unsigned char * pIpHdr,* pData;
+unsigned int vv1,vv2,vv3;
+unsigned int sum_vv1=0;
+unsigned int sum_vv2=0;
+unsigned int sum_vv3=0;
+unsigned int sum_vv4=0;
+unsigned int sum_vv5=0;
+
+unsigned int nwal_flow_vv1,nwal_flow_vv2;
+unsigned int nwal_sum_vv1=0;
+unsigned int nwal_sum_vv2=0;
+unsigned int nwal_sum_vv3=0;
+unsigned int nwal_sum_vv4=0;
+unsigned int nwal_sum_vv5=0;
+unsigned int nwal_sum_vv6=0;
+
+unsigned int nwal_sum_flow_vv1=0;
+unsigned int nwal_sum_flow_vv2=0;
+static int first =0;
+Cppi_HostDesc* pPktDesc;
+
+Osal_cache_op_measure_reset();
+memset(&meta_tx,0,sizeof(meta_tx));
+for(p=0;p<TX_BURST;p++) {
+//reguest stats
+if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
+{
+ printf("net_test> request stats at n=%d \n",house_pkts_gened);
+ netcp_cfgReqStats(netapi_handle, our_stats_cb, 0,&err);
+ if (err!=0) {printf("stats req failed\n");}
+}
+
+
+ if (house_pkts_gened >= np2process+ 100)
+ {
+ //shutdown
+ netapi_schedShutdown(s,NULL,&err);
+ continue;
+ }
+
+ else if (house_pkts_gened >= np2process) { house_pkts_gened+=1; continue;}
+
+
+/* manufacture a pkt to transmit */
+ tip = get_pkt(house_pkts_gened, &len);
+ if(!tip) { house_pkts_gened +=1; continue; }
+
+
+ /* set the pkt length */
+ vv1 = netapi_timing_start();
+ Pktlib_setPacketLen(tip, len);
+
+ /* set up meta data */
+ meta.sa_handle=nwal_HANDLE_INVALID;
+ meta_tx.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM | NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID);
+ meta_tx.startOffset = 0;
+ //GONE in V2 meta_tx.pktLen = len;
+ meta_tx.ipOffBytes = TEST_PKT_IP_OFFSET_BYTES;
+ meta_tx.l4OffBytes = TEST_PKT_UDP_OFFSET_BYTES;
+ meta_tx.l4HdrLen = TEST_PKT_UDP_HDR_LEN;
+ //GONE in V2 meta_tx.ploadOffBytes = TEST_PKT_PLOAD_OFFSET_BYTES;
+ meta_tx.ploadLen = TEST_PAYLOAD_LEN;
+
+ Pktlib_getDataBuffer(tip,&pData,&len);
+ pIpHdr = pData + meta_tx.ipOffBytes;
+ meta_tx.pseudoHdrChecksum =
+ test_utilGetIpv4PsudoChkSum(pIpHdr,(TEST_PAYLOAD_LEN+TEST_PKT_UDP_HDR_LEN));
+
+ /* post it to netcp tx channel*/
+ meta.u.tx_meta=&meta_tx;
+#ifdef DEBUG_DESC
+ if (house_pkts_gened<16) dump_descr((long *) tip, house_pkts_gened);
+ else if (house_pkts_gened>99) dump_descr((long *) tip,house_pkts_gened);
+#endif
+
+ if(!first)
+ {
+ first++;
+ nwal_flow_vv1= netapi_timing_stop();
+ if(nwal_initPSCmdInfo(PKTIO_GET_NWAL_INSTANCE(netcp_tx_chan),
+ &meta_tx,
+ &flowPSCmdInfo) != nwal_OK)
+ {
+ printf("nwal_initPSCmdInfo() ERROR \n");
+ }
+ nwal_flow_vv2= netapi_timing_stop();
+ nwal_sum_flow_vv1 += (nwal_flow_vv1-vv1);
+ nwal_sum_flow_vv2 += (nwal_flow_vv2-nwal_flow_vv1);
+ }
+
+ vv2= netapi_timing_stop();
+ nwal_mCmdSetL4CkSumPort( tip,
+ &flowPSCmdInfo,
+ TEST_PKT_UDP_OFFSET_BYTES,
+ (TEST_PKT_UDP_HDR_LEN + TEST_PAYLOAD_LEN),
+ meta_tx.pseudoHdrChecksum,
+ meta_tx.enetPort);
+
+ pPktDesc = Pktlib_getDescFromPacket(tip);
+ /* Send the packet out to transmit Q*/
+ Qmss_queuePushDescSize (flowPSCmdInfo.txQueue,
+ pPktDesc,
+ NWAL_DESC_SIZE);
+ vv3= netapi_timing_stop();
+
+
+ sum_vv1 += (vv2-vv1);
+ if(!house_pkts_gened)
+ {
+ /* first packet. Take out the PS command label creation cost */
+ sum_vv1 = sum_vv1 - nwal_sum_flow_vv2;
+ }
+
+ sum_vv3 += (vv3-vv2);
+
+ // printf("pktio send. full=%d metadata=%d pktio_send=%d\n", vv3-vv1, vv2-vv1, vv3-vv2);
+
+
+ stats.itx +=1;
+ house_pkts_gened +=1;
+ }
+{
+ unsigned int ccycles;
+ int n_c_ops;
+ ccycles =Osal_cache_op_measure(&n_c_ops);
+ if (sum_vv1)
+ {
+ printf("BURST NWAL Fast send %d pkts. metadata=%d Cmd Label Creation Cost=%d nwal Fast Send Cost= %d n_c_ops=%d cache_op_time=%d (pp-> %d)\n",
+ stats.itx, sum_vv1/stats.itx, nwal_sum_flow_vv2, sum_vv3/stats.itx,
+ n_c_ops, ccycles, n_c_ops? (ccycles/(n_c_ops/2)) : 0);
+
+ printf("NWAL Profile Cycles: Prof1= %d,Prof2=%d,Prof3=%d,Prof4=%d,Prof5=%d ,Prof6=%d \n",
+ nwal_sum_vv1/stats.itx,nwal_sum_vv2/stats.itx,nwal_sum_vv3/stats.itx,
+ nwal_sum_vv4/stats.itx,nwal_sum_vv5/stats.itx,nwal_sum_vv6/stats.itx);
+
+
+ if(stats.itx2)
+ {
+ printf("nwal_flowSend Profile Cycles: Prof1= %d,Prof2=%d \n",
+ nwal_sum_flow_vv1/stats.itx2,nwal_sum_flow_vv2/stats.itx2);
+ }
+
+ }
+}
+}
+
+
+/***************************************
+ ********** test driver*****************
+ ***************************************/
+int main(int argc, char **argv)
+{
+int err;
+rlim_t oss,ss = 1024*1024;
+struct rlimit rl;
+
+Pktlib_HeapCfg heapCfg;
+int32_t errCode;
+Pktlib_HeapIfTable* pPktifTable;
+
+err= getrlimit(RLIMIT_STACK,&rl);
+if (!err) printf(" stack limit = %d\n",rl.rlim_cur); else printf("getrlimit failed\n");
+#if 0
+rl.rlim_cur = ss;
+err=setrlimit(RLIMIT_STACK,&rl);
+if (!err) printf("set stack to %d\n",rl.rlim_cur); else printf("setrlimit failed\n");
+#endif
+
+if (argc>=2) np2process = atoi(argv[1]);
+if (np2process<0) np2process = NP; /* default */
+if (argc==3) perslow = atoi(argv[2]);
+if ((perslow<0)||(perslow>100)) perslow=PERSLOW;//default
+if (argc>3) {printf("net_test <no of pkts to process> <percent slow path>\n"); exit(1);}
+
+
+//real mode, so update our test packet mac header and ip header
+if (pktloopback==0)
+{
+memcpy(&testPkt,&real_mac_header[0],14); //overwrite test pkt mac address
+memcpy(&testPkt[26],&real_ip_addr[0],8);//overrite test pkt ip addresses
+}
+
+/*******************************************/
+/*************NETAPI STARTUP****************/
+/*******************************************/
+
+/* create netapi */
+netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);
+
+/* open the main heap */
+OurHeap = Pktlib_findHeapByName("netapi");
+if (!OurHeap) {printf("findheapbyname fail\n"); exit(1);}
+
+/* create two secondary heaps */
+/* Initialize the heap configuration. */
+memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));
+
+pPktifTable = netapi_getPktlibIfTable();
+/* Populate the heap configuration */
+heapCfg.name = "netapi-small";
+heapCfg.memRegion = NETAPI_GLOBAL_REGION;
+heapCfg.sharedHeap = 1;
+heapCfg.useStarvationQueue = 0;
+heapCfg.dataBufferSize = 512;
+heapCfg.numPkts = 64;
+heapCfg.numZeroBufferPackets= 0;
+heapCfg.heapInterfaceTable.data_malloc = pPktifTable->data_malloc;
+heapCfg.heapInterfaceTable.data_free = pPktifTable->data_free;
+heapCfg.dataBufferPktThreshold = 0;
+heapCfg.zeroBufferPktThreshold = 0;
+
+specialSmall = Pktlib_createHeap(&heapCfg, &errCode);
+heapCfg.name = "netapi-big";
+heapCfg.dataBufferSize = 1600;
+specialLarge = Pktlib_createHeap(&heapCfg, &errCode);
+//register these heaps so poll routine will include their garbage queues.
+netapi_registerHeap(netapi_handle, specialSmall);
+netapi_registerHeap(netapi_handle, specialLarge);
+
+#ifdef REASSEMBLE_BENCH
+our_reassemble_bench(2);
+exit(1);
+#endif
+
+/* create a pktio channel */
+our_chan=pktio_create(netapi_handle,"our1stq",(PKTIO_CB) recv_cb_bench, &our_chan_cfg,&err);
+if (!our_chan) {printf("pktio create failed err=%d\n",err); exit(1);}
+
+/* open netcp default tx, rx queues */
+netcp_tx_chan= pktio_open(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg, &err);
+if (!netcp_tx_chan) {printf("pktio open TX failed err=%d\n",err); exit(1);}
+netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb, &netcp_rx_cfg, &err);
+if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}
+
+/* create a pktio channel for specially classified pkts */
+netcp_rx_chan2= pktio_create(netapi_handle, "classq", (PKTIO_CB) recv_cb, &netcp_rx_cfg2, &err);
+if (!netcp_rx_chan2) {printf("pktio create RX2 failed err=%d\n",err); exit(1);}
+
+/* open netcp default tx, rx queues for sideband crypto */
+netcp_sb_tx_chan= pktio_open(netapi_handle, NETCP_SB_TX, NULL, &netcp_sb_tx_cfg, &err);
+if (!netcp_sb_tx_chan) {printf("pktio open SB TX failed err=%d\n",err); exit(1);}
+netcp_sb_rx_chan= pktio_open(netapi_handle, NETCP_SB_RX, (PKTIO_CB) recv_sb_cb, &netcp_sb_rx_cfg, &err);
+if (!netcp_sb_rx_chan) {printf("pktio open SB RX failed err=%d\n",err); exit(1);}
+
+printf("net_test> %d bytes left in our CMA area\n", netapi_getBufMemRemainder());
+/* create scheduler instance */
+our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);
+if (!our_sched) {printf("sched create failed\n"); exit(1);}
+
+/********************************************
+* Basic pkt loopback test
+*********************************************/
+printf("...running pure push/pop benchmark\n");
+our_pktio_bench(1000);
+our_pktio_bench(1000);
+our_pktio_bench(1000);
+our_pktio_bench(1000);
+our_pktio_bench(1000);
+/*********************************************/
+
+
+
+
+/* add mac intefaces */
+netcp_cfgCreateMacInterface(
+ netapi_handle,
+ &mac0[0],
+ 0,0,
+ (NETCP_CFG_ROUTE_HANDLE_T) NULL,
+ (NETCP_CFG_VLAN_T ) NULL , //future
+ 1,
+ &err);
+if (err) {printf("addmac0 failed %d\n",err); exit(1); }
+
+//attach an IP to this interface
+ip_rule0=netcp_addIp(
+ netapi_handle,
+ 0,
+ nwal_IPV4,
+ &OurIp0,
+ NULL, //all IP
+ (NETCP_CFG_ROUTE_HANDLE_T) NULL,
+ &err
+ );
+if (err) {printf("addip0 failed %d\n",err); exit(1); }
+
+//create a 2nd mac instance
+netcp_cfgCreateMacInterface(
+ netapi_handle,
+ &mac1[0],
+ 1,1,
+ (NETCP_CFG_ROUTE_HANDLE_T) NULL,
+ (NETCP_CFG_VLAN_T ) NULL , //future
+ 1,
+ &err);
+if (err) {printf("addmac1 failed %d\n",err); exit(1); }
+
+//attach an IP to this interface
+ip_rule1=netcp_addIp(
+ netapi_handle,
+ 1,
+ nwal_IPV4,
+ &OurIp1,
+ NULL, //all IP
+ (NETCP_CFG_ROUTE_HANDLE_T) NULL,
+ &err
+ );
+if (err) {printf("addip1 failed %d\n",err); exit(1); }
+
+//attach 2 classifiers to iface 0, ip0
+class_0_cfg.u.c_l4.ip = ip_rule0;
+class_0 = netcp_cfgAddClass(netapi_handle,
+ &class_0_cfg,
+ NULL,
+ NETCP_CFG_ACTION_TO_SW,
+ &err);
+if (err) {printf("addclass0 failed %d\n",err); exit(1);}
+
+class_1_cfg.u.c_l4.ip = ip_rule0;
+class_1 = netcp_cfgAddClass(netapi_handle,
+ &class_1_cfg,
+ NULL,
+ NETCP_CFG_ACTION_TO_SW,
+ &err);
+if (err) {printf("addclass1 failed %d\n",err); exit(1);}
+
+
+//3rd classifier has a different IP and route
+class_2_cfg.u.c_l3_l4.ip_addr = &OurIp2;
+
+//create specialFlow for this classifier
+{
+Pktlib_HeapHandle heaps[2];
+int sizes[2];
+heaps[0]= specialSmall;
+heaps[1]= specialLarge;
+#define SPECIAL_SOP_OFF 128
+sizes[0]=512-SPECIAL_SOP_OFF;
+sizes[1]=1600-SPECIAL_SOP_OFF;
+specialFlow = netcp_cfgAddFlow( netapi_handle,
+ 2,
+ heaps,
+ sizes,
+ SPECIAL_SOP_OFF, //offset to start rx is 128
+ &err);
+if (err) {printf("add flow failed\n", err); exit(1);}
+}
+#if 0
+//special route for this classifier: different flow + destination q
+class2_route.p_dest_q = netcp_rx_chan2;
+class2_route.p_flow = specialFlow;
+class_2 = netcp_cfgAddClass(netapi_handle,
+ &class_2_cfg,
+ (void*) &class2_route,
+ NETCP_CFG_ACTION_TO_SW,
+ &err);
+if (err) {printf("addclass2 failed %d\n",err); exit(1);}
+#endif
+
+//security stuff
+ourRXKeyParams.pEncKey = &ourEncrKey[0];
+ourRXKeyParams.pAuthKey = &ourAuthKey[0];
+memcpy(&rx_sa.src, &TheirIp4IPSEC,4);
+memcpy(&rx_sa.dst, &OurIp4IPSEC,4);
+
+#if 1
+rx_tunnel = netapi_secAddSA( netapi_handle,
+ 0, //iface #0
+ &rx_sa,
+ &ourRXKeyParams,
+#ifdef IPSEC_MODE_RX_SIDEBAND
+ NETAPI_SEC_SA_SIDEBAND,
+#else
+ NETAPI_SEC_SA_INFLOW, //USE inflow mode
+#endif
+ NULL, //use default route
+ &rx_data_mode_handle,
+ &rx_inflow_mode_handle,
+ &err);
+if (err) {printf("addRxSa failed %d\n",err); exit(1);}
+
+#ifdef IPSEC_MODE_RX_INFLOW
+//assume inner and outer ip is the same
+rx_policy= netapi_secAddRxPolicy( netapi_handle,
+ rx_tunnel, //link to tunnel above
+ 4, //ipv4
+ &TheirIp4IPSEC, //src -> them
+ &OurIp4IPSEC, //dst -> us
+ NULL, // no qualifiers
+ NULL, //default route
+ &err);
+if (err) {printf("addSaPolicy failed %d\n",err); exit(1);}
+#else
+rx_policy = 0;
+#endif
+#endif
+
+//tx SA
+//security stuff
+ourTXKeyParams.pEncKey = &ourEncrKey[0];
+ourTXKeyParams.pAuthKey = &ourAuthKey[0];
+memcpy(&tx_sa.src, &OurIp4IPSEC,4);
+memcpy(&tx_sa.dst, &TheirIp4IPSEC,4);
+tx_tunnel = netapi_secAddSA( netapi_handle,
+ 0, //iface #0
+ &tx_sa,
+ &ourTXKeyParams,
+#ifdef IPSEC_MODE_TX_SIDEBAND
+ NETAPI_SEC_SA_SIDEBAND,
+#else
+ NETAPI_SEC_SA_INFLOW, //USE inflow mode
+#endif
+ NULL, //use default route
+ &tx_data_mode_handle,
+ &tx_inflow_mode_handle,
+ &err);
+if (err) {printf("addTxSa failed %d\n",err); exit(1);}
+
+
+#ifdef TEST_TIMERS
+//timers
+ourTimerBlock = netapi_TimerGroupCreate(
+ netapi_handle,
+ "our1sttimer",
+ our_timer_cb,
+ 0, //1 if timers local to thread
+ 0, //1 if expect to cancel
+ netapi_getTicksPerSec()/1000, /* 1 msc resolution for these timers */
+ netapi_getTicksPerSec()/5000, /* would like .5 msc tolerence */
+ 10, //small # of timers to test garbage collection
+ &err);
+if (err) {printf("timergroupcreate failed %d\n",err); exit(1);}
+
+//start a couple of timers
+t1 = netapi_TimerGroupStartTimer(
+ ourTimerBlock,
+ (void *) 1,
+ 100LL, //timer group ticks
+ &err);
+if (err) {printf("timerstart failed %d\n");}
+t2 = netapi_TimerGroupStartTimer(
+ ourTimerBlock,
+ (void *) 2,
+ 200LL, //timer group ticks
+ &err);
+if (err) {printf("timerstart failed %d\n");}
+t3 = netapi_TimerGroupStartTimer(
+ ourTimerBlock,
+ (void *) 3,
+ 300LL, //timer group ticks
+ &err);
+if (err) {printf("timerstart failed %d\n");}
+#endif
+netcp_cfgReqStats(netapi_handle, our_stats_cb, 1,&err);
+if (err!=0) {printf("stats req failed\n");}
+
+/*********************************************/
+/*****************end NETAPI STARTUP**********/
+/*********************************************/
+
+
+/********************************************
+* Basic pkt loopback test
+*********************************************/
+printf("...runnining pure push/pop benchmark\n");
+our_pktio_bench(100);
+
+
+/**************unused stuff******************/
+/* create TRIE */
+P_trie = trie_new();
+if (!P_trie) {printf("trie alloc failed\n"); exit(1);}
+
+nat = (HEAD_T *) malloc(NE * sizeof(HEAD_T));
+if (!nat) {printf("malloc of nat table failed\n"); exit(1);}
+
+//gen_pkts(np2process<NP ? np2process:NP);
+n_pkt= np2process;
+
+/* build table */
+build_table(P_trie);
+
+
+/* processing loop: get pkt, check it, look up in table, copy new header,
+ send packet */
+srand((unsigned) np2process);
+
+
+/*********************************************/
+/**************Entry point into scheduler ****/
+/*********************************************/
+netapi_schedWaitForEvents(our_sched, &err);
+
+/* done */
+our_stats_cb(netapi_handle, NULL);
+
+
+#define DO_FAST_POLL
+#ifdef DO_FAST_POLL
+example_fast_poll(netcp_rx_chan);
+#endif
+
+/*************************************************
+ ************CLEAN UP****************************
+ ************************************************/
+
+//delete Classifiers
+netcp_cfgDelClass(netapi_handle, class_0, &err);
+netcp_cfgDelClass(netapi_handle, class_1, &err);
+//netcp_cfgDelClass(netapi_handle, class_2, &err);
+
+//delete flow
+netcp_cfgDelFlow(netapi_handle, specialFlow, &err);
+
+#if 1
+//delete policy
+if (rx_policy)
+ netapi_secDelRxPolicy(netapi_handle, rx_policy, &err);
+
+//delete tunnels
+netapi_secDelSA(netapi_handle, 0, rx_tunnel, &err);
+netapi_secDelSA(netapi_handle, 0, tx_tunnel, &err);
+#endif
+
+//delete IPs and MAC Interfacess
+netcp_cfgDelIp(netapi_handle, 0, 0, NULL, NULL, ip_rule0, &err);
+netcp_cfgDelIp(netapi_handle, 1, 0, NULL, NULL, ip_rule1, &err);
+netcp_cfgDelMac(netapi_handle,0,&err);
+netcp_cfgDelMac(netapi_handle,1,&err);
+
+
+//close pktio channels we opened
+pktio_close(netcp_tx_chan ,&err);
+pktio_close(netcp_rx_chan ,&err);
+pktio_close(netcp_sb_tx_chan ,&err);
+pktio_close(netcp_sb_rx_chan ,&err);
+
+//clear pktio channel we created
+pktio_control(our_chan, (PKTIO_CB) NULL, (PKTIO_CFG_T *) NULL, &zap_channel_control, &err);
+pktio_control(netcp_rx_chan2, (PKTIO_CB) NULL, (PKTIO_CFG_T *) NULL, &zap_channel_control, &err);
+
+//delete pktio channels we created
+pktio_delete(our_chan, &err);
+pktio_delete(netcp_rx_chan2,&err);
+
+netapi_shutdown(netapi_handle);
+
+}
+
+//EXAMPLE FAST POLL
+/* PLD */
+void netapi_pld(void * x)
+{
+ asm volatile("pld [r0]");
+}
+#include "ti/drv/nwal/nwal_util.h"
+
+#define M 1008
+static int l3_off[M], l4_off[M], L3_chk_ok[M], L4_chk_ok[M], appid[M], len[M] ;
+static unsigned char * buf[M];
+#define N2POLL 8 //batch size
+void example_fast_poll( PKTIO_HANDLE_T * p_pktio)
+{
+int j=0;
+int jj=0;
+int i,k,l=0,ltot=0;
+int n= N2POLL; //max # of pkts to poll
+Ti_Pkt * pHd[N2POLL];
+Ti_Pkt * tempVA;
+pasahoLongInfo_t* pinfo;
+unsigned long t1;
+unsigned long t2;
+unsigned long t11;
+unsigned long t12;
+unsigned long np;
+unsigned long sumt=0;
+unsigned long sumf=0;
+unsigned long sump=0;
+unsigned long totlen=0;
+int max_batch=0;
+
+//this should be done once and saved
+Qmss_QueueHnd rxQ= PKTIO_GET_DEFAULT_NETCP_Q(p_pktio);
+Qmss_QueueHnd freeQ;
+//loop forever
+for(;;)
+{
+ t1= netapi_timing_stop();
+ pHd[0] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (rxQ));
+ if (!pHd[0]) continue;
+ //got pkt
+ for(i=1;(i<n) && (pHd[i-1]);i++)
+ {
+ //convert previous descriptor PA -> VA
+ tempVA = Osal_qmssPhyToVirt(pHd[i-1]);
+
+ //try and preload desriptor
+ __builtin_prefetch(tempVA);
+ //netapi_pld(tempVA);
+
+ //read next descriptor from queue
+ pHd[i] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (rxQ));
+#if 1
+ /* extract some meta data */
+ Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
+ pinfo = PKTIO_GET_PROTO_INFO(tempVA);
+ l3_off[jj]= PKTIO_GET_L3_OFFSET(pinfo);
+ l4_off[jj]= PKTIO_GET_L4_OFFSET(pinfo);
+ appid[jj]= PKTIO_GET_APPID(tempVA);
+//#define VERIFY_SOP
+#ifdef VERIFY_SOP
+ if (sump < 200) printf("..sop off=%d\n", (int) buf[jj]-
+ (int) ((Cppi_HostDesc *) tempVA)->origBuffPtr) ;
+#endif
+#endif
+ jj+=1;
+ }
+ //finish last pkt in burst
+ if(pHd[i-1])
+ {
+ //convert previous descriptor PA -> VA
+ tempVA = Osal_qmssPhyToVirt(pHd[i-1]);
+
+ /* extract some meta data */
+#if 1
+ pinfo = PKTIO_GET_PROTO_INFO(tempVA);
+ l3_off[jj]= PKTIO_GET_L3_OFFSET(pinfo);
+ l4_off[jj]= PKTIO_GET_L4_OFFSET(pinfo);
+ appid[jj]= PKTIO_GET_APPID(tempVA);
+#endif
+ //get ptr (Physical address) and length of associate buffer
+ Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
+ jj+=1;
+ }
+ t2= netapi_timing_stop();
+ j+=(pHd[i-1]? i: (i-1)) ;
+ if (jj>(M-n)) jj=0;
+ l+=1; //n batches
+ ltot+=1;
+ if(pHd[i-1])
+ {
+ if (i>max_batch) max_batch= i;
+ }
+ else
+ {
+ if( (i-1) >max_batch) max_batch = i-1;
+ }
+
+ //cleanup
+ //printf("cleanup %d\n",i);
+ for(k=0;k<i;k++)
+ {
+ //cleanup. need to covert all of desriptor to VA so that i can use freePacket()
+ //alternative would be to just do cache ops plus descriptor raw push to pktlib
+ // heap free queue
+ if(pHd[k])
+ {
+
+ //tempVA=Qmss_osalConvertDescPhyToVirt(pHd[k]);
+ tempVA = Osal_qmssPhyToVirt(pHd[k]);
+ freeQ=Qmss_getQueueHandle(Cppi_getReturnQueue (Cppi_DescType_HOST, tempVA));
+ netapi_utilCacheWbInv(tempVA,128);
+ //would need to wbInv buffer also in practice. Also need to walk
+ // descriptor chain
+ t11= netapi_timing_stop();
+ // Pktlib_freePacket(tempVA);
+ PKTIO_QMSS_QUEUE_PUSH_DESC_SIZE_RAW (freeQ,
+ (void *) pHd[k],
+ 128);
+
+ t12= netapi_timing_stop();
+ sumf += (t12-t11);
+ }
+ }
+ sumt += (t2-t1);
+ sump +=(pHd[i-1]? i: (i-1));
+ //printf("end cleanup %d %d %d\n",sumt,sumf,sump );
+ if (sump > 10000) {
+ printf("pkts rx %d batches=%d appid=%x l3_off=%d l4_off=%d len=%d buf=0x%x rxcycle= %d pkts/batchx1000=%d maxbatch=%d cycles per rawpush = %d\n",
+ j,ltot, appid[j%M],
+ l3_off[j%M],l4_off[j%M],
+ len[j%M],buf[j%M],
+ sumt/sump, (sump*1000)/l, max_batch,
+ sumf/sump);
+ sumt=sump=sumf=0;
+ l=0;
+ }
+}
+
+
+}
+
+