net test modifications to support configuration of mutliple SA's and config file...
authorTinku Mannan <tmannan@ti.com>
Fri, 21 Sep 2012 15:26:47 +0000 (11:26 -0400)
committerTinku Mannan <tmannan@ti.com>
Fri, 21 Sep 2012 15:26:47 +0000 (11:26 -0400)
28 files changed:
ti/runtime/netapi/makefile_armv7
ti/runtime/netapi/netapi.h
ti/runtime/netapi/netapi_err.h
ti/runtime/netapi/netapi_sched.h
ti/runtime/netapi/netapi_sec.h [changed mode: 0644->0755]
ti/runtime/netapi/netapi_timer.h
ti/runtime/netapi/netapi_tune.h
ti/runtime/netapi/netsync.h
ti/runtime/netapi/pktio.h
ti/runtime/netapi/src/netapi_init.c
ti/runtime/netapi/src/netapi_sched.c
ti/runtime/netapi/src/netapi_sec.c [changed mode: 0644->0755]
ti/runtime/netapi/src/netapi_timer.c
ti/runtime/netapi/src/netcp_cfg.c
ti/runtime/netapi/src/osal.c
ti/runtime/netapi/src/pktio.c
ti/runtime/netapi/src/timer_loc.h
ti/runtime/netapi/src/timlist.c
ti/runtime/netapi/test/build/Makefile
ti/runtime/netapi/test/net_test.c [changed mode: 0644->0755]
ti/runtime/netapi/test/net_test.h [new file with mode: 0755]
ti/runtime/netapi/test/net_test_config.txt [new file with mode: 0644]
ti/runtime/netapi/test/router.c [new file with mode: 0755]
ti/runtime/netapi/test/stubs.c
ti/runtime/netapi/test/synchtest.c
ti/runtime/netapi/test/synchtest2.c
ti/runtime/netapi/test/trie.c
ti/runtime/netapi/test/udpif.c [new file with mode: 0755]

index 890ef117cfc14c217a8b09c5eb108ea18945ef18..bc82fc9c51fd09a50a0b0de6c479f16a13f74b33 100755 (executable)
@@ -1,75 +1,75 @@
-#*******************************************************************************\r
-#* FILE PURPOSE: Top level makefile for Creating Component Libraries for ARM\r
-#* architectures\r
-#*******************************************************************************\r
-#* FILE NAME: makefile\r
-#*\r
-#* DESCRIPTION: Defines Compiler tools paths, libraries , Build Options \r
-#*\r
-#*\r
-#*******************************************************************************\r
-#*\r
-# (Mandatory) Specify where various tools are installed.\r
-\r
-# Output for prebuilt generated libraries\r
-export ARMV7LIBDIR ?= ./lib\r
-export ARMV7OBJDIR ?= ./obj\r
-\r
-# ROOT Directory\r
-export ROOTDIR := ../../..\r
-\r
-\r
-# INCLUDE Directory\r
-export INCDIR := ../;$(PDK_INSTALL_PATH);$(ROOTDIR)\r
-\r
-# Common Macros used in make\r
-\r
-ifndef RM\r
-export RM = rm -f\r
-endif\r
-\r
-ifndef CP\r
-export CP = cp -p\r
-endif\r
-\r
-export MKDIR = mkdir -p\r
-\r
-ifndef RMDIR\r
-export RMDIR = rm -rf\r
-endif\r
-\r
-ifndef SED\r
-export SED = sed\r
-endif\r
-\r
-ifndef MAKE\r
-export MAKE = make\r
-endif\r
-\r
-# PHONY Targets\r
-.PHONY: lib tests  examples all clean\r
-\r
-# all rule\r
-all: .executables\r
-.executables: lib tests examples\r
-lib:\r
-\r
-# Make rule to create $(ARMV7LIBDIR)/libnetapi.a library\r
-lib: $(ARMV7LIBDIR)/libnetapi.a\r
-\r
-$(ARMV7LIBDIR)/libnetapi.a:\r
-       -@echo Building library...\r
-       @$(MAKE) -f ./build/Makefile $@\r
-\r
-# Rule to clean $(ARMV7LIBDIR)/libnetapi.a library\r
-clean:\r
-       -@echo Cleaning netapi package...\r
-       @$(MAKE) -f ./build/Makefile $@\r
-       @$(MAKE) -f ./test/build/Makefile $@\r
-\r
-# Make rule to create tests\r
-tests:\r
-       -@echo compiling tests ...\r
-       @$(MAKE) -f ./test/build/Makefile $@\r
-\r
-examples:\r
+#*******************************************************************************
+#* FILE PURPOSE: Top level makefile for Creating Component Libraries for ARM
+#* architectures
+#*******************************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Defines Compiler tools paths, libraries , Build Options 
+#*
+#*
+#*******************************************************************************
+#*
+# (Mandatory) Specify where various tools are installed.
+
+# Output for prebuilt generated libraries
+export ARMV7LIBDIR ?= ./lib
+export ARMV7OBJDIR ?= ./obj
+
+# ROOT Directory
+export ROOTDIR := ../../..
+
+
+# INCLUDE Directory
+export INCDIR := ../;$(PDK_INSTALL_PATH);$(ROOTDIR)
+
+# Common Macros used in make
+
+ifndef RM
+export RM = rm -f
+endif
+
+ifndef CP
+export CP = cp -p
+endif
+
+export MKDIR = mkdir -p
+
+ifndef RMDIR
+export RMDIR = rm -rf
+endif
+
+ifndef SED
+export SED = sed
+endif
+
+ifndef MAKE
+export MAKE = make
+endif
+
+# PHONY Targets
+.PHONY: lib tests  examples all clean
+
+# all rule
+all: .executables
+.executables: lib tests examples
+lib:
+
+# Make rule to create $(ARMV7LIBDIR)/libnetapi.a library
+lib: $(ARMV7LIBDIR)/libnetapi.a
+
+$(ARMV7LIBDIR)/libnetapi.a:
+       -@echo Building library...
+       @$(MAKE) -f ./build/Makefile $@
+
+# Rule to clean $(ARMV7LIBDIR)/libnetapi.a library
+clean:
+       -@echo Cleaning netapi package...
+       @$(MAKE) -f ./build/Makefile $@
+       @$(MAKE) -f ./test/build/Makefile $@
+
+# Make rule to create tests
+tests:
+       -@echo compiling tests ...
+       @$(MAKE) -f ./test/build/Makefile $@
+
+examples:
index ab710e4184d88e8148219a2d69264d18ed2b9eb9..40e748671f818d883e97f259c794a36f748ff86b 100755 (executable)
@@ -179,6 +179,15 @@ Cppi_HostDesc->origBuffPtr
 #include "ti/drv/nwal/nwal.h"
 #include "netapi_timer.h"
 #include "src/netapi_loc.h"
+#include "ti/drv/sa/salld.h"
+#define NETAPI_INFLOW_MODE_ACTIVE 1
+#define NETAPI_SIDEBAND_MODE_ACTIVE 2
+typedef struct NETAPI_SA_STATS_Tag
+{
+    Sa_IpsecStats_t     saIpsecStats;
+    Sa_DataModeStats_t  dataModeStats;
+    uint8_t mode_active;
+} NETAPI_SA_STATS_T;
 
 /************************************************
  **********BUILD TIME CONTROLS *****************
index fc301d62960130b574b4893c2a23917f18a87b82..8981991a57e72136f998deaa87c51c73142eae83 100755 (executable)
-/*******************************\r
- * file: netapi_err.h\r
- * purpose: netapi error codes\r
- **************************************************************\r
- * @file netapi.h\r
- * \r
- * @brief DESCRIPTION:  netapi Error Definitions for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- ******************************/\r
-\r
-#ifndef __NETAPI_ERR__\r
-#define __NETAPI_ERR__\r
-/**\r
- *   @defgroup NETAPI_RetValue NETAPI Return Codes\r
- */\r
-/**  @ingroup NETAPI_RetValue */\r
-\r
-/**\r
- *  @def  NETAPI_ERR_OK\r
- *       No error \r
- */\r
-#define NETAPI_ERR_OK  0\r
-/**\r
- *  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NOMEM\r
- *  @brief   out of memory error  \r
- */\r
-#define NETAPI_ERR_NOMEM -1\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_BAD_INPUT\r
- *       arguments or configuraiton is invalid\r
- */\r
-#define NETAPI_ERR_BAD_INPUT -2\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_QLLD \r
- *       QUEUE MANAGER Reports an error\r
- */\r
-#define NETAPI_ERR_QLLD -3\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NOTFOUND\r
- *       the resource cannot be located\r
- */\r
-#define NETAPI_ERR_NOTFOUND -4\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_BUSY\r
- *       Temporarily out of resources or resource leak\r
- */\r
-#define NETAPI_ERR_BUSY -5 \r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NWAL_ERR0\r
- *       NWAL subsytem reports error \r
- */\r
-#define NETAPI_ERR_NWAL_ERR0 -6\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NOT_IMLEMENTED_\r
- *       Feature not implemented in this version    \r
- */\r
-#define NETAPI_ERR_NOT_IMPLEMENTED -7\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NORES\r
- *      no free (hw) resources available \r
- */\r
-#define NETAPI_ERR_NORES -8\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_ALREADY_CANCELLED\r
- *       timer has already been cancelled\r
- */\r
-#define NETAPI_ERR_ALREADY_CANCELLED -100\r
-/**\r
-*  @ingroup NETAPI_RetValue\r
- *  @def  NETAPI_ERR_NWAL_TX_ERR\r
- *       error trying to send to NWAL. \r
- */\r
-#define NETAPI_ERR_NWAL_TX_ERR -65536\r
-#endif\r
+/*******************************
+ * file: netapi_err.h
+ * purpose: netapi error codes
+ **************************************************************
+ * @file netapi.h
+ * 
+ * @brief DESCRIPTION:  netapi Error Definitions for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************/
+
+#ifndef __NETAPI_ERR__
+#define __NETAPI_ERR__
+/**
+ *   @defgroup NETAPI_RetValue NETAPI Return Codes
+ */
+/**  @ingroup NETAPI_RetValue */
+
+/**
+ *  @def  NETAPI_ERR_OK
+ *       No error 
+ */
+#define NETAPI_ERR_OK  0
+/**
+ *  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NOMEM
+ *  @brief   out of memory error  
+ */
+#define NETAPI_ERR_NOMEM -1
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_BAD_INPUT
+ *       arguments or configuraiton is invalid
+ */
+#define NETAPI_ERR_BAD_INPUT -2
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_QLLD 
+ *       QUEUE MANAGER Reports an error
+ */
+#define NETAPI_ERR_QLLD -3
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NOTFOUND
+ *       the resource cannot be located
+ */
+#define NETAPI_ERR_NOTFOUND -4
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_BUSY
+ *       Temporarily out of resources or resource leak
+ */
+#define NETAPI_ERR_BUSY -5 
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NWAL_ERR0
+ *       NWAL subsytem reports error 
+ */
+#define NETAPI_ERR_NWAL_ERR0 -6
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NOT_IMLEMENTED_
+ *       Feature not implemented in this version    
+ */
+#define NETAPI_ERR_NOT_IMPLEMENTED -7
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NORES
+ *      no free (hw) resources available 
+ */
+#define NETAPI_ERR_NORES -8
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_ALREADY_CANCELLED
+ *       timer has already been cancelled
+ */
+#define NETAPI_ERR_ALREADY_CANCELLED -100
+/**
+*  @ingroup NETAPI_RetValue
+ *  @def  NETAPI_ERR_NWAL_TX_ERR
+ *       error trying to send to NWAL. 
+ */
+#define NETAPI_ERR_NWAL_TX_ERR -65536
+#endif
index 485488ffe076bd3dfd3e9ce3f497057862ccf399..f8375f8c22c511febcef1b9231d4b981d8206a15 100755 (executable)
-/***********************************\r
- * File: netapi_sched.h\r
- * Purpose:  netapi scheduler module\r
- **************************************************************\r
- * FILE: netapi_sched.h\r
- * \r
- * DESCRIPTION:  netapi sample event scheduler  header file for \r
- *         user space transport library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- ***********************************/\r
-#ifndef __NETAPI_SCHED__\r
-#define __NETAPI_SCHED__\r
-#include "netapi.h"\r
-\r
-/****************************\r
- **********CONTEXT**********\r
- ****************************/\r
-struct  NETAPI_SCHED_HANDLE_Tag;\r
-\r
-typedef void (*NETAPI_SCHED_CB)(struct NETAPI_SCHED_HANDLE_Tag *h);\r
-\r
-\r
-typedef struct NETAPI_SCHED_CONFIG_Tag\r
-{\r
-int valid_flags;  //which is being configured\r
-#define NETAPI_SCHED_DURATION 0x1\r
-#define NETAPI_SCHED_POWER 0x2\r
-#define NETAPI_SCHED_FINE  0x4 //future\r
-#define NETAPI_SCHED_CBV  0x8 //callback\r
-\r
-/*----duration------*/\r
-uint64_t duration;  //0=forever  or #tics to run for \r
-#define NETAPI_SCHED_FOREVER 0L\r
-\r
-/*-----house callback-----*/\r
-NETAPI_SCHED_CB house_cb;\r
-\r
-uint32_t interval;  // how many poll loop intervals after which to call the house keeping function \r
-\r
-\r
-/*------power control-------*/\r
-int power_control;  //0= always on, >0 = duty cycle \r
-#define NETAPI_SCHED_POWER_ALWAYS_OFF 0  //drop to idle\r
-#define NETAPI_SCHED_POWER_ALWAYS_ON 100 //always runs, no drop to idle\r
-\r
-int idle_time;   //in ticks\r
-\r
-/*-----fine control-----*/\r
-//future..\r
-\r
-} NETAPI_SCHED_CONFIG_T;\r
-\r
-\r
-/* the schedule context */\r
-typedef struct NETAPI_SCHED_HANDLE_Tag\r
-{\r
- volatile int state;   //0= shutdown, 1= shutting down, 2=active\r
-#define NETAPI_SCHED_STATE_SHUT 0\r
-#define NETAPI_SCHED_STATE_SHUTTING 1\r
-#define NETAPI_SCHED_STATE_ACTIVE 2\r
- void * back;  //pointer back to netapi handle\r
- NETAPI_SCHED_CONFIG_T config;\r
- uint64_t start;   /* start time */ \r
- volatile int shutdown_reason;\r
- volatile uint64_t shutdown_time;\r
-\r
-} NETAPI_SCHED_HANDLE_T;\r
-\r
-/* how to shut down */\r
-typedef struct NETAPI_SCHED_SHUTDOWN_Tag\r
-{\r
-int shutdown_type;\r
-#define NETAPI_SCHED_SHUTDOWN_NOW 0\r
-#define NETAPI_SCHED_SHUTDOWN_TO  1\r
-#define NETAPI_SCHED_SHUTDOWN_NEXT_IDLE  2\r
-int timeout;  //ticks from now to close\r
-\r
-} NETAPI_SCHED_SHUTDOWN_T;\r
-\r
-/****************************\r
- **************API **********\r
- ****************************/\r
-\r
-/* open a scheduling contex */\r
-NETAPI_SCHED_HANDLE_T * netapi_schedOpen(NETAPI_T n, NETAPI_SCHED_CONFIG_T * p_config, int *p_err);\r
-\r
-/* re-configure a scheduling context */\r
-int netapi_schedControl(NETAPI_SCHED_HANDLE_T *s, NETAPI_SCHED_CONFIG_T *p_config, int *p_err);\r
-\r
-/* return codes for wait_for_events() */\r
-#define NETAPI_SCHED_RETURN_ERR 0   //unknown, err\r
-#define NETAPI_SCHED_RETURN_TO 1    // returned after timeout\r
-#define NETAPI_SCHED_RETURN_SHUTDOWN 2 //returned after shutdown\r
-\r
-/* main entry point.  caller gives up control to scheduler */\r
-int netapi_schedWaitForEvents(NETAPI_SCHED_HANDLE_T *s, int * p_err);\r
-\r
-/* shutdown scheduler context */\r
-int netapi_schedShutdown(NETAPI_SCHED_HANDLE_T * s, NETAPI_SCHED_SHUTDOWN_T * p_close, int *p_err);\r
-\r
-static NETAPI_T netapi_schedGetNetapiHandle(NETAPI_SCHED_HANDLE_T *s)\r
-  { return (NETAPI_T)s->back;}\r
-#endif\r
+/***********************************
+ * File: netapi_sched.h
+ * Purpose:  netapi scheduler module
+ **************************************************************
+ * FILE: netapi_sched.h
+ * 
+ * DESCRIPTION:  netapi sample event scheduler  header file for 
+ *         user space transport library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ***********************************/
+#ifndef __NETAPI_SCHED__
+#define __NETAPI_SCHED__
+#include "netapi.h"
+
+/****************************
+ **********CONTEXT**********
+ ****************************/
+struct  NETAPI_SCHED_HANDLE_Tag;
+
+typedef void (*NETAPI_SCHED_CB)(struct NETAPI_SCHED_HANDLE_Tag *h);
+
+
+typedef struct NETAPI_SCHED_CONFIG_Tag
+{
+int valid_flags;  //which is being configured
+#define NETAPI_SCHED_DURATION 0x1
+#define NETAPI_SCHED_POWER 0x2
+#define NETAPI_SCHED_FINE  0x4 //future
+#define NETAPI_SCHED_CBV  0x8 //callback
+
+/*----duration------*/
+uint64_t duration;  //0=forever  or #tics to run for 
+#define NETAPI_SCHED_FOREVER 0L
+
+/*-----house callback-----*/
+NETAPI_SCHED_CB house_cb;
+
+uint32_t interval;  // how many poll loop intervals after which to call the house keeping function 
+
+
+/*------power control-------*/
+int power_control;  //0= always on, >0 = duty cycle 
+#define NETAPI_SCHED_POWER_ALWAYS_OFF 0  //drop to idle
+#define NETAPI_SCHED_POWER_ALWAYS_ON 100 //always runs, no drop to idle
+
+int idle_time;   //in ticks
+
+/*-----fine control-----*/
+//future..
+
+} NETAPI_SCHED_CONFIG_T;
+
+
+/* the schedule context */
+typedef struct NETAPI_SCHED_HANDLE_Tag
+{
+ volatile int state;   //0= shutdown, 1= shutting down, 2=active
+#define NETAPI_SCHED_STATE_SHUT 0
+#define NETAPI_SCHED_STATE_SHUTTING 1
+#define NETAPI_SCHED_STATE_ACTIVE 2
+ void * back;  //pointer back to netapi handle
+ NETAPI_SCHED_CONFIG_T config;
+ uint64_t start;   /* start time */ 
+ volatile int shutdown_reason;
+ volatile uint64_t shutdown_time;
+
+} NETAPI_SCHED_HANDLE_T;
+
+/* how to shut down */
+typedef struct NETAPI_SCHED_SHUTDOWN_Tag
+{
+int shutdown_type;
+#define NETAPI_SCHED_SHUTDOWN_NOW 0
+#define NETAPI_SCHED_SHUTDOWN_TO  1
+#define NETAPI_SCHED_SHUTDOWN_NEXT_IDLE  2
+int timeout;  //ticks from now to close
+
+} NETAPI_SCHED_SHUTDOWN_T;
+
+/****************************
+ **************API **********
+ ****************************/
+
+/* open a scheduling contex */
+NETAPI_SCHED_HANDLE_T * netapi_schedOpen(NETAPI_T n, NETAPI_SCHED_CONFIG_T * p_config, int *p_err);
+
+/* re-configure a scheduling context */
+int netapi_schedControl(NETAPI_SCHED_HANDLE_T *s, NETAPI_SCHED_CONFIG_T *p_config, int *p_err);
+
+/* return codes for wait_for_events() */
+#define NETAPI_SCHED_RETURN_ERR 0   //unknown, err
+#define NETAPI_SCHED_RETURN_TO 1    // returned after timeout
+#define NETAPI_SCHED_RETURN_SHUTDOWN 2 //returned after shutdown
+
+/* main entry point.  caller gives up control to scheduler */
+int netapi_schedWaitForEvents(NETAPI_SCHED_HANDLE_T *s, int * p_err);
+
+/* shutdown scheduler context */
+int netapi_schedShutdown(NETAPI_SCHED_HANDLE_T * s, NETAPI_SCHED_SHUTDOWN_T * p_close, int *p_err);
+
+static NETAPI_T netapi_schedGetNetapiHandle(NETAPI_SCHED_HANDLE_T *s)
+  { return (NETAPI_T)s->back;}
+void netapi_sched_get_stats(unsigned long long * p_pkts, 
+                            unsigned long long * p_cycles,
+                            unsigned long long * p_ccycles);
+#endif
old mode 100644 (file)
new mode 100755 (executable)
index 6c8486c..d88473a
@@ -44,7 +44,7 @@
 #include "netapi.h"
 #include "ti/runtime/pktlib/pktlib.h"
 #include "ti/drv/nwal/nwal.h"
-
+#include <ti/drv/sa/salld.h>
 
 // To hold SA info */
 typedef struct NETAPI_SEC_SA_INFO_tag
index 033b757bf81c1496175a629117349b0760413aa6..83aedd4b675ae72e8e020c4a0db0c85173a341a5 100755 (executable)
-/************************************************\r
- *FILE: netapi_timer.h\r
- *Purpose:  netapi timer related functions\r
- **************************************************************\r
- * @file  netapi_timer.h\r
- * \r
- * @breif DESCRIPTION:  netapi timer library header file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- ***********************************************/\r
-\r
-/**  @mainpage Netapi Timer Lib \r
- *\r
- *   @section intro  Introduction\r
- *\r
- *   The network API provides a user space interface to timers\r
- *      - a function to read a hw provided 64bit time stamp, @ref netapi_getTimestamp\r
- *        This returns a tick running at 1/6 cpu frequency\r
- *      - functions to create or open timer groups: @ref netapi_TimerGroupCreateTimer\r
- *        and @ref  netapi_TimerGroupOpenTimer.  A timer group\r
- *        is a group of timers with the same characteristics:\r
- *        -> local or global\r
- *        -> timer resolution (msc, 10 msc, etc)\r
- *        -> expect to fire or expect to cancel\r
- *        -> the same call back function for fired timers\r
- *      - functions to close or delete timer groups\r
- *      - function to start a timer,  @ref netapi_TimerGroupStartTimer\r
- *      - function to cancel a timer,  @ref netapi_TimerGroupCancelTimer\r
- *      - function to poll a timer group, or all timer groups registered to a NETAPI \r
- *        instance\r
- *  \par\r
- *  NOTE:\r
- *      (C) Copyright 2010-2011 Texas Instruments, Inc.\r
- *  \par\r
- */\r
-\r
-\r
-#ifndef __NETAPI_TIMER__H\r
-#define __NETAPI_TIMER__H\r
-#include "netapi.h"\r
-\r
-extern volatile unsigned long * t64_virt_addr;\r
-extern unsigned int cpu_cycles_sec;\r
-\r
-//return hw timer clock ticks per second\r
-unsigned long t64_ticks_sec(void);\r
-#define netapi_getTicksPerSec t64_ticks_sec\r
-\r
-\r
-/**  @ingroup netapi_api_functions */\r
-\r
-/*\r
- *  @brief  API returns a 64bit h/w timestamp \r
- *\r
- *  @details reads a h/w timer (TIMER64 on Appleton SOC) and returns a 64 bit time stamp    \r
- *           timer runs at @ref t64_ticks_sec.  Nominally this should be 1/6 CPU clk (@ref cpu_cycles_sec)\r
- *           \r
- *  @param[in]  none \r
- *  @retval     unsigned long long timestamp (64 buts) \r
- *  @pre        @ref netapi_init \r
- */\r
-//return 64 bit timestamp from hw timer\r
-volatile static inline unsigned long long netapi_getTimestamp(void) \r
-{\r
- volatile unsigned long long t1;\r
- volatile unsigned long long t2;\r
- unsigned long long val;\r
- t1 = t64_virt_addr[0x10/4]; //lo\r
- t2 = t64_virt_addr[0x14/4]; //hi\r
- val = ((unsigned long long) t2) <<32 | t1;\r
- return val;\r
-}\r
-\r
-/******************************************************/\r
-/*******************TIMER API***************************/\r
-/******************************************************/\r
-typedef void * NETAPI_TIMER_GROUP_HANDLE_T;     \r
-typedef void * NETAPI_TIMER_T;\r
-typedef void * NETAPI_TIMER_LIST_T;\r
-\r
-/* timer filter values */\r
-typedef int NETAPI_TIMER_FILTER_T;\r
-#define NETAPI_TIMER_NA   (void*) NULL\r
-#define NETAPI_TIMER_FILTER_GLOBAL 0x1\r
-#define NETAPI_TIMER_FILTER_LOCAL 0x2\r
-#define NETAPI_TIMER_FILTER_E2F 0x4\r
-#define NETAPI_TIMER_FILTER_E2C 0x8\r
-#define NETAPI_TIMER_FITLER_ALL 0xf\r
-\r
-//iterator on TIMER_LIST_T\r
-NETAPI_TIMER_T netapi_TimerGetFirst( NETAPI_TIMER_LIST_T list);\r
-NETAPI_TIMER_T netapi_TimerGetNext( NETAPI_TIMER_LIST_T list,NETAPI_TIMER_T prev);\r
-void * netapi_TimerGetCookie(NETAPI_TIMER_T timer);\r
-unsigned long long netapi_TimerGetTs(NETAPI_TIMER_T timer); //debug\r
-\r
-/*\r
- *  @brief  API callback for timer expiration \r
- *\r
- *  @details this function, provided by application,  is registered by application \r
- *  when timer group is created.  It is called by timer library when a timer or set of timers\r
- *  expire. The timer list can be walled with iterators: @ref netapi_TimerGetFirst, \r
- *  @ref netapi_TimerGetNext.  The timer id or "cookie" can be accessed via @ref netapi_TimerGetCookie\r
- *  NOTE: callback should check for cookie==NULL since timer could be cancelled as it is being fired\r
- *  @param[in]   @ref NETAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group\r
- *  @param[in]   int  : the number of timers that have fired \r
- *  @param[in]   @ref NETAPI_TIMER_LIST_T : the list of timers that hace expired \r
- *  @param[in]   uint64_t : the current time\r
- *  @retval     none \r
- *  @pre        @ref netapi_init , @ref netapi_TimerGroupCreate, @ref netapi_TimerGroupStartTimer\r
- */\r
-//timer callback\r
-typedef void (*NETAPI_TIMER_CB_T) (\r
-       NETAPI_TIMER_GROUP_HANDLE_T th,  //timer group\r
-       int n_fired,     //# timers fired\r
-       NETAPI_TIMER_LIST_T fired_list,  //the list of fired timers. Access via iterators above\r
-       uint64_t currentTime);  //current timestamp\r
-\r
-/*\r
-*  @brief  API  for Timer Group Creation \r
- *\r
- *  @details this function is used to create a timer group. A timer group is a block of timers\r
- *  that share the same characteristics.\r
- *  @param[in]   @ref NETAPI_T : the handle to the NETAPI Instance \r
- *  @param[in]   char * : the name of the timer\r
- *  @param[in]   @ref NETAPI_TIMER_CB_T :  the callback function\r
- *  @param[in]   int  : local   (=1 if this timer group is local to this netapi instance, =0 if global)\r
- *  @param[in]   int  : exp2cancel. (=1 if this timer group is expected to be cancelled, =0 otherwise))\r
- *  @param[in]   int  : the timer group 'tick'. This is the group timer resolution in hw timestamp units. \r
- *                Eg for 10 msc , enter @ref netapi_getTicksPerSec()/100\r
- *  @param[in]   int  : timerTolerence in hw timestamp ticks.  This is FUTURE.\r
- *  @param[in]   int  : maxTimers - the max number of timers that can be handled by the group.\r
- *  @param[in]   int* : pointer to error return\r
- *  @retval     @ref NETAPI_TIMER_GROUP_HANDLE_T : handle for this timer group \r
- *  @pre        @ref netapi_init \r
- */\r
-//create a timer group\r
-NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupCreate(\r
-       NETAPI_T  netHandle,  //netapi instance\r
-       char * name, //name of the timer block\r
-       NETAPI_TIMER_CB_T cb, //the callback function\r
-       int local,    //1 if timers local to thread\r
-       int exp2cancel,//1 if expect to cancel\r
-       int timerTicksPerGroupTick,  //resolution for this timer block, in hw timer ticks\r
-        int timerTolerence,          //tolerence for this timer block, in hw timer ticksi [FUTURE]\r
-       int maxTimers, //max # of timer objects for this group\r
-       int *pErr);\r
-\r
-//open a [global] timer group [FUTURE]\r
-NETAPI_TIMER_GROUP_HANDLE_T  netapi_TimerGroupOpen(\r
-       NETAPI_T netHandle,\r
-        char * name,\r
-       NETAPI_TIMER_CB_T cb,\r
-       int *pErr);\r
-\r
-/*\r
-*  @brief  API  for Start a Timer \r
- *\r
- *  @details this function is used to start a timer. When it expires, the @ref NETAPI_TIMER_CB_T\r
- *           will be called.\r
- *  @param[in]   @ref NATAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group \r
- *  @param[in]   void * :  application provided timer id or cookie. MUST NOT BE NULL!!!\r
- *  @param[in]   uint64_t  : offset from current time when to fire this timer.  This offset MUST be in\r
- *                           units of timer group ticks (set at create time).  Eg. For 10 msc timer group,\r
- *                           offset2fire =1 =>  timer is to fire in 10 msc.\r
- *  @param[in]   int* : pointer to error return\r
- *  @retval     @ref NETAPI_TIMER_T : handle for this timer. Used to reference the timer for cancel\r
- *  @pre        @ref netapi_init , @ref netapi_TimerGroupCreate\r
- */\r
-//start an individual timer\r
-NETAPI_TIMER_T netapi_TimerGroupStartTimer(\r
-       NETAPI_TIMER_GROUP_HANDLE_T th,  //the group handle\r
-       void * cookie,       //user id ->  CANNONT BE NULL \r
-       uint64_t offs2fire,  //offset in timerGroup ticks (eg msc)\r
-       int * pErr);         //error return\r
-\r
-/*\r
-*  @brief  API  for Cancel a Timer \r
- *\r
- *  @details this function is used to cancel a timer. When it expires, the @ref NETAPI_TIMER_CB_T\r
- *           will be called.\r
- *  @param[in]   @ref NATAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group \r
- *  @param[in]   @ref NATAPI_TIMER_T : the handle to the  individual timer to cancel\r
- *  @param[in]   int* : pointer to error return\r
- *  @retval    none \r
- *  @pre        @ref netapi_TimerGroupStartTimer\r
- */\r
-//Cancel a timer\r
-void  netapi_TimerGroupCancel(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-       NETAPI_TIMER_T timerId,\r
-        int *pErr);\r
-\r
-//close an opened timer group\r
-void netapi_TimerGroupClose(\r
-       NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        int *pErr);\r
-\r
-//close an opened timer group\r
-void netapi_TimerGroupDelete(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        int *pErr);\r
-\r
-//extract netapi handle from timer group handle\r
-NETAPI_T netap_TimerGroupGetNH( NETAPI_TIMER_GROUP_HANDLE_T th);\r
-\r
-//poll a specific timer group\r
-int  netapi_TimerGroupPoll(NETAPI_TIMER_GROUP_HANDLE_T th, int maxTimers);\r
-\r
-/*\r
-*  @brief  API  for Polling all timer groups attached to an instance \r
- *\r
- *  @details this function is used to poll all or a specified subset of the timer groups of an \r
- *  instance. A mask can be set to filter which categories of timer groups (local vs global etc)\r
- *  to poll. The approximate max # of timers to process can also be set.\r
- *  @param[in]   @ref NATAPI_T : the handle of the netapi instance. \r
- *  @param[in]   @ref NATAPI_TIMER_FILTER_T : the bit mask of timer group types to poll \r
- *  @param[in]   int : approximate max number of timers to process.  NOTE: this can be used to\r
- *               coarsely control how many timers to process. In general, all timers that have been \r
- *               hashed into the same cell and have expired will be processed regardless of the\r
- *               maxTmers setting.. [FUTURE]\r
- *  @retval    none \r
- *  @pre        @ref netapi_init, @ref netapi_TimerGroupCreate\r
- */\r
-\r
-//poll all timers\r
-int  netapi_TimerGroupPollAll(NETAPI_T nh, NETAPI_TIMER_FILTER_T f,  int maxTimers);\r
-\r
-/*****************END API*********************************/\r
-\r
-\r
-#endif\r
+/************************************************
+ *FILE: netapi_timer.h
+ *Purpose:  netapi timer related functions
+ **************************************************************
+ * @file  netapi_timer.h
+ * 
+ * @breif DESCRIPTION:  netapi timer library header file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ***********************************************/
+
+/**  @mainpage Netapi Timer Lib 
+ *
+ *   @section intro  Introduction
+ *
+ *   The network API provides a user space interface to timers
+ *      - a function to read a hw provided 64bit time stamp, @ref netapi_getTimestamp
+ *        This returns a tick running at 1/6 cpu frequency
+ *      - functions to create or open timer groups: @ref netapi_TimerGroupCreateTimer
+ *        and @ref  netapi_TimerGroupOpenTimer.  A timer group
+ *        is a group of timers with the same characteristics:
+ *        -> local or global
+ *        -> timer resolution (msc, 10 msc, etc)
+ *        -> expect to fire or expect to cancel
+ *        -> the same call back function for fired timers
+ *      - functions to close or delete timer groups
+ *      - function to start a timer,  @ref netapi_TimerGroupStartTimer
+ *      - function to cancel a timer,  @ref netapi_TimerGroupCancelTimer
+ *      - function to poll a timer group, or all timer groups registered to a NETAPI 
+ *        instance
+ *  \par
+ *  NOTE:
+ *      (C) Copyright 2010-2011 Texas Instruments, Inc.
+ *  \par
+ */
+
+
+#ifndef __NETAPI_TIMER__H
+#define __NETAPI_TIMER__H
+#include "netapi.h"
+
+extern volatile unsigned long * t64_virt_addr;
+extern unsigned int cpu_cycles_sec;
+
+//return hw timer clock ticks per second
+unsigned long t64_ticks_sec(void);
+#define netapi_getTicksPerSec t64_ticks_sec
+
+
+/**  @ingroup netapi_api_functions */
+
+/*
+ *  @brief  API returns a 64bit h/w timestamp 
+ *
+ *  @details reads a h/w timer (TIMER64 on Appleton SOC) and returns a 64 bit time stamp    
+ *           timer runs at @ref t64_ticks_sec.  Nominally this should be 1/6 CPU clk (@ref cpu_cycles_sec)
+ *           
+ *  @param[in]  none 
+ *  @retval     unsigned long long timestamp (64 buts) 
+ *  @pre        @ref netapi_init 
+ */
+//return 64 bit timestamp from hw timer
+volatile static inline unsigned long long netapi_getTimestamp(void) 
+{
+ volatile unsigned long long t1;
+ volatile unsigned long long t2;
+ unsigned long long val;
+ t1 = t64_virt_addr[0x10/4]; //lo
+ t2 = t64_virt_addr[0x14/4]; //hi
+ val = ((unsigned long long) t2) <<32 | t1;
+ return val;
+}
+
+/******************************************************/
+/*******************TIMER API***************************/
+/******************************************************/
+typedef void * NETAPI_TIMER_GROUP_HANDLE_T;     
+typedef void * NETAPI_TIMER_T;
+typedef void * NETAPI_TIMER_LIST_T;
+
+/* timer filter values */
+typedef int NETAPI_TIMER_FILTER_T;
+#define NETAPI_TIMER_NA   (void*) NULL
+#define NETAPI_TIMER_FILTER_GLOBAL 0x1
+#define NETAPI_TIMER_FILTER_LOCAL 0x2
+#define NETAPI_TIMER_FILTER_E2F 0x4
+#define NETAPI_TIMER_FILTER_E2C 0x8
+#define NETAPI_TIMER_FITLER_ALL 0xf
+
+//iterator on TIMER_LIST_T
+NETAPI_TIMER_T netapi_TimerGetFirst( NETAPI_TIMER_LIST_T list);
+NETAPI_TIMER_T netapi_TimerGetNext( NETAPI_TIMER_LIST_T list,NETAPI_TIMER_T prev);
+void * netapi_TimerGetCookie(NETAPI_TIMER_T timer);
+unsigned long long netapi_TimerGetTs(NETAPI_TIMER_T timer); //debug
+
+/*
+ *  @brief  API callback for timer expiration 
+ *
+ *  @details this function, provided by application,  is registered by application 
+ *  when timer group is created.  It is called by timer library when a timer or set of timers
+ *  expire. The timer list can be walled with iterators: @ref netapi_TimerGetFirst, 
+ *  @ref netapi_TimerGetNext.  The timer id or "cookie" can be accessed via @ref netapi_TimerGetCookie
+ *  NOTE: callback should check for cookie==NULL since timer could be cancelled as it is being fired
+ *  @param[in]   @ref NETAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group
+ *  @param[in]   int  : the number of timers that have fired 
+ *  @param[in]   @ref NETAPI_TIMER_LIST_T : the list of timers that hace expired 
+ *  @param[in]   uint64_t : the current time
+ *  @retval     none 
+ *  @pre        @ref netapi_init , @ref netapi_TimerGroupCreate, @ref netapi_TimerGroupStartTimer
+ */
+//timer callback
+typedef void (*NETAPI_TIMER_CB_T) (
+       NETAPI_TIMER_GROUP_HANDLE_T th,  //timer group
+       int n_fired,     //# timers fired
+       NETAPI_TIMER_LIST_T fired_list,  //the list of fired timers. Access via iterators above
+       uint64_t currentTime);  //current timestamp
+
+/*
+*  @brief  API  for Timer Group Creation 
+ *
+ *  @details this function is used to create a timer group. A timer group is a block of timers
+ *  that share the same characteristics.
+ *  @param[in]   @ref NETAPI_T : the handle to the NETAPI Instance 
+ *  @param[in]   char * : the name of the timer
+ *  @param[in]   @ref NETAPI_TIMER_CB_T :  the callback function
+ *  @param[in]   int  : local   (=1 if this timer group is local to this netapi instance, =0 if global)
+ *  @param[in]   int  : exp2cancel. (=1 if this timer group is expected to be cancelled, =0 otherwise))
+ *  @param[in]   int  : the timer group 'tick'. This is the group timer resolution in hw timestamp units. 
+ *                Eg for 10 msc , enter @ref netapi_getTicksPerSec()/100
+ *  @param[in]   int  : timerTolerence in hw timestamp ticks.  This is FUTURE.
+ *  @param[in]   int  : maxTimers - the max number of timers that can be handled by the group.
+ *  @param[in]   int* : pointer to error return
+ *  @retval     @ref NETAPI_TIMER_GROUP_HANDLE_T : handle for this timer group 
+ *  @pre        @ref netapi_init 
+ */
+//create a timer group
+NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupCreate(
+       NETAPI_T  netHandle,  //netapi instance
+       char * name, //name of the timer block
+       NETAPI_TIMER_CB_T cb, //the callback function
+       int local,    //1 if timers local to thread
+       int exp2cancel,//1 if expect to cancel
+       int timerTicksPerGroupTick,  //resolution for this timer block, in hw timer ticks
+        int timerTolerence,          //tolerence for this timer block, in hw timer ticksi [FUTURE]
+       int maxTimers, //max # of timer objects for this group
+       int *pErr);
+
+//open a [global] timer group [FUTURE]
+NETAPI_TIMER_GROUP_HANDLE_T  netapi_TimerGroupOpen(
+       NETAPI_T netHandle,
+        char * name,
+       NETAPI_TIMER_CB_T cb,
+       int *pErr);
+
+/*
+*  @brief  API  for Start a Timer 
+ *
+ *  @details this function is used to start a timer. When it expires, the @ref NETAPI_TIMER_CB_T
+ *           will be called.
+ *  @param[in]   @ref NATAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group 
+ *  @param[in]   void * :  application provided timer id or cookie. MUST NOT BE NULL!!!
+ *  @param[in]   uint64_t  : offset from current time when to fire this timer.  This offset MUST be in
+ *                           units of timer group ticks (set at create time).  Eg. For 10 msc timer group,
+ *                           offset2fire =1 =>  timer is to fire in 10 msc.
+ *  @param[in]   int* : pointer to error return
+ *  @retval     @ref NETAPI_TIMER_T : handle for this timer. Used to reference the timer for cancel
+ *  @pre        @ref netapi_init , @ref netapi_TimerGroupCreate
+ */
+//start an individual timer
+NETAPI_TIMER_T netapi_TimerGroupStartTimer(
+       NETAPI_TIMER_GROUP_HANDLE_T th,  //the group handle
+       void * cookie,       //user id ->  CANNONT BE NULL 
+       uint64_t offs2fire,  //offset in timerGroup ticks (eg msc)
+       int * pErr);         //error return
+
+/*
+*  @brief  API  for Cancel a Timer 
+ *
+ *  @details this function is used to cancel a timer. When it expires, the @ref NETAPI_TIMER_CB_T
+ *           will be called.
+ *  @param[in]   @ref NATAPI_TIMER_GROUP_HANDLE_T : the handle to the timer group 
+ *  @param[in]   @ref NATAPI_TIMER_T : the handle to the  individual timer to cancel
+ *  @param[in]   int* : pointer to error return
+ *  @retval    none 
+ *  @pre        @ref netapi_TimerGroupStartTimer
+ */
+//Cancel a timer
+void  netapi_TimerGroupCancel(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+       NETAPI_TIMER_T timerId,
+        int *pErr);
+
+//close an opened timer group
+void netapi_TimerGroupClose(
+       NETAPI_TIMER_GROUP_HANDLE_T th,
+        int *pErr);
+
+//close an opened timer group
+void netapi_TimerGroupDelete(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        int *pErr);
+
+//extract netapi handle from timer group handle
+NETAPI_T netap_TimerGroupGetNH( NETAPI_TIMER_GROUP_HANDLE_T th);
+
+//poll a specific timer group
+int  netapi_TimerGroupPoll(NETAPI_TIMER_GROUP_HANDLE_T th, int maxTimers);
+
+/*
+*  @brief  API  for Polling all timer groups attached to an instance 
+ *
+ *  @details this function is used to poll all or a specified subset of the timer groups of an 
+ *  instance. A mask can be set to filter which categories of timer groups (local vs global etc)
+ *  to poll. The approximate max # of timers to process can also be set.
+ *  @param[in]   @ref NATAPI_T : the handle of the netapi instance. 
+ *  @param[in]   @ref NATAPI_TIMER_FILTER_T : the bit mask of timer group types to poll 
+ *  @param[in]   int : approximate max number of timers to process.  NOTE: this can be used to
+ *               coarsely control how many timers to process. In general, all timers that have been 
+ *               hashed into the same cell and have expired will be processed regardless of the
+ *               maxTmers setting.. [FUTURE]
+ *  @retval    none 
+ *  @pre        @ref netapi_init, @ref netapi_TimerGroupCreate
+ */
+
+//poll all timers
+int  netapi_TimerGroupPollAll(NETAPI_T nh, NETAPI_TIMER_FILTER_T f,  int maxTimers);
+
+/*****************END API*********************************/
+
+
+#endif
index d6e133bb64b8daa5c051d2633ddb476d42e5969c..d02ef127ad2879731e9cb75424866e64b2405e54 100755 (executable)
 //(7) # of QM descriptors (total)
 //     this can be set set in netapi_init
 // MUST BE POWER OF 2
-#define TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM  1024 /* 16384 is abs max */
+#define TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM  2048 /* 16384 is abs max */
 
 //(8) Region info
 #define TUNE_NETAPI_NUM_LOCAL_DESC  64 
 
 /* at least as big as DEFAULT_NUM_SOLO+DEFAULT_NUM_BUFFERS but also a power of 2*/
-#define TUNE_NETAPI_NUM_GLOBAL_DESC  512 
+#define TUNE_NETAPI_NUM_GLOBAL_DESC  1024 
 
 #define TUNE_NETAPI_DESC_SIZE  128 //don't change!!
 #ifdef NETAPI_USE_DDR
 
 
 //(10) NWAL (internal) config. Should not have to change
-#define TUNE_NETAPI_CONFIG_MAX_PA_TO_SA_DESC       16
-#define TUNE_NETAPI_CONFIG_MAX_SA_TO_PA_DESC       16
+#define TUNE_NETAPI_CONFIG_MAX_PA_TO_SA_DESC       32
+#define TUNE_NETAPI_CONFIG_MAX_SA_TO_PA_DESC       32
 
 #define TUNE_NETAPI_MAX_NUM_MAC                2    //2 'logical' mac addresses
-#define TUNE_NETAPI_MAX_NUM_IP                 4    //2 ip addresses 
+#define TUNE_NETAPI_MAX_NUM_IP                 32    //2 ip addresses 
 #define TUNE_NETAPI_MAX_NUM_PORTS_PER_CORE     4    //udp/tcp ports -> for lUT2 )      
 #define TUNE_NETAPI_MAX_NUM_PORTS     (TUNE_NETAPI_MAX_NUM_PORTS_PER_CORE * (TUNE_NETAPI_NUM_CORES)) 
 
 #ifdef NETAPI_ENABLE_SECURITY
-#define TUNE_NETAPI_MAX_NUM_IPSEC_CHANNELS     4
+#define TUNE_NETAPI_MAX_NUM_IPSEC_CHANNELS     32
 #else
 #define TUNE_NETAPI_MAX_NUM_IPSEC_CHANNELS     0
 #endif
index f316d0656e1eab4407237d2e3f67aeea67077c33..8ab74729a00509ced215ba91b71c5adc488a522f 100755 (executable)
-/*********************************************\r
- * File: netsync.h\r
- * Purpose: NETAPI Synchronization primitives\r
- **************************************************************\r
- * FILE: netsync.h\r
- * \r
- * DESCRIPTION:  netapi synch utilities header file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- **********************************************/\r
-#ifndef NETAPI_SYNC_H\r
-#define NETAPI_SYNCH_H\r
-\r
-/*--------------------------*/\r
-/*----------spinlock--------*/\r
-/*--------------------------*/\r
-\r
-typedef int NETAPI_SPINLOCK_T;\r
-\r
-#define NETAPI_SPINLOCK_LOCKVAL 1\r
-#define NETAPI_SPINLOCK_UNLOCKVAL 0 //never change!!\r
-#define NETAPI_SPINLOCK_UNLOCKED_INITIALIZER (NETAPI_SPINLOCK_UNLOCKVAL)\r
-\r
-/* init a lock */\r
-static inline void netapi_spinlock_init (NETAPI_SPINLOCK_T * val) {*val=NETAPI_SPINLOCK_UNLOCKVAL;}\r
-\r
-/* lock a spinlock */\r
-static inline void netapi_spinlock_lock(NETAPI_SPINLOCK_T * val)\r
-{\r
-while(__sync_lock_test_and_set(val, NETAPI_SPINLOCK_LOCKVAL))\r
-    {\r
-        asm volatile("nop" ::  );\r
-        asm volatile("nop" ::  );\r
-        asm volatile("nop" ::  );\r
-        asm volatile("nop" ::  );\r
-    }\r
-}\r
-\r
-/* try to get lock 1 time. Return 1 if ok, 0 if un-successful */\r
-static inline int netapi_spinlock_try_lock( NETAPI_SPINLOCK_T* val)\r
-{\r
-  int i=0;\r
-  if (__sync_lock_test_and_set(val, NETAPI_SPINLOCK_LOCKVAL))  return 0;\r
-  return 1;\r
-}\r
-\r
-\r
-/* unlock a spinlock.   */\r
-static inline void netapi_spinlock_unlock(NETAPI_SPINLOCK_T * val)\r
-{\r
-  __sync_lock_release(val);\r
-}\r
-\r
-/* poll a lock, return 0 if unlocked, NETAPI_SPINLOCK_LOCKVAL if locked */\r
-static inline int netapi_spinlock_is_locked(NETAPI_SPINLOCK_T * val)\r
-{\r
-   return *val;\r
-}\r
-\r
-/*--------------------------*/\r
-/*----------rwlock--------*/\r
-/*--------------------------*/\r
-\r
-/* a rw lock strucuture */\r
-typedef struct RWLOCK_Tag\r
-{\r
-      NETAPI_SPINLOCK_T lock_outer; //lock this structure. very short duration lock\r
-      NETAPI_SPINLOCK_T lock_w;     //real write lock\r
-      unsigned long n_readers; /* # readers active */\r
-} NETAPI_RWLOCK_T;\r
-\r
-//initialize a rw lock \r
-static inline void netapi_rwlock_init(NETAPI_RWLOCK_T * p_lock)\r
-{\r
-        netapi_spinlock_init(&p_lock->lock_outer);\r
-       netapi_spinlock_init(&p_lock->lock_w);\r
-        p_lock->n_readers=0;\r
-}\r
-\r
-// lock a write lock.  \r
-static inline void netapi_rwlock_write_lock(NETAPI_RWLOCK_T * p_lock)\r
-{\r
-  int ret;\r
-  while(1)\r
-  {\r
-        netapi_spinlock_lock(&p_lock->lock_outer); //get outer lock - now nothing can change\r
-       // check for 0 readers\r
-        if(p_lock->n_readers)\r
-        {\r
-           netapi_spinlock_unlock(&p_lock->lock_outer); //give up outer & spin\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           continue;\r
-        }\r
-\r
-       //ok, no readers.  see if we can get writer lock\r
-        ret=netapi_spinlock_try_lock(&p_lock->lock_w); //try get writer lock 1 time\r
-        if(!ret)      \r
-        {\r
-           netapi_spinlock_unlock(&p_lock->lock_outer); //give up outer & spin\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           asm volatile("nop" ::  );\r
-           continue;  /* try again */\r
-        }\r
-        netapi_spinlock_unlock(&p_lock->lock_outer); //got write lock=> no other writer, no readers!  Keep the writelock but unlock the outer.\r
-        return;\r
-  }\r
-}\r
-\r
-//unlock a writer part of rwlock */\r
-static inline void netapi_rwlock_write_unlock(NETAPI_RWLOCK_T * p_lock)\r
-{\r
-  netapi_spinlock_unlock(&p_lock->lock_w);\r
-}\r
-\r
-//grab a read lock\r
-//=> can be other readers, but no writer\r
-static inline void netapi_rwlock_read_lock(NETAPI_RWLOCK_T * p_lock)\r
-{\r
-int ret;\r
-\r
-while(1)\r
-{\r
-  /*1st grab outer lock. once we have it, nothing can change */\r
-  netapi_spinlock_lock(&p_lock->lock_outer);\r
-\r
-  /* see if there is a writer */\r
-  ret= netapi_spinlock_is_locked(&p_lock->lock_w);\r
-\r
-  //there is a writer\r
-  if (ret)\r
-  {\r
-     netapi_spinlock_unlock(&p_lock->lock_outer);  //give up outer and spin\r
-     asm volatile("nop" ::  );\r
-     asm volatile("nop" ::  );\r
-     asm volatile("nop" ::  );\r
-     asm volatile("nop" ::  );\r
-     continue; \r
-  }\r
-\r
-  /* there is no writer so we can read!*/\r
-  p_lock->n_readers+=1;\r
-\r
-  /* mb ? */\r
-  __sync_synchronize();  //make sure every core sees that n_readers has changed\r
-\r
-  /* now give back the outer lock */\r
-  netapi_spinlock_unlock(&p_lock->lock_outer);\r
-  return;\r
-}\r
-}\r
-\r
-//rw_lock reader unlock\r
-static inline void netapi_rwlock_read_unlock(NETAPI_RWLOCK_T * p_lock)\r
-{\r
-  //grab outer\r
-  netapi_spinlock_lock(&p_lock->lock_outer);\r
-\r
-  //decrement # of readers.  Make sure all cores see update\r
-  p_lock->n_readers--;\r
-  __sync_synchronize(); \r
-  //TBD: need to check for <0? \r
-  \r
-  /* give up the outer */\r
-  netapi_spinlock_unlock(&p_lock->lock_outer);\r
-}\r
-\r
-/*--------------------------*/\r
-/*----------atomic32--------*/\r
-/*--------------------------*/\r
-typedef struct NETAPI_ATOMIC32_tag\r
-{\r
-       long val;\r
-} NETAPI_ATOMIC32_T;\r
-\r
-#define NETAPI_ATOMIC_INIT32(x) {x}\r
-static inline int netapi_atomic_read32(NETAPI_ATOMIC32_T *p) {return p->val;}\r
-\r
-static inline void netapi_atomic_set32(NETAPI_ATOMIC32_T *p, int val) \r
-{__sync_fetch_and_add(&p->val,0); } //todo crude, why not p->val=val?\r
-\r
-static inline void netapi_atomic_add32(NETAPI_ATOMIC32_T *p, int val)\r
-{__sync_fetch_and_add(&p->val,val);}\r
-\r
-static inline void netapi_atomic_sub32(NETAPI_ATOMIC32_T *p, int val)\r
-{__sync_fetch_and_sub(&p->val,val);}\r
-\r
-#define NETAPI_atomic_inc32(p) netapi_atomic_add32(p,1);\r
-#define NETAPI_atomic_dec32(p) netapi_atomic_sub32(p,1);\r
-\r
-static inline int netapi_atomic_add_return32(NETAPI_ATOMIC32_T *p, int val)\r
-{return __sync_add_and_fetch(&p->val,val);}\r
-\r
-static inline int netapi_atomic_sub_return32(NETAPI_ATOMIC32_T *p, int val)\r
-{return __sync_sub_and_fetch(&p->val,val);}\r
-\r
-static inline int netapi_atomic_inc_and_test32(NETAPI_ATOMIC32_T *p)\r
-{return __sync_add_and_fetch(&p->val,1);}\r
-\r
-static inline int netapi_atomic_dec_and_test32(NETAPI_ATOMIC32_T *p)\r
-{return !__sync_sub_and_fetch(&p->val,1);}\r
-\r
-static inline int netapi_atomic_test_and_set32(NETAPI_ATOMIC32_T *p)\r
-{return (! _sync_lock_test_and_set(p, 1));}\r
-\r
-#define netapi_atomic_clear32(p) netapi_atomic_set32(p,0);\r
-\r
-/*--------------------------*/\r
-/*----------atomic64--------*/\r
-/*--------------------------*/\r
-typedef struct NETAPI_ATOMIC64_Tag\r
-{\r
-       NETAPI_SPINLOCK_T lock;\r
-       long long val;\r
-} NETAPI_ATOMIC64_T;\r
-\r
-#define NETAPI_ATOMIC_INIT64(x) {NETAPI_SPINLOCK_UNLOCKED_INITIALIZER,x}\r
-\r
-static inline long long  netapi_atomic_read64(NETAPI_ATOMIC64_T *p)\r
-{\r
-long long latch_val;\r
-netapi_spinlock_lock(&p->lock);  //acquire lock\r
-latch_val = p->val;\r
-netapi_spinlock_unlock(&p->lock);  //free lock\r
-return latch_val;\r
-}\r
-\r
-static inline void netapi_atomic_set64(NETAPI_ATOMIC64_T *p,long long val)\r
-{\r
-netapi_spinlock_lock(&p->lock);  //acquire lock\r
-p->val = val;\r
-//__sync_synchronize();  //todo: may not need as unlock will do this also probably\r
-netapi_spinlock_unlock(&p->lock);  //free lock\r
-}\r
-\r
-static inline void netapi_atomic_add64(NETAPI_ATOMIC64_T *p, long long val) \r
-{\r
-netapi_spinlock_lock(&p->lock);  //acquire lock\r
-p->val += val;\r
-//__sync_synchronize();  //todo: may not need as unlock will do this also probably\r
-netapi_spinlock_unlock(&p->lock);  //free lock\r
-}\r
-\r
-/*******************************************************\r
- ****************memory barrier************************\r
-******************************************************/\r
-static inline void netapi_mb(){__sync_synchronize();}\r
-static inline void netapi_rmb(){__sync_synchronize();}\r
-static inline void netapi_wmb(){__sync_synchronize();}\r
-\r
-\r
-#endif\r
+/*********************************************
+ * File: netsync.h
+ * Purpose: NETAPI Synchronization primitives
+ **************************************************************
+ * FILE: netsync.h
+ * 
+ * DESCRIPTION:  netapi synch utilities header file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ **********************************************/
+#ifndef NETAPI_SYNC_H
+#define NETAPI_SYNCH_H
+
+/*--------------------------*/
+/*----------spinlock--------*/
+/*--------------------------*/
+
+typedef int NETAPI_SPINLOCK_T;
+
+#define NETAPI_SPINLOCK_LOCKVAL 1
+#define NETAPI_SPINLOCK_UNLOCKVAL 0 //never change!!
+#define NETAPI_SPINLOCK_UNLOCKED_INITIALIZER (NETAPI_SPINLOCK_UNLOCKVAL)
+
+/* init a lock */
+static inline void netapi_spinlock_init (NETAPI_SPINLOCK_T * val) {*val=NETAPI_SPINLOCK_UNLOCKVAL;}
+
+/* lock a spinlock */
+static inline void netapi_spinlock_lock(NETAPI_SPINLOCK_T * val)
+{
+while(__sync_lock_test_and_set(val, NETAPI_SPINLOCK_LOCKVAL))
+    {
+        asm volatile("nop" ::  );
+        asm volatile("nop" ::  );
+        asm volatile("nop" ::  );
+        asm volatile("nop" ::  );
+    }
+}
+
+/* try to get lock 1 time. Return 1 if ok, 0 if un-successful */
+static inline int netapi_spinlock_try_lock( NETAPI_SPINLOCK_T* val)
+{
+  int i=0;
+  if (__sync_lock_test_and_set(val, NETAPI_SPINLOCK_LOCKVAL))  return 0;
+  return 1;
+}
+
+
+/* unlock a spinlock.   */
+static inline void netapi_spinlock_unlock(NETAPI_SPINLOCK_T * val)
+{
+  __sync_lock_release(val);
+}
+
+/* poll a lock, return 0 if unlocked, NETAPI_SPINLOCK_LOCKVAL if locked */
+static inline int netapi_spinlock_is_locked(NETAPI_SPINLOCK_T * val)
+{
+   return *val;
+}
+
+/*--------------------------*/
+/*----------rwlock--------*/
+/*--------------------------*/
+
+/* a rw lock strucuture */
+typedef struct RWLOCK_Tag
+{
+      NETAPI_SPINLOCK_T lock_outer; //lock this structure. very short duration lock
+      NETAPI_SPINLOCK_T lock_w;     //real write lock
+      unsigned long n_readers; /* # readers active */
+} NETAPI_RWLOCK_T;
+
+//initialize a rw lock 
+static inline void netapi_rwlock_init(NETAPI_RWLOCK_T * p_lock)
+{
+        netapi_spinlock_init(&p_lock->lock_outer);
+       netapi_spinlock_init(&p_lock->lock_w);
+        p_lock->n_readers=0;
+}
+
+// lock a write lock.  
+static inline void netapi_rwlock_write_lock(NETAPI_RWLOCK_T * p_lock)
+{
+  int ret;
+  while(1)
+  {
+        netapi_spinlock_lock(&p_lock->lock_outer); //get outer lock - now nothing can change
+       // check for 0 readers
+        if(p_lock->n_readers)
+        {
+           netapi_spinlock_unlock(&p_lock->lock_outer); //give up outer & spin
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           continue;
+        }
+
+       //ok, no readers.  see if we can get writer lock
+        ret=netapi_spinlock_try_lock(&p_lock->lock_w); //try get writer lock 1 time
+        if(!ret)      
+        {
+           netapi_spinlock_unlock(&p_lock->lock_outer); //give up outer & spin
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           asm volatile("nop" ::  );
+           continue;  /* try again */
+        }
+        netapi_spinlock_unlock(&p_lock->lock_outer); //got write lock=> no other writer, no readers!  Keep the writelock but unlock the outer.
+        return;
+  }
+}
+
+//unlock a writer part of rwlock */
+static inline void netapi_rwlock_write_unlock(NETAPI_RWLOCK_T * p_lock)
+{
+  netapi_spinlock_unlock(&p_lock->lock_w);
+}
+
+//grab a read lock
+//=> can be other readers, but no writer
+static inline void netapi_rwlock_read_lock(NETAPI_RWLOCK_T * p_lock)
+{
+int ret;
+
+while(1)
+{
+  /*1st grab outer lock. once we have it, nothing can change */
+  netapi_spinlock_lock(&p_lock->lock_outer);
+
+  /* see if there is a writer */
+  ret= netapi_spinlock_is_locked(&p_lock->lock_w);
+
+  //there is a writer
+  if (ret)
+  {
+     netapi_spinlock_unlock(&p_lock->lock_outer);  //give up outer and spin
+     asm volatile("nop" ::  );
+     asm volatile("nop" ::  );
+     asm volatile("nop" ::  );
+     asm volatile("nop" ::  );
+     continue; 
+  }
+
+  /* there is no writer so we can read!*/
+  p_lock->n_readers+=1;
+
+  /* mb ? */
+  __sync_synchronize();  //make sure every core sees that n_readers has changed
+
+  /* now give back the outer lock */
+  netapi_spinlock_unlock(&p_lock->lock_outer);
+  return;
+}
+}
+
+//rw_lock reader unlock
+static inline void netapi_rwlock_read_unlock(NETAPI_RWLOCK_T * p_lock)
+{
+  //grab outer
+  netapi_spinlock_lock(&p_lock->lock_outer);
+
+  //decrement # of readers.  Make sure all cores see update
+  p_lock->n_readers--;
+  __sync_synchronize(); 
+  //TBD: need to check for <0? 
+  
+  /* give up the outer */
+  netapi_spinlock_unlock(&p_lock->lock_outer);
+}
+
+/*--------------------------*/
+/*----------atomic32--------*/
+/*--------------------------*/
+typedef struct NETAPI_ATOMIC32_tag
+{
+       long val;
+} NETAPI_ATOMIC32_T;
+
+#define NETAPI_ATOMIC_INIT32(x) {x}
+static inline int netapi_atomic_read32(NETAPI_ATOMIC32_T *p) {return p->val;}
+
+static inline void netapi_atomic_set32(NETAPI_ATOMIC32_T *p, int val) 
+{__sync_fetch_and_add(&p->val,0); } //todo crude, why not p->val=val?
+
+static inline void netapi_atomic_add32(NETAPI_ATOMIC32_T *p, int val)
+{__sync_fetch_and_add(&p->val,val);}
+
+static inline void netapi_atomic_sub32(NETAPI_ATOMIC32_T *p, int val)
+{__sync_fetch_and_sub(&p->val,val);}
+
+#define NETAPI_atomic_inc32(p) netapi_atomic_add32(p,1);
+#define NETAPI_atomic_dec32(p) netapi_atomic_sub32(p,1);
+
+static inline int netapi_atomic_add_return32(NETAPI_ATOMIC32_T *p, int val)
+{return __sync_add_and_fetch(&p->val,val);}
+
+static inline int netapi_atomic_sub_return32(NETAPI_ATOMIC32_T *p, int val)
+{return __sync_sub_and_fetch(&p->val,val);}
+
+static inline int netapi_atomic_inc_and_test32(NETAPI_ATOMIC32_T *p)
+{return __sync_add_and_fetch(&p->val,1);}
+
+static inline int netapi_atomic_dec_and_test32(NETAPI_ATOMIC32_T *p)
+{return !__sync_sub_and_fetch(&p->val,1);}
+
+static inline int netapi_atomic_test_and_set32(NETAPI_ATOMIC32_T *p)
+{return (! _sync_lock_test_and_set(p, 1));}
+
+#define netapi_atomic_clear32(p) netapi_atomic_set32(p,0);
+
+/*--------------------------*/
+/*----------atomic64--------*/
+/*--------------------------*/
+typedef struct NETAPI_ATOMIC64_Tag
+{
+       NETAPI_SPINLOCK_T lock;
+       long long val;
+} NETAPI_ATOMIC64_T;
+
+#define NETAPI_ATOMIC_INIT64(x) {NETAPI_SPINLOCK_UNLOCKED_INITIALIZER,x}
+
+static inline long long  netapi_atomic_read64(NETAPI_ATOMIC64_T *p)
+{
+long long latch_val;
+netapi_spinlock_lock(&p->lock);  //acquire lock
+latch_val = p->val;
+netapi_spinlock_unlock(&p->lock);  //free lock
+return latch_val;
+}
+
+static inline void netapi_atomic_set64(NETAPI_ATOMIC64_T *p,long long val)
+{
+netapi_spinlock_lock(&p->lock);  //acquire lock
+p->val = val;
+//__sync_synchronize();  //todo: may not need as unlock will do this also probably
+netapi_spinlock_unlock(&p->lock);  //free lock
+}
+
+static inline void netapi_atomic_add64(NETAPI_ATOMIC64_T *p, long long val) 
+{
+netapi_spinlock_lock(&p->lock);  //acquire lock
+p->val += val;
+//__sync_synchronize();  //todo: may not need as unlock will do this also probably
+netapi_spinlock_unlock(&p->lock);  //free lock
+}
+
+/*******************************************************
+ ****************memory barrier************************
+******************************************************/
+static inline void netapi_mb(){__sync_synchronize();}
+static inline void netapi_rmb(){__sync_synchronize();}
+static inline void netapi_wmb(){__sync_synchronize();}
+
+
+#endif
index 48b6966f622d0cb844e21f0857cf1f845b63f010..bc1d87472cb46fb98f6caeb1767cfb7957630ce0 100755 (executable)
@@ -290,7 +290,7 @@ static inline int pktio_poll(PKTIO_HANDLE_T * handle,   //handle to pktio
                PKTIO_POLL_T * p_poll_cfg,  //polling configuration
                int * err)
 {
-       handle->_poll((struct PKTIO_HANDLE_tag *) handle, p_poll_cfg, err);
+       return handle->_poll((struct PKTIO_HANDLE_tag *) handle, p_poll_cfg, err);
 }
 
 /*
index ef1a0f9c4c5549b4ac956851ce7474810f9178c8..ffe4fc89c15aabfbebc8f01b54910a8f5800e378 100755 (executable)
@@ -369,7 +369,8 @@ uint8_t paBuf0[NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF0]ALIGN(CACHE_LINESZ);
 #define NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF1    128
 uint8_t paBuf1[NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF1]ALIGN(CACHE_LINESZ);
 
-#define NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF2   768 
+//#define NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF2   768 
+#define NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF2   6144
 uint8_t paBuf2[NETAPI_NWAL_CONFIG_BUFSIZE_PA_BUF2]ALIGN(CACHE_LINESZ);
 
 /* Memory used for SA LLD global Handle */
index 5c5f85bb690a071738eb6e90b30e6c603cc9b2e9..1b5ea732334176c8b7d11e42b3534ef8458a14fb 100755 (executable)
-/****************************************\r
- * File: netapi_sched.c\r
- * Purpose:  netapi scheduling module\r
- * NOTE: This sample right now.\r
- **************************************************************\r
- * FILE: netapi_sched.c\r
- * \r
- * DESCRIPTION:  netapi sample scheduler source file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- ****************************************/\r
-\r
-#include "netapi.h"\r
-#include "netapi_sched.h"\r
-\r
-\r
-/****************************************/\r
-/************API************************/\r
-/**************************************/\r
-\r
-/* open a scheduling contex */\r
-NETAPI_SCHED_HANDLE_T * netapi_schedOpen(NETAPI_T n, NETAPI_SCHED_CONFIG_T * p_config, int *p_err)\r
-{\r
-  *p_err=0;\r
-   NETAPI_SCHED_HANDLE_T * ph = (NETAPI_SCHED_HANDLE_T *) netapi_get_scheduler(n);\r
-  if(!ph) {*p_err= NETAPI_ERR_NOMEM; return NULL;}\r
-  if(!p_config) {*p_err=  NETAPI_ERR_BAD_INPUT; return NULL;}\r
-  memcpy(&ph->config,p_config,sizeof(NETAPI_SCHED_CONFIG_T));\r
-  ph->start =   netapi_getTimestamp();\r
-  ph->back = (void *) n;\r
-  if (ph->config.valid_flags & NETAPI_SCHED_DURATION)\r
-  {\r
-    if (ph->config.duration == NETAPI_SCHED_FOREVER) \r
-       {\r
-       ph->shutdown_time=(uint64_t) -1; \r
-       }\r
-    else\r
-       {\r
-       ph->shutdown_time = ph->start + ph->config.duration;\r
-       }\r
-  }\r
-  else ph->shutdown_time = (uint64_t) -1;\r
-  ph->state =NETAPI_SCHED_STATE_ACTIVE; \r
-  return(ph);\r
-\r
-}\r
-\r
-/* re-configure a scheduling context */\r
-int netapi_schedControl(NETAPI_SCHED_HANDLE_T *s, NETAPI_SCHED_CONFIG_T *p_config, int *p_err)\r
-{\r
-  /* not implemented */\r
-\r
-  return 0;\r
-}\r
-\r
-\r
-/* main entry point.  caller gives up control to scheduler */\r
-int netapi_schedWaitForEvents(NETAPI_SCHED_HANDLE_T *s, int *p_err)\r
-{\r
-  int err;\r
-  *p_err=0;\r
-  unsigned long long t =  netapi_getTimestamp();\r
-  int next_house;\r
-\r
-  next_house =  s->config.interval;\r
-  /* loop for duration or until shutdown */\r
-  for(;t< s->shutdown_time;)\r
-  {\r
-    t = netapi_getTimestamp();\r
-    next_house -=1;\r
-    //poll all  pktio channels we have open in RX mode \r
-     pktio_pollAll((NETAPI_T) s->back, NULL, &err);\r
-\r
-    //poll pktlib garbage collections for registered heaps..\r
-    netapi_pollHeapGarbage((NETAPI_T) s->back);\r
-    \r
-    //todo timers (local and global)\r
-    netapi_TimerGroupPollAll((NETAPI_T) s->back, NETAPI_TIMER_FITLER_ALL, 100000);\r
-\r
-    //poll NETCP/PA control channels \r
-    netapi_netcpPoll((NETAPI_T) s->back);\r
-\r
-    //see if time to do a house keeping callback\r
-     if ((s->config.valid_flags & NETAPI_SCHED_CBV) && s->config.house_cb)\r
-        if (next_house<=0)\r
-        {\r
-          s->config.house_cb(s);\r
-           next_house = s->config.interval;\r
-        }\r
-    //see if we were closed and/or its time to close\r
-    if (s->state!= NETAPI_SCHED_STATE_ACTIVE) \r
-         { s->state=NETAPI_SCHED_STATE_SHUT; break;}\r
-  }\r
-  return 1;\r
-}\r
-\r
-/* shutdown scheduler context */\r
-int netapi_schedShutdown(NETAPI_SCHED_HANDLE_T * s, NETAPI_SCHED_SHUTDOWN_T * p_close, int * p_err)\r
-{\r
-  *p_err=0;\r
-  s->state=NETAPI_SCHED_STATE_SHUTTING;  //say we are closing\r
-\r
-  return 1;\r
-}\r
-\r
-\r
+/****************************************
+ * File: netapi_sched.c
+ * Purpose:  netapi scheduling module
+ * NOTE: This sample right now.
+ **************************************************************
+ * FILE: netapi_sched.c
+ * 
+ * DESCRIPTION:  netapi sample scheduler source file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ****************************************/
+
+#include "netapi.h"
+#include "netapi_sched.h"
+
+#define NO_TIMER  //turn off timer related scheduling
+#define NO_GARBAGE  //turn off garbage collection
+
+volatile unsigned long long netapi_sched_num_pkts=0L;
+volatile unsigned long long netapi_sched_busy_cycles=0L;
+volatile unsigned long long netapi_sched_cache_cycles=0L;
+void netapi_sched_get_stats(unsigned long long * p_pkts, unsigned long long * p_cycles,
+                            unsigned long long * p_cache_cycles)
+{
+   *p_pkts= netapi_sched_num_pkts;
+   *p_cycles= netapi_sched_busy_cycles;
+   *p_cache_cycles= netapi_sched_cache_cycles;
+   return;
+}
+/****************************************/
+/************API************************/
+/**************************************/
+
+/* open a scheduling contex */
+NETAPI_SCHED_HANDLE_T * netapi_schedOpen(NETAPI_T n, NETAPI_SCHED_CONFIG_T * p_config, int *p_err)
+{
+  *p_err=0;
+   NETAPI_SCHED_HANDLE_T * ph = (NETAPI_SCHED_HANDLE_T *) netapi_get_scheduler(n);
+  if(!ph) {*p_err= NETAPI_ERR_NOMEM; return NULL;}
+  if(!p_config) {*p_err=  NETAPI_ERR_BAD_INPUT; return NULL;}
+  memcpy(&ph->config,p_config,sizeof(NETAPI_SCHED_CONFIG_T));
+  ph->start =   netapi_getTimestamp();
+  ph->back = (void *) n;
+  if (ph->config.valid_flags & NETAPI_SCHED_DURATION)
+  {
+    if (ph->config.duration == NETAPI_SCHED_FOREVER) 
+       {
+       ph->shutdown_time=(uint64_t) -1; 
+       }
+    else
+       {
+       ph->shutdown_time = ph->start + ph->config.duration;
+       }
+  }
+  else ph->shutdown_time = (uint64_t) -1;
+  ph->state =NETAPI_SCHED_STATE_ACTIVE; 
+  return(ph);
+
+}
+
+/* re-configure a scheduling context */
+int netapi_schedControl(NETAPI_SCHED_HANDLE_T *s, NETAPI_SCHED_CONFIG_T *p_config, int *p_err)
+{
+  /* not implemented */
+
+  return 0;
+}
+
+
+/* main entry point.  caller gives up control to scheduler */
+int netapi_schedWaitForEvents(NETAPI_SCHED_HANDLE_T *s, int *p_err)
+{
+  int err;
+  *p_err=0;
+  unsigned long long t =  netapi_getTimestamp();
+  int next_house;
+  volatile int pkts;
+  volatile unsigned long t1;
+  volatile unsigned long t2;
+  volatile unsigned int cache_op_b2;
+  volatile int n_c_ops;
+
+  next_house =  s->config.interval;
+  /* loop for duration or until shutdown */
+  for(;t< s->shutdown_time;)
+  {
+#ifndef NO_TIMER
+    t = netapi_getTimestamp();
+#endif
+    next_house -=1;
+    //poll all  pktio channels we have open in RX mode 
+     Osal_cache_op_measure_reset();
+     t1=netapi_timing_start();
+     pkts=pktio_pollAll((NETAPI_T) s->back, NULL, &err);
+     t2=netapi_timing_start();
+     if (pkts)
+     {
+        netapi_sched_num_pkts+= (unsigned long long) pkts;
+        netapi_sched_busy_cycles += (unsigned long long) (t2-t1);
+        cache_op_b2= Osal_cache_op_measure(&n_c_ops);
+        netapi_sched_cache_cycles += (unsigned long long) cache_op_b2;
+     }
+
+#ifndef NO_GARBAGE
+    //poll pktlib garbage collections for registered heaps..
+    netapi_pollHeapGarbage((NETAPI_T) s->back);
+#endif    
+    
+#ifndef NO_TIMER
+    //todo timers (local and global)
+    netapi_TimerGroupPollAll((NETAPI_T) s->back, NETAPI_TIMER_FITLER_ALL, 100000);
+#endif
+    //poll NETCP/PA control channels 
+    netapi_netcpPoll((NETAPI_T) s->back);
+
+    //see if time to do a house keeping callback
+     if ((s->config.valid_flags & NETAPI_SCHED_CBV) && s->config.house_cb)
+        if (next_house<=0)
+        {
+          s->config.house_cb(s);
+           next_house = s->config.interval;
+        }
+    //see if we were closed and/or its time to close
+    if (s->state!= NETAPI_SCHED_STATE_ACTIVE) 
+         { s->state=NETAPI_SCHED_STATE_SHUT; break;}
+  }
+  return 1;
+}
+
+/* shutdown scheduler context */
+int netapi_schedShutdown(NETAPI_SCHED_HANDLE_T * s, NETAPI_SCHED_SHUTDOWN_T * p_close, int * p_err)
+{
+  *p_err=0;
+  s->state=NETAPI_SCHED_STATE_SHUTTING;  //say we are closing
+
+  return 1;
+}
+
+
old mode 100644 (file)
new mode 100755 (executable)
index a718821..2ab6c26
@@ -193,8 +193,6 @@ nwalCreateSAParams_t    createParam =
         dmSaParam.dmSaParam.aadSize=0;        /**todo: pass in or deduce */
         dmSaParam.dmSaParam.enc1st =  (sa_info->dir ==NWAL_SA_DIR_OUTBOUND) ? nwal_TRUE : nwal_FALSE;  //encypt 1st for outbound
         //todo; allow app q for Sideband return
-        dmSaParam.dmSaParam.appRxPktFlowId= CPPI_PARAM_NOT_SPECIFIED; 
-        dmSaParam.dmSaParam.appRxPktQueue= CPPI_PARAM_NOT_SPECIFIED; 
         memcpy(&dmSaParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
         retValue = nwal_setDMSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
                                   (nwal_AppId)appId,
@@ -483,4 +481,30 @@ netapi_secDelRxPolicy_internal(h,  policy_app_id, 0, perr);
 
 
 
+void  netapi_getSaStats (NETAPI_T h, NETCP_CFG_SA_T handle,
+                                       NETAPI_SA_STATS_T*      pSaStats)
+{
 
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+void * handle_inflow;
+void * handle_sideband;
+int tunnelId = (handle >>8) &0xffff;
+int have_to_wait = 1;
+    handle_inflow = netcp_cfgp_get_sa_handles(&netapi_get_global()->nwal_context,
+                                          tunnelId, &handle_sideband);
+    if(handle_inflow)
+    {
+        //printf("netapi_getSaStats(): handle inflow valid\n");
+        nwal_getSecAssocStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
+                                                handle_inflow, &(pSaStats->saIpsecStats));
+        pSaStats->mode_active |= NETAPI_INFLOW_MODE_ACTIVE;
+    }
+    if(handle_sideband)
+    {
+        //printf("netapi_getSaStats(): handle sideband valid\n");
+        nwal_getDataModeStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
+                                                handle_sideband, &(pSaStats->dataModeStats));
+         pSaStats->mode_active |= NETAPI_SIDEBAND_MODE_ACTIVE;
+    }
+    
+}
index 3cf1abe3e61a778f6edb0c8dcc48cb4eb3f24199..34b118e95d69055d7a04c2a89d436cc2ac19febd 100755 (executable)
-/*******************************\r
- * FILE: netapi_timer.c\r
- * Purpose:  implementation of user space timers \r
- **************************************************************\r
- * FILE: netapi.c\r
- * \r
- * DESCRIPTION:  user space timers main source file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
-*\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- ***************************************************************/\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <string.h>\r
-#include "netapi.h"\r
-#include "netapi_timer.h"\r
-#include "timer_loc.h"\r
-\r
-\r
-/*******************************************************************\r
- *  hash function:  returns cell to place timer object in\r
- *   \r
- ******************************************************************/\r
-/* static */ int our_hash(\r
-       unsigned long long ct,\r
-       int n_cells,\r
-       unsigned int cell_width)\r
-{\r
-int c;\r
-   //simple hash function\r
-   c=  (ct/cell_width) % n_cells;\r
-  return c;\r
-\r
-}\r
-\r
-//iterator on TIMER_LIST_T\r
-NETAPI_TIMER_T netapi_TimerGetFirst( NETAPI_TIMER_LIST_T list)\r
-{ return (NETAPI_TIMER_T) ((TIM_LIST_T *)list)->head; }\r
-\r
-NETAPI_TIMER_T netapi_TimerGetNext( NETAPI_TIMER_LIST_T list,NETAPI_TIMER_T prev)\r
-{return prev ? (NETAPI_TIMER_T) ((TIM_T*) prev)->next:NULL ;}\r
-\r
-//return cookie associated with timer object \r
-void * netapi_TimerGetCookie(NETAPI_TIMER_T timer)\r
-{ return ((TIM_T*) timer)->cookie; }\r
-\r
-//return timeer value associated with timer object \r
-unsigned long long netapi_TimerGetTs(NETAPI_TIMER_T timer)\r
-{ return ((TIM_T*) timer)->t; }\r
-\r
-#if 0\r
-//timer callback\r
-typedef void (*NETAPI_TIMER_CB_T) (\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        int n_fired,     //# timers fired\r
-        NETAPI_TIMER_LIST_T fired_list,\r
-        uint64_t currentTime);\r
-#endif\r
-\r
-static TIMER_GROUP_T temp_g; //temp. todo: put inot netHandle\r
-\r
-//create a timer group\r
-NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupCreate(\r
-        NETAPI_T  netHandle,\r
-        char * name,\r
-        NETAPI_TIMER_CB_T cb,\r
-        int local,    //1 if timers local to thread\r
-        int exp2cancel,//1 if expect to cancel\r
-        int cell_width, //in ticks\r
-       int tol,        //in ticks\r
-        int maxTimers,\r
-        int *pErr)\r
-{\r
- int ret= tim_group_create(&temp_g, TUNE_NETAPI_NUM_TIMER_CELLS, maxTimers);\r
- if (!ret) {*pErr = NETAPI_ERR_NOMEM; return NULL;}\r
- *pErr=0;\r
- temp_g.cb = cb;\r
- temp_g.local = local;\r
- temp_g.exp2cancel= exp2cancel;\r
- temp_g.cell_width=cell_width;\r
- temp_g.tol=tol;\r
- temp_g.h = netHandle;\r
- temp_g.last_polled=(netapi_getTimestamp()/cell_width) * cell_width + (cell_width-1);\r
- printf(">timer group %s created. width = %d (ticks)\n", name, cell_width);\r
- return (NETAPI_TIMER_GROUP_HANDLE_T) &temp_g;\r
-}\r
-\r
-//open a [global] timer group\r
-NETAPI_TIMER_GROUP_HANDLE_T  netapi_TimerGroupOpen(\r
-        NETAPI_T netHandle,\r
-        char * name,\r
-        NETAPI_TIMER_CB_T cb,\r
-        int *pErr)\r
-{\r
-printf(">timer group open not implemented \n");\r
-\r
-}\r
-\r
-//start an individual timer\r
-NETAPI_TIMER_T netapi_TimerGroupStartTimer(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        void * cookie,\r
-        uint64_t offs2fire,  //offset in group ticks \r
-        int * pErr)\r
-{\r
-TIM_T * timer_obj;\r
-unsigned long long ct= netapi_getTimestamp() + offs2fire* ((TIMER_GROUP_T*) th)->cell_width;\r
-int cell;\r
-*pErr=0;\r
-\r
-//find cell where to insert\r
-cell = our_hash(ct,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width);\r
-\r
-//get object and insert into this cell\r
-timer_obj =tim_set(\r
-   &((TIMER_GROUP_T*) th)->cells[cell],\r
-   &((TIMER_GROUP_T*) th)->free , \r
-   ct,\r
-   cookie,\r
-   pErr);\r
-if (!timer_obj)  {return NULL;}\r
-//DEBUGprintf(">timer: setting timer %x for %lld ticks -> hased to cell %d\n",cookie, ct,cell);\r
-return (NETAPI_TIMER_T) timer_obj;\r
-}\r
-\r
-//Cancel a timer\r
-void  netapi_TimerGroupCancel(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        NETAPI_TIMER_T timerId,\r
-        int *pErr)\r
-{\r
-    tim_cancel((TIM_T *) timerId, pErr);\r
-}\r
-\r
-//close an opened timer group\r
-void netapi_TimerGroupClose(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        int *pErr){}\r
-\r
-//delete atimer group\r
-void netapi_TimerGroupDelete(\r
-        NETAPI_TIMER_GROUP_HANDLE_T th,\r
-        int *pErr) {printf(">timer group delete not implemented\n");}\r
-\r
-//extract netapi handle from timer group handle\r
-NETAPI_T netap_TimerGroupGetNH( NETAPI_TIMER_GROUP_HANDLE_T th) { return ((TIMER_GROUP_T*) th)->h; }\r
-\r
-\r
-//-----for timer debuggingi-------\r
-struct\r
-{\r
-//last poll stats\r
-int n_tot;\r
-int c_seen;\r
-\r
-int max_c_seen;\r
-int max_n_tot;\r
-\r
-} timer_poll_stats;\r
-void dump_poll_stats(void)\r
-{\r
-  printf("debug timer poll> n_tot=%d c_seen=%d mnt=%d mcs=%d\n",\r
-             timer_poll_stats.n_tot, timer_poll_stats.c_seen,\r
-             timer_poll_stats.max_n_tot, timer_poll_stats.max_c_seen);\r
-}\r
-//-------end timer debugging----\r
-\r
-//poll a specific timer group\r
-int  netapi_TimerGroupPoll(NETAPI_TIMER_GROUP_HANDLE_T th, int maxTimers)\r
-{\r
-unsigned long long ct= netapi_getTimestamp(); \r
-unsigned long long i;\r
-int cell;\r
-TIM_LIST_T res={NULL,NULL};\r
-int n;\r
-int n_tot=0;\r
-int c_seen=0;\r
-\r
-   for(i=((TIMER_GROUP_T*) th)->last_polled; (i<= ct) && (n_tot<maxTimers); )\r
-   {\r
-      cell =  our_hash(i,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width); \r
-      tim_return_fired_list(&((TIMER_GROUP_T*) th)->cells[cell],\r
-                           &res,\r
-                            &((TIMER_GROUP_T*) th)->free,\r
-                            i,  \r
-                            &n);\r
-      n_tot+=n;\r
-      i += ((TIMER_GROUP_T*) th)->cell_width; \r
-      c_seen+=1;\r
-   }\r
-   if (n_tot)\r
-      {\r
-           ((TIMER_GROUP_T*) th)->cb(th, n_tot, (NETAPI_TIMER_LIST_T) &res, ct);\r
-           tim_return_free(&((TIMER_GROUP_T*) th)->free,&res,n_tot);\r
-      }\r
-\r
-   ((TIMER_GROUP_T*) th)->last_polled = i;\r
-   if (c_seen) timer_poll_stats.n_tot = n_tot;\r
-   if (c_seen) timer_poll_stats.c_seen = c_seen;\r
-   if (n_tot > timer_poll_stats.max_n_tot) timer_poll_stats.max_n_tot = n_tot;\r
-   if (c_seen > timer_poll_stats.max_c_seen) timer_poll_stats.max_c_seen = c_seen;\r
-   return n_tot;\r
-}\r
-\r
-//poll all timers\r
-int  netapi_TimerGroupPollAll(NETAPI_T nh, NETAPI_TIMER_FILTER_T f,  int maxTimers)\r
-{\r
- //todo: use filters and poll global, local lists in nh\r
- if (temp_g.h)\r
-    netapi_TimerGroupPoll(&temp_g, maxTimers);\r
- return 0;\r
-}\r
-\r
-\r
+/*******************************
+ * FILE: netapi_timer.c
+ * Purpose:  implementation of user space timers 
+ **************************************************************
+ * FILE: netapi.c
+ * 
+ * DESCRIPTION:  user space timers main source file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+*
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "netapi.h"
+#include "netapi_timer.h"
+#include "timer_loc.h"
+
+
+/*******************************************************************
+ *  hash function:  returns cell to place timer object in
+ *   
+ ******************************************************************/
+/* static */ int our_hash(
+       unsigned long long ct,
+       int n_cells,
+       unsigned int cell_width)
+{
+int c;
+   //simple hash function
+   c=  (ct/cell_width) % n_cells;
+  return c;
+
+}
+
+//iterator on TIMER_LIST_T
+NETAPI_TIMER_T netapi_TimerGetFirst( NETAPI_TIMER_LIST_T list)
+{ return (NETAPI_TIMER_T) ((TIM_LIST_T *)list)->head; }
+
+NETAPI_TIMER_T netapi_TimerGetNext( NETAPI_TIMER_LIST_T list,NETAPI_TIMER_T prev)
+{return prev ? (NETAPI_TIMER_T) ((TIM_T*) prev)->next:NULL ;}
+
+//return cookie associated with timer object 
+void * netapi_TimerGetCookie(NETAPI_TIMER_T timer)
+{ return ((TIM_T*) timer)->cookie; }
+
+//return timeer value associated with timer object 
+unsigned long long netapi_TimerGetTs(NETAPI_TIMER_T timer)
+{ return ((TIM_T*) timer)->t; }
+
+#if 0
+//timer callback
+typedef void (*NETAPI_TIMER_CB_T) (
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        int n_fired,     //# timers fired
+        NETAPI_TIMER_LIST_T fired_list,
+        uint64_t currentTime);
+#endif
+
+static TIMER_GROUP_T temp_g; //temp. todo: put inot netHandle
+
+//create a timer group
+NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupCreate(
+        NETAPI_T  netHandle,
+        char * name,
+        NETAPI_TIMER_CB_T cb,
+        int local,    //1 if timers local to thread
+        int exp2cancel,//1 if expect to cancel
+        int cell_width, //in ticks
+       int tol,        //in ticks
+        int maxTimers,
+        int *pErr)
+{
+ int ret= tim_group_create(&temp_g, TUNE_NETAPI_NUM_TIMER_CELLS, maxTimers);
+ if (!ret) {*pErr = NETAPI_ERR_NOMEM; return NULL;}
+ *pErr=0;
+ temp_g.cb = cb;
+ temp_g.local = local;
+ temp_g.exp2cancel= exp2cancel;
+ temp_g.cell_width=cell_width;
+ temp_g.tol=tol;
+ temp_g.h = netHandle;
+ temp_g.last_polled=(netapi_getTimestamp()/cell_width) * cell_width + (cell_width-1);
+ printf(">timer group %s created. width = %d (ticks)\n", name, cell_width);
+ return (NETAPI_TIMER_GROUP_HANDLE_T) &temp_g;
+}
+
+//open a [global] timer group
+NETAPI_TIMER_GROUP_HANDLE_T  netapi_TimerGroupOpen(
+        NETAPI_T netHandle,
+        char * name,
+        NETAPI_TIMER_CB_T cb,
+        int *pErr)
+{
+printf(">timer group open not implemented \n");
+
+}
+
+//start an individual timer
+NETAPI_TIMER_T netapi_TimerGroupStartTimer(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        void * cookie,
+        uint64_t offs2fire,  //offset in group ticks 
+        int * pErr)
+{
+TIM_T * timer_obj;
+unsigned long long ct= netapi_getTimestamp() + offs2fire* ((TIMER_GROUP_T*) th)->cell_width;
+int cell;
+*pErr=0;
+
+//find cell where to insert
+cell = our_hash(ct,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width);
+
+//get object and insert into this cell
+timer_obj =tim_set(
+   &((TIMER_GROUP_T*) th)->cells[cell],
+   &((TIMER_GROUP_T*) th)->free , 
+   ct,
+   cookie,
+   pErr);
+if (!timer_obj)  {return NULL;}
+//DEBUGprintf(">timer: setting timer %x for %lld ticks -> hased to cell %d\n",cookie, ct,cell);
+return (NETAPI_TIMER_T) timer_obj;
+}
+
+//Cancel a timer
+void  netapi_TimerGroupCancel(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        NETAPI_TIMER_T timerId,
+        int *pErr)
+{
+    tim_cancel((TIM_T *) timerId, pErr);
+}
+
+//close an opened timer group
+void netapi_TimerGroupClose(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        int *pErr){}
+
+//delete atimer group
+void netapi_TimerGroupDelete(
+        NETAPI_TIMER_GROUP_HANDLE_T th,
+        int *pErr) {printf(">timer group delete not implemented\n");}
+
+//extract netapi handle from timer group handle
+NETAPI_T netap_TimerGroupGetNH( NETAPI_TIMER_GROUP_HANDLE_T th) { return ((TIMER_GROUP_T*) th)->h; }
+
+
+//-----for timer debuggingi-------
+struct
+{
+//last poll stats
+int n_tot;
+int c_seen;
+
+int max_c_seen;
+int max_n_tot;
+
+} timer_poll_stats;
+void dump_poll_stats(void)
+{
+  printf("debug timer poll> n_tot=%d c_seen=%d mnt=%d mcs=%d\n",
+             timer_poll_stats.n_tot, timer_poll_stats.c_seen,
+             timer_poll_stats.max_n_tot, timer_poll_stats.max_c_seen);
+}
+//-------end timer debugging----
+
+//poll a specific timer group
+int  netapi_TimerGroupPoll(NETAPI_TIMER_GROUP_HANDLE_T th, int maxTimers)
+{
+unsigned long long ct= netapi_getTimestamp(); 
+unsigned long long i;
+int cell;
+TIM_LIST_T res={NULL,NULL};
+int n;
+int n_tot=0;
+int c_seen=0;
+
+   for(i=((TIMER_GROUP_T*) th)->last_polled; (i<= ct) && (n_tot<maxTimers); )
+   {
+      cell =  our_hash(i,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width); 
+      tim_return_fired_list(&((TIMER_GROUP_T*) th)->cells[cell],
+                           &res,
+                            &((TIMER_GROUP_T*) th)->free,
+                            i,  
+                            &n);
+      n_tot+=n;
+      i += ((TIMER_GROUP_T*) th)->cell_width; 
+      c_seen+=1;
+   }
+   if (n_tot)
+      {
+           ((TIMER_GROUP_T*) th)->cb(th, n_tot, (NETAPI_TIMER_LIST_T) &res, ct);
+           tim_return_free(&((TIMER_GROUP_T*) th)->free,&res,n_tot);
+      }
+
+   ((TIMER_GROUP_T*) th)->last_polled = i;
+   if (c_seen) timer_poll_stats.n_tot = n_tot;
+   if (c_seen) timer_poll_stats.c_seen = c_seen;
+   if (n_tot > timer_poll_stats.max_n_tot) timer_poll_stats.max_n_tot = n_tot;
+   if (c_seen > timer_poll_stats.max_c_seen) timer_poll_stats.max_c_seen = c_seen;
+   return n_tot;
+}
+
+//poll all timers
+int  netapi_TimerGroupPollAll(NETAPI_T nh, NETAPI_TIMER_FILTER_T f,  int maxTimers)
+{
+ //todo: use filters and poll global, local lists in nh
+ if (temp_g.h)
+    netapi_TimerGroupPoll(&temp_g, maxTimers);
+ return 0;
+}
+
+
index 77003686fde0119873ded4b2d3952855df72f050..1cfd679cd63b36f63ea66b72762859e84c08dcff 100755 (executable)
@@ -876,7 +876,7 @@ int iface_no;
 int ip_slot=-1;
 NETCP_CFG_CLASS_T  classHandle;  //returned by us
 nwal_appProtoType_t proto;
-nwalLocConnCfg_t tempCfg={
+nwalRxConnCfg_t tempCfg={
 0,  //nwal_handle: to be filled in
 {0}, // l4 ports: to be filled in
 0,  //core id (NA)
index b6f4d3c44f6ad67569a071bd74b6af94684ab9bb..eb29c1a2496c5dd8f8d211a93a3de52b83bd6ebf 100755 (executable)
@@ -114,6 +114,10 @@ static inline void nwalTest_osalLeaveCS()
 
 #endif
 
+unsigned long peek(unsigned long * p)
+{
+   return *p;
+}
 
 
 /**********USE SPACE ACCESS TO KERNEL MEMORY SERVICES*************/
index b5c41d20e7f343282569ccf4c4ce49a3ba23f210..f86f50a6b581e3c86558de70b9ab50cb71aa1a4c 100755 (executable)
@@ -209,13 +209,7 @@ int r=0;
 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
 *err=0;
       r=nwal_pollDm(p->nwalInstanceHandle,
-                    nwal_POLL_DM_DEF_GLOB_ENCRYPT_Q,
-                     (uint32_t) p,
-                     p->max_n,
-                     QMSS_PARAM_NOT_SPECIFIED,
-                     (void *)  NULL);
-      r+=nwal_pollDm(p->nwalInstanceHandle,
-                     nwal_POLL_DM_DEF_GLOB_DECRYPT_Q,
+                    nwal_POLL_DM_DEF_SB_SA_Q,
                      (uint32_t) p,
                      p->max_n,
                      QMSS_PARAM_NOT_SPECIFIED,
@@ -646,13 +640,7 @@ uint64_t ts=0LL;
         else if(p->use_nwal==PKTIO_DEF_SB)
         {
                 r=nwal_pollDm(p->nwalInstanceHandle,
-                     nwal_POLL_DM_DEF_GLOB_ENCRYPT_Q,
-                     (uint32_t) p,
-                     p->max_n,
-                     QMSS_PARAM_NOT_SPECIFIED,
-                     (void *)  NULL);
-                 r+=nwal_pollDm(p->nwalInstanceHandle,
-                     nwal_POLL_DM_DEF_GLOB_DECRYPT_Q,
+                     nwal_POLL_DM_DEF_SB_SA_Q,
                      (uint32_t) p,
                      p->max_n,
                      QMSS_PARAM_NOT_SPECIFIED,
index 67098bfb40450a11349af69601a034918516b730..a0535aa8dad0323b3fe07312f7e485d62d6e9dc3 100755 (executable)
@@ -1,81 +1,81 @@
-/********************************************************\r
-  * File: timer_loc.h\r
-  * Purpose: local definitions for timer module\r
-  ******************************************************/\r
-\r
-#ifndef __TIMER_LOC__H\r
-#define __TIMER_LOC__H\r
-\r
-\r
-#ifndef NULL\r
-#define NULL 0\r
-#endif\r
-\r
-\r
-/**********************************\r
- * A timer object\r
- *  active timrs have non zero cookie\r
- **********************************/\r
-struct TIM_tag;\r
-typedef struct TIM_tag\r
-{\r
-struct TIM_tag * next;\r
-void * cookie;\r
-unsigned long long t;\r
-} TIM_T;\r
-\r
-//a list of timers \r
-typedef struct TIM_LIST_tAG\r
-{\r
-   TIM_T * head;\r
-   TIM_T * tail;\r
-} TIM_LIST_T;\r
-\r
-\r
-//the timer group context\r
-typedef struct TIMER_GROUP_Tag\r
-{\r
-  NETAPI_T  h;       //back pointer\r
-  int n_cells;       //#of cells (hash entries)\r
-  int n_timers;      //# of timer objects\r
-  int cell_width;    //size of each cell in ticks\r
-  TIM_LIST_T free;   //free list of timer objects\r
-  TIM_LIST_T * cells;//active timers hash table\r
-  unsigned long long last_polled;  //in ticks\r
-  NETAPI_TIMER_CB_T cb; //timer callback\r
-  int local;   //1 => local timer, 0 =>global timer\r
-  int exp2cancel; //1=> expect to cancel, 0=> expect to fire\r
-  int tol;     //in ticks  [FUTURE]\r
-} TIMER_GROUP_T;\r
-\r
-/**********************INTERNAL API*******************/\r
-//create a timer group\r
-int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers);\r
-\r
-//return a list of timer objects to free list\r
-void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n);  \r
-\r
-//get a free timer oblject\r
-TIM_T * tim_get_free(TIM_LIST_T *ftl, void *cookie, unsigned long long t);\r
-\r
-//return a list of timers that have fired\r
-void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf);\r
-\r
-\r
-//cancel a timer\r
-void tim_cancel(TIM_T * p, int *pErr);\r
-\r
-//insert an active timer into hash cell\r
-TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr);\r
-\r
-/********************************************************/\r
-/********************internal control of hw*************/\r
-/******************************************************/\r
-//memmap t64 registers. fd is open(/dev/mem)\r
-int t64_memmap(int fd);\r
-\r
-//start the timer \r
-int t64_start(void);\r
-\r
-\r
-#endif\r
+/********************************************************
+  * File: timer_loc.h
+  * Purpose: local definitions for timer module
+  ******************************************************/
+
+#ifndef __TIMER_LOC__H
+#define __TIMER_LOC__H
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/**********************************
+ * A timer object
+ *  active timrs have non zero cookie
+ **********************************/
+struct TIM_tag;
+typedef struct TIM_tag
+{
+struct TIM_tag * next;
+void * cookie;
+unsigned long long t;
+} TIM_T;
+
+//a list of timers 
+typedef struct TIM_LIST_tAG
+{
+   TIM_T * head;
+   TIM_T * tail;
+} TIM_LIST_T;
+
+
+//the timer group context
+typedef struct TIMER_GROUP_Tag
+{
+  NETAPI_T  h;       //back pointer
+  int n_cells;       //#of cells (hash entries)
+  int n_timers;      //# of timer objects
+  int cell_width;    //size of each cell in ticks
+  TIM_LIST_T free;   //free list of timer objects
+  TIM_LIST_T * cells;//active timers hash table
+  unsigned long long last_polled;  //in ticks
+  NETAPI_TIMER_CB_T cb; //timer callback
+  int local;   //1 => local timer, 0 =>global timer
+  int exp2cancel; //1=> expect to cancel, 0=> expect to fire
+  int tol;     //in ticks  [FUTURE]
+} TIMER_GROUP_T;
+
+/**********************INTERNAL API*******************/
+//create a timer group
+int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers);
+
+//return a list of timer objects to free list
+void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n);  
+
+//get a free timer oblject
+TIM_T * tim_get_free(TIM_LIST_T *ftl, void *cookie, unsigned long long t);
+
+//return a list of timers that have fired
+void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf);
+
+
+//cancel a timer
+void tim_cancel(TIM_T * p, int *pErr);
+
+//insert an active timer into hash cell
+TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr);
+
+/********************************************************/
+/********************internal control of hw*************/
+/******************************************************/
+//memmap t64 registers. fd is open(/dev/mem)
+int t64_memmap(int fd);
+
+//start the timer 
+int t64_start(void);
+
+
+#endif
index b5fe712bfb699d0475b3990575ecefef8f3927cd..9eb69d6ea667254dff2167c90b9a65abfb0b3109 100755 (executable)
-/******************************************\r
- * FILE:timlist.c \r
- * Purpose:  timer low level primitives\r
- ***********************************************\r
-* FILE:timlist.c\r
- * \r
- * DESCRIPTION:  netapi timer library source file for user space transport\r
- *               library\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- ***************************************/\r
-//#define TEST_DRIVER\r
-#ifdef TEST_DRIVER\r
-typedef void * NETAPI_T;\r
-typedef void * NETAPI_TIMER_CB_T;\r
-#else\r
-#include "../netapi_timer.h"\r
-#endif\r
-#include "timer_loc.h"\r
-#include "../netapi_err.h"\r
-\r
-#ifndef NULL\r
-#define NULL 0\r
-#endif\r
-\r
-\r
-//create a timer group\r
-int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers)\r
-{\r
-char * mem= (char *) malloc(n_timers * sizeof (TIM_T));\r
-if (!mem) return -1;\r
-g->n_cells = n_cells;\r
-tim_build_free(&g->free, mem, sizeof(TIM_T) * n_timers);\r
-g->cells=(TIM_LIST_T *) malloc(n_cells * sizeof(TIM_LIST_T));\r
-if (!g->cells) {free(mem);  return -1;}\r
-g->n_timers=n_timers;\r
-g->last_polled=0;\r
-return 1;\r
-}\r
-\r
-//return as single timer to end of free list, zero cookie, etc\r
-void tim_return_single_free(TIM_LIST_T *ftl,  TIM_T *p)\r
-{\r
-TIM_T * pt;\r
-int i;\r
-pt = ftl->tail;\r
-if (!pt)\r
-{\r
-ftl->head=p;\r
-ftl->tail=p;\r
-}\r
-else\r
-{\r
-pt->next=p;\r
-ftl->tail = p;\r
-}\r
-  p->t=0LL;\r
-  p->cookie=NULL;\r
-  p->next=NULL;\r
-}\r
-\r
-\r
-//return a list of N timers to  end of [free] list.  zero cookie, etc \r
-void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n)\r
-{\r
-TIM_T * pt;\r
-int i;\r
-pt = ftl->tail;\r
-if (!pt) \r
-{\r
-ftl->head=p->head;\r
-ftl->tail=p->tail;\r
-}\r
-else \r
-{\r
-pt->next=p->head;\r
-ftl->tail = p->tail;\r
-}\r
-\r
-pt= p->head;\r
-for(i=0;i<n;i++)\r
-{\r
-  pt->t=0LL;\r
-  pt->cookie=NULL;\r
-  pt= pt->next;\r
-}\r
-ftl->tail->next=NULL;\r
-}\r
-\r
-//get a [free] entry from front of a list \r
-TIM_T * tim_get_free(TIM_LIST_T *tl, void *cookie, unsigned long long t)\r
-{\r
-TIM_T *p = tl->head;\r
-if  (p)\r
-{\r
-   tl->head=p->next;\r
-   p->next=NULL;\r
-   p->cookie = cookie;\r
-   p->t = t;\r
-   if (!tl->head) tl->tail=NULL;\r
-}\r
-return p;\r
-}\r
-\r
-//build a timer list from chunk of memory\r
-int tim_build_free(TIM_LIST_T *tl, char *p_mem, int mem_size)\r
-{\r
-TIM_T * p = (TIM_T*) p_mem;\r
-TIM_T * p_old = (TIM_T*) p_mem;\r
-int i=0;\r
-tl->head = p;\r
-while(mem_size)\r
-{\r
-   p_old = p;\r
-   p->cookie=NULL;\r
-   p->t = 0LL;\r
-   mem_size -= sizeof(TIM_T);\r
-   p+=1;\r
-   i+=1;\r
-   p_old->next=p;\r
-}\r
-p_old->next = NULL;\r
-tl->tail = p_old;\r
-return i;\r
-}\r
-\r
-//return a list of timers that have fired\r
-void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf)\r
-{\r
-int i=0;\r
-int got_start=0;\r
-int found_end=0;\r
-TIM_T * p_last, *p, *temp_p_next;\r
-TIM_LIST_T p_free={NULL,NULL};\r
-if (! tl->head) { *p_nf=0; return ;}\r
-\r
-p =  tl->head;\r
-p_last= NULL; \r
-\r
-for(i=0;p;)\r
-{\r
-  if(p->t <= t) \r
-  {\r
-    if(!got_start)\r
-    {\r
-       if(p->cookie)\r
-       {\r
-       //start results chain\r
-         got_start=1;\r
-         if(pr->tail)  {pr->tail->next = p; pr->tail=p;}\r
-         else {pr->head=pr->tail = p;}\r
-         i+=1;\r
-         p_last=p;\r
-         p=p->next;\r
-         continue;\r
-       }\r
-       else //skip over cancelled timer..\r
-       {\r
-         //skip & free. make sure we adjust head or tail if necessary\r
-         if (p_last){\r
-             p_last->next=p->next; \r
-         }\r
-         else {\r
-            tl->head = p->next; /* we are freeing old head..*/\r
-         }\r
-         if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */\r
-         temp_p_next=p->next;\r
-         tim_return_single_free(ftl,p);\r
-         p=temp_p_next; \r
-         /*keep p_last the same! */\r
-         continue;     \r
-       }\r
-    } \r
-    else\r
-    {\r
-      if(!p->cookie)\r
-      {\r
-         //skip & free\r
-         if (p_last){ \r
-             p_last->next=p->next; \r
-         }\r
-         else {\r
-            tl->head = p->next;\r
-         }\r
-         if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */\r
-         temp_p_next=p->next;\r
-         tim_return_single_free(ftl,p);\r
-         p=temp_p_next;      \r
-         /*keep p_last the same! */\r
-         continue;\r
-      }  \r
-      else { //valid entry for list.\r
-        p_last=p; \r
-        p=p->next;\r
-        i+=1;\r
-        continue;\r
-      }  \r
-    }\r
-  }\r
-  else  /* p->t > t */\r
-  {\r
-    if(got_start)\r
-    {\r
-       found_end =1; //found end of chain to return.  All is good\r
-       pr->tail = p_last;\r
-       p_last->next=NULL;\r
-       tl->head=p;\r
-    }\r
-    // done\r
-    break;\r
-  }\r
-}\r
-\r
-*p_nf=i;\r
-if ((got_start) && (!found_end)) \r
-{\r
-  //cleared the list\r
-  //DEBUGprintf("clearingthelist\n");\r
-  tl->head = tl->tail=NULL;\r
-}\r
-return;\r
-}\r
-\r
-//cancel a timer\r
-void tim_cancel(TIM_T * p, int *pErr)\r
-{\r
- *pErr =0;\r
- if (!p) {*pErr = NETAPI_ERR_BAD_INPUT; return; }\r
- if (!p->cookie) {*pErr= NETAPI_ERR_ALREADY_CANCELLED; return;}\r
- p->cookie = NULL;\r
- return;\r
-}\r
-\r
-//set a timer \r
-TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr)\r
-{\r
-TIM_T *pt = tl->head;\r
-TIM_T *p = tim_get_free(free_tl, cookie, t);\r
-TIM_T *pt_last= NULL;\r
-int i;\r
-*pErr=0;\r
-if (!p ) { *pErr=NETAPI_ERR_NOMEM; return NULL;}  \r
-\r
-if (!pt) //first one\r
-{\r
-  tl->head = p;\r
-  tl->tail =p;\r
-  return p;  \r
-}\r
-\r
-//see if we can place at front of list\r
-if (pt->t >=t)\r
-{\r
-  tl->head=p;\r
-  p->next=pt;\r
-  return p;\r
-}\r
-\r
- //timer has hashed into this chain.  find out where\r
-for(;pt;)\r
-{\r
-   if (pt->t >= t)       \r
-   {\r
-      if (pt_last) {\r
-        pt_last->next = p;\r
-        p->next=pt;\r
-        return p;\r
-      }\r
-      else\r
-      {\r
-        tl->head=p;\r
-        p->next=pt;\r
-        return p;\r
-      }\r
-   }\r
-   else {pt_last=pt;pt=pt->next;}\r
-}\r
-//last one\r
-pt_last->next=p;\r
-p->next=NULL;\r
-tl->tail=p;\r
-return p;\r
-}\r
-\r
-#ifdef TEST_DRIVER\r
-TIM_LIST_T the_base={NULL,NULL};\r
-TIM_LIST_T cell_base={NULL,NULL};\r
-char *mem;\r
-TIM_T * timers[10];\r
-TIM_LIST_T res;\r
-main()\r
-{\r
- int err;\r
- mem= malloc(100*sizeof(TIM_T));\r
- TIM_T *p;\r
- int n;\r
- int i;\r
\r
- tim_build_free(&the_base, mem , 100*sizeof(TIM_T));\r
-\r
- timers[0]=tim_set(&cell_base, &the_base, 100LL, (void *) 1, &err);\r
- timers[1]=tim_set(&cell_base, &the_base, 101LL, (void *) 2, &err);\r
- timers[2]=tim_set(&cell_base, &the_base, 105LL, (void *) 3, &err);\r
- timers[3]=tim_set(&cell_base, &the_base,  95LL, (void *) 4, &err);\r
- timers[4]=tim_set(&cell_base, &the_base,  95LL, (void *) 5, &err);\r
- timers[5]=tim_set(&cell_base, &the_base,  95LL, (void *) 6, &err);\r
- timers[6]=tim_set(&cell_base, &the_base,  104LL, (void *) 7, &err);\r
- timers[7]=tim_set(&cell_base, &the_base,  104LL, (void *) 8, &err);\r
- timers[8]=tim_set(&cell_base, &the_base,  104LL, (void *) 9, &err);\r
-\r
- tim_cancel(timers[6], &err);\r
-\r
-\r
- res.head=res.tail=NULL;\r
-for(i=90;i<106;i++)\r
- {\r
-tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) i,  &n);\r
- printf("at %d got %d\n", i, n);\r
- if (n) {tim_return_free(&the_base,&res,n); res.head=res.tail=NULL;\r
-\r
- }\r
-\r
-//special cases..\r
- res.head=res.tail=NULL;\r
- timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);\r
- tim_cancel(timers[0],&err);\r
- tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);\r
\r
- res.head=res.tail=NULL;\r
- timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);\r
- timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);\r
- tim_cancel(timers[0],&err);\r
- tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);\r
-\r
- res.head=res.tail=NULL;\r
- timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);\r
- timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);\r
- tim_cancel(timers[0],&err);\r
- tim_cancel(timers[1],&err);\r
- tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);\r
\r
-}\r
-#endif\r
+/******************************************
+ * FILE:timlist.c 
+ * Purpose:  timer low level primitives
+ ***********************************************
+* FILE:timlist.c
+ * 
+ * DESCRIPTION:  netapi timer library source file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ***************************************/
+//#define TEST_DRIVER
+#ifdef TEST_DRIVER
+typedef void * NETAPI_T;
+typedef void * NETAPI_TIMER_CB_T;
+#else
+#include "../netapi_timer.h"
+#endif
+#include "timer_loc.h"
+#include "../netapi_err.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+//create a timer group
+int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers)
+{
+char * mem= (char *) malloc(n_timers * sizeof (TIM_T));
+if (!mem) return -1;
+g->n_cells = n_cells;
+tim_build_free(&g->free, mem, sizeof(TIM_T) * n_timers);
+g->cells=(TIM_LIST_T *) malloc(n_cells * sizeof(TIM_LIST_T));
+if (!g->cells) {free(mem);  return -1;}
+g->n_timers=n_timers;
+g->last_polled=0;
+return 1;
+}
+
+//return as single timer to end of free list, zero cookie, etc
+void tim_return_single_free(TIM_LIST_T *ftl,  TIM_T *p)
+{
+TIM_T * pt;
+int i;
+pt = ftl->tail;
+if (!pt)
+{
+ftl->head=p;
+ftl->tail=p;
+}
+else
+{
+pt->next=p;
+ftl->tail = p;
+}
+  p->t=0LL;
+  p->cookie=NULL;
+  p->next=NULL;
+}
+
+
+//return a list of N timers to  end of [free] list.  zero cookie, etc 
+void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n)
+{
+TIM_T * pt;
+int i;
+pt = ftl->tail;
+if (!pt) 
+{
+ftl->head=p->head;
+ftl->tail=p->tail;
+}
+else 
+{
+pt->next=p->head;
+ftl->tail = p->tail;
+}
+
+pt= p->head;
+for(i=0;i<n;i++)
+{
+  pt->t=0LL;
+  pt->cookie=NULL;
+  pt= pt->next;
+}
+ftl->tail->next=NULL;
+}
+
+//get a [free] entry from front of a list 
+TIM_T * tim_get_free(TIM_LIST_T *tl, void *cookie, unsigned long long t)
+{
+TIM_T *p = tl->head;
+if  (p)
+{
+   tl->head=p->next;
+   p->next=NULL;
+   p->cookie = cookie;
+   p->t = t;
+   if (!tl->head) tl->tail=NULL;
+}
+return p;
+}
+
+//build a timer list from chunk of memory
+int tim_build_free(TIM_LIST_T *tl, char *p_mem, int mem_size)
+{
+TIM_T * p = (TIM_T*) p_mem;
+TIM_T * p_old = (TIM_T*) p_mem;
+int i=0;
+tl->head = p;
+while(mem_size)
+{
+   p_old = p;
+   p->cookie=NULL;
+   p->t = 0LL;
+   mem_size -= sizeof(TIM_T);
+   p+=1;
+   i+=1;
+   p_old->next=p;
+}
+p_old->next = NULL;
+tl->tail = p_old;
+return i;
+}
+
+//return a list of timers that have fired
+void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf)
+{
+int i=0;
+int got_start=0;
+int found_end=0;
+TIM_T * p_last, *p, *temp_p_next;
+TIM_LIST_T p_free={NULL,NULL};
+if (! tl->head) { *p_nf=0; return ;}
+
+p =  tl->head;
+p_last= NULL; 
+
+for(i=0;p;)
+{
+  if(p->t <= t) 
+  {
+    if(!got_start)
+    {
+       if(p->cookie)
+       {
+       //start results chain
+         got_start=1;
+         if(pr->tail)  {pr->tail->next = p; pr->tail=p;}
+         else {pr->head=pr->tail = p;}
+         i+=1;
+         p_last=p;
+         p=p->next;
+         continue;
+       }
+       else //skip over cancelled timer..
+       {
+         //skip & free. make sure we adjust head or tail if necessary
+         if (p_last){
+             p_last->next=p->next; 
+         }
+         else {
+            tl->head = p->next; /* we are freeing old head..*/
+         }
+         if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */
+         temp_p_next=p->next;
+         tim_return_single_free(ftl,p);
+         p=temp_p_next; 
+         /*keep p_last the same! */
+         continue;     
+       }
+    } 
+    else
+    {
+      if(!p->cookie)
+      {
+         //skip & free
+         if (p_last){ 
+             p_last->next=p->next; 
+         }
+         else {
+            tl->head = p->next;
+         }
+         if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */
+         temp_p_next=p->next;
+         tim_return_single_free(ftl,p);
+         p=temp_p_next;      
+         /*keep p_last the same! */
+         continue;
+      }  
+      else { //valid entry for list.
+        p_last=p; 
+        p=p->next;
+        i+=1;
+        continue;
+      }  
+    }
+  }
+  else  /* p->t > t */
+  {
+    if(got_start)
+    {
+       found_end =1; //found end of chain to return.  All is good
+       pr->tail = p_last;
+       p_last->next=NULL;
+       tl->head=p;
+    }
+    // done
+    break;
+  }
+}
+
+*p_nf=i;
+if ((got_start) && (!found_end)) 
+{
+  //cleared the list
+  //DEBUGprintf("clearingthelist\n");
+  tl->head = tl->tail=NULL;
+}
+return;
+}
+
+//cancel a timer
+void tim_cancel(TIM_T * p, int *pErr)
+{
+ *pErr =0;
+ if (!p) {*pErr = NETAPI_ERR_BAD_INPUT; return; }
+ if (!p->cookie) {*pErr= NETAPI_ERR_ALREADY_CANCELLED; return;}
+ p->cookie = NULL;
+ return;
+}
+
+//set a timer 
+TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr)
+{
+TIM_T *pt = tl->head;
+TIM_T *p = tim_get_free(free_tl, cookie, t);
+TIM_T *pt_last= NULL;
+int i;
+*pErr=0;
+if (!p ) { *pErr=NETAPI_ERR_NOMEM; return NULL;}  
+
+if (!pt) //first one
+{
+  tl->head = p;
+  tl->tail =p;
+  return p;  
+}
+
+//see if we can place at front of list
+if (pt->t >=t)
+{
+  tl->head=p;
+  p->next=pt;
+  return p;
+}
+
+ //timer has hashed into this chain.  find out where
+for(;pt;)
+{
+   if (pt->t >= t)       
+   {
+      if (pt_last) {
+        pt_last->next = p;
+        p->next=pt;
+        return p;
+      }
+      else
+      {
+        tl->head=p;
+        p->next=pt;
+        return p;
+      }
+   }
+   else {pt_last=pt;pt=pt->next;}
+}
+//last one
+pt_last->next=p;
+p->next=NULL;
+tl->tail=p;
+return p;
+}
+
+#ifdef TEST_DRIVER
+TIM_LIST_T the_base={NULL,NULL};
+TIM_LIST_T cell_base={NULL,NULL};
+char *mem;
+TIM_T * timers[10];
+TIM_LIST_T res;
+main()
+{
+ int err;
+ mem= malloc(100*sizeof(TIM_T));
+ TIM_T *p;
+ int n;
+ int i;
+ tim_build_free(&the_base, mem , 100*sizeof(TIM_T));
+
+ timers[0]=tim_set(&cell_base, &the_base, 100LL, (void *) 1, &err);
+ timers[1]=tim_set(&cell_base, &the_base, 101LL, (void *) 2, &err);
+ timers[2]=tim_set(&cell_base, &the_base, 105LL, (void *) 3, &err);
+ timers[3]=tim_set(&cell_base, &the_base,  95LL, (void *) 4, &err);
+ timers[4]=tim_set(&cell_base, &the_base,  95LL, (void *) 5, &err);
+ timers[5]=tim_set(&cell_base, &the_base,  95LL, (void *) 6, &err);
+ timers[6]=tim_set(&cell_base, &the_base,  104LL, (void *) 7, &err);
+ timers[7]=tim_set(&cell_base, &the_base,  104LL, (void *) 8, &err);
+ timers[8]=tim_set(&cell_base, &the_base,  104LL, (void *) 9, &err);
+
+ tim_cancel(timers[6], &err);
+
+
+ res.head=res.tail=NULL;
+for(i=90;i<106;i++)
+ {
+tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) i,  &n);
+ printf("at %d got %d\n", i, n);
+ if (n) {tim_return_free(&the_base,&res,n); res.head=res.tail=NULL;
+
+ }
+
+//special cases..
+ res.head=res.tail=NULL;
+ timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
+ tim_cancel(timers[0],&err);
+ tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
+ res.head=res.tail=NULL;
+ timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
+ timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
+ tim_cancel(timers[0],&err);
+ tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
+
+ res.head=res.tail=NULL;
+ timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
+ timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
+ tim_cancel(timers[0],&err);
+ tim_cancel(timers[1],&err);
+ tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
+}
+#endif
index 691208e6e7ddc06cd17695dac327265ecda33b0a..6519591df9d35bc379a0dd933e2d4d4c6fc98965 100755 (executable)
@@ -13,6 +13,7 @@ QMSS_INC_DIR = $(PDK_INSTALL_PATH)/ti/drv/qmss
 CPPI_INC_DIR = $(PDK_INSTALL_PATH)/ti/drv/cppi
 
 NETAPI_INC_DIR = $(NETAPI_INSTALL_PATH)/ti/runtime/netapi
+SA_INC_DIR = $(SA_INSTALL_PATH)
 
 #NETAPI LIB Build directory
 NETAPI_BUILD_DIR = $(NETAPI_INC_DIR)/build
@@ -38,14 +39,14 @@ PKTUTL_LIB=$(SA_INSTALL_PATH)/ti/mas/pktutl/gcarmv7a/pktutl_c.av7A
 CC = $(CROSS_TOOL_INSTALL_PATH)/$(CROSS_TOOL_PRFX)gcc
 AR = $(CROSS_TOOL_INSTALL_PATH)/$(CROSS_TOOL_PRFX)ar -r
 
-CFLAGS= $(DEBUG_FLAG) -I../ -I. -I$(NETAPI_INC_DIR) -I$(NETAPI_INC_DIR)/src -I$(PDK_INSTALL_PATH)  -I$(NWAL_INSTALL_PATH) -I$(PKTLIB_INSTALL_PATH) -I$(TRANS_SDK_INSTALL_PATH) -I$(QMSS_INC_DIR) -I$(CPPI_INC_DIR)  -D__ARMv7 -D_VIRTUAL_ADDR_SUPPORT -D__LINUX_USER_SPACE -D_LITTLE_ENDIAN=1 -DMAKEFILE_BUILD -pthread -D _GNU_SOURCE
+CFLAGS= $(DEBUG_FLAG) -I../ -I. -I$(NETAPI_INC_DIR) -I$(NETAPI_INC_DIR)/src -I$(PDK_INSTALL_PATH)  -I$(NWAL_INSTALL_PATH) -I$(PKTLIB_INSTALL_PATH) -I$(TRANS_SDK_INSTALL_PATH) -I$(QMSS_INC_DIR) -I$(CPPI_INC_DIR) -I$(SA_INC_DIR) -D__ARMv7 -D_VIRTUAL_ADDR_SUPPORT -D__LINUX_USER_SPACE -D_LITTLE_ENDIAN=1 -DMAKEFILE_BUILD -pthread -D _GNU_SOURCE
 # Linker options
 INTERNALLINKDEFS = --start-group -L$(ARMV7LIBDIR) -L$(PDK_ARMV7LIBDIR) $(NETAPI_LIB) $(PKTLIB_LIB) $(QMSS_LIB) $(CPPI_LIB) $(NWAL_LIB) $(PA_LIB) $(SA_LIB) $(AES_LIB) $(SHA1_LIB) $(PKTUTL_LIB) -lrt --end-group
 
 
 all: tests 
 
-tests: $(ARMV7BINDIR)/netapi/test/.created $(ARMV7BINDIR)/netapi/test/net_test $(ARMV7BINDIR)/netapi/test/synchtest $(ARMV7BINDIR)/netapi/test/synchtest2 
+tests: $(ARMV7BINDIR)/netapi/test/.created $(ARMV7BINDIR)/netapi/test/net_test $(ARMV7BINDIR)/netapi/test/synchtest $(ARMV7BINDIR)/netapi/test/synchtest2 $(ARMV7BINDIR)/netapi/test/udpif  
 
 api_clean:
        rm -f  $(ARMV7LIBDIR)/libnetapi.a
@@ -54,7 +55,7 @@ api_clean:
 clean: 
        rm -f $(ARMV7OBJDIR)/netapi/test/*.o
        rm -f $(ARMV7LIBDIR)/libnetapi.a
-       rm -f $(ARMV7BINDIR)/netapi/test/net_test $(ARMV7BINDIR)/netapi/test/synchtest $(ARMV7BINDIR)/netapi/test/synchtest2
+       rm -f $(ARMV7BINDIR)/netapi/test/net_test $(ARMV7BINDIR)/netapi/test/synchtest $(ARMV7BINDIR)/netapi/test/synchtest2 $(ARMV7BINDIR)/netapi/test/udpif
 
 
 $(ARMV7OBJDIR)/netapi/test/%.o:$(NETAPI_INC_DIR)/test/%.c $(ARMV7OBJDIR)/netapi/test/.created
@@ -79,4 +80,6 @@ $(ARMV7BINDIR)/netapi/test/synchtest: $(ARMV7OBJDIR)/netapi/test/synchtest.o
 
 $(ARMV7BINDIR)/netapi/test/synchtest2: $(ARMV7OBJDIR)/netapi/test/synchtest2.o
        $(CC) $(LDFLAGS) $(ARMV7OBJDIR)/netapi/test/synchtest2.o -o $(ARMV7BINDIR)/netapi/test/synchtest2 -lpthread
-       
+
+$(ARMV7BINDIR)/netapi/test/udpif: $(ARMV7OBJDIR)/netapi/test/udpif.o
+       $(CC) $(LDFLAGS) $(ARMV7OBJDIR)/netapi/test/udpif.o -o $(ARMV7BINDIR)/netapi/test/udpif
old mode 100644 (file)
new mode 100755 (executable)
index ec51790..fc7124f
 #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********************/
@@ -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
@@ -141,8 +155,11 @@ static uint8_t testPkt[] = {
 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)
 {
@@ -202,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,
@@ -268,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;
@@ -309,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; 
@@ -361,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_3DES_CBC and 0 bytes Salt*/
+    20, /* macKeySize: 16 bytes NWAL_SA_AALG_HMAC_SHA1 */
+    NULL, //set below
+    NULL, //set below
+},
 {
-    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 */
+    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***********************/
@@ -702,7 +816,7 @@ for(i=0;i<ntrials;i++)
 }
 /*-----------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;
@@ -715,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;};
 
@@ -752,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----------------------------
@@ -770,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);
@@ -784,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)
+    //tbd udp checksum (leave at 0)
 
-//outer ip, set to 0 (we will compute on way out
-memset(&p_pkt[14+10],0,2);
-
-#else //inflow, don't touch outer , clear inner 
-memset(&p_pkt[14+20+8+16+10],0,2); //inner checksum, we will compute on way out
+    //outer ip, 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
 {
@@ -837,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
 {
@@ -952,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++)
    {
@@ -960,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 ((int)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]);
@@ -972,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, (int)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],
@@ -980,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((int)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]);
@@ -996,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, (int)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],
@@ -1005,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
@@ -1015,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;
@@ -1049,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;
 
@@ -1063,72 +1300,123 @@ 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
 
-         //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, (int)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
@@ -1147,12 +1435,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");
 }
 
@@ -1212,6 +1500,43 @@ 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);
+    printf("------------- IPSec Stats END ----------------------------\n\n");
+}
+
+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;
 /******************************************************
@@ -1223,14 +1548,40 @@ 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);
@@ -1284,20 +1635,73 @@ 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();
 
+    for (i = 0; i < MAX_SEC_INDEX; i++)
+    {
+        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;
@@ -1326,6 +1730,19 @@ 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++) {  
@@ -1349,7 +1766,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; }
 
 
@@ -1371,10 +1788,19 @@ 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;
@@ -1465,33 +1891,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");
+
+
+    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");
+    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
+
+#if 0
+    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);
+        }
+    }
+
 #endif
 
-if (argc>=2)  np2process = atoi(argv[1]);
-if (np2process<0) np2process = NP; /* default */
-if (argc==3)  perslow = atoi(argv[2]);
-if ((perslow<0)||(perslow>100)) perslow=PERSLOW;//default
-if (argc>3) {printf("net_test  <no of pkts to process> <percent slow path>\n"); exit(1);}
+    memset(&sa_info, 0, sizeof(sa_info));
 
 
 //real mode, so update our test packet mac header and ip header
@@ -1500,6 +2404,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****************/
@@ -1543,16 +2454,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);}
@@ -1562,6 +2480,7 @@ 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 */
@@ -1587,7 +2506,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
@@ -1600,7 +2519,7 @@ ip_rule0=netcp_addIp(
                   netapi_handle,
                   0,
                   nwal_IPV4,
-                  &OurIp0,
+                  &config.ip0,
                   NULL,  //all IP
                   (NETCP_CFG_ROUTE_HANDLE_T) NULL,
                   &err
@@ -1610,7 +2529,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
@@ -1623,13 +2542,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,
@@ -1649,7 +2569,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
 {
@@ -1660,6 +2580,7 @@ heaps[1]= specialLarge;
 #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,
@@ -1667,6 +2588,7 @@ specialFlow = netcp_cfgAddFlow( netapi_handle,
                                 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
@@ -1680,66 +2602,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(
@@ -1791,6 +2717,7 @@ 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);}
@@ -1808,7 +2735,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 ****/
@@ -1821,32 +2748,37 @@ our_stats_cb(netapi_handle, NULL);
 
 #define DO_FAST_POLL
 #ifdef DO_FAST_POLL
-example_fast_pushpop(OurHeap, 500);
-example_fast_poll(netcp_rx_chan,100000);
+//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);
@@ -1857,6 +2789,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);
 
@@ -1867,7 +2800,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);
 
 }
@@ -2081,7 +3014,170 @@ for(;max_pkts>0;)
     }
 }
 
-
+    //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
diff --git a/ti/runtime/netapi/test/net_test.h b/ti/runtime/netapi/test/net_test.h
new file mode 100755 (executable)
index 0000000..f537b94
--- /dev/null
@@ -0,0 +1,186 @@
+/******************************************************************************
+ * FILE PURPOSE:  local defines for net_test application.
+ ******************************************************************************
+ * FILE NAME:   net_test.h
+ *
+ * DESCRIPTION: NET TEST definitions and defines
+ *
+ * REVISION HISTORY:
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* ============================================================= */
+
+//IPSEC MODE(only choose one rx and one tx)
+
+#define IPSEC_MODE_RX_INFLOW 1
+#define IPSEC_MODE_TX_INFLOW 2
+#define IPSEC_MODE_RX_SIDEBAND 3
+#define IPSEC_MODE_TX_SIDEBAND 4
+
+#define MAX_SEC_INDEX 4
+#define netTest_MAC_HEADER_LEN          14
+#define netTest_IP_HEADER_LEN           20
+#define netTest_UDP_HEADER_LEN          8
+#define netTest_ESP_HEADER_LEN          8
+#define netTest_AES_CBC_IV_LEN          16
+#define netTest_AES_CTR_IV_CONTEXT_LEN          16
+#define netTest_AES_CTR_IV_PACKET_LEN          8
+#define netTest_3DES_CBC_IV_LEN          8
+#define netTest_NULL_IV_LEN 0
+#define netTest_ICV_LEN          12
+
+
+
+/* The input strings for the input config file is given below */
+#define INIT_CONFIG_MAC0      "mac0"
+#define INIT_CONFIG_MAC1      "mac1"
+#define INIT_CONFIG_IP0         "ip0"
+#define INIT_CONFIG_IP1         "ip1"
+#define INIT_CONFIG_IP2         "ip2"
+#define INIT_CONFIG_LOCAL_IPSEC_IP         "local_ipsec_ip"
+#define INIT_CONFIG_REMOTE_IPSEC_IP         "remote_ipsec_ip"
+#define INIT_CONFIG_IPSEC_MODE_RX   "ipsec_mode_rx"
+#define INIT_CONFIG_IPSEC_MODE_TX   "ipsec_mode_tx"
+#define INIT_CONFIG_IPSEC_IF_NO     "ipsec_if"
+
+
+#define CONFIG_STRING_LEN 25
+
+
+
+
+#define MAX_ROUTES 16
+/* tmannan - begin */
+
+typedef struct {
+    nwalDmTxPayloadInfo_t   tx_payload_info;
+    uint8_t inner_ip_offset;
+    NETCP_CFG_SA_T rx_tunnel;
+    void * rx_data_mode_handle;
+    void * rx_inflow_mode_handle;
+    NETCP_CFG_SA_T tx_tunnel;
+    void * tx_data_mode_handle;
+    void * tx_inflow_mode_handle;
+    uint8_t enc_key_length;
+    uint8_t auth_tag_size;
+    nwalTxPktInfo_t tx_pkt_info;
+    nwal_saEALG         cipherMode;
+    /*stuff for routing use case */
+    unsigned int src;  //BE
+    unsigned int dst;  //BE
+    unsigned int spi;  //BE
+    unsigned int seq;  //BE
+    int iv_len; //iv len (size of iv in pkt)
+    int bl; //block len (for padding calc)
+} netTestSA_t;
+
+
+
+typedef struct{
+    char mac0[CONFIG_STRING_LEN];
+    char mac1[CONFIG_STRING_LEN];
+    char ip0[CONFIG_STRING_LEN];
+    char ip1[CONFIG_STRING_LEN];
+    char ip2[CONFIG_STRING_LEN];
+    char local_ipsec_ip[CONFIG_STRING_LEN];
+    char remote_ipsec_ip[CONFIG_STRING_LEN];
+    char ipsec_mode_rx[CONFIG_STRING_LEN];
+    char ipsec_mode_tx[CONFIG_STRING_LEN];
+    char routes[MAX_ROUTES][CONFIG_STRING_LEN];
+    char ports[MAX_ROUTES][CONFIG_STRING_LEN];
+    char dst_ips[MAX_ROUTES][CONFIG_STRING_LEN];
+    char paths[MAX_ROUTES][CONFIG_STRING_LEN];
+    char ipsec_if_no[CONFIG_STRING_LEN];
+} netTestConfigFile_t;
+
+
+
+
+typedef struct {
+unsigned char mac0[6];
+unsigned char mac1[6];
+nwalIpAddr_t ip0;
+nwalIpAddr_t ip1;
+nwalIpAddr_t ip2;
+nwalIpAddr_t local_ipsec_ip;
+nwalIpAddr_t remote_ipsec_ip;
+uint8_t ipsec_mode_rx;
+uint8_t ipsec_mode_tx;
+int ipsec_if_no;  /* 0 if mac0, 1 if mac 1 */
+
+} netTestConfig_t;
+
+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;
+        unsigned long long  app_cycles;
+        unsigned long long  send_cycles;
+        unsigned long long  tx_cache_cycles;
+        unsigned long long total_decrypt_time;
+        unsigned long long total_encrypt_time;
+               long rx_min;
+               long tx_min;
+} 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;
+
+
diff --git a/ti/runtime/netapi/test/net_test_config.txt b/ti/runtime/netapi/test/net_test_config.txt
new file mode 100644 (file)
index 0000000..8dbd7a6
--- /dev/null
@@ -0,0 +1,19 @@
+mac0 = 00-01-02-03-05-05
+mac1 = 00-01-02-03-05-06
+ip0 = 10.0.0.100
+ip1 = 10.0.1.100
+ip2 = 10.0.2.100
+local_ipsec_ip = 192.168.1.100
+remote_ipsec_ip = 192.168.1.10
+ipsec_if = 0
+#ipsec_mode_rx = SIDEBAND
+#ipsec_mode_rx = SIDEBAND
+ipsec_mode_rx = INFLOW
+ipsec_mode_tx = INFLOW
+
+
+route0 =  MAC00-23-24-08-67-46  1
+route1 =  MAC00-22-33-44-55-56  2
+
+dstip0 =  10.1.0.100 route1
+dspip1 =  10.0.0.10  route0
diff --git a/ti/runtime/netapi/test/router.c b/ti/runtime/netapi/test/router.c
new file mode 100755 (executable)
index 0000000..a088127
--- /dev/null
@@ -0,0 +1,169 @@
+#include "trie.h"
+
+#define BE(x) ( (((x)&0xff000000)>>24) | (((x)&0xff0000)>>8) | (((x)&0xff00)<<8) | (((x)&0xff)<<24)  )
+
+typedef struct iphead_t
+{
+  unsigned long w1;
+  unsigned long w2;
+  unsigned long w3;
+  unsigned long src;
+  unsigned long dst;
+} IP_HEAD_T;
+
+#define ROUTE_SEC_T netTestSA_t
+
+typedef struct our_route_t
+{
+   int out_port;
+   unsigned char out_mac[14];
+   ROUTE_SEC_T * sec_ptr;
+} OUR_ROUTE_T;
+
+
+Trie * route_init(void)
+
+{
+
+Trie *Pt = trie_new();
+
+return Pt;
+
+}
+
+
+void route_add(Trie * Pt, unsigned int * Pdest_ipBE, void * Pour_route)
+{
+
+   trie_insert(Pt,(char *)Pdest_ipBE, sizeof(int), Pour_route); 
+}
+
+//route the packet 
+//  lookup next hop in route trie
+int route_pkt(Trie *Pt, void * Ppkt, IP_HEAD_T *Phead, unsigned char * Pbuf, int * Plen, ROUTE_SEC_T **Prs)
+{
+   OUR_ROUTE_T *Pr;
+   int ret;
+   Pr = trie_lookup(Pt, (char *) &Phead->dst, 4);
+   if (!Pr ) return -1;  //can't route
+   if (Pr->sec_ptr) 
+   {
+      if(!Prs) return -3;
+     //tunnel i/f
+      ret=process_tunnel(Pt, Ppkt, Phead, Pbuf, Plen, Pr);             
+      *Prs = Pr->sec_ptr;
+      return ret;
+   }
+   if (Prs) *Prs=NULL;
+   //simple route
+   //copy new mac
+    memcpy(Pbuf,Pr->out_mac,14);
+    Pbuf[14+8]-=1;  //ttl--
+    //todo do check ttl!
+    Pbuf[14+10]=0; Pbuf[14+11]=0;  //zap [outer] header checksum
+   return 1;
+}
+
+int process_tunnel(Trie *Pt, void *Ppkt, IP_HEAD_T * Phead, 
+                   unsigned char * Pbuf, int* Plen, OUR_ROUTE_T * Proute)
+{
+unsigned char *sb = Pbuf;
+unsigned char *eb= &Pbuf[*Plen]; 
+int newlen=*Plen;
+int seq;
+int pl_len;
+int new_pl_len;
+int pad_len;
+//unsigned char IV[20];
+ROUTE_SEC_T * p_sec=Proute->sec_ptr;
+unsigned char *pc;
+int nb;
+int i;
+int ret;
+
+/* move sb to new start */
+sb = sb - p_sec->iv_len-8-20;  //make room for esp header and new outer ip
+newlen +=  (Pbuf-sb);
+
+//adjust IP_Header to make outer:
+Phead->src=p_sec->src;
+Phead->dst=p_sec->dst;
+
+//next_proto
+pc = (unsigned char *)&Phead->w3;
+pc[1]=50;
+
+//payload len
+pc= (unsigned char*)&Phead->w1;
+pl_len=  ((pc[2]<<8) | (pc[3]));  
+
+//pad length
+nb = pl_len/p_sec->bl;       //128 for AES
+pad_len =   pl_len - nb*p_sec->bl;
+switch(pad_len)
+{
+  case(15):
+   pad_len=15;
+   break;
+  default:
+    pad_len = p_sec->bl-pad_len-2;
+}
+
+new_pl_len = pl_len + +20+ 8 + p_sec->iv_len + pad_len + p_sec->auth_tag_size +2;
+pc[2] =  (new_pl_len&0xff00)>>8;
+pc[3] =  (new_pl_len&0xff);
+memcpy(&sb[14],Phead,20);  //copy outer ip header into buffer 
+
+//build esp header
+memcpy(&sb[14+20],(unsigned char *)&p_sec->spi,4);
+seq=BE(p_sec->seq++); //TODO: multicore safe ;  CHECK to make sure that SA does this, if so remove this code
+memcpy(&sb[14+24],(unsigned char *)&seq,4);
+
+//IV: don't need:   Sa does it.
+//memcpy(&sb[14+28],&IV[0],p_sec->iv_len);
+
+//Padding, trailer, room for tag
+for(i=1;i<=pad_len;i++) *eb++ = i;
+*eb++=pad_len; //pad len
+*eb++=4;  //next proto= ipinip
+newlen += pad_len+2+p_sec->auth_tag_size;
+Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) Ppkt, sb,newlen);
+Pktlib_setPacketLen(Ppkt,newlen);
+
+//now route based on outer ip
+ret=route_pkt(Pt, Ppkt, Phead, sb, &newlen,NULL);
+if (ret<0) return ret;
+*Plen=newlen;
+return 1;
+} 
+//#define TEST
+#ifdef TEST
+#define NR 4
+OUR_ROUTE_T routes[]=
+{
+{1,{0x00,0x01,0x2,0x03,0x4,0x2, 0x00,0x01,0x02,0x03,0x14,0x02,0x00,0x80},0},
+{2,{0x00,0x01,0x2,0x03,0x4,0x3, 0x00,0x01,0x02,0x03,0x24,0x02,0x00,0x80},0},
+{3,{0x00,0x01,0x2,0x03,0x4,0x4, 0x00,0x01,0x02,0x03,0x34,0x02,0x00,0x80},0},
+{4,{0x00,0x01,0x2,0x03,0x4,0x5, 0x00,0x01,0x02,0x03,0x44,0x02,0x00,0x80},0}};
+
+unsigned int ip[]={BE(0x0a000010),BE(0xa0000110),BE(0x0a000210),BE(0x0a000310)};
+Trie *rt;
+char tp[1500];
+IP_HEAD_T th={0x00,0x00,0x00,0x01020304,0x1002000a};
+main()
+{
+int i;
+int l;
+rt = route_init();
+for (i=0;i<NR;i++)
+{  
+  route_add(rt,&ip[i],&routes[i]);
+}
+
+memcpy(&tp[14],&th,20);
+l=1500;
+route_pkt(rt, 0, &th, &tp[0],&l,NULL);
+}
+#endif
index 639954c2c4e8efe152213ba82da50241747c5146..b8ce04b688e9441684e0572bc96cce069e3a2b3c 100755 (executable)
@@ -1,2 +1,2 @@
-/* stubs .. */\r
-/* place holder...*/\r
+/* stubs .. */
+/* place holder...*/
index 1a1f5c7913dbaec756a74fa3fb5af359bbd6654a..d5de741960fa97c13bf53f8feda00fc7307f625f 100755 (executable)
-/********************************\r
- * file: synchtest.c\r
- * sync primitives unit test\r
- ************************************************\r
-* FILE:  synchtest.c \r
- * \r
- * DESCRIPTION:  netapi user space transport\r
- *               library  test application -> synchronization primitives\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- ******************************/\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <string.h>\r
-#include "netsync.h"\r
-#include "netapi_util.h"\r
-\r
-#if 0\r
-/* timing */\r
-static inline unsigned long timing_start(void)\r
-{\r
-       volatile int vval;\r
-        //read clock\r
-        asm volatile("mrc p15, 0, %0, c9, c13, 0" :  "=r"(vval));\r
-        return vval;\r
-}\r
-static inline unsigned long timing_stop(void)\r
-{\r
-        volatile int vval2;\r
-        //read clock\r
-        asm volatile("mrc p15, 0, %0, c9, c13, 0" :  "=r"(vval2));\r
-        return vval2;\r
-}\r
-#endif\r
-#define timing_start netapi_timing_start\r
-#define timing_stop netapi_timing_stop\r
-\r
-int spot=0;\r
-\r
-NETAPI_RWLOCK_T  temp;\r
-\r
-void test1()\r
-{\r
-int v1, v2;\r
-netapi_rwlock_init(&temp);\r
-v1 = timing_start();\r
-netapi_rwlock_write_lock(&temp);\r
-v2 = timing_stop();\r
-printf("rwlock write locked, cycles= %d \n", v2-v1);\r
-}\r
-\r
-void test2()\r
-{\r
-int v1, v2;\r
-\r
-v1 = timing_start();\r
-netapi_rwlock_write_unlock(&temp);\r
-v2 = timing_stop();\r
-printf("rwlock write unlocked, cycles= %d \n",v2-v1);\r
-}\r
-void test3()\r
-{\r
-int v1,v2;\r
-v1 = timing_start();\r
-netapi_rwlock_read_lock(&temp);\r
-v2 = timing_stop();\r
-printf("rwlock read locked, cycles= %d \n", v2-v1);\r
-}\r
-void test4()\r
-{\r
-int v1,v2;\r
-v1 = timing_start();\r
-netapi_rwlock_read_unlock(&temp);\r
-v2 = timing_stop();\r
-printf("rwlock read_unlocked, cycles= %d\n", v2-v1);\r
-}\r
-\r
-main()\r
-{\r
-NETAPI_SPINLOCK_T val;\r
-int i;\r
-unsigned long v1,v2;\r
-int val2;\r
-for(i=0;i<10;i++) {\r
-val=__sync_fetch_and_add(&spot, 1);\r
-printf(" val = %d %d\n",val,spot);\r
-\r
-//now we try the synch_lock_and_test\r
-netapi_spinlock_init(&val);\r
-v1 = timing_start();\r
-netapi_spinlock_lock(&val);\r
-v2 = timing_stop();\r
-printf("locked, val= %d cycles=%d\n",val,v2-v1);\r
-\r
-//try the lock\r
-v1 = timing_start();\r
-val2=netapi_spinlock_try_lock(&val);\r
-v2 = timing_stop();\r
-printf("try lock has returns %d, cycles=%d\n", val2, v2-v1);\r
-\r
-//poll the lock \r
-v1 = timing_start();\r
-val2=netapi_spinlock_is_locked(&val);\r
-v2 = timing_stop();\r
-printf("is_locked has returns %d, cycles=%d\n", val2, v2-v1);\r
-\r
-\r
-//unlock\r
-v1 = timing_start();\r
-netapi_spinlock_unlock(&val);\r
-v2 = timing_stop();\r
-printf("unlocked, val= %d cycles=%d\n", val,v2-v1);\r
-\r
-/*-------now try rwlock--------*/\r
-test1();\r
-test2();\r
-test3();\r
-test3();\r
-test4();\r
-test4();\r
-\r
-}\r
-}\r
-\r
-\r
-\r
+/********************************
+ * file: synchtest.c
+ * sync primitives unit test
+ ************************************************
+* FILE:  synchtest.c 
+ * 
+ * DESCRIPTION:  netapi user space transport
+ *               library  test application -> synchronization primitives
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "netsync.h"
+#include "netapi_util.h"
+
+#if 0
+/* timing */
+static inline unsigned long timing_start(void)
+{
+       volatile int vval;
+        //read clock
+        asm volatile("mrc p15, 0, %0, c9, c13, 0" :  "=r"(vval));
+        return vval;
+}
+static inline unsigned long timing_stop(void)
+{
+        volatile int vval2;
+        //read clock
+        asm volatile("mrc p15, 0, %0, c9, c13, 0" :  "=r"(vval2));
+        return vval2;
+}
+#endif
+#define timing_start netapi_timing_start
+#define timing_stop netapi_timing_stop
+
+int spot=0;
+
+NETAPI_RWLOCK_T  temp;
+
+void test1()
+{
+int v1, v2;
+netapi_rwlock_init(&temp);
+v1 = timing_start();
+netapi_rwlock_write_lock(&temp);
+v2 = timing_stop();
+printf("rwlock write locked, cycles= %d \n", v2-v1);
+}
+
+void test2()
+{
+int v1, v2;
+
+v1 = timing_start();
+netapi_rwlock_write_unlock(&temp);
+v2 = timing_stop();
+printf("rwlock write unlocked, cycles= %d \n",v2-v1);
+}
+void test3()
+{
+int v1,v2;
+v1 = timing_start();
+netapi_rwlock_read_lock(&temp);
+v2 = timing_stop();
+printf("rwlock read locked, cycles= %d \n", v2-v1);
+}
+void test4()
+{
+int v1,v2;
+v1 = timing_start();
+netapi_rwlock_read_unlock(&temp);
+v2 = timing_stop();
+printf("rwlock read_unlocked, cycles= %d\n", v2-v1);
+}
+
+main()
+{
+NETAPI_SPINLOCK_T val;
+int i;
+unsigned long v1,v2;
+int val2;
+for(i=0;i<10;i++) {
+val=__sync_fetch_and_add(&spot, 1);
+printf(" val = %d %d\n",val,spot);
+
+//now we try the synch_lock_and_test
+netapi_spinlock_init(&val);
+v1 = timing_start();
+netapi_spinlock_lock(&val);
+v2 = timing_stop();
+printf("locked, val= %d cycles=%d\n",val,v2-v1);
+
+//try the lock
+v1 = timing_start();
+val2=netapi_spinlock_try_lock(&val);
+v2 = timing_stop();
+printf("try lock has returns %d, cycles=%d\n", val2, v2-v1);
+
+//poll the lock 
+v1 = timing_start();
+val2=netapi_spinlock_is_locked(&val);
+v2 = timing_stop();
+printf("is_locked has returns %d, cycles=%d\n", val2, v2-v1);
+
+
+//unlock
+v1 = timing_start();
+netapi_spinlock_unlock(&val);
+v2 = timing_stop();
+printf("unlocked, val= %d cycles=%d\n", val,v2-v1);
+
+/*-------now try rwlock--------*/
+test1();
+test2();
+test3();
+test3();
+test4();
+test4();
+
+}
+}
+
+
+
index b18f6db19a49e1e1b81ae970491b271ad5eb03b2..5a3717e1a3dae57263a0cbb01bfffb75170592de 100755 (executable)
-/**************************************\r
- * file : synchtest2.c\r
- **************************************\r
- * * FILE:  synchtest2.c\r
- * \r
- * DESCRIPTION:  netapi user space transport\r
- *               library  test application - more synchtest\r
- * \r
- * REVISION HISTORY:  rev 0.0.1 \r
- *\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
- * \r
- *  Redistribution and use in source and binary forms, with or without \r
- *  modification, are permitted provided that the following conditions \r
- *  are met:\r
- *\r
- *    Redistributions of source code must retain the above copyright \r
- *    notice, this list of conditions and the following disclaimer.\r
- *\r
- *    Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the \r
- *    documentation and/or other materials provided with the   \r
- *    distribution.\r
- *\r
- *    Neither the name of Texas Instruments Incorporated nor the names of\r
- *    its contributors may be used to endorse or promote products derived\r
- *    from this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- ******************************************************************************/\r
-\r
-#include <stdio.h>\r
-#include <pthread.h>\r
-#include <unistd.h>\r
-#include <stdlib.h>\r
-#include <sched.h>\r
-#include <linux/unistd.h>\r
-#include <sys/syscall.h>\r
-#include <errno.h>\r
-\r
-#include "netsync.h"\r
-#include "netapi_util.h"\r
-//#define INC_TO 1000000 // one million.\r
-#define INC_TO 10000 // one million...\r
-\r
-NETAPI_ATOMIC64_T global_int=NETAPI_ATOMIC_INIT64(0LL)  ;\r
-__thread blah=0;\r
-int blah2=0;\r
-NETAPI_SPINLOCK_T spin_test;\r
-\r
-pid_t gettid( void )\r
-{\r
-       return syscall( __NR_gettid );\r
-}\r
-\r
-void *thread_routine( void *arg )\r
-{\r
-       int i;\r
-       int proc_num = (int)(long)arg;\r
-       cpu_set_t set;\r
-       int v1, v2,v3;\r
-\r
-#if 0\r
-       CPU_ZERO( &set );\r
-       CPU_SET( proc_num, &set );\r
-\r
-       if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))\r
-       {\r
-               perror( "sched_setaffinity" );\r
-               return NULL;\r
-       }\r
-#endif\r
-\r
-       for (i = 0; i < INC_TO; i++)\r
-       {\r
-               \r
-               v1 = netapi_timing_start(); \r
-              netapi_atomic_add64(&global_int,1LL);\r
-              v1= netapi_timing_stop() - v1;\r
-               sched_yield();\r
-               v2 = netapi_timing_start(); \r
-               blah+=1;        \r
-              v2= netapi_timing_stop() - v2;\r
-              \r
-               v3 = netapi_timing_start(); \r
-               blah2+=1;       \r
-              v3= netapi_timing_stop() - v3;\r
-               if(i<10) { printf("thread %d -> a64 costs %d,  tls costs %d simple++ costs %d\n", proc_num,v1,v2,v3);}\r
-               sched_yield();\r
-       }\r
-        printf("thead %d -> blah=%d\n",proc_num, blah);\r
-\r
-        printf("now try spin lock test. i'm thread %d, about to grab lock \n", proc_num);\r
-\r
-        //now we try the synch_lock_and_test\r
-        v1 = netapi_timing_start();\r
-        netapi_spinlock_lock(&spin_test);\r
-        v2 = netapi_timing_stop();\r
-        printf("i'm thread %d. I've locked it, val= %d, it took cycles=%d to get it\ngoing to sleep..",proc_num,spin_test,v2-v1);\r
-        sleep(1);\r
-        printf(" i'm back.  i'm thread %d. i'm unlocking now\n",proc_num); \r
-        netapi_spinlock_unlock(&spin_test);\r
-       return NULL;\r
-}\r
-\r
-int main()\r
-{\r
-       int procs = 0;\r
-       int i;\r
-       pthread_t *thrs;\r
-        printf("at start up\n");\r
-\r
-       // Getting number of CPUs\r
-       procs = (int)sysconf( _SC_NPROCESSORS_ONLN );\r
-       if (procs < 0)\r
-       {\r
-               perror( "sysconf" );\r
-               return -1;\r
-       }\r
-        printf(" num cpus = %d\n",procs);\r
-        if (procs==1) {procs+=1; printf("adding 2nd 'core' \n");}\r
-       thrs = malloc( sizeof( pthread_t ) * procs );\r
-       if (thrs == NULL)\r
-       {\r
-               perror( "malloc" );\r
-               return -1;\r
-       }\r
-\r
-        //initialize spinlock\r
-        netapi_spinlock_init(&spin_test);\r
-       printf( "Starting %d threads...\n", procs );\r
-\r
-       for (i = 0; i < procs; i++)\r
-       {\r
-               if (pthread_create( &thrs[i], NULL, thread_routine,\r
-                       (void *)(long)i ))\r
-               {\r
-                       perror( "pthread_create" );\r
-                       procs = i;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       for (i = 0; i < procs; i++)\r
-               pthread_join( thrs[i], NULL );\r
-\r
-       free( thrs );\r
-\r
-       printf( "global_int value is: %lld bare global_int is %d\n",\r
-               global_int.val, blah2 );\r
-       printf( "Expected value is: %d\n", INC_TO * procs );\r
-\r
-       return 0;\r
-}\r
+/**************************************
+ * file : synchtest2.c
+ **************************************
+ * * FILE:  synchtest2.c
+ * 
+ * DESCRIPTION:  netapi user space transport
+ *               library  test application - more synchtest
+ * 
+ * REVISION HISTORY:  rev 0.0.1 
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <linux/unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+#include "netsync.h"
+#include "netapi_util.h"
+//#define INC_TO 1000000 // one million.
+#define INC_TO 10000 // one million...
+
+NETAPI_ATOMIC64_T global_int=NETAPI_ATOMIC_INIT64(0LL)  ;
+__thread blah=0;
+int blah2=0;
+NETAPI_SPINLOCK_T spin_test;
+
+pid_t gettid( void )
+{
+       return syscall( __NR_gettid );
+}
+
+void *thread_routine( void *arg )
+{
+       int i;
+       int proc_num = (int)(long)arg;
+       cpu_set_t set;
+       int v1, v2,v3;
+
+#if 0
+       CPU_ZERO( &set );
+       CPU_SET( proc_num, &set );
+
+       if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
+       {
+               perror( "sched_setaffinity" );
+               return NULL;
+       }
+#endif
+
+       for (i = 0; i < INC_TO; i++)
+       {
+               
+               v1 = netapi_timing_start(); 
+              netapi_atomic_add64(&global_int,1LL);
+              v1= netapi_timing_stop() - v1;
+               sched_yield();
+               v2 = netapi_timing_start(); 
+               blah+=1;        
+              v2= netapi_timing_stop() - v2;
+              
+               v3 = netapi_timing_start(); 
+               blah2+=1;       
+              v3= netapi_timing_stop() - v3;
+               if(i<10) { printf("thread %d -> a64 costs %d,  tls costs %d simple++ costs %d\n", proc_num,v1,v2,v3);}
+               sched_yield();
+       }
+        printf("thead %d -> blah=%d\n",proc_num, blah);
+
+        printf("now try spin lock test. i'm thread %d, about to grab lock \n", proc_num);
+
+        //now we try the synch_lock_and_test
+        v1 = netapi_timing_start();
+        netapi_spinlock_lock(&spin_test);
+        v2 = netapi_timing_stop();
+        printf("i'm thread %d. I've locked it, val= %d, it took cycles=%d to get it\ngoing to sleep..",proc_num,spin_test,v2-v1);
+        sleep(1);
+        printf(" i'm back.  i'm thread %d. i'm unlocking now\n",proc_num); 
+        netapi_spinlock_unlock(&spin_test);
+       return NULL;
+}
+
+int main()
+{
+       int procs = 0;
+       int i;
+       pthread_t *thrs;
+        printf("at start up\n");
+
+       // Getting number of CPUs
+       procs = (int)sysconf( _SC_NPROCESSORS_ONLN );
+       if (procs < 0)
+       {
+               perror( "sysconf" );
+               return -1;
+       }
+        printf(" num cpus = %d\n",procs);
+        if (procs==1) {procs+=1; printf("adding 2nd 'core' \n");}
+       thrs = malloc( sizeof( pthread_t ) * procs );
+       if (thrs == NULL)
+       {
+               perror( "malloc" );
+               return -1;
+       }
+
+        //initialize spinlock
+        netapi_spinlock_init(&spin_test);
+       printf( "Starting %d threads...\n", procs );
+
+       for (i = 0; i < procs; i++)
+       {
+               if (pthread_create( &thrs[i], NULL, thread_routine,
+                       (void *)(long)i ))
+               {
+                       perror( "pthread_create" );
+                       procs = i;
+                       break;
+               }
+       }
+
+       for (i = 0; i < procs; i++)
+               pthread_join( thrs[i], NULL );
+
+       free( thrs );
+
+       printf( "global_int value is: %lld bare global_int is %d\n",
+               global_int.val, blah2 );
+       printf( "Expected value is: %d\n", INC_TO * procs );
+
+       return 0;
+}
index 9db33e52ce0a74c6e8bd1a22feb4faa4486bda86..2324d52f9a46f2636a96bf9c367aea19f2cf9d43 100755 (executable)
-/*\r
-\r
-Copyright (c) 2005, Simon Howard\r
-All rights reserved.\r
-\r
-Redistribution and use in source and binary forms, with or without \r
-modification, are permitted provided that the following conditions \r
-are met:\r
-\r
- * Redistributions of source code must retain the above copyright \r
-   notice, this list of conditions and the following disclaimer.\r
- * Redistributions in binary form must reproduce the above copyright \r
-   notice, this list of conditions and the following disclaimer in \r
-   the documentation and/or other materials provided with the \r
-   distribution.\r
- * Neither the name of the C Algorithms project nor the names of its \r
-   contributors may be used to endorse or promote products derived \r
-   from this software without specific prior written permission.\r
-\r
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \r
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \r
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT \r
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN \r
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \r
-POSSIBILITY OF SUCH DAMAGE.\r
-\r
- *ALSO:   TI modifications made to support binary data keys\r
-*\r
- *  Copyright (c) Texas Instruments Incorporated 2010-2011\r
-*/\r
-\r
-/* Trie: fast mapping of strings to values */\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#include "trie.h"\r
-\r
-typedef struct _TrieNode TrieNode;\r
-\r
-struct _TrieNode {\r
-       void *data;\r
-       unsigned int use_count;\r
-       TrieNode *next[256];\r
-};\r
-\r
-struct _Trie {\r
-       TrieNode *root_node;\r
-};\r
-\r
-static void trie_free_node(TrieNode *node)\r
-{\r
-       int i;\r
-\r
-       if (node == NULL)\r
-               return;\r
-       \r
-       /* First, free all subnodes */\r
-\r
-       for (i=0; i<256; ++i) {\r
-               trie_free_node(node->next[i]);\r
-       }\r
-\r
-       /* Free this node */\r
-\r
-       free(node);\r
-}\r
-\r
-Trie *trie_new(void)\r
-{\r
-       Trie *new_trie;\r
-\r
-       new_trie = (Trie *) malloc(sizeof(Trie));\r
-       new_trie->root_node = NULL;\r
-\r
-       return new_trie;\r
-}\r
-\r
-void trie_free(Trie *trie)\r
-{\r
-       /* Free the subnode, and all others by implication */\r
-\r
-       trie_free_node(trie->root_node);\r
-\r
-       /* Free the trie */\r
-\r
-       free(trie);\r
-}\r
-\r
-void trie_insert(Trie *trie, char *key, int keylen, void *value)\r
-{\r
-       TrieNode **rover;\r
-       TrieNode *node;\r
-       unsigned char *p;\r
-       unsigned char c;\r
-       int k;\r
-\r
-       /* Cannot insert NULL values */\r
-\r
-       if (value == NULL) {\r
-               return;\r
-       }\r
-\r
-       /* Search down the trie until we reach the end of string,\r
-        * creating nodes as necessary */\r
-\r
-       rover = &trie->root_node;\r
-       p = (unsigned char *) key;\r
-\r
-       for (k=0;;) {\r
-\r
-               node = *rover;\r
-\r
-               if (node == NULL) {\r
-                       \r
-                       /* Node does not exist, so create it */\r
-\r
-                       node = (TrieNode *) malloc(sizeof(TrieNode));\r
-                       memset(node, 0, sizeof(TrieNode));\r
-\r
-                       /* Link in to the trie */\r
-\r
-                       *rover = node;\r
-               }\r
-\r
-               /* One more use of this node */\r
-\r
-               ++node->use_count;\r
-\r
-               /* Current character */\r
-\r
-               c = *p;\r
-\r
-               /* Reached the end of string?  If so, we're finished. */\r
-\r
-               if (k>=keylen) {\r
-\r
-                       /* Set the data at the node we have reached */\r
-\r
-                       node->data = value;\r
-\r
-                       break;\r
-               }\r
-\r
-               /* Advance to the next node in the chain */\r
-\r
-               rover = &node->next[c];\r
-               ++p; \r
-               k+=1;\r
-       }\r
-}\r
-\r
-void trie_remove(Trie *trie, char *key, int keylen)\r
-{\r
-       TrieNode *node;\r
-       TrieNode *next;\r
-       TrieNode **last_next_ptr;\r
-       unsigned char *p;\r
-       unsigned char c;\r
-       int k=0;\r
-       \r
-       /* First, search down to the ending node so that the data can\r
-        * be removed. */\r
-\r
-       /* Search down the trie until the end of string is reached */\r
-\r
-       node = trie->root_node;\r
-\r
-       for (p=(unsigned char *) key, k=0; k<keylen; ++p, k+=1) {\r
-\r
-               if (node == NULL) {\r
-                       /* Not found in the tree. Return. */\r
-\r
-                       return;\r
-               }\r
-\r
-               /* Jump to the next node */\r
-\r
-               c = *p;\r
-               node = node->next[c];\r
-       }\r
-\r
-       /* Remove the data at this node */\r
-\r
-       node->data = NULL;\r
-\r
-       /* Now traverse the tree again as before, decrementing the use\r
-        * count of each node.  Free back nodes as necessary. */\r
-\r
-       node = trie->root_node;\r
-       last_next_ptr = &trie->root_node;\r
-       p = key;\r
-\r
-       for (k=0;;k++) {\r
-\r
-               /* Find the next node */\r
-               \r
-               c = *p;\r
-               next = node->next[c];\r
-\r
-               /* Free this node if necessary */\r
-\r
-               --node->use_count;\r
-\r
-               if (node->use_count <= 0) {\r
-                       free(node);\r
-\r
-                       /* Set the "next" pointer on the previous node to NULL,\r
-                        * to unlink the free'd node from the tree.  This only\r
-                        * needs to be done once in a remove.  After the first\r
-                        * unlink, all further nodes are also going to be\r
-                        * free'd. */\r
-\r
-                       if (last_next_ptr != NULL) {\r
-                               *last_next_ptr = NULL;\r
-                               last_next_ptr = NULL;\r
-                       }\r
-               }\r
-               \r
-               /* Go to the next character or finish */\r
-\r
-               if (k>=keylen) {\r
-                       break;\r
-               } else {\r
-                       ++p;\r
-               }\r
-\r
-               /* If necessary, save the location of the "next" pointer\r
-                * so that it may be set to NULL on the next iteration if\r
-                * the next node visited is freed. */\r
-\r
-               if (last_next_ptr != NULL) {\r
-                       last_next_ptr = &node->next[c];\r
-               }\r
-               \r
-               /* Jump to the next node */\r
-\r
-               node = next;\r
-       }\r
-}\r
-\r
-void *trie_lookup(Trie *trie, char *key, int keylen)\r
-{\r
-       TrieNode *node;\r
-       unsigned char *p;\r
-       unsigned char c;\r
-       int k=0;\r
-\r
-       /* Search down the trie until the end of string is found */\r
-       \r
-       node = trie->root_node;\r
-       p = (unsigned char *) key;\r
-\r
-       while (k<keylen ) {\r
-               if (node == NULL) {\r
-                       /* Not found - reached end of branch */\r
-\r
-                       return NULL;\r
-               }\r
-\r
-               /* Advance to the next node in the chain, next character */\r
-\r
-               c = *p;\r
-               node = node->next[c];\r
-               ++p;\r
-               k+=1;\r
-       }\r
-        /* bug! */\r
-        \r
-       return (node ? node->data : NULL);\r
-\r
-}\r
-\r
-int trie_num_entries(Trie *trie)\r
-{\r
-       /* To find the number of entries, simply look at the use count\r
-        * of the root node. */\r
-\r
-       if (trie->root_node == NULL) {\r
-               return 0;\r
-       } else {\r
-               return trie->root_node->use_count;\r
-       }\r
-}\r
-\r
-//#define TEST\r
-#ifdef TEST\r
-main()\r
-{\r
-Trie * p_trie;\r
-char * p_res;\r
-p_trie = trie_new();\r
-if (!p_trie) {printf("trie alloc failed\n"); exit(1);}\r
-\r
-trie_insert(p_trie,"key1","this is key 1");\r
-trie_insert(p_trie,"key12","this is key 2");\r
-trie_insert(p_trie,"key3","this is key 3");\r
-trie_insert(p_trie,"key4","this is key 4");\r
-\r
-p_res= trie_lookup(p_trie,"key1");\r
-printf("lookup %s = %s\n", "key1", p_res ?  p_res : "not found");\r
-\r
-p_res= trie_lookup(p_trie,"key12");\r
-printf("lookup %s = %s\n", "key2", p_res ?  p_res : "not found");\r
-\r
-p_res= trie_lookup(p_trie,"key3");\r
-printf("lookup %s = %s\n", "key3", p_res ?  p_res : "not found");\r
-\r
-p_res= trie_lookup(p_trie,"key4");\r
-printf("lookup %s = %s\n", "key4", p_res ?  p_res : "not found");\r
-\r
-p_res= trie_lookup(p_trie,"key5");\r
-printf("lookup %s = %s\n", "key5", p_res ?  p_res : "not found");\r
-\r
-p_res= trie_lookup(p_trie,"k5");\r
-printf("lookup %s = %s\n", "k5", p_res ?  p_res : "not found");\r
-\r
-trie_free(p_trie);\r
-\r
-}\r
-#endif\r
+/*
+
+Copyright (c) 2005, Simon Howard
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions 
+are met:
+
+ * Redistributions of source code must retain the above copyright 
+   notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright 
+   notice, this list of conditions and the following disclaimer in 
+   the documentation and/or other materials provided with the 
+   distribution.
+ * Neither the name of the C Algorithms project nor the names of its 
+   contributors may be used to endorse or promote products derived 
+   from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE.
+
+ *ALSO:   TI modifications made to support binary data keys
+*
+ *  Copyright (c) Texas Instruments Incorporated 2010-2011
+*/
+
+/* Trie: fast mapping of strings to values */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "trie.h"
+
+typedef struct _TrieNode TrieNode;
+
+struct _TrieNode {
+       void *data;
+       unsigned int use_count;
+       TrieNode *next[256];
+};
+
+struct _Trie {
+       TrieNode *root_node;
+};
+
+static void trie_free_node(TrieNode *node)
+{
+       int i;
+
+       if (node == NULL)
+               return;
+       
+       /* First, free all subnodes */
+
+       for (i=0; i<256; ++i) {
+               trie_free_node(node->next[i]);
+       }
+
+       /* Free this node */
+
+       free(node);
+}
+
+Trie *trie_new(void)
+{
+       Trie *new_trie;
+
+       new_trie = (Trie *) malloc(sizeof(Trie));
+       new_trie->root_node = NULL;
+
+       return new_trie;
+}
+
+void trie_free(Trie *trie)
+{
+       /* Free the subnode, and all others by implication */
+
+       trie_free_node(trie->root_node);
+
+       /* Free the trie */
+
+       free(trie);
+}
+
+void trie_insert(Trie *trie, char *key, int keylen, void *value)
+{
+       TrieNode **rover;
+       TrieNode *node;
+       unsigned char *p;
+       unsigned char c;
+       int k;
+
+       /* Cannot insert NULL values */
+
+       if (value == NULL) {
+               return;
+       }
+
+       /* Search down the trie until we reach the end of string,
+        * creating nodes as necessary */
+
+       rover = &trie->root_node;
+       p = (unsigned char *) key;
+
+       for (k=0;;) {
+
+               node = *rover;
+
+               if (node == NULL) {
+                       
+                       /* Node does not exist, so create it */
+
+                       node = (TrieNode *) malloc(sizeof(TrieNode));
+                       memset(node, 0, sizeof(TrieNode));
+
+                       /* Link in to the trie */
+
+                       *rover = node;
+               }
+
+               /* One more use of this node */
+
+               ++node->use_count;
+
+               /* Current character */
+
+               c = *p;
+
+               /* Reached the end of string?  If so, we're finished. */
+
+               if (k>=keylen) {
+
+                       /* Set the data at the node we have reached */
+
+                       node->data = value;
+
+                       break;
+               }
+
+               /* Advance to the next node in the chain */
+
+               rover = &node->next[c];
+               ++p; 
+               k+=1;
+       }
+}
+
+void trie_remove(Trie *trie, char *key, int keylen)
+{
+       TrieNode *node;
+       TrieNode *next;
+       TrieNode **last_next_ptr;
+       unsigned char *p;
+       unsigned char c;
+       int k=0;
+       
+       /* First, search down to the ending node so that the data can
+        * be removed. */
+
+       /* Search down the trie until the end of string is reached */
+
+       node = trie->root_node;
+
+       for (p=(unsigned char *) key, k=0; k<keylen; ++p, k+=1) {
+
+               if (node == NULL) {
+                       /* Not found in the tree. Return. */
+
+                       return;
+               }
+
+               /* Jump to the next node */
+
+               c = *p;
+               node = node->next[c];
+       }
+
+       /* Remove the data at this node */
+
+       node->data = NULL;
+
+       /* Now traverse the tree again as before, decrementing the use
+        * count of each node.  Free back nodes as necessary. */
+
+       node = trie->root_node;
+       last_next_ptr = &trie->root_node;
+       p = key;
+
+       for (k=0;;k++) {
+
+               /* Find the next node */
+               
+               c = *p;
+               next = node->next[c];
+
+               /* Free this node if necessary */
+
+               --node->use_count;
+
+               if (node->use_count <= 0) {
+                       free(node);
+
+                       /* Set the "next" pointer on the previous node to NULL,
+                        * to unlink the free'd node from the tree.  This only
+                        * needs to be done once in a remove.  After the first
+                        * unlink, all further nodes are also going to be
+                        * free'd. */
+
+                       if (last_next_ptr != NULL) {
+                               *last_next_ptr = NULL;
+                               last_next_ptr = NULL;
+                       }
+               }
+               
+               /* Go to the next character or finish */
+
+               if (k>=keylen) {
+                       break;
+               } else {
+                       ++p;
+               }
+
+               /* If necessary, save the location of the "next" pointer
+                * so that it may be set to NULL on the next iteration if
+                * the next node visited is freed. */
+
+               if (last_next_ptr != NULL) {
+                       last_next_ptr = &node->next[c];
+               }
+               
+               /* Jump to the next node */
+
+               node = next;
+       }
+}
+
+void *trie_lookup(Trie *trie, char *key, int keylen)
+{
+       TrieNode *node;
+       unsigned char *p;
+       unsigned char c;
+       int k=0;
+
+       /* Search down the trie until the end of string is found */
+       
+       node = trie->root_node;
+       p = (unsigned char *) key;
+
+       while (k<keylen ) {
+               if (node == NULL) {
+                       /* Not found - reached end of branch */
+
+                       return NULL;
+               }
+
+               /* Advance to the next node in the chain, next character */
+
+               c = *p;
+               node = node->next[c];
+               ++p;
+               k+=1;
+       }
+        /* bug! */
+        
+       return (node ? node->data : NULL);
+
+}
+
+int trie_num_entries(Trie *trie)
+{
+       /* To find the number of entries, simply look at the use count
+        * of the root node. */
+
+       if (trie->root_node == NULL) {
+               return 0;
+       } else {
+               return trie->root_node->use_count;
+       }
+}
+
+//#define TEST
+#ifdef TEST
+main()
+{
+Trie * p_trie;
+char * p_res;
+p_trie = trie_new();
+if (!p_trie) {printf("trie alloc failed\n"); exit(1);}
+
+trie_insert(p_trie,"key1","this is key 1");
+trie_insert(p_trie,"key12","this is key 2");
+trie_insert(p_trie,"key3","this is key 3");
+trie_insert(p_trie,"key4","this is key 4");
+
+p_res= trie_lookup(p_trie,"key1");
+printf("lookup %s = %s\n", "key1", p_res ?  p_res : "not found");
+
+p_res= trie_lookup(p_trie,"key12");
+printf("lookup %s = %s\n", "key2", p_res ?  p_res : "not found");
+
+p_res= trie_lookup(p_trie,"key3");
+printf("lookup %s = %s\n", "key3", p_res ?  p_res : "not found");
+
+p_res= trie_lookup(p_trie,"key4");
+printf("lookup %s = %s\n", "key4", p_res ?  p_res : "not found");
+
+p_res= trie_lookup(p_trie,"key5");
+printf("lookup %s = %s\n", "key5", p_res ?  p_res : "not found");
+
+p_res= trie_lookup(p_trie,"k5");
+printf("lookup %s = %s\n", "k5", p_res ?  p_res : "not found");
+
+trie_free(p_trie);
+
+}
+#endif
diff --git a/ti/runtime/netapi/test/udpif.c b/ti/runtime/netapi/test/udpif.c
new file mode 100755 (executable)
index 0000000..0af9b15
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ *
+ * udpIf.c - provides udp 
+ *
+ */
+//#define BENCHMARK
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+
+int nSent=0;
+
+#ifdef BENCHMARK
+struct timeval stime,mtime,etime;
+#endif
+
+#define SENDSZ 1396
+int SendSize=SENDSZ;
+
+#define MAIN_NEEDED
+#ifdef MAIN_NEEDED
+/******************************************************************************
+    main
+*******************************************************************************/
+/* argv[1] = S for Send, R for Receive
+   argv[2] = fileName
+   argv[3] = port
+   argv[4] = ipAddress
+   argv[5] = send size
+*/
+main(argc,argv)
+int argc;
+char **argv;
+{
+int  sending = 0;
+char fileName[256];
+int  port;
+char ipAddress[64];
+    if (argc < 4) 
+        {
+        printf ("usage:udpIf S|R fileName port [ipAddress] [send size]\n");
+        exit(-1);
+        }
+    sending = (*argv[1] == 'S') ? 1 : 0;
+    strcpy(fileName,argv[2]);
+    port = atoi(argv[3]);
+    if (argc >= 5)
+        strcpy(ipAddress,argv[4]);
+    else
+        strcpy(ipAddress,"");
+    if (argc ==6) SendSize=atoi(argv[5]);
+    if (SendSize > SENDSZ) SendSize=SENDSZ;
+    udpif(sending,fileName,port,ipAddress);
+}
+#endif
+char startstring[]="start";
+char endstring[]="done";
+/******************************************************************************
+    udpif
+*******************************************************************************/
+udpif(sending,fileName,port,ipAddress)
+int  sending;
+char *fileName;
+int  port;
+char *ipAddress;
+{
+struct sockaddr_in addr,fraddr;
+int    addrlen, fd, cnt;
+socklen_t fraddrlen;
+char message[SENDSZ+3];
+int  numTries = 0;
+#define MAX_TRIES 5
+int rc;
+int sstate=0;
+int total, rtotal;
+total=rtotal=0; 
+    if (sending)
+        {    
+        int inFile;
+        inFile = open(fileName,O_RDONLY);
+        if (inFile < 0)
+            {
+            printf ("Can't read %s in tcpIf\n",fileName);
+            exit(-1);
+            }
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+        printf ("socket is %d\n",fd);
+        if (fd < 0) 
+            {
+            perror("socket");
+            exit(1);
+            }
+        bzero(&addr, sizeof(addr));
+        addr.sin_family = AF_INET;
+        addr.sin_addr.s_addr = INADDR_ANY;
+        addr.sin_port = 0;
+        addrlen = sizeof(addr);
+        rc = bind(fd, &addr, sizeof(addr));
+        printf ("Sender:bind rc is %d\n",rc);
+        if (rc < 0) 
+            {
+            perror("bind");
+            exit(1);
+            }
+        addr.sin_addr.s_addr = inet_addr(ipAddress);
+        addr.sin_port = htons(port);
+        printf("dbg: %x %x\n", addr.sin_addr.s_addr, addr.sin_port);
+#ifdef BENCHMARK
+               sendto(fd,
+                     startstring,
+                     strlen(startstring)+1,
+                     0,&addr,sizeof(addr));
+#endif
+        while(1)
+            {
+            char *mPtr;
+            int len;
+            int count = read(inFile,message,/*4096*/ /*SENDSZ*/SendSize);
+#ifndef BENCHMARK
+            //printf ("Sender:in count is %d\n",count);
+#endif
+            if (count == 0) 
+                {
+                close(inFile);
+#ifdef BENCHMARK
+               sendto(fd,
+                     endstring,
+                     strlen(endstring)+1,
+                     0,&addr,sizeof(addr));
+                                     
+ sendto(fd,
+                     endstring,
+                     strlen(endstring)+1,
+                     0,&addr,sizeof(addr));
+ sendto(fd,
+                     endstring,
+                     strlen(endstring)+1,
+                     0,&addr,sizeof(addr));
+               printf("sending done %d\n",nSent);
+               sleep(1);
+#endif
+                printf("sending done %d\n",nSent);
+
+                break;
+                }
+            mPtr = message;
+            len = count==-1 ? 5: count;
+            do {
+                cnt = sendto(fd, 
+                     mPtr,
+                     len,
+                     0,&addr,sizeof(addr));
+#ifndef BENCHMARK
+               // printf ("Sender:sendto count is %d\n",cnt);
+#endif
+                if (cnt < 0) 
+                    {
+                    close(inFile);
+                    perror("sendto");
+                    exit(1);
+                    }
+                nSent+=1;
+                mPtr += cnt;
+                len -= cnt;
+                } while(len > 0);
+            }
+        } 
+    else 
+        { 
+        /* receive */
+        int outFile;
+        int newSocket;
+        int rc;
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+        printf ("socket is %d\n",fd);
+        if (fd < 0) 
+            {
+            perror("socket");
+            exit(1);
+            }
+        bzero(&addr, sizeof(addr));
+        addr.sin_family = AF_INET;
+        addr.sin_addr.s_addr = htonl(INADDR_ANY);
+        addr.sin_port = htons(port);
+        addrlen = sizeof(addr);
+        rc = bind(fd, &addr, sizeof(addr));
+        printf ("Receiver:bind is %d\n",rc);
+        if (rc < 0) 
+            {
+            perror("bind");
+            exit(1);
+            }
+        /*outFile = open(fileName,O_WRONLY | O_CREAT);
+        if (outFile < 0)
+            {
+            printf ("Can't write to %s in tcpIf\n",fileName);
+            exit(-1);
+            }*/
+       memset(&fraddr,0,sizeof(fraddr));
+       fraddr.sin_family= AF_INET;
+       fraddrlen = sizeof(fraddr); 
+#ifdef BENCHMARK
+        gettimeofday(&stime, 0                  );
+        printf("rcv start @ %d: %d\n",stime.tv_sec, stime.tv_usec);
+
+#endif
+       while(1)
+            {
+#ifdef BENCHMARK
+
+        gettimeofday(&mtime, 0                  );
+        if(rtotal >= 10000000) 
+        {
+        printf("rcv mtime @ %d: %d %d %d\n",mtime.tv_sec, mtime.tv_usec,total, rtotal);
+        rtotal=0;
+        }
+#endif
+            cnt = recvfrom(fd, 
+                       message, 
+                       sizeof(message), 
+                       0,
+                       NULL,
+                       &fraddrlen);
+            //printf ("Receiver:recv count = %d\n",cnt);
+            if (cnt == 0) 
+                {
+                /*close(outFile);*/
+                continue;
+                }
+            if (cnt < 0) 
+                {
+                /*close(outFile);*/
+                perror("recvfrom");
+                exit(1);
+                }
+           rtotal+=cnt;
+           total+=cnt;
+           message[cnt+1] = '\0';
+#ifndef BENCHMARK
+            printf("rcvd %s\n",message);
+#else
+            if (strcmp("done",message)==0)
+            {
+                time_t blah1;
+                suseconds_t blah2;
+                gettimeofday(&etime, 0                  );
+                blah1= (etime.tv_usec>stime.tv_usec) ?
+                               etime.tv_sec-stime.tv_sec :
+                               etime.tv_sec-stime.tv_sec-1;
+                blah2 = (etime.tv_usec>stime.tv_usec) ?
+                                     etime.tv_usec-stime.tv_usec :
+                                     1000000-stime.tv_usec+etime.tv_usec;
+                printf("DONE @ %d: %d {%d %d}\n",etime.tv_sec, etime.tv_usec,
+                                                 blah1, blah2 );
+                gettimeofday(&etime, 0                  );
+            }
+            if (strcmp("start",message)==0)
+            {
+                gettimeofday(&stime, 0                  );
+                printf("START @ %d: %d\n",stime.tv_sec, stime.tv_usec);
+            }
+
+#endif
+            }
+        }
+}