]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blobdiff - ti/runtime/netapi/test/net_test.c
Update packet length in recv_cb to subtract out 4 byte CRC
[keystone-rtos/netapi.git] / ti / runtime / netapi / test / net_test.c
old mode 100644 (file)
new mode 100755 (executable)
index 3da0c35..db5c0b9
 #include "netapi.h"
 #include "pktio.h"
 #include <sys/resource.h>
+#include "net_test.h"
+#include <ti/drv/sa/salld.h>
+#define EXPERIMENTAL
+#ifdef EXPERIMENTAL
+#include "router.c"
+Trie * our_router;
+
+OUR_ROUTE_T routes[MAX_ROUTES]=
+{
+{0,{0xD4,0xbe,0xd9,0x00,0xd3,0x7e, 0x00,0x01,0x02,0x03,0x14,0x02,0x08,0x00},0},
+{0,{0x00,0x00,0x0,0x00,0x0,0x0, 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00},0},
+{0,{0xD4,0xbe,0xd9,0x00,0xd3,0x7e, 0x00,0x01,0x02,0x03,0x14,0x02,0x08,0x00},0},
+{0,{0x00,0x15,0x60,0xa1,0xf7,0xbe, 0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x00},0},
+{0,{0xd4,0xbe,0xd9,0x00,0xd3,0x7e, 0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x00},0}};
 
-//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
+unsigned int ip[MAX_ROUTES]={BE(0x0a0100c8),BE(0x0a00000a),BE(0x0a02000a),BE(0xc0a8010a),BE(0x9eda6719)};
 
+#endif
 //#define TEST_TIMERS
 
 /*************debug********************/
@@ -83,7 +94,7 @@ void dump_header(unsigned long *p, int n, int a, int r)
 
 
 //************for multi pkt burst  xfer test in loopback mode
-#define TX_BURST 800 
+#define TX_BURST 700 
 int pktloopback=TUNE_NETAPI_NWAL_ENABLE_PASS_LOOPBACK;
 nwalTxPSCmdInfo_t   flowPSCmdInfo;
 
@@ -123,6 +134,9 @@ static uint8_t testPkt[] = {
 
 };
 
+char    input_file_name[] = "net_test_config.txt";
+#define MAX_LINE_LENGTH 40
+
 #define TEST_PAYLOAD_LEN            80
 
 #define TEST_PKT_IP_OFFSET_BYTES        14
@@ -138,9 +152,14 @@ static uint8_t testPkt[] = {
 /* 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);
+void example_fast_poll( PKTIO_HANDLE_T * p_pktio, int max_pkts);
+void example_fast_pushpop(Pktlib_HeapHandle p_heap, int ntrials);
+
+void recv_cb_router(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
+                         PKTIO_METADATA_T meta[], int n_pkts,
+                         uint64_t ts );
+
 
-#if 1
 //#include "arpa/inet.h"
 long htonl(long x)
 {
@@ -200,51 +219,20 @@ uint16_t test_utilGetIpv4PsudoChkSum (uint8_t *data, uint16_t payloadLen)
 
 
 
-#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 };
-
+/* net test default configuration */
+netTestConfig_t config =
+{
+    {0x00,0x01,0x02,0x03,0x05,0x05},
+    {0x00,0x01,0x02,0x03,0x05,0x06},
+    {10, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {10, 0, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {10, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {192,168 , 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+    {192,168 , 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    IPSEC_MODE_RX_SIDEBAND,
+    IPSEC_MODE_TX_SIDEBAND,
+    0
+};
 
 #if 1  //goes with real tx (to laptop) 
 unsigned char real_mac_header[]={0xd4,0xbe,0xd9,0x00,0xd3,0x7e,
@@ -266,6 +254,7 @@ int n_pkt = NP;
 STATS_T stats;
 
 Trie * P_trie;
+Trie *p_trie_sa;
 HEAD_T pkts[NP];
 #define PERSLOW  10  //% of pkts that will not be fastpath'd 
 int perslow= PERSLOW;
@@ -276,12 +265,14 @@ int perslow= PERSLOW;
 static NETAPI_CFG_T our_netapi_default_cfg=
 {
 TUNE_NETAPI_PERM_MEM_SZ,
-256,  //start of packet offset for hw to place data on rx for default flow
+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
-0, //#descriptors w/o buffers in default heap
-TUNE_NETAPI_DEFAULT_BUFFER_SIZE+256   //size of 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;
@@ -305,7 +296,7 @@ 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
+  NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 5000000  //every 5000000 poll loops
 };
 void our_stats_cb(NETAPI_T h, paSysStats_t* pPaStats);
 NETAPI_TIMER_GROUP_HANDLE_T ourTimerBlock; 
@@ -357,70 +348,197 @@ NETCP_CFG_CLASSIFIER_T class_2_cfg=
 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;
+netTestSA_t sa_info[6];
+int netapi_algorithm_set = 0;
+int netapi_sec_sa_mode = 2;
+/* tmannan-end */
+//NETCP_CFG_SA_T rx_tunnel;
+//NETCP_CFG_SA_T tx_tunnel;
+NETCP_CFG_IPSEC_POLICY_T rx_policy[4];
+//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
+
+
+NETAPI_SEC_SA_INFO_T rx_sa [4] = {
+{
+    NWAL_SA_DIR_INBOUND,
+    0x11111111,  //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
+},
+{
+    NWAL_SA_DIR_INBOUND,
+    0x22222222,  //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_SHA2_256,
+    NWAL_SA_EALG_AES_CTR,
+    0,0  //na
+},
+{
+    NWAL_SA_DIR_INBOUND,
+    0x33333333,  //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_SHA2_256,
+    NWAL_SA_EALG_3DES_CBC,
+    0,0  //na
+},
+{
+    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_MD5,
+    NWAL_SA_EALG_NULL,
+    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
+NETAPI_SEC_SA_INFO_T tx_sa[4]= {
+{
+    NWAL_SA_DIR_OUTBOUND,
+    0x11111111,  //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
+},
+    {
+    NWAL_SA_DIR_OUTBOUND,
+    0x22222222,  //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_SHA2_256,
+    NWAL_SA_EALG_AES_CTR,
+    0,0  //seq no
+},
+{
+    NWAL_SA_DIR_OUTBOUND,
+    0x33333333,  //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_SHA2_256,
+    NWAL_SA_EALG_3DES_CBC,
+    0,0  //seq no
+},
+{
+    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_MD5,
+    NWAL_SA_EALG_NULL,
+    0,0  //seq no
+}
 };
 
-//since we are doing loopback, the rx key params = tx key params
-static nwalSecKeyParams_t ourTXKeyParams =
+static nwalSecKeyParams_t ourTXKeyParams[4] ={
 {
-    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 */
+    16, /* encKeySize: CTR 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_3DES_CBC and 0 bytes Salt*/
+    20, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA1 */
+    NULL, //set below
     NULL, //set below
+},
+{
+    20, /* encKeySize: CTR 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_AES_CTR and 0 bytes Salt*/
+    32, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA2_256 */
+    NULL, //set below
+    NULL, //set below
+},
+{
+    24, /* encKeySize: DES-CBC: 24 bytes:NWAL_SA_EALG_3DES_CBC and 0 bytes Salt*/
+    32, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA2_256 */
+    NULL, //set below
+    NULL, //set below
+},
+{
+    0, /* NULL*/
+    16, /* MD5, 16 bytes */
     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 */
+/* these keys are for aes-ctr and hmac sha2_256 */
+static nwalSecKeyParams_t ourRXKeyParams[4] ={
+{
+    16, /* encKeySize: CTR 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_3DES_CBC and 0 bytes Salt*/
+    20, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA1 */
+    NULL, //set below
     NULL, //set below
+},
+{
+    20, /* encKeySize: CTR 16 bytes Encryption Key and 4 bytes Salt : 24 bytes:NWAL_SA_EALG_AES_CTR and 0 bytes Salt*/
+    32, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA2_256 */
+    NULL, //set below
+    NULL, //set below
+},
+{
+    24, /* encKeySize: DES-CBC: 24 bytes:NWAL_SA_EALG_3DES_CBC and 0 bytes Salt*/
+    32, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA2_256 */
     NULL, //set below
+    NULL, //set below
+},
+{
+    0, /* NWAL_SA_EALG_NULL*/
+    16, /* NWAL_SA_AALG_HMAC_MD5, 16 bytes */
+    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] =
+;
+
+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 };
+         0x30, 0x31, 0x32, 0x33 }; 
 
 
 /*************************END NETAPI OBJECTS***********************/
@@ -571,19 +689,21 @@ 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;
+#ifdef PKTIO_GET_BENCHMARK
+extern unsigned int vv7p;
+extern unsigned int vv8p;
+extern unsigned int vv9p;
+extern unsigned int vv10p;
+extern unsigned int vv11p;
+extern unsigned int vv12p;
+
+extern unsigned int vv13p;  //rcv path
+extern unsigned int vv14p;
+extern unsigned int vv15p;
+#endif
 
 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
@@ -669,31 +789,34 @@ for(i=0;i<ntrials;i++)
    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[3]+=(vv4-vv3); 
    timings[5]+=(vv3-vv1);
+   timings[8]+=(vv11-vv6);
+
+#ifdef PKTIO_GET_BENCHMARK
+   timings[2]+=(vv7p-vv4);
+   timings[4]+=(vv8p-vv3);
    timings[6]+=(vv9p-vv8p);
    timings[7]+=(vv10p-vv7p);
-   timings[8]+=(vv11-vv6);
+#endif
 }
+
+#ifdef PKTIO_GET_BENCHMARK
    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);
-}
+   {
+       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);
+   }
+#endif
 
 }
 /*-----------test driver: gen an input pkt------- */
 //char buffer[sizeof(HEAD_T)+PKT_LEN];
-Ti_Pkt * get_pkt(int n, unsigned int *p_len)
+Ti_Pkt * get_pkt(int n, unsigned int *p_len, Pktlib_HeapHandle heap2use, int size, unsigned char * buf2cpy, int copy_size)
 {
    int ind;
    long long temp;
@@ -706,7 +829,7 @@ Ti_Pkt * get_pkt(int n, unsigned int *p_len)
        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);
+  b=Pktlib_allocPacket(heap2use,size);
   if (!b) 
     {printf("net_test: get_pkt() heap empty!! %d pkts gen'd %d \n", n); return NULL;};
 
@@ -743,13 +866,13 @@ else
 
    //copy test packet into buffer
 {
-    memcpy(&buffer[0], &testPkt[0],TEST_PKT_LEN);
-    *p_len = TEST_PKT_LEN;
+    memcpy(&buffer[0], buf2cpy, copy_size);
+    *p_len = copy_size;
 }
     return b; 
 }
 
-
+static int eof=0;
 /*--------------------------------------------------------------
  *----------utility to flip a packet and send 
  *--------------------back to source----------------------------
@@ -761,6 +884,13 @@ unsigned char mac_temp[6];
 unsigned char ip_temp[4];
 unsigned char new_dest_port[2]={0x75,0x30};  // 30000
 uint16_t blah; 
+uint16_t i=1;   /* for testing only */
+
+uint8_t *p_spi; 
+netTestSA_t * p_sa_info;
+uint8_t p_iv[16];
+
+Pktlib_setPacketLen(tip,len);
 //mac
 memcpy(&mac_temp,&p_pkt[0],6);
 memcpy(&p_pkt[0],&p_pkt[6],6);
@@ -775,49 +905,64 @@ 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) 
 {
+    p_spi = &(p_pkt[netTest_MAC_HEADER_LEN+netTest_IP_HEADER_LEN]);
+    p_sa_info = (netTestSA_t *) trie_lookup(p_trie_sa, (char *)p_spi ,4);
+    if (p_sa_info == NULL)
+    {
+        printf("flip_and_send_pkt(): trie_lookup() failed\n");
+        return;
+    }
     //just drop non-udp packet
-    if (p_pkt[14+20+8+16+9]!=0x11)
+    if (p_pkt[p_sa_info->tx_payload_info.encOffset+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);
+memcpy(&ip_temp, &p_pkt[p_sa_info->tx_payload_info.encOffset+12],4);
+memcpy(&p_pkt[p_sa_info->tx_payload_info.encOffset+12],&p_pkt[p_sa_info->tx_payload_info.encOffset+12+4],4);
+memcpy(&p_pkt[p_sa_info->tx_payload_info.encOffset+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
+memcpy(&p_pkt[p_sa_info->tx_payload_info.encOffset+20+2],&new_dest_port[0],2);
+memset(&p_pkt[p_sa_info->tx_payload_info.encOffset+20+6],0,2); //checksum
+
 
-#ifdef IPSEC_MODE_TX_SIDEBAND
 
-//inner ip checksum : leave alone
+
+if (config.ipsec_mode_tx == 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;
+    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);
+    //tbd udp checksum (leave at 0)
 
-#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, set to 0 (we will compute on way out
+    memset(&p_pkt[14+10],0,2);
+}
+else
+{
+//#else //inflow, don't touch outer , clear inner 
+//DALmemset(&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
 {
@@ -828,58 +973,129 @@ memcpy(&p_pkt[14+20+2],&new_dest_port[0],2);
 //IPSEC case, 
 if (flag)
 {
-#ifdef IPSEC_MODE_TX_SIDEBAND
+        if (config.ipsec_mode_tx == 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.sa_handle=p_sa_info->tx_data_mode_handle;  //use TX SA context
+
+#if 0
            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.encOffset =p_sa_info->tx_payload_info.encOffset;
+           
+           meta_tx.authOffset =netTest_MAC_HEADER_LEN+netTest_IP_HEADER_LEN;
+
+           //meta_tx.encSize=len - 14- 20-8-16-12;
+           meta_tx.encSize = len - p_sa_info->tx_payload_info.encOffset -netTest_ICV_LEN;
+           
+           //meta_tx.authSize= len -14-20-12;
+           meta_tx.authSize = len - meta_tx.authOffset - netTest_ICV_LEN;
+           //meta_tx.encIvSize=16;
+           meta_tx.encIvSize = p_sa_info->tx_payload_info.encIvSize;
+           //meta_tx.pEncIV= &p_pkt[14+20+8];  //just use same IV..
+#endif
+            memcpy(&meta_tx, &(p_sa_info->tx_payload_info), sizeof(nwalDmTxPayloadInfo_t));
+
+           meta_tx.ploadLen = len;
+           meta_tx.encSize = len - p_sa_info->tx_payload_info.encOffset -netTest_ICV_LEN;
+           meta_tx.authSize = len - meta_tx.authOffset - netTest_ICV_LEN;
+
+           meta_tx.encIvSize = p_sa_info->tx_payload_info.encIvSize;
+#if 0
+            printf("flip_and_send_pkt(): encOffset %d\n", meta_tx.encOffset);
+            printf("flip_and_send_pkt():authOffset %d\n", meta_tx.authOffset);
+            printf("flip_and_send_pkt(): encSize %d\n", meta_tx.encSize);
+            printf("flip_and_send_pkt(): authSize %d\n", meta_tx.authSize);
+            printf("flip_and_send_pkt(): encIvSize %d\n", meta_tx.encIvSize);
+#endif
+
+        if (p_sa_info->cipherMode ==  NWAL_SA_EALG_AES_CTR)
+        {
+           memcpy(&p_iv[0], &ourEncrKey[16], 4);
+           memcpy(&p_iv[4], &p_pkt[netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN + netTest_ESP_HEADER_LEN], 8);
+            p_iv[12] = 0;
+            p_iv[13] = 0;
+            p_iv[14] = 0;
+            p_iv[15] = 1;
+           meta_tx.pEncIV = &p_iv[0];
+         }
+        else if (p_sa_info->cipherMode ==  NWAL_SA_EALG_NULL)
+        {
+            meta_tx.pEncIV = NULL;
+        }
+        else
+        {
+            meta_tx.pEncIV = &p_pkt[netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN + netTest_ESP_HEADER_LEN ];
+        }
            meta_tx.authIvSize=0;
            meta_tx.pAuthIV=NULL;
            meta_tx.aadSize=0;
            meta_tx.pAad=NULL;
            /* post it to netcp sb tx channel*/
+           meta_tx.appCtxId = netapi_timing_start();
            meta.u.tx_sb_meta=&meta_tx;
            pktio_send(netcp_sb_tx_chan,tip,&meta,&err);
        }
-
-#else
+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;  
+#define USE_COPY
+#ifdef USE_COPY
+//debug:  see if re-using RX descriptor for TX is causing our SA lockup
+{
+  int new_len=0;
+  Ti_Pkt new_tip =  get_pkt(0, &new_len, specialLarge , len+10 , &p_pkt[0]   , len);
+  if (!new_tip)
+  {
+     printf("net_test> new_tip NULL\n");
+  }
+  else
+  {
+    Pktlib_setPacketLen(new_tip,new_len);
+    Pktlib_freePacket(tip);
+    tip=new_tip;  
+    Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&new_len);  //reset p_pkt to point to new buffer as its used below
+    Cppi_setTimeStamp (Cppi_DescType_HOST, (Cppi_Desc *) tip,stats.sec_tx); 
+  }
+}
+if (len <1500)  
+{
+  eof+=1;
+}
+#endif
+           meta.sa_handle=p_sa_info->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.txFlag1 = p_sa_info->tx_pkt_info.txFlag1;
+           meta_tx.enetPort=0;
+           //meta_tx.saOffBytes=14+20;  
+           meta_tx.saOffBytes=  p_sa_info->tx_pkt_info.saOffBytes;
            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.startOffset = 0;
+           meta_tx.startOffset = p_sa_info->tx_pkt_info.startOffset;
+           //meta_tx.ipOffBytes = 14+20+8+16;   //to inner header
+           meta_tx.ipOffBytes =p_sa_info->tx_payload_info.encOffset; 
+           //meta_tx.l4OffBytes = 14+20+8+16+20; //to L4
+           meta_tx.l4OffBytes = p_sa_info->tx_pkt_info.l4OffBytes;
+           meta_tx.l4HdrLen = p_sa_info->tx_pkt_info.l4HdrLen;
+           meta_tx.ploadLen = (unsigned) ((p_pkt[meta_tx.l4OffBytes+4]<<8)|p_pkt[meta_tx.l4OffBytes+4+1]) -8 ;
            meta_tx.pseudoHdrChecksum =
-             test_utilGetIpv4PsudoChkSum(&p_pkt[14+20+8+16],8+ meta_tx.ploadLen);
+             test_utilGetIpv4PsudoChkSum(&p_pkt[meta_tx.ipOffBytes],8+ meta_tx.ploadLen);
 
            /* post it to netcp tx channel*/
            meta.u.tx_meta=&meta_tx;
+           if (stats.sec_tx<20) dump_descr((long *) tip, stats.sec_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
 {
@@ -943,7 +1159,11 @@ HEAD_T * p_head;
 HEAD_T temp_head;
 int tag_cmp=0;
 unsigned int hash[3];
+uint8_t *p_spi;
+netTestSA_t *p_sa_info;
 
+//nwal_AppId time;
+unsigned long time, delta_time;
  /* loop over received pkts */
    for(i=0;i<n_pkts;i++)
    {
@@ -951,10 +1171,24 @@ unsigned int hash[3];
         Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
         len = Pktlib_getPacketLen(tip);//real length
 
+
+         p_spi = &(p_pkt[netTest_MAC_HEADER_LEN+netTest_IP_HEADER_LEN]);
+        p_sa_info = (netTestSA_t *) trie_lookup(p_trie_sa, (char *)p_spi ,4);
+        if (p_sa_info == NULL)
+        {
+            printf("recv_sb_cb(): trie_lookup failed\n");
+            continue;
+        }
+
+
         //is this a decrypt (rx_tunnel) complete
-        if (meta[i].u.rx_sb_meta->appId == rx_tunnel)
+        if ((int)meta[i].u.rx_sb_meta->appId == p_sa_info->rx_tunnel)
         {
-           stats.sb_rx+=1;
+           
+            time = netapi_timing_start();
+           delta_time = time -(unsigned long) meta[i].u.rx_sb_meta->appCtxId;
+            stats.total_decrypt_time += delta_time;
+            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]);
@@ -963,7 +1197,8 @@ unsigned int hash[3];
            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);
+             //dump_header((long*)p_pkt, stats.sb_rx, (int)meta[i].u.rx_sb_meta->appId,0);
+#if 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],
@@ -971,14 +1206,16 @@ unsigned int hash[3];
              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]);
+#endif
            }
            //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
+           
+            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 )
+        else if((int)meta[i].u.rx_sb_meta->appId== p_sa_info->tx_tunnel )
         {
            hash[0]= htonl( meta[i].u.rx_sb_meta->pAuthTag[0]);
            hash[1]= htonl( meta[i].u.rx_sb_meta->pAuthTag[1]);
@@ -987,7 +1224,8 @@ unsigned int hash[3];
            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);
+             //dump_header((long*)p_pkt, stats.sb_tx, (int)meta[i].u.rx_sb_meta->appId,0);
+#if 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],
@@ -996,6 +1234,7 @@ unsigned int hash[3];
              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]);
+#endif
            }
            //put the computed tag in the packet
            memcpy(&p_pkt[len-12],(char*)&hash[0],12); //todo, really use meta->authTagLen
@@ -1006,11 +1245,15 @@ unsigned int hash[3];
            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;
+           meta_tx.ipOffBytes = netTest_MAC_HEADER_LEN;
            //not used
            meta_tx.l4OffBytes = 0;
            meta_tx.l4HdrLen = 0;
            meta_tx.ploadLen = 0;
+            time = netapi_timing_start();
+            delta_time = time -(unsigned long) meta[i].u.rx_sb_meta->appCtxId;
+           stats.total_encrypt_time += delta_time;
+        
 
            /* post it to netcp tx channel*/
            meta2.u.tx_meta=&meta_tx;
@@ -1040,6 +1283,9 @@ KEY_T key;
 char * p_pkt;
 HEAD_T * p_head;
 HEAD_T temp_head;
+netTestSA_t *p_sa_info;
+uint8_t *p_spi;
+uint8_t p_iv[16];
 
     p_head=&temp_head;
 
@@ -1054,72 +1300,125 @@ HEAD_T temp_head;
     //test_alloc_free(7);
     //printf("recv start\n");
 
-   /* loop over received pkts */
-   for(i=0;i<n_pkts;i++)
+    /* 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
+        tip = p_recv[i];
+        Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
+        len = Pktlib_getPacketLen(tip)-4;//real length, subtract mac trailer
+        Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
+        Pktlib_setPacketLen(tip,len);
 
-         //debug: validate descriptor */
-         if(Pktlib_getNextPacket(tip) != 0) {printf(" rcv_cb, nexpkt != NULL");}
+        //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;
+        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);}
+        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 0
+        if(stats.rx<=16)
+        {
+            dump_header((long*)p_pkt, stats.rx, (int)meta[i].u.rx_meta->appId,meta[i].u.rx_meta->rxFlag1);
+        }
+#endif
+        /* 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
+            if (!check_header(p_head,&meta[i]))
+            {
+                stats.n_bad+=1;Pktlib_freePacket(tip); 
+                continue;
+            }
+
+
+
+
+            //process IP SEC PACKET
+        if (config.ipsec_mode_rx == IPSEC_MODE_RX_SIDEBAND)
         {
+            p_spi = &(p_pkt[netTest_MAC_HEADER_LEN+netTest_IP_HEADER_LEN]);
+            p_sa_info = (netTestSA_t *) trie_lookup(p_trie_sa, (char *)p_spi ,4);
+            if (p_sa_info == NULL)
+            {
+                printf("recv_cb(): trie_lookup() failed\n");
+                continue;
+            }
            //ship to crypto for decrypt!!
            //12 byte auth tag
-          PKTIO_METADATA_T meta2 = {PKTIO_META_SB_TX,{0},0};
+            PKTIO_METADATA_T meta2 = {PKTIO_META_SB_TX,{0},0};
            nwalDmTxPayloadInfo_t meta_tx={0};
-           meta2.sa_handle=rx_data_mode_handle;
+           meta2.sa_handle=p_sa_info->rx_data_mode_handle;
+
+           memcpy(&meta_tx, &(p_sa_info->tx_payload_info), sizeof(nwalDmTxPayloadInfo_t));
+
            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;
+           meta_tx.encSize = len - p_sa_info->tx_payload_info.encOffset -netTest_ICV_LEN;
+           meta_tx.authSize = len - meta_tx.authOffset - netTest_ICV_LEN;
+
+           meta_tx.encIvSize = p_sa_info->tx_payload_info.encIvSize;
+#if 0
+            printf("recv_cb(): encOffset %d\n", meta_tx.encOffset);
+            printf("recv_cb():authOffset %d\n", meta_tx.authOffset);
+            printf("recv_cb(): encSize %d\n", meta_tx.encSize);
+            printf("recv_cb(): authSize %d\n", meta_tx.authSize);
+            printf("recv_cb(): encIvSize %d\n", meta_tx.encIvSize);
+#endif
+
+            if (p_sa_info->cipherMode ==  NWAL_SA_EALG_AES_CTR)
+            {
+                memcpy(&p_iv[0], &ourEncrKey[16], 4);
+                memcpy(&p_iv[4], &p_pkt[netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN + netTest_ESP_HEADER_LEN], 8);
+                p_iv[12] = 0;
+                p_iv[13] = 0;
+                p_iv[14] = 0;
+                p_iv[15] = 1;
+                 meta_tx.pEncIV = &p_iv[0];
+            }
+            else if (p_sa_info->cipherMode ==  NWAL_SA_EALG_NULL)
+            {
+                meta_tx.pEncIV = NULL;
+            }
+            else
+            {
+                meta_tx.pEncIV = &p_pkt[netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN + netTest_ESP_HEADER_LEN ];
+            }
+            meta_tx.appCtxId = netapi_timing_start();
+            //printf("recv_cb appCtxId: %lu\n", meta_tx.appCtxId);
+
            /* 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 
+            //inflow mode.  flip and send
+            flip_and_send_pkt(tip,p_pkt,len,1);
     }
     else if ((p_head->ip[2]&0x0000ff00)!=0x00001100)
     {
-               stats.n_new+=1;Pktlib_freePacket(tip); continue;
+        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;
+               stats.n_bad+=1;Pktlib_freePacket(tip); 
+        continue;
        }
 
 #if 0
@@ -1138,12 +1437,12 @@ HEAD_T temp_head;
         /* update_mac(&p_pkt[0]);  */
 
        /* 'simulate' send pkt */
-       send_pkt(tip,len);
+        send_pkt(tip,len);
 #endif
-        //just flip and send
-        flip_and_send_pkt(tip,p_pkt,len,0);
+             //just flip and send
+            flip_and_send_pkt(tip,p_pkt,len,0);
+        }
     }
-  }
     //printf("recv done\n");
 }
 
@@ -1203,6 +1502,42 @@ for(i=0;i<n_fired;i++)
 }
 }
 
+void print_ipsec_stats(Sa_IpsecStats_t     *p_saIpsecStats, nwal_saAALG auth, nwal_saEALG cipher)
+{
+#if 0
+    if(retVal != nwal_OK)
+    {
+        System_printf("CORE: %d Error getting IP Sec Stats: Ret Status: %d \n",
+                       retVal);
+        return(nwal_FALSE);
+    }
+    if((p_saIpsecStats->pktEncHi) ||(p_saIpsecStats->pktEncLo))
+    {
+        printf("------------- IPSec TX (Encryption Channel) Stats BEGIN --\n");
+    }
+    else
+    {
+        printf("------------- IPSec RX (Decryption Channel) Stats BEGIN --\n");
+    }
+#endif
+    printf("\nAutentication mode: %d, Encryption Mode: %d\n", auth, cipher);
+    printf("IPSec replayOld:0x%x,replayDup:0x%x,authFail:0x%x \n",
+                   p_saIpsecStats->replayOld,p_saIpsecStats->replayDup,p_saIpsecStats->authFail);
+    printf("IPSec txESN:0x%x,rxESN:0x%x,pktEncHi:0x%x,pktEncLo:0x%x,pktDecHi:0x%x,pktDecLo:0x%x \n",
+                   p_saIpsecStats->txESN,p_saIpsecStats->rxESN,p_saIpsecStats->pktEncHi,
+                   p_saIpsecStats->pktEncLo,p_saIpsecStats->pktDecHi,p_saIpsecStats->pktDecLo);
+}
+
+void print_datamode_stats(Sa_DataModeStats_t     *p_saDataModeStats, nwal_saAALG auth, nwal_saEALG cipher)
+{
+
+    printf("\nAutentication mode: %d, Encryption Mode: %d\n", auth, cipher);
+    printf(" Packets processedHi: 0x%x, Packets processed Lo:0x%x\n",
+            p_saDataModeStats->pktHi, p_saDataModeStats->pktLo);
+}
+
+
+
 
 static int np2process = NP;
 /******************************************************
@@ -1214,35 +1549,69 @@ uint32_t numFreeDataPackets;
 uint32_t            numZeroBufferPackets;
 uint32_t            numPacketsinGarbage;
 Pktlib_HeapStats    pktLibHeapStats;
+int i;
+unsigned long long bcpp;
+unsigned long long bcpp_noc;
+unsigned long long bcpp_app;
+unsigned long long bcpp_tx;
+unsigned long long npL;
+unsigned long long cyclesL;
+unsigned long long ccyclesL; //cache cycles
+NETAPI_SA_STATS_T netapi_sa_stats;
 
 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, 
+printf(">itx=%d rx=%d tx=%d bad=%d slow=%d \n>rx_class0=%d rx_class1=%d rx_class2=%d  secRx=%d  secPRX=%d sb_rx=%d sb_tx=%d auth_ok=%d sec_tx=%d\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);
-
+         stats.sec_tx);
+
+if (stats.rx && stats.tx)
+    printf("decrypt time per packet(avg): %lu, encrypt  time per packet(avg): %lu\n", 
+    (unsigned long) stats.total_decrypt_time/stats.rx, (unsigned long) stats.total_encrypt_time/stats.tx);
+netapi_sched_get_stats(&npL,&cyclesL,&ccyclesL);
+if (npL && stats.rx) {
+   bcpp = cyclesL/npL; 
+   bcpp_noc = (cyclesL-ccyclesL)/npL; 
+   bcpp_app = (stats.app_cycles-stats.tx_cache_cycles)/stats.rx;
+} 
+else {bcpp = bcpp_noc=bcpp_app=0L;}
+if (stats.tx)
+{
+    bcpp_tx = (stats.send_cycles-stats.tx_cache_cycles)/stats.tx;
+}else {bcpp_tx = 0L;}
+printf(">         ++ busy cycles pp=%lld (%lld wo cache ops) (app+tx= %lld) (tx= %lld) ++\n",
+         bcpp,bcpp_noc,bcpp_app, bcpp_tx);
 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 IPv6 packets:        %d\n", pPaStats->classify1.nIpv6Packets);
+       printf("C1 number Custom packets:        %d\n", pPaStats->classify1.nCustomPackets);
+       printf("C1 number SRIO packets:        %d\n", pPaStats->classify1.nSrioPackets);
+       printf("C1 number LLC/SNAP Fail packets:        %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 IP Fragmented packets: %d\n", pPaStats->classify1.nIpFrag);
+       printf("C1 number IP Depth Overflow: %d\n", pPaStats->classify1.nIpDepthOverflow);
+       printf("C1 number VLAN Depth Overflow: %d\n", pPaStats->classify1.nVlanDepthOverflow);
+       printf("C1 number GRE Depth Overflow: %d\n", pPaStats->classify1.nGreDepthOverflow);
+       printf("C1 number MPLS Packets: %d\n", pPaStats->classify1.nMplsPackets);
        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 Invalid IPv6 Opt:  %d\n", pPaStats->classify1.nInvalidIPv6Opt);
+       printf("C1 number of TX IP Fragments:  %d\n", pPaStats->classify1.nTxIpFrag);
        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 Packets  :           %d\n",pPaStats->classify2.nPackets);
        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 Custom       :      %d\n",pPaStats->classify2.nCustom);
        printf ("C2 number silent drop   :      %d\n",pPaStats->classify2.nSilentDiscard);
        printf ("C2 number invalid cntrl :      %d\n\n",pPaStats->classify2.nInvalidControl);
+       printf ("C2 number Modify Stats Cmd Fail :      %d\n\n",pPaStats->modify.nCommandFail);
 }
 Pktlib_getHeapStats(OurHeap, &pktLibHeapStats);
 printf("main heap stats>  #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
@@ -1267,20 +1636,77 @@ printf("                       >  #dataBufThreshStatus=%d #dataBufStarvCounter=%
                                 pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
 
 
+#if 0
+printf("pa2sa descriptor area dump\n");
+for(i=0;i<TUNE_NETAPI_CONFIG_MAX_PA_TO_SA_DESC;i++)
+{
+   extern long * pa2sa_descr_base;
+   long * tip= &pa2sa_descr_base[32*i]; 
+   dump_descr(tip, i);
+}
+printf("sa2pa descriptor area dump\n");
+for(i=0;i<TUNE_NETAPI_CONFIG_MAX_SA_TO_PA_DESC;i++)
+{
+   extern long * sa2pa_descr_base;
+   long * tip= &sa2pa_descr_base[32*i]; 
+   dump_descr(tip, i);
+}
+#endif
 //debug = dump timer polling stats
-dump_poll_stats();
+//dump_poll_stats();
 
+#ifndef EXPERIMENTAL
+    for (i = 0; i < MAX_SEC_INDEX; i++)
+#else
+    for (i=0; i < 1;i++)
+#endif
+    {
+        if (config.ipsec_mode_rx == IPSEC_MODE_RX_INFLOW)
+        {
+            memset(&netapi_sa_stats, 0, sizeof(netapi_sa_stats));
+            netapi_getSaStats(netapi_handle, sa_info[i].rx_tunnel, &netapi_sa_stats);
+            if (netapi_sa_stats.mode_active & NETAPI_INFLOW_MODE_ACTIVE)
+                print_ipsec_stats(&(netapi_sa_stats.saIpsecStats), rx_sa[i].authMode, rx_sa[i].cipherMode);
+        }
+#if 0
+        else
+        {
+            memset(&netapi_sa_stats, 0, sizeof(netapi_sa_stats));
+            netapi_getSaStats(netapi_handle, sa_info[i].rx_tunnel, &netapi_sa_stats);
+             if (netapi_sa_stats.mode_active & NETAPI_SIDEBAND_MODE_ACTIVE)
+            print_datamode_stats(&(netapi_sa_stats.dataModeStats),rx_sa[i].authMode, rx_sa[i].cipherMode);
+        }
+#endif
 
+        if (config.ipsec_mode_tx == IPSEC_MODE_TX_INFLOW)
+        {
+            memset(&netapi_sa_stats, 0, sizeof(netapi_sa_stats));
+            netapi_getSaStats(netapi_handle, sa_info[i].tx_tunnel, &netapi_sa_stats);
+             if (netapi_sa_stats.mode_active & NETAPI_INFLOW_MODE_ACTIVE)
+                print_ipsec_stats(&(netapi_sa_stats.saIpsecStats), tx_sa[i].authMode, tx_sa[i].cipherMode);
+        }
+#if 0
+        else
+        {
+            memset(&netapi_sa_stats, 0, sizeof(netapi_sa_stats));
+            netapi_getSaStats(netapi_handle, sa_info[i].tx_tunnel, &netapi_sa_stats);
+            if (netapi_sa_stats.mode_active & NETAPI_SIDEBAND_MODE_ACTIVE)
+                print_datamode_stats(&(netapi_sa_stats.dataModeStats),tx_sa[i].authMode, tx_sa[i].cipherMode);
+        }
+ #endif
+        
+    }
 }
 
 //******************************************************
 //use scheduling housekeeping callback to generate pkts
 //******************************************************
+static int done_burst=0;
 void house(NETAPI_SCHED_HANDLE_T * s)
 {
 Ti_Pkt * tip;
 unsigned int len;
-nwalTxPktInfo_t meta_tx;
+nwalTxPktInfo_t meta_tx = {0};
 PKTIO_METADATA_T meta = {PKTIO_META_TX,{0},0};
 int err;
 static int house_pkts_gened=0;
@@ -1303,9 +1729,25 @@ unsigned int nwal_sum_vv6=0;
 
 unsigned int nwal_sum_flow_vv1=0;
 unsigned int nwal_sum_flow_vv2=0;
+unsigned int cache_op_b1;
+unsigned int cache_op_b2;
+int n_c_ops;
 static int first =0;
 Cppi_HostDesc*      pPktDesc;
 
+if(done_burst)
+{
+  house_pkts_gened+=TX_BURST;
+  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)
+  {
+     netapi_schedShutdown(s,NULL,&err);
+  }
+  return;
+}
+done_burst=1;
 Osal_cache_op_measure_reset();
 memset(&meta_tx,0,sizeof(meta_tx));
 for(p=0;p<TX_BURST;p++) {  
@@ -1329,7 +1771,7 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
   
 
 /* manufacture a pkt to transmit */
-   tip = get_pkt(house_pkts_gened, &len);
+   tip = get_pkt(house_pkts_gened, &len, OurHeap, PKT_LEN,&testPkt[0]  , TEST_PKT_LEN);
    if(!tip) { house_pkts_gened +=1; continue; }
 
 
@@ -1339,6 +1781,8 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
 
    /* set up meta data */
     meta.sa_handle=nwal_HANDLE_INVALID;
+//#define BENCH_UDP_SEND
+#ifdef BEND_UDP_SEND
     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;
@@ -1349,10 +1793,23 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
     meta_tx.ploadLen = TEST_PAYLOAD_LEN;
 
     Pktlib_getDataBuffer(tip,&pData,&len);
+   if(house_pkts_gened &0x1)
+   {
+        memcpy(&pData[6],&config.mac1[0] ,6);
+   }
     pIpHdr = pData + meta_tx.ipOffBytes;
     meta_tx.pseudoHdrChecksum =
         test_utilGetIpv4PsudoChkSum(pIpHdr,(TEST_PAYLOAD_LEN+TEST_PKT_UDP_HDR_LEN));
-
+#else
+   Pktlib_getDataBuffer(tip,&pData,&len);
+   if(house_pkts_gened &0x1)
+   {
+        memcpy(&pData[6],&config.mac1[0] ,6);
+   }
+    meta_tx.txFlag1 = NWAL_TX_FLAG1_META_DATA_VALID;
+    meta_tx.startOffset = 0;
+    meta_tx.ploadLen = TEST_PAYLOAD_LEN;
+#endif
    /* post it to netcp tx channel*/
    meta.u.tx_meta=&meta_tx;
 #ifdef DEBUG_DESC
@@ -1375,13 +1832,21 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
        nwal_sum_flow_vv2 += (nwal_flow_vv2-nwal_flow_vv1); 
    }
        
+   cache_op_b1= Osal_cache_op_measure(&n_c_ops);
    vv2= netapi_timing_stop();
+#ifdef BEND_UDP_SEND
    nwal_mCmdSetL4CkSumPort(  tip,
                              &flowPSCmdInfo,
                              TEST_PKT_UDP_OFFSET_BYTES,
                              (TEST_PKT_UDP_HDR_LEN + TEST_PAYLOAD_LEN),
                              meta_tx.pseudoHdrChecksum,
                              meta_tx.enetPort);
+#else
+   nwal_mCmdSetPort  (tip,
+                      &flowPSCmdInfo,  //could be NULL
+                      0);  //port 0 -> switch decides
+
+#endif
 
    pPktDesc = Pktlib_getDescFromPacket(tip);
    /* Send the packet out to transmit Q*/
@@ -1389,7 +1854,7 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
                         pPktDesc, 
                         NWAL_DESC_SIZE);
    vv3= netapi_timing_stop();
-   
+   cache_op_b2= Osal_cache_op_measure(&n_c_ops);
 
    sum_vv1 += (vv2-vv1);
    if(!house_pkts_gened)
@@ -1398,7 +1863,7 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
        sum_vv1 = sum_vv1 - nwal_sum_flow_vv2;
    }
 
-   sum_vv3 += (vv3-vv2);
+   sum_vv3 += (vv3-vv2)-(cache_op_b2-cache_op_b1); //sub out cache op cost
 
    // printf("pktio send. full=%d metadata=%d pktio_send=%d\n", vv3-vv1,  vv2-vv1,  vv3-vv2);
    
@@ -1408,18 +1873,18 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
  }
 {
    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", 
+      printf("BURST NWAL Fast send %d pkts.  metadata=%d Cmd Label Creation Cost=%d  nwal Fast Send Cost (less cacheop)= %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);
-
+#if 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);
-    
+  
+#endif  
 
       if(stats.itx2)
       {
@@ -1431,33 +1896,511 @@ if ((house_pkts_gened>0) && (! (house_pkts_gened%1000)) )
 }
 }
 
+void  build_sa_db(int i)
+{
+
+    if ((tx_sa[i].authMode == NWAL_SA_AALG_HMAC_SHA1) && (tx_sa[i].cipherMode == NWAL_SA_EALG_AES_CBC))
+    {
+        /* static configuration, will not change */
+        sa_info[i].tx_payload_info.aadSize = 0;
+        sa_info[i].tx_payload_info.pAad = NULL;
+        sa_info[i].tx_payload_info.authIvSize = 0;
+        sa_info[i].tx_payload_info.pAuthIV = NULL;
+        sa_info[i].tx_payload_info.authOffset = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;        /*done: same for all cipher suites */
+        sa_info[i].tx_payload_info.encIvSize = netTest_AES_CBC_IV_LEN;
+        sa_info[i].tx_payload_info.encOffset = netTest_MAC_HEADER_LEN +
+                                                                     netTest_IP_HEADER_LEN +
+                                                                    netTest_ESP_HEADER_LEN +
+                                                                    netTest_AES_CBC_IV_LEN;
+
+       
+
+        /* dynamic configuration, will  be calculated on the fly */
+        sa_info[i].tx_payload_info.authSize = 0; /* pkt len - mac - ip -icv (12) */
+        sa_info[i].tx_payload_info.encSize = 0;   /* authSize - esp header size (always 8 bytes) */
+        sa_info[i].tx_payload_info.ploadLen = 0;  /* will be packet length */
+        sa_info[i].tx_payload_info.pEncIV = 0;
+       sa_info[i].tx_payload_info.pPkt = 0;     /* not being referenced in net_test */
+
+        sa_info[i].cipherMode = NWAL_SA_EALG_AES_CBC;
+        sa_info[i].inner_ip_offset = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].auth_tag_size = netTest_ICV_LEN;  /* icv or mac size,. always 12 except for AES_CCM/AES_GCM */
+#ifdef EXPERIMENTAL
+        sa_info[i].iv_len=16;
+        sa_info[i].bl=16;
+        sa_info[i].spi = tx_sa[i].spi;
+        sa_info[i].src =*((unsigned int *)(&config.local_ipsec_ip.ipv4[0]));
+        sa_info[i].dst =*((unsigned int *)(&config.remote_ipsec_ip.ipv4[0]));
+#endif
+        sa_info[i].tx_pkt_info.enetPort = 0;
+        sa_info[i].tx_pkt_info.ipOffBytes = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].tx_pkt_info.l4HdrLen = netTest_UDP_HEADER_LEN; /*UDP header len */
+        sa_info[i].tx_pkt_info.l4OffBytes = sa_info[i].inner_ip_offset + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.startOffset = 0;
+        sa_info[i].tx_pkt_info.lpbackPass = 0;
+        sa_info[i].tx_pkt_info.ploadLen = 0; /*sa_info[i].tx_pkt_info.l4OffBytes + 4 */
+        sa_info[i].tx_pkt_info.pPkt = NULL;
+        sa_info[i].tx_pkt_info.saOffBytes = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.saPayloadLen = 0;
+        sa_info[i].tx_pkt_info.pseudoHdrChecksum =0;
+       
+        sa_info[i].tx_pkt_info.txFlag1 = NWAL_TX_FLAG1_DO_IPSEC_CRYPTO| NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID ;
+
+         trie_insert(p_trie_sa,(char *)&(tx_sa[i].spi),4, (void *) &sa_info[i]); //asociate with tx sa SPI
+         
+    }
+    else if ((tx_sa[i].authMode == NWAL_SA_AALG_HMAC_SHA2_256) && (tx_sa[i].cipherMode == NWAL_SA_EALG_AES_CTR))
+    {
+        printf("inside build_sa_db, index %d\n", i);
+        /* static configuration, will not change */
+        sa_info[i].tx_payload_info.aadSize = 0;
+        sa_info[i].tx_payload_info.pAad = NULL;
+        sa_info[i].tx_payload_info.authIvSize = 0;
+        sa_info[i].tx_payload_info.pAuthIV = NULL;
+        sa_info[i].tx_payload_info.authOffset = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;        /*done: same for all cipher suites */
+        sa_info[i].tx_payload_info.encIvSize = netTest_AES_CTR_IV_CONTEXT_LEN;
+        sa_info[i].tx_payload_info.encOffset = netTest_MAC_HEADER_LEN +
+                                                                     netTest_IP_HEADER_LEN +
+                                                                    netTest_ESP_HEADER_LEN +
+                                                                    netTest_AES_CTR_IV_PACKET_LEN;
+
+
+
+
+        /* dynamic configuration, will  be calculated on the fly */
+        sa_info[i].tx_payload_info.authSize = 0;
+        sa_info[i].tx_payload_info.encSize = 0;
+        sa_info[i].tx_payload_info.ploadLen = 0;
+        sa_info[i].tx_payload_info.pEncIV = 0;
+        sa_info[i].tx_payload_info.pPkt = 0;
+
+        sa_info[i].cipherMode = NWAL_SA_EALG_AES_CTR;
+        sa_info[i].inner_ip_offset = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].auth_tag_size = netTest_ICV_LEN;  /* icv or mac size,. always 12 except for AES_CCM/AES_GCM */
+#ifdef EXPERIMENTAL
+        sa_info[i].iv_len=8;
+        sa_info[i].bl=8;
+        sa_info[i].spi = tx_sa[i].spi;
+        sa_info[i].src =*((unsigned int *)(&config.local_ipsec_ip.ipv4[0]));
+        sa_info[i].dst =*((unsigned int *)(&config.remote_ipsec_ip.ipv4[0]));
+#endif
+
+        sa_info[i].tx_pkt_info.enetPort = 0;
+        sa_info[i].tx_pkt_info.ipOffBytes = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].tx_pkt_info.l4HdrLen = netTest_UDP_HEADER_LEN; /*UDP header len */
+        sa_info[i].tx_pkt_info.l4OffBytes = sa_info[i].inner_ip_offset + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.startOffset = 0;
+        sa_info[i].tx_pkt_info.lpbackPass = 0;
+        sa_info[i].tx_pkt_info.ploadLen = 0; /*sa_info[i].tx_pkt_info.l4OffBytes + 4 */
+        sa_info[i].tx_pkt_info.pPkt = NULL;
+        sa_info[i].tx_pkt_info.saOffBytes = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.saPayloadLen = 0;
+        sa_info[i].tx_pkt_info.pseudoHdrChecksum =0;
+       
+        sa_info[i].tx_pkt_info.txFlag1 = NWAL_TX_FLAG1_DO_IPSEC_CRYPTO| NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID ;
+
+       trie_insert(p_trie_sa,(char *)&(tx_sa[i].spi),4, (void *) &sa_info[i]); //asociate with tx sa SPI
+    }
+    else if ((tx_sa[i].authMode == NWAL_SA_AALG_HMAC_SHA2_256) && (tx_sa[i].cipherMode == NWAL_SA_EALG_3DES_CBC))
+    {
+        /* static configuration, will not change */
+        sa_info[i].tx_payload_info.aadSize = 0;
+        sa_info[i].tx_payload_info.pAad = NULL;
+        sa_info[i].tx_payload_info.authIvSize = 0;
+        sa_info[i].tx_payload_info.pAuthIV = NULL;
+        sa_info[i].tx_payload_info.authOffset = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;        /*done: same for all cipher suites */
+        sa_info[i].tx_payload_info.encIvSize = netTest_3DES_CBC_IV_LEN;
+        sa_info[i].tx_payload_info.encOffset = netTest_MAC_HEADER_LEN +
+                                                                     netTest_IP_HEADER_LEN +
+                                                                    netTest_ESP_HEADER_LEN +
+                                                                    netTest_3DES_CBC_IV_LEN;
+
+        /* dynamic configuration, will  be calculated on the fly */
+        sa_info[i].tx_payload_info.authSize = 0;
+        sa_info[i].tx_payload_info.encSize = 0;
+        sa_info[i].tx_payload_info.ploadLen = 0;
+        sa_info[i].tx_payload_info.pEncIV = 0;
+        sa_info[i].tx_payload_info.pPkt = 0;
+
+        sa_info[i].cipherMode = NWAL_SA_EALG_3DES_CBC;
+        sa_info[i].inner_ip_offset = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].auth_tag_size = netTest_ICV_LEN;  /* icv or mac size,. always 12 except for AES_CCM/AES_GCM */
+#ifdef EXPERIMENTAL
+        sa_info[i].iv_len=8;
+        sa_info[i].bl=8;
+        sa_info[i].spi = tx_sa[i].spi;
+        sa_info[i].src =*((unsigned int *)(&config.local_ipsec_ip.ipv4[0]));
+        sa_info[i].dst =*((unsigned int *)(&config.remote_ipsec_ip.ipv4[0]));
+#endif
+
+        sa_info[i].tx_pkt_info.enetPort = 0;
+        sa_info[i].tx_pkt_info.ipOffBytes = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].tx_pkt_info.l4HdrLen = netTest_UDP_HEADER_LEN; /*UDP header len */
+        sa_info[i].tx_pkt_info.l4OffBytes = sa_info[i].inner_ip_offset + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.startOffset = 0;
+        sa_info[i].tx_pkt_info.lpbackPass = 0;
+        sa_info[i].tx_pkt_info.ploadLen = 0; /*sa_info[i].tx_pkt_info.l4OffBytes + 4 */
+        sa_info[i].tx_pkt_info.pPkt = NULL;
+        sa_info[i].tx_pkt_info.saOffBytes = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.saPayloadLen = 0;
+        sa_info[i].tx_pkt_info.pseudoHdrChecksum =0;
+       
+        sa_info[i].tx_pkt_info.txFlag1 = NWAL_TX_FLAG1_DO_IPSEC_CRYPTO| NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID ;
+
+       trie_insert(p_trie_sa,(char *)&(tx_sa[i].spi),4, (void *) &sa_info[i]); //asociate with tx sa SPI
+    }
+    else if ((tx_sa[i].authMode == NWAL_SA_AALG_HMAC_MD5) && (rx_sa[i].cipherMode == NWAL_SA_EALG_NULL))
+    {
+        /* static configuration, will not change */
+        sa_info[i].tx_payload_info.aadSize = 0;
+        sa_info[i].tx_payload_info.pAad = NULL;
+        sa_info[i].tx_payload_info.authIvSize = 0;
+        sa_info[i].tx_payload_info.pAuthIV = NULL;
+        sa_info[i].tx_payload_info.authOffset = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;        /*done: same for all cipher suites */
+        sa_info[i].tx_payload_info.encIvSize = netTest_NULL_IV_LEN;
+
+        sa_info[i].tx_payload_info.encOffset =         netTest_MAC_HEADER_LEN +
+                                                                     netTest_IP_HEADER_LEN +
+                                                                    netTest_ESP_HEADER_LEN +
+                                                                    netTest_NULL_IV_LEN;
+#ifdef EXPERIMENTAL
+        sa_info[i].iv_len=0;
+        sa_info[i].bl=4;
+        sa_info[i].spi = tx_sa[i].spi;
+        sa_info[i].src =*((unsigned int *)(&config.local_ipsec_ip.ipv4[0]));
+        sa_info[i].dst =*((unsigned int *)(&config.remote_ipsec_ip.ipv4[0]));
+#endif
+
+
+        /* dynamic configuration, will  be calculated on the fly */
+        sa_info[i].tx_payload_info.authSize = 0;
+        sa_info[i].tx_payload_info.encSize = 0;
+        sa_info[i].tx_payload_info.ploadLen = 0;
+        sa_info[i].tx_payload_info.pEncIV = 0;
+        sa_info[i].tx_payload_info.pPkt = 0;
+
+        sa_info[i].cipherMode = NWAL_SA_EALG_NULL;
+        sa_info[i].inner_ip_offset = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].auth_tag_size = netTest_ICV_LEN;  /* icv or mac size,. always 12 except for AES_CCM/AES_GCM */
+
+        sa_info[i].tx_pkt_info.enetPort = 0;
+        sa_info[i].tx_pkt_info.ipOffBytes = sa_info[i].tx_payload_info.encOffset;
+        sa_info[i].tx_pkt_info.l4HdrLen = netTest_UDP_HEADER_LEN; /*UDP header len */
+        sa_info[i].tx_pkt_info.l4OffBytes = sa_info[i].inner_ip_offset + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.startOffset = 0;
+        sa_info[i].tx_pkt_info.lpbackPass = 0;
+        sa_info[i].tx_pkt_info.ploadLen = 0; /*sa_info[i].tx_pkt_info.l4OffBytes + 4 */
+        sa_info[i].tx_pkt_info.pPkt = NULL;
+        sa_info[i].tx_pkt_info.saOffBytes = netTest_MAC_HEADER_LEN  + netTest_IP_HEADER_LEN;
+        sa_info[i].tx_pkt_info.saPayloadLen = 0;
+        sa_info[i].tx_pkt_info.pseudoHdrChecksum =0;
+       
+        sa_info[i].tx_pkt_info.txFlag1 = NWAL_TX_FLAG1_DO_IPSEC_CRYPTO| NWAL_TX_FLAG1_DO_UDP_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID ;
+
+       trie_insert(p_trie_sa,(char *)&(tx_sa[i].spi),4, (void *) &sa_info[i]); //asociate with tx sa SPI
+    }
+    else
+        printf("build_sa_db(): invalid encryption/authentication combination selected\n");
+
+    //printf("sa_build_db(): authOffset %d, innerIpOffset %d, encOffset %d\n", sa_info[i].tx_payload_info.authOffset, sa_info[i].inner_ip_offset, sa_info[i].tx_payload_info.encOffset);
+    
+    
+}
+
+
+
+#define CHECK_SET_PARAM(ARG1, ARG2)     \
+    do { \
+        if(strcmp(key, ARG1) == 0) { \
+        if(data)strncpy(ARG2,data,CONFIG_STRING_LEN); \
+        printf("CHECK_SET_PARM, match found, input cong string %s\n", ARG2); \
+        continue; \
+        } \
+    } while(0)
+
+#define CHECK_SET_PARAM2(ARG1, ARG2,  ARG3)     \
+    do { \
+        if(strcmp(key, ARG1) == 0) { \
+        if(data) strncpy(ARG2,data,CONFIG_STRING_LEN); \
+        if(data2) strncpy(ARG3,data2,CONFIG_STRING_LEN); \
+        printf("CHECK_SET_PARM, match found, input cong string %s %s\n", ARG2, ARG3); \
+        continue; \
+        } \
+    } while(0)
+
+unsigned char hex2dec(char *p_s)
+{
+  int val;
+  sscanf(p_s,"%x",&val); 
+ return val&0xff;
+}
+void parse_one_mac(char * p_mac_str, unsigned char *p_mac)
+{
+    int index = 0;
+    int i;
+    char *pch = strtok (&(p_mac_str[0]),"-");
+
+    while (pch != NULL)
+    {
+         printf ("%s\n",pch);
+         p_mac[index] = hex2dec(pch);
+         index++;
+         pch = strtok (NULL,"-");
+    }
+     printf("index value : %d\n", index);
+    for (i=0; i<6;i++)
+         printf("************mac0[%d]: 0x%x\n",i,  p_mac[i]);
+}
+
+void parse_one_ip(char * p_ip_addr_str, unsigned char * p_ip)
+{
+    int index = 0;
+    int i;
+    char * pch = strtok (&p_ip_addr_str[0],".");
+
+     while (pch != NULL)
+     {
+        printf ("xxxxx: %s\n",pch);
+        p_ip[index] = atoi(pch);
+        index++;
+        pch = strtok (NULL,".");
+    }
+    printf("index value : %d\n", index);
+    for (i=0; i<4;i++)
+        printf("************ip[%d]: 0x%x\n",i, p_ip[i]);
+
+
+}
+
+void parse_mac_address(netTestConfigFile_t *pConfig)
+{
+    if (strlen(&pConfig->mac0[0]))
+        parse_one_mac(&pConfig->mac0[0],&config.mac0[0]);
+    if (strlen(&pConfig->mac1[0]))
+        parse_one_mac(&pConfig->mac1[0],&config.mac1[0]);
+}
+void parse_ip_address(netTestConfigFile_t *pConfig)
+{
+    if (strlen(&pConfig->ip0[0]))
+        parse_one_ip(&pConfig->ip0[0],&config.ip0.ipv4[0]);
+    if (strlen(&pConfig->ip1[0]))
+        parse_one_ip(&pConfig->ip1[0],&config.ip1.ipv4[0]);
+    if (strlen(&pConfig->ip2[0]))
+        parse_one_ip(&pConfig->ip2[0],&config.ip2.ipv4[0]);
+    if (strlen(&pConfig->local_ipsec_ip[0]))
+        parse_one_ip(&pConfig->local_ipsec_ip[0],&config.local_ipsec_ip.ipv4[0]);
+    if (strlen(&pConfig->remote_ipsec_ip[0]))
+    parse_one_ip(&pConfig->remote_ipsec_ip[0],&config.remote_ipsec_ip.ipv4[0]);
+}
+
+
+void parse_ipsec_mode(netTestConfigFile_t *pConfig)
+{
+
+    printf("parse_ipsec_mode, string length %d\n", strlen(&pConfig->ipsec_mode_rx));
+    if (strlen(&pConfig->ipsec_mode_rx[0]))
+    {
+        if (strcmp(pConfig->ipsec_mode_rx, "SIDEBAND") == 0)
+        {
+            config.ipsec_mode_rx = IPSEC_MODE_RX_SIDEBAND;
+        }
+        else if (strcmp(pConfig->ipsec_mode_rx, "INFLOW") == 0)
+        {
+            config.ipsec_mode_rx = IPSEC_MODE_RX_INFLOW;
+        }
+        else
+            printf("parse_ipsec_mode(), invalid RX ipsec mode in config file \n");
+    }
+
+    if (strlen(&pConfig->ipsec_mode_tx[0]))
+    {
+        if (strcmp(pConfig->ipsec_mode_tx, "SIDEBAND") == 0)
+        {
+            config.ipsec_mode_tx = IPSEC_MODE_TX_SIDEBAND;
+        }
+        else if (strcmp(pConfig->ipsec_mode_tx, "INFLOW") == 0)
+        {
+            config.ipsec_mode_tx = IPSEC_MODE_TX_INFLOW;
+        }
+    else
+        printf("parse_ipsec_mode(), invalid TX ipsec mode in config file \n");
+    }
+
+    printf("parse_ipsec_mode(): RX mode %d\n", config.ipsec_mode_rx);
+    printf("parse_ipsec_mode(): TX mode %d\n", config.ipsec_mode_tx);
+
+    
+}
+
+#ifdef EXPERIMENTAL
+int n_routes=0;
+int n_dst_ips=0;
+void parse_routes(netTestConfigFile_t *pConfig)
+{
+int i;
+int said=0;
+for(i=0;i<MAX_ROUTES;i++)
+{
+   int port;
+   if (pConfig->routes[i][0])
+   {
+      port=atoi(&pConfig->ports[i][0]);
+      if((port<1)||(port>2)) continue; //bad port #: only 1 or 2 valid
+      if(strncmp(&pConfig->routes[i][0],"MAC",3)==0)
+      {
+         routes[i].out_port = port;
+         parse_one_mac(&pConfig->routes[i][3],&routes[i].out_mac[0]);
+         memcpy(&routes[i].out_mac[6], ((port==1) ?&config.mac0[0]: &config.mac1[0] ),6); 
+         routes[i].out_mac[12]=0x08;
+         routes[i].out_mac[13]=0x00;
+         routes[i].sec_ptr=NULL;
+         n_routes+=1;
+      }
+      else if (strncmp(&pConfig->routes[i][0],"SA",2)==0)
+      {      
+         said=atoi(&pConfig->routes[i][2]) ;
+         routes[i].sec_ptr=&sa_info[said];
+         n_routes+=1;
+      }
+   }
+}
+our_router = route_init();
+for (i=0;i<MAX_ROUTES;i++)
+{
+  unsigned long ip_be;
+  int route_index;
+  if (pConfig->dst_ips[i][0])
+  {
+     parse_one_ip(&pConfig->dst_ips[i][0],(unsigned char *)&ip_be);
+     sscanf(&pConfig->paths[i][0],"route%d",&route_index);
+     route_add(our_router,&ip_be,&routes[route_index]);
+     n_dst_ips+=1;
+  }
+}
+printf(">Route DB built.  %d entries\n",n_dst_ips);
+}
+#endif
+static void parse_config_file(FILE * fpr, netTestConfigFile_t *pConfig)
+{
+    char line[MAX_LINE_LENGTH + 1];
+    int i;
+    char *key, *data, *ep, *data2;
+    char tokens[] = " :=;\n";
+    char temp_str[50];
+    memset(line, 0, MAX_LINE_LENGTH + 1);
+    memset(pConfig, 0, sizeof(netTestConfigFile_t));
+    while (fgets(line, MAX_LINE_LENGTH + 1, fpr)) 
+    {
+        if(line[0]=='#') continue; //skip comment
+        key  = (char *)strtok(line, tokens);
+        data = (char *)strtok(NULL, tokens);
+        data2 = (char *)strtok(NULL, tokens);
+        if (!key) continue;
+        if (!data) continue;
+
+        if(strlen(data) == 0) 
+        {
+            continue;
+        }
+
+         CHECK_SET_PARAM(INIT_CONFIG_MAC0,&(pConfig->mac0[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_MAC1,&(pConfig->mac1[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IP0,&(pConfig->ip0[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IP1,&(pConfig->ip1[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IP2,&(pConfig->ip2[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_LOCAL_IPSEC_IP,&(pConfig->local_ipsec_ip[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_REMOTE_IPSEC_IP,&(pConfig->remote_ipsec_ip[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IPSEC_MODE_RX,&(pConfig->ipsec_mode_rx[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IPSEC_MODE_TX,&(pConfig->ipsec_mode_tx[0]));
+         CHECK_SET_PARAM(INIT_CONFIG_IPSEC_IF_NO,&(pConfig->ipsec_if_no[0]));
+#ifdef EXPERIMENTAL
+    for(i=0;i<MAX_ROUTES;i++)
+    {
+        sprintf(temp_str,"route%d",i);
+        CHECK_SET_PARAM2(temp_str,&pConfig->routes[i][0],&pConfig->ports[i][0] );
+    }
+    for(i=0;i<MAX_ROUTES;i++)
+    {
+        sprintf(temp_str,"dstip%d",i);
+        CHECK_SET_PARAM2(temp_str,&pConfig->dst_ips[i][0],&pConfig->paths[i][0] );
+    }
+#endif
+         
+    }
+    parse_mac_address(pConfig);
+
+    parse_ip_address(pConfig);
+
+    parse_ipsec_mode(pConfig);
+#ifdef EXPERIMENTAL
+     if (strlen(&pConfig->ipsec_if_no[0]))
+        config.ipsec_if_no = atoi(&pConfig->ipsec_if_no[0]);
+    parse_routes(pConfig);
+#endif
+}
 
+static  netTestConfigFile_t config_file;
 /***************************************
  ********** 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;
+    int err,i;
+    rlim_t oss,ss = 1024*1024;
+    struct rlimit rl;
+
+    Pktlib_HeapCfg      heapCfg;
+    int32_t             errCode;
+    Pktlib_HeapIfTable*  pPktifTable;
+    FILE * fpr = NULL;
+
+
+
+    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);
+i   f (!err) printf("set stack to %d\n",rl.rlim_cur); else printf("setrlimit failed\n");
+#endif
+
+
+    if (argc>=2)  np2process = atoi(argv[1]);
+        printf("*************** np2process %d\n", np2process);
+    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);}
+#if 1
 
-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");
+    if (argc >= 2) 
+    {
+        fpr = fopen(argv[2], "r");
+        if (fpr == NULL) 
+        {
+            printf("Error in opening %s input file\n", argv[2]);
+        }
+    } 
+    else
 #endif
+    {
+        fpr = fopen(input_file_name, "r");
+        if (fpr == NULL) 
+        {
+            printf("Error in opening %s input file\n", input_file_name);
+        }
+        else
+        {
+            parse_config_file(fpr,&config_file);
+        }
+    }
 
-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);}
+#endif
+
+    memset(&sa_info, 0, sizeof(sa_info));
 
 
 //real mode, so update our test packet mac header and ip header
@@ -1466,6 +2409,13 @@ 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
 }
+#if 0 
+our_router = route_init();
+for (i=0;i<n_dst_ips;i++)
+{
+  route_add(our_router,&ip[i],&routes[i]);
+}
+#endif
 
 /*******************************************/
 /*************NETAPI STARTUP****************/
@@ -1488,7 +2438,7 @@ heapCfg.name                = "netapi-small";
 heapCfg.memRegion           = NETAPI_GLOBAL_REGION;
 heapCfg.sharedHeap          = 1;
 heapCfg.useStarvationQueue  = 0;
-heapCfg.dataBufferSize      = 256;
+heapCfg.dataBufferSize      = 512;
 heapCfg.numPkts             = 64;
 heapCfg.numZeroBufferPackets= 0;
 heapCfg.heapInterfaceTable.data_malloc  = pPktifTable->data_malloc;
@@ -1509,16 +2459,23 @@ our_reassemble_bench(2);
 exit(1);
 #endif
 
+#ifndef EXPERIMENTAL
 /* 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);}
+#endif
 
 /* 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);}
+#ifdef EXPERIMENTAL
+netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg,  &err);
+#else
 netcp_rx_chan= pktio_open(netapi_handle, NETCP_RX, (PKTIO_CB) recv_cb, &netcp_rx_cfg,  &err);
+#endif
 if (!netcp_rx_chan) {printf("pktio open RX failed err=%d\n",err); exit(1);}
 
+#ifndef EXPERIMENTAL
 /* 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);}
@@ -1528,12 +2485,14 @@ netcp_sb_tx_chan= pktio_open(netapi_handle, NETCP_SB_TX, NULL, &netcp_sb_tx_cfg,
 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);}
+#endif
 
-
+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);}
 
+#if 0
 /********************************************
 * Basic pkt loopback test
 *********************************************/
@@ -1544,6 +2503,7 @@ our_pktio_bench(1000);
 our_pktio_bench(1000);
 our_pktio_bench(1000);
 /*********************************************/
+#endif
 
 
 
@@ -1551,7 +2511,7 @@ our_pktio_bench(1000);
 /* add mac intefaces */
 netcp_cfgCreateMacInterface(
                   netapi_handle,
-                  &mac0[0],
+                  &config.mac0[0],
                   0,0,
                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,
                   (NETCP_CFG_VLAN_T ) NULL ,  //future
@@ -1564,7 +2524,7 @@ ip_rule0=netcp_addIp(
                   netapi_handle,
                   0,
                   nwal_IPV4,
-                  &OurIp0,
+                  &config.ip0,
                   NULL,  //all IP
                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,
                   &err
@@ -1574,7 +2534,7 @@ if (err) {printf("addip0 failed %d\n",err); exit(1); }
 //create a 2nd mac instance
 netcp_cfgCreateMacInterface(
                   netapi_handle,
-                  &mac1[0],
+                  &config.mac1[0],
                   1,1,
                   (NETCP_CFG_ROUTE_HANDLE_T)  NULL,
                   (NETCP_CFG_VLAN_T ) NULL ,  //future
@@ -1587,13 +2547,14 @@ ip_rule1=netcp_addIp(
                   netapi_handle,
                   1,
                   nwal_IPV4,
-                  &OurIp1,
+                  &config.ip1,
                   NULL,  //all IP
                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,
                   &err
                   );
 if (err) {printf("addip1 failed %d\n",err); exit(1); }
 
+#ifndef EXPERIMENTAL
 //attach 2 classifiers to iface 0, ip0
 class_0_cfg.u.c_l4.ip = ip_rule0;
 class_0 =  netcp_cfgAddClass(netapi_handle,
@@ -1613,7 +2574,7 @@ 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;
+class_2_cfg.u.c_l3_l4.ip_addr = &config.ip2;
 
 //create specialFlow for this classifier
 {
@@ -1621,15 +2582,18 @@ Pktlib_HeapHandle heaps[2];
 int sizes[2];
 heaps[0]= specialSmall;
 heaps[1]= specialLarge;
-sizes[0]=256;
-sizes[1]=1600;
+#define SPECIAL_SOP_OFF 128
+sizes[0]=512-SPECIAL_SOP_OFF;
+sizes[1]=1600-SPECIAL_SOP_OFF;
+#if 0
 specialFlow = netcp_cfgAddFlow( netapi_handle,
                                2,
                                 heaps,
                                 sizes,
-                                0,  //offset to start rx is 0
+                                SPECIAL_SOP_OFF,  //offset to start rx is 128 
                                 &err);
 if (err) {printf("add flow failed\n", err); exit(1);}
+#endif
 }
 #if 0
 //special route for this classifier:  different flow + destination q
@@ -1643,66 +2607,70 @@ class_2 = netcp_cfgAddClass(netapi_handle,
 if (err) {printf("addclass2 failed %d\n",err); exit(1);}
 #endif
 
+#endif
 //security stuff 
-ourRXKeyParams.pEncKey = &ourEncrKey[0];
-ourRXKeyParams.pAuthKey = &ourAuthKey[0];
-memcpy(&rx_sa.src, &TheirIp4IPSEC,4);
-memcpy(&rx_sa.dst, &OurIp4IPSEC,4);
+    p_trie_sa = trie_new();
+   if (!p_trie_sa) {printf("trie alloc for SA  failed\n"); exit(1);}
 
-#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
+
+
+    for (i=0; i < MAX_SEC_INDEX;i++)
+    {
+        ourRXKeyParams[i].pEncKey = &ourEncrKey[0];
+        ourRXKeyParams[i].pAuthKey = &ourAuthKey[0];
+        memcpy(&(rx_sa[i].src), &config.remote_ipsec_ip,4);
+        memcpy(&(rx_sa[i].dst), &config.local_ipsec_ip,4);
+
+        build_sa_db(i);
+        sa_info[i].rx_tunnel = netapi_secAddSA(
+            netapi_handle,
+            config.ipsec_if_no, //iface #0 
+            &rx_sa[i],
+            &ourRXKeyParams[i],
+            config.ipsec_mode_rx == IPSEC_MODE_RX_SIDEBAND ? NETAPI_SEC_SA_SIDEBAND: NETAPI_SEC_SA_INFLOW,
                 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
+            &(sa_info[i].rx_data_mode_handle),
+            &(sa_info[i].rx_inflow_mode_handle),
+            &err);
+        if (err) {printf("addRxSa failed %d\n",err); exit(1);}
+
+    if (config.ipsec_mode_rx == IPSEC_MODE_RX_INFLOW)
+    {
+        //assume inner and outer ip is the same
+        rx_policy[i]= netapi_secAddRxPolicy( netapi_handle,
+                         sa_info[i].rx_tunnel,  //link to tunnel above
                          4,         //ipv4
-                         &TheirIp4IPSEC, //src -> them
-                        &OurIp4IPSEC,  //dst -> us
-                        NULL,  // no qualifiers
-                        NULL,  //default route
+                         &config.remote_ipsec_ip, //src -> them
+                         &config.local_ipsec_ip,  //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
+        if (err) {printf("addSaPolicy failed  %d, for index %d\n",err,i); exit(1);}
+    }
+    else 
+        rx_policy[i] = 0;
+    }
 
 //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,
+     for (i=0; i < MAX_SEC_INDEX;i++)
+    {
+    ourTXKeyParams[i].pEncKey = &ourEncrKey[0];
+    ourTXKeyParams[i].pAuthKey = &ourAuthKey[0];
+    memcpy(&(tx_sa[i].src), &config.local_ipsec_ip,4);
+    memcpy(&(tx_sa[i].dst), &config.remote_ipsec_ip,4);
+    sa_info[i].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
+                &(tx_sa[i]),
+                &ourTXKeyParams[i],
+                config.ipsec_mode_tx == IPSEC_MODE_TX_SIDEBAND ? NETAPI_SEC_SA_SIDEBAND: NETAPI_SEC_SA_INFLOW,
                 NULL,  //use default route 
-                &tx_data_mode_handle,
-                &tx_inflow_mode_handle,
+                &(sa_info[i].tx_data_mode_handle),
+                &(sa_info[i].tx_inflow_mode_handle),
                 &err);
 if (err) {printf("addTxSa failed %d\n",err); exit(1);}
 
-
+    }
 #ifdef TEST_TIMERS
 //timers
 ourTimerBlock = netapi_TimerGroupCreate(
@@ -1745,14 +2713,16 @@ if (err!=0) {printf("stats req failed\n");}
 /*********************************************/
 
 
+#if 0
 /********************************************
 * Basic pkt loopback test
 *********************************************/
 printf("...runnining pure push/pop benchmark\n");
 our_pktio_bench(100);
-
+#endif
 
 /**************unused stuff******************/
+#if 0
 /* create TRIE */
 P_trie = trie_new();
 if (!P_trie) {printf("trie alloc failed\n"); exit(1);}
@@ -1770,7 +2740,7 @@ build_table(P_trie);
 /* processing loop: get pkt, check it, look up in table, copy new header,
    send packet */
 srand((unsigned) np2process);
-
+#endif
 
 /*********************************************/
 /**************Entry point into scheduler ****/
@@ -1783,31 +2753,37 @@ our_stats_cb(netapi_handle, NULL);
 
 #define DO_FAST_POLL
 #ifdef DO_FAST_POLL
-example_fast_poll(netcp_rx_chan);
+//example_fast_pushpop(OurHeap, 500);
+//example_fast_poll(netcp_rx_chan,20000);
 #endif
 
 /*************************************************
  ************CLEAN UP****************************
  ************************************************/
 
+#ifndef EXPERIMENTAL
 //delete Classifiers
 netcp_cfgDelClass(netapi_handle, class_0, &err); 
 netcp_cfgDelClass(netapi_handle, class_1, &err); 
 //netcp_cfgDelClass(netapi_handle, class_2, &err); 
 
+#if 0
 //delete flow 
 netcp_cfgDelFlow(netapi_handle, specialFlow, &err);
-
+#endif
+#endif
 #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);
+     for (i=0; i < MAX_SEC_INDEX;i++)
+    {
+        if (rx_policy[i])
+            netapi_secDelRxPolicy(netapi_handle, rx_policy[i], &err);
+     
+        //delete tunnels
+        netapi_secDelSA(netapi_handle, 0, sa_info[i].rx_tunnel, &err);
+        netapi_secDelSA(netapi_handle, 0, sa_info[i].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);
@@ -1818,6 +2794,7 @@ netcp_cfgDelMac(netapi_handle,1,&err);
 //close pktio channels we opened
 pktio_close(netcp_tx_chan ,&err);
 pktio_close(netcp_rx_chan ,&err);
+#ifndef EXPERIMENTAL
 pktio_close(netcp_sb_tx_chan ,&err);
 pktio_close(netcp_sb_rx_chan ,&err);
 
@@ -1828,7 +2805,7 @@ pktio_control(netcp_rx_chan2, (PKTIO_CB) NULL, (PKTIO_CFG_T *) NULL, &zap_channe
 //delete pktio channels we created
 pktio_delete(our_chan, &err);
 pktio_delete(netcp_rx_chan2,&err);
-
+#endif
 netapi_shutdown(netapi_handle);
 
 }
@@ -1839,18 +2816,80 @@ 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 int l3_off[M], l4_off[M], L3_chk_ok[M], L4_chk_ok[M], len[M] ;
+static nwal_AppId appid[M];
 static unsigned char * buf[M];
-#define N2POLL 8
-void example_fast_poll( PKTIO_HANDLE_T * p_pktio)
+#define N2POLL 8 //batch size
+#define NTOPOP 190
+Ti_Pkt * pHd[NTOPOP];
+void example_fast_pushpop(Pktlib_HeapHandle h , int n_trials)
+{
+int i,j;
+unsigned long t1;
+unsigned long t2;
+unsigned long sumf=0;
+unsigned long sumt=0;
+unsigned long sump=0;
+#define NTOPOP 190
+Ti_Pkt * tempVA;
+Qmss_QueueHnd freeQ=Pktlib_getInternalHeapQueue(h);
+
+//n_trials of NTOPOP actions
+for(i=0;i<n_trials;i++)
+{
+    //raw pop
+    t1= netapi_timing_start();
+    pHd[0] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (freeQ));
+    for(j=1;j<NTOPOP;j++)
+    {
+       tempVA  =  _Osal_qmssPhyToVirt(pHd[j-1]);
+       netapi_pld(tempVA);
+        //__builtin_prefetch(tempVA);
+       pHd[j] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (freeQ));
+       sumf+= (int) (   ((Cppi_HostDesc *) tempVA)->origBuffPtr -
+                  ((Cppi_HostDesc *) tempVA)->buffPtr);
+    }
+    tempVA  =  _Osal_qmssPhyToVirt(pHd[j-1]);
+    sumf+= (int) (   ((Cppi_HostDesc *) tempVA)->origBuffPtr -
+                  ((Cppi_HostDesc *) tempVA)->buffPtr);
+    t2=netapi_timing_stop();
+    sumt+= (t2-t1);
+
+    //invalidate/wb 
+    for(j=0;j<NTOPOP;j++)
+    {
+        tempVA  =  _Osal_qmssPhyToVirt(pHd[j]);
+        netapi_utilCacheWbInv(tempVA,128);
+    }
+
+    //raw push 
+    t1=netapi_timing_start();
+    for(j=0;j<NTOPOP;j++)
+    {
+        PKTIO_QMSS_QUEUE_PUSH_DESC_SIZE_RAW (freeQ,
+                                             (void *) pHd[j],
+                                             128);
+    }
+    t2=netapi_timing_stop();
+    sump += (t2-t1);
+}
+printf("\nfast poppush: np=%d  pop=%d  push=%d sumf=%d\n", (n_trials*NTOPOP),
+        sumt/(n_trials*NTOPOP),  sump/(n_trials*NTOPOP), sumf);
+sleep(1);
+return;
+}
+
+
+
+void example_fast_poll( PKTIO_HANDLE_T * p_pktio, int max_pkts)
 {
 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;
@@ -1868,7 +2907,7 @@ int max_batch=0;
 Qmss_QueueHnd rxQ= PKTIO_GET_DEFAULT_NETCP_Q(p_pktio);
 Qmss_QueueHnd freeQ;
 //loop forever
-for(;;)
+for(;max_pkts>0;)
 {
     t1= netapi_timing_stop();
     pHd[0] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (rxQ));
@@ -1878,22 +2917,29 @@ for(;;)
     {
         //convert previous descriptor PA -> VA
         tempVA  =  Osal_qmssPhyToVirt(pHd[i-1]); 
-        Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
 
         //try and preload desriptor
-        //__builtin_prefetch(tempVA);
+         __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 */
-        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);
-        //get ptr (Physical address) and length of associate buffer
-        //Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
+        Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
+        pinfo =  nwal_mGetProtoInfo(tempVA);
+        l3_off[jj]= nwal_mGetL3OffBytes(pinfo);
+        l4_off[jj]= nwal_mGetL4Offset(pinfo);
+        if(nwal_mGetAppidFmPkt(tempVA,&appid[jj]) != nwal_TRUE)
+        {
+            printf("ERROR!!!! AppID not available in incoming packet \n");
+        }
+//#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
@@ -1903,10 +2949,15 @@ for(;;)
         tempVA  =  Osal_qmssPhyToVirt(pHd[i-1]); 
 
         /* extract some meta data */
-        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);
+#if 1
+        pinfo =  nwal_mGetProtoInfo(tempVA);
+        l3_off[jj]= nwal_mGetL3OffBytes(pinfo);
+        l4_off[jj]= nwal_mGetL4Offset(pinfo);
+        if(nwal_mGetAppidFmPkt(tempVA,&appid[jj]) != nwal_TRUE)
+        {
+            printf("ERROR!!!! AppID not available in incoming packet \n");
+        }
+#endif
         //get ptr (Physical address) and length of associate buffer
         Cppi_getData (Cppi_DescType_HOST, (Cppi_Desc*)tempVA, &buf[jj], &len[jj]);
         jj+=1;
@@ -1937,8 +2988,8 @@ for(;;)
 
         //tempVA=Qmss_osalConvertDescPhyToVirt(pHd[k]);
         tempVA  =  Osal_qmssPhyToVirt(pHd[k]);
-        freeQ=Qmss_getQueueHandle(Cppi_getReturnQueue (Cppi_DescType_HOST, tempVA));
-        netapi_utilCacheWbInv(pHd[k],128);
+        freeQ=Qmss_getQueueHandle(Cppi_getReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)tempVA));
+        netapi_utilCacheWbInv(tempVA,128);
         //would need to wbInv buffer also in practice. Also need to walk
         // descriptor chain 
         t11= netapi_timing_stop();
@@ -1953,6 +3004,8 @@ for(;;)
     }
     sumt += (t2-t1);
     sump +=(pHd[i-1]? i: (i-1));
+    max_pkts -= (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", 
@@ -1966,7 +3019,170 @@ for(;;)
     }
 }
 
-
+    //cleanup any remaining buffers
+    for(;;)
+    {
+        pHd[0] = (Ti_Pkt *)QMSS_DESC_PTR(PKTIO_QMSS_QUEUE_POP_RAW (rxQ));
+        if(!pHd[0]) break;
+       tempVA  =  Osal_qmssPhyToVirt(pHd[0]);
+        freeQ=Qmss_getQueueHandle(Cppi_getReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)tempVA));
+        netapi_utilCacheWbInv(tempVA,128);
+        PKTIO_QMSS_QUEUE_PUSH_DESC_SIZE_RAW (freeQ,
+                                             (void *) pHd[0],
+                                             128);
+    }
 }
 
+#ifdef EXPERIMENTAL
 
+static inline void send_it(Ti_Pkt *tip, int len, ROUTE_SEC_T * p_sec)
+{
+  unsigned long st1;
+  unsigned long st2;
+  int err=0;
+  PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
+  nwalTxPktInfo_t meta_tx2={0};
+  st1=netapi_timing_start();
+  if (len<60) 
+  { 
+     unsigned int templen;
+     char * p_pkt;
+     len=60; 
+     Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
+     Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
+     stats.tx_min+=1;
+  }
+  Pktlib_setPacketLen(tip,len);
+  meta_tx2.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID );
+  meta_tx2.startOffset = 0;
+  meta_tx2.ipOffBytes = 14;
+  meta_tx2.ploadLen = len ;
+  if(p_sec)
+  {   
+       meta_tx2.txFlag1 |= NWAL_TX_FLAG1_DO_IPSEC_CRYPTO ;
+       meta2.sa_handle=p_sec->tx_inflow_mode_handle; //this tells netapi that inflow crypto needs to be applied
+       meta_tx2.enetPort=0;
+       meta_tx2.saOffBytes=14+20;
+       meta_tx2.saPayloadLen=len-14-20;   //don't include tag, mac and outer header
+       stats.sec_tx+=1;
+  }
+  meta2.u.tx_meta=&meta_tx2;
+  pktio_send(netcp_tx_chan,tip,&meta2,&err);
+  stats.tx +=1;
+  st2=netapi_timing_start();
+  stats.send_cycles += (unsigned long long) (st2-st1);  
+} 
+void recv_cb_router(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;
+Ti_Pkt * tip;
+unsigned int templen;
+char * p_pkt;
+HEAD_T temp_head;
+unsigned int appid;
+IP_HEAD_T th;
+ROUTE_SEC_T *sec_data=NULL;
+unsigned long t1;
+unsigned long t2;
+unsigned long ct1;
+unsigned long ct2;
+unsigned short ip_pl;
+int n_c_ops;
+t1=netapi_timing_start();
+ct1 =Osal_cache_op_measure(&n_c_ops);
+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
+        stats.rx+=1;
+        appid = ((unsigned int)meta[i].u.rx_meta->appId)&0xff000000;
+        switch(appid)
+        {
+           case(NETAPI_NETCP_MATCH_IPSEC):
+           case(NETAPI_NETCP_MATCH_IPSEC_POLICY):
+           {
+             int tailen=12+2;
+             memcpy(&temp_head,&p_pkt[14],sizeof(HEAD_T));
+             if (!check_header(&temp_head,&meta[i])) {
+                stats.n_bad+=1;
+                Pktlib_freePacket(tip); 
+                continue;
+             }
+             tailen+=p_pkt[len-12-2]; //padding length  (12)should come from sec_ptr
+             p_pkt = &p_pkt[8+16+20];   //16= iv len, should come from sec_ptr
+             len -= (8+16+20+tailen);  //16= iv len should come from sec ptr
+            
+             //now check inner headder.
+             memcpy(&th,&p_pkt[14],20);
+             if (!check_header(&temp_head,&meta[i])) {
+                stats.n_bad+=1;
+                Pktlib_freePacket(tip);
+                continue;
+             }
+             Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
+             Pktlib_setPacketLen(tip,len);
+             
+             if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data)<0)
+              {
+                stats.n_bad+=1;
+                Pktlib_freePacket(tip);
+             }
+             else
+             {
+               send_it(tip,len,sec_data);
+             }
+             break;
+           }
+           case(NETAPI_NETCP_MATCH_GENERIC_MAC):
+              if((p_pkt[12]!=0x8)||(p_pkt[13]!=0x00)) 
+              {
+                stats.n_new+=1;
+                Pktlib_freePacket(tip); 
+                continue;
+              }
+              if (!check_header(&temp_head,&meta[i])) 
+              {
+                stats.n_bad+=1;
+                Pktlib_freePacket(tip);
+                continue;
+              }
+              memcpy(&th,&p_pkt[14],20);
+              ip_pl= (((unsigned char *)&th.w1)[2]<<8) | ((unsigned char *)&th.w1)[3];
+              if ((ip_pl+14)<60)
+              {
+                len-= (60-(ip_pl+14));
+                stats.rx_min+=1;
+              }
+              Pktlib_setPacketLen(tip,len);
+              if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data)<0)
+              {
+                stats.n_bad+=1;
+                Pktlib_freePacket(tip);
+              }
+              else
+              {
+                 send_it(tip,len,sec_data);
+              }
+              break;
+           case(NETAPI_NETCP_MATCH_GENERIC_IP):
+              Pktlib_freePacket(tip); 
+              stats.n_new=1;
+              break;
+           default:
+              stats.n_new+=1;
+              Pktlib_freePacket(tip);
+              break;
+       }
+}
+t2=netapi_timing_start();
+ct2 =Osal_cache_op_measure(&n_c_ops);
+stats.app_cycles +=  (unsigned long long) (t2-t1);
+stats.tx_cache_cycles += (unsigned long long) (ct2-ct1);
+return;
+}
+#endif