]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blobdiff - ti/runtime/netapi/src/netcp_cfg.c
Add support for etherType field for netapi_netcpCfgCraeteMacInterface
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netcp_cfg.c
index 2ae66eb34b75873a7bc1197b2d3486e9a5981f99..823b28bca2bef1066653626d9b55241e8506a2df 100755 (executable)
-/**********************************************************\r
- * file: netcp_cfg.c\r
- * purpose: netcp configurations routines\r
- **************************************************************\r
- * FILE: netcp_cfg.c\r
- * \r
- * DESCRIPTION:  netcp configuration 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
- *  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 "netcp_cfg.h"\r
-#include "netapi_loc.h"\r
-\r
-/******************************************************************\r
- ********************Utility*************************************\r
-*******************************************************************/\r
-\r
-\r
-//get a free transaction id\r
-NetapiNwalTransInfo_t *  netapip_GetFreeTransInfo(NETAPI_GLOBAL_T *p_global, nwal_TransID_t *pTransId)\r
-{\r
-         uint16_t    count=0;\r
-\r
-       count=0;\r
-        while(count < TUNE_NETAPI_MAX_NUM_TRANS)\r
-        {\r
-            if((p_global->nwal_context.transInfos[count].inUse) != nwal_TRUE)\r
-            {\r
-                p_global->nwal_context.transInfos[count].inUse = nwal_TRUE;\r
-                *pTransId = count;\r
-                return(&p_global->nwal_context.transInfos[count]);\r
-            }\r
-            count++;\r
-        }\r
-         \r
-        /* trouble.  need to wait for one to free up*/\r
-        /* to do: handle this by forcing a poll of cntrl queue*/\r
-        printf(">netcp_cfg: trying to get free transaction slot but all full!!\n");\r
-        return NULL;\r
-\r
-}\r
-//internal: build route\r
-void netcp_cfgp_build_route(NETCP_CFG_ROUTE_T * p_route, int16_t * p_flow,  Qmss_QueueHnd * p_q)\r
-{\r
-    if (!p_route) return;\r
-    if (p_route->p_flow)  *p_flow= p_route->p_flow->flowid;\r
-    else *p_flow = CPPI_PARAM_NOT_SPECIFIED;\r
-    if (p_route->p_dest_q) *p_q = pktio_get_q(p_route->p_dest_q);\r
-    else *p_q=QMSS_PARAM_NOT_SPECIFIED;\r
-}\r
-/*-----------------------------------------------------------*/\r
-/*----------------database management stuff-------------------*/\r
-/*-----------------------------------------------------------*/\r
-\r
-/*=====================Policies=============================*/\r
-//internal: find a free slot for an SA \r
-int netcp_cfgp_find_policy_slot( NETAPI_NWAL_GLOBAL_CONTEXT_T *p, int tunnel)\r
-{\r
-   int i;\r
-   if ((tunnel <0 ) || (tunnel >=TUNE_NETAPI_MAX_SA)) return -1;\r
-\r
-         //find a free entry\r
-   for(i=0;i<TUNE_NETAPI_MAX_POLICY;i++)\r
-   {\r
-       if (!p->policy[i].in_use)\r
-       {\r
-           p->policy[i].in_use = 2; //pending\r
-           p->policy[i].tunnel= tunnel; //save tunnel this is linked to \r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
-\r
-//internal: delete a policy from list \r
-void netcp_cfgp_delete_policy(\r
-         NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-         int policy_slot )\r
-{\r
-   if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))\r
-   {\r
-        return ;\r
-   }\r
-   p->policy[policy_slot].in_use=0;\r
-   return;\r
-}\r
-\r
-//internal:  insert an policy into the list  \r
-void netcp_cfgp_insert_policy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int policy_slot,  //we 'reserved it already'\r
-                          void * handle)\r
-{\r
-        p->policy[policy_slot].in_use=1;\r
-        p->policy[policy_slot].nwal_handle = handle;\r
-        return;\r
-}\r
-\r
-//internal: return nwal_handle for policy \r
-void *netcp_cfgp_get_policy( NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int policy_slot)\r
-{\r
-   if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY)) return NULL;\r
-   if (!p->policy[policy_slot].in_use) return NULL;\r
-   return p->policy[policy_slot].nwal_handle;\r
-}\r
-\r
-\r
-\r
-/*======================SAs==================================*/\r
-//internal: find a free slot for an SA \r
-int netcp_cfgp_find_sa_slot( NETAPI_NWAL_GLOBAL_CONTEXT_T *p, int iface)\r
-{                                    \r
-   int i;\r
-   if (iface != NETCP_CFG_NO_INTERFACE)\r
-   {\r
-   if ((iface <0 ) || (iface >=TUNE_NETAPI_MAX_INTERFACES)) return -1;\r
-   }\r
-         //find a free entry\r
-   for(i=0;i<TUNE_NETAPI_MAX_SA;i++)\r
-   {                       \r
-       if (!p->tunnel[i].in_use)\r
-       {\r
-           p->tunnel[i].in_use = 2; //pending\r
-           p->tunnel[i].iface= iface; //save iface\r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
- //internal: delete an SAr from list \r
-void netcp_cfgp_delete_sa(\r
-         NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-         int sa_slot )\r
-{\r
-   if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))\r
-   {\r
-        return ;\r
-   }\r
-   p->tunnel[sa_slot].in_use=0;\r
-   return;\r
-}\r
-\r
-//internal:  insert an SA into the list  \r
-void netcp_cfgp_insert_sa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int sa_slot,  //we 'reserved it already'\r
-                          int dir,\r
-                          int mode,\r
-                          void * temp1,\r
-                          void * temp2,\r
-                          void * handle_inflow,\r
-                          void * handle_sideband)\r
-{\r
-        p->tunnel[sa_slot].in_use=1;\r
-        p->tunnel[sa_slot].inbound = dir;\r
-        p->tunnel[sa_slot].sa_mode = mode;\r
-        p->tunnel[sa_slot].sa_handle_inflow = handle_inflow;\r
-        p->tunnel[sa_slot].sa_handle_sideband = handle_sideband;\r
-        return;\r
-}\r
-\r
-//internal: return nwal_handles for SA   \r
-void *netcp_cfgp_get_sa_handles( NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int sa_slot, void ** p_sideband)\r
-{\r
-   if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA)) return NULL;\r
-   if (!p->tunnel[sa_slot].in_use) return NULL;\r
-   *p_sideband = p->tunnel[sa_slot].sa_handle_sideband;\r
-   return p->tunnel[sa_slot].sa_handle_inflow;\r
-}\r
-\r
-\r
-/*==============================fLOWS=============================*/\r
-//internal: find a free slot for a flow \r
-static int netcp_cfgp_find_flow_slot( NETAPI_NWAL_GLOBAL_CONTEXT_T *p)\r
-{\r
-   int i;\r
-         //find a free entry\r
-   for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)\r
-   {\r
-       if (!p->flows[i].in_use)\r
-       {\r
-           p->flows[i].in_use = 2; //pending\r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
-\r
-//internal: clear flow slot \r
-static void netcp_cfgp_delete_flow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,int slot)\r
-{\r
-   if ((slot >=0 ) && (slot < TUNE_NETAPI_MAX_FLOWS))\r
-   {\r
-        p->flows[slot].in_use = 0;\r
-   }\r
-}\r
-\r
-//internal:  insert a flow into flow slot\r
-static NETCP_CFG_FLOW_HANDLE_T netcp_cfgp_insert_flow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int slot,  //we 'reserved it already'\r
-                          void * handle)  //cppi flow handle. Save this for delete\r
-{\r
-        p->flows[slot].in_use=1;\r
-        p->flows[slot].handle = handle;\r
-       p->flows[slot].flow.flowid  = Cppi_getFlowId(handle);\r
-        return (NETCP_CFG_FLOW_HANDLE_T) &p->flows[slot].flow;\r
-}\r
-\r
-//find entry matching the flowid.  return slot# and the cppi handle\r
-static int netcp_cfgp_find_flow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int flowid,  \r
-                          void ** handle) \r
-{\r
-int i;\r
-   *handle=NULL;\r
-   for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)\r
-   {\r
-       if ((p->flows[i].in_use)&&(p->flows[i].flow.flowid == flowid))\r
-       {\r
-           *handle = p->flows[i].handle;\r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
-\r
-\r
-/*============================IP ADDRESSES==========================*/\r
-\r
-//internal: find a free slot for IP rule \r
-static int netcp_cfgp_find_ip_slot(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int iface_no)\r
-{\r
-   int i;\r
-\r
-   //find a free entry\r
-   for(i=0;i<TUNE_NETAPI_MAX_IP;i++)\r
-   {\r
-       if (!p->ips[i].in_use)\r
-       {\r
-           p->ips[i].in_use = 2; //pending\r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
-\r
-\r
-//internal:  insert an IP address into iface\r
-static void netcp_cfgp_insert_ip(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, \r
-                          nwal_IpType ipType,\r
-                          nwalIpAddr_t *ip_addr, \r
-                          nwalIpOpt_t *ip_qualifiers, \r
-                          int iface_no,\r
-                          int ip_slot,  //we 'reserved it already'\r
-                          void * handle)\r
-{\r
-        p->ips[ip_slot].in_use=1;\r
-        memcpy(&p->ips[ip_slot].ip_addr, ip_addr, sizeof(nwalIpAddr_t));\r
-        if(ip_qualifiers)\r
-        memcpy(&p->ips[ip_slot].ip_qualifiers, ip_qualifiers, sizeof(nwalIpOpt_t));\r
-        else\r
-        memset(&p->ips[ip_slot].ip_qualifiers, 0, sizeof(nwalIpOpt_t));\r
-        p->ips[ip_slot].ip_type = ipType;\r
-        p->ips[ip_slot].nwal_handle = handle;\r
-        return;\r
-}\r
-\r
-\r
-//internal: free IP slot associated with ip address \r
-static void netcp_cfgp_delete_ip(\r
-         NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-         int iface_no,\r
-         int ip_slot )\r
-{\r
-   if ((ip_slot <0)||(ip_slot>TUNE_NETAPI_MAX_IP)) return ;\r
-   p->ips[ip_slot].in_use=0;\r
-   return;\r
-}\r
-\r
-\r
-//internal: get IP handle associated with ip address \r
-static void *netcp_cfgp_get_ip_handle(\r
-         NETAPI_NWAL_GLOBAL_CONTEXT_T *p, \r
-         int iface_no,\r
-         int ip_slot )\r
-{\r
-   if ((ip_slot <0)||(ip_slot>=TUNE_NETAPI_MAX_IP)) return NULL;\r
-   if (!p->ips[ip_slot].in_use) return NULL;\r
-   return (void *) p->ips[ip_slot].nwal_handle;\r
-}\r
-\r
-/*==========================MAC INTERFACES======================*/\r
-//internal: insert interface info into global context\r
-static void netcp_cfgp_insert_mac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, unsigned char * p_mac,\r
-                           int iface_no, int state, NETCP_CFG_VLAN_T vlan, void * handle)\r
-{\r
-   if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_INTERFACES))\r
-   {\r
-        memset(&p->interfaces[iface_no],0,sizeof(NETCP_INTERFACE_T));\r
-        p->interfaces[iface_no].in_use = 1;\r
-        memcpy(&p->interfaces[iface_no].mac[0], p_mac,6);\r
-        p->interfaces[iface_no].state = state;\r
-        //todo p->interfaces[iface_no].vlan = vlan;\r
-        p->interfaces[iface_no].nwal_handle = handle; //save handle assoicated with this rule\r
-   }\r
-   else printf(">netcp_cfg insert interface # out of range %d\n",iface_no);\r
-\r
-}\r
-\r
-//internal: get handle associated with interface\r
-void* netcp_cfgp_get_mac_handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,int iface_no)\r
-{\r
-   if (iface_no == NETCP_CFG_NO_INTERFACE) return NULL;\r
-   if ((iface_no <0 ) || (iface_no >= TUNE_NETAPI_MAX_INTERFACES))\r
-   {\r
-       return NULL;\r
-   }\r
-   else if ( p->interfaces[iface_no].in_use)\r
-   {\r
-     return (void *) p->interfaces[iface_no].nwal_handle;\r
-   }\r
-   //no valid entry in slot\r
-   return NULL;\r
-}\r
-//internal: clear inteface entry\r
-static void netcp_cfgp_delete_mac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,int iface_no)\r
-{\r
-   if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_INTERFACES))\r
-   {\r
-        p->interfaces[iface_no].in_use = 0;\r
-   }\r
-}\r
-\r
-\r
-/*========================CLASSIFIERS==========================*/\r
-//internal: find a free slot for classifier rule\r
-static int netcp_cfgp_find_class_slot( NETAPI_NWAL_GLOBAL_CONTEXT_T *p)\r
-{\r
-   int i;\r
-         //find a free entry\r
-   for(i=0;i<TUNE_NETAPI_MAX_CLASSIFIERS;i++)\r
-   {\r
-       if (!p->classi[i].in_use)\r
-       {\r
-           p->classi[i].in_use = 2; //pending\r
-           return i;\r
-       }\r
-   }\r
-   return -1;\r
-}\r
-\r
- //internal: delete a classifer from list \r
-static void netcp_cfgp_delete_class(\r
-         NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-         int class_slot )\r
-{\r
-   if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))\r
-   {\r
-        return ;\r
-   }\r
-   p->classi[class_slot].in_use=0;\r
-   return;\r
-}\r
-\r
-//internal:  insert a classifier into list \r
-static void netcp_cfgp_insert_class(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int class_slot,  //we 'reserved it already'\r
-                         int class_type,\r
-                          void * L2_handle,\r
-                          void * L3_handle,\r
-                          void * L4_handle)\r
-{\r
-        p->classi[class_slot].in_use=1;\r
-        p->classi[class_slot].nwal_L2_handle = L2_handle;\r
-        p->classi[class_slot].nwal_L3_handle = L3_handle;\r
-        p->classi[class_slot].nwal_L4_handle = L4_handle;\r
-       p->classi[class_slot].class_type = class_type;\r
-        return;\r
-}\r
-\r
-//internal: return L4 nwal_handle for class\r
-static void *netcp_cfgp_get_l4_handle( NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int class_slot)\r
-{\r
-   if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS)) return NULL;\r
-   if (!p->classi[class_slot].in_use) return NULL;\r
-   return p->classi[class_slot].nwal_L4_handle;\r
-}\r
-\r
-//internal: return L3 nwal_handle for class\r
-static void *netcp_cfgp_get_l3_handle( NETAPI_NWAL_GLOBAL_CONTEXT_T *p,\r
-                          int class_slot)\r
-{\r
-   if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS)) return NULL;\r
-   if (!p->classi[class_slot].in_use) return NULL;\r
-   return p->classi[class_slot].nwal_L3_handle;\r
-}\r
-\r
-\r
-/***********************************************************************************/\r
-/****************************************API****************************************/\r
-/***********************************************************************************/\r
-\r
-\r
-/*****************************************************************\r
- *  Queury Stats\r
- ****************************************************************/\r
-void netcp_cfgReqStats(NETAPI_T  h, NETCP_CFG_STATS_CB cb, int doClear, int *err) \r
-{\r
-nwal_RetValue ret;\r
-NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-NetapiNwalTransInfo_t *pTransInfo;\r
-nwal_TransID_t     transId;\r
-if ((!n) || (!cb)) {*err = NETAPI_ERR_BAD_INPUT; return ;}\r
-*err =0;\r
-\r
-\r
-pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &transId);\r
-if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}\r
-pTransInfo->transType = NETAPI_NWAL_HANDLE_STAT_REQUEST;\r
-pTransInfo->netapi_handle = h;\r
-n->nwal_local.stats_cb = cb;\r
-ret = nwal_getPAStats( ((NETAPI_GLOBAL_T *) n->global)->nwal_context.nwalInstHandle,\r
-                          transId,\r
-                          NULL,\r
-                          doClear);\r
-if(ret !=  nwal_OK)\r
-{\r
-   pTransInfo->inUse = nwal_FALSE;\r
-   *err = NETAPI_ERR_BUSY;  //no resources??\r
-   printf("> netcp_cfg reqStats failed, err=%d\n",ret);\r
-}\r
-\r
-}\r
-/*****************************************************************\r
- *  CREATE A MAC INTERFACE\r
- ****************************************************************/\r
-NETCP_CFG_MACIF_T  netcp_cfgCreateMacInterface(\r
-                  NETAPI_T  h,\r
-                  uint8_t *p_mac,\r
-                 int  iface_no, \r
-                  int switch_port, \r
-                  NETCP_CFG_ROUTE_HANDLE_T  route,\r
-                  NETCP_CFG_VLAN_T  vlan,  //future\r
-                  int state,  //0=down, 1=up  //ignored\r
-                  int * err\r
-                  )\r
-{\r
-NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-nwalMacParam_t   MacInfo= {\r
-    0,      /* validParams */\r
-    0,      /* ifNum */\r
-    0,      /* vlanId      */\r
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Local mac */\r
-    NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */\r
-    NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */\r
-    CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */\r
-    QMSS_PARAM_NOT_SPECIFIED                     /* Use default queue configured to NWAL if packet is routed to host */\r
-};\r
-\r
-nwal_RetValue       retValue;\r
-NetapiNwalTransInfo_t *pTransInfo;\r
-nwal_TransID_t     trans_id;\r
-\r
-    if ((!n) || (!p_mac)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}\r
-    *err =0;\r
-\r
-    pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-    if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return -1;}\r
-    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;\r
-    pTransInfo->netapi_handle = h; \r
-\r
-    /* set up MacInfo */\r
-    memcpy(&MacInfo.macAddr,p_mac,6); \r
-    /* todo: vlan */\r
-    MacInfo.ifNum = switch_port;  /* todo: check for 0/1 relative*/\r
-\r
-    if (route != NULL)\r
-    {\r
-        netcp_cfgp_build_route(route,&MacInfo.appRxPktFlowId, &MacInfo.appRxPktQueue);\r
-    }\r
-    pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;\r
-    retValue = nwal_setMacIface( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                                  trans_id,\r
-                                  (nwal_AppId) (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no),\r
-                                  &MacInfo,\r
-                                  &pTransInfo->handle);\r
-    if(retValue !=  nwal_OK)\r
-    {\r
-       *err = NETAPI_ERR_NWAL_ERR0;\r
-        printf (">netcp cfg - ERROR: nwal_setMacIface returned Error Code %d\n",\r
-                    retValue);\r
-        pTransInfo->inUse = nwal_FALSE;\r
-        return -1;\r
-    }\r
-    //pTransInfo->inUse = nwal_FALSE;\r
-\r
-    //wait here until its done since scheduler isn't running yet most likely..\r
-    // todo:  make this handled by scheduler poll later ??\r
-    if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-        n->nwal_local.numPendingCfg++;\r
-        while ((volatile) n->nwal_local.numPendingCfg)\r
-        {\r
-           // if response is there, then this poll squirts out in the CTl poll callback, \r
-            // which handles the rest (including decrmenting #pending!!\r
-            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-        }\r
-    }\r
-    printf (">netcp cfg: MAC i/f %d added\n", iface_no);\r
-    netcp_cfgp_insert_mac(&netapi_get_global()->nwal_context, \r
-                          p_mac, iface_no, state,vlan,\r
-                          (void *) pTransInfo->handle);\r
-    pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-    pTransInfo->inUse = nwal_FALSE;\r
-    return  (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no);\r
-}\r
-\r
-\r
-/*****************************************************************/\r
-/***************Delete a mac interface****************************/\r
-/*****************************************************************/\r
-void netcp_cfgDelMac(NETAPI_T h,int iface_no,  int *err)\r
-{\r
-    nwal_RetValue ret;\r
-    NetapiNwalTransInfo_t *pTransInfo;\r
-    nwal_TransID_t     trans_id;\r
-    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-    void * ifHandle;\r
-\r
-    //get the nwal handle assoicated with this iface\r
-    ifHandle = netcp_cfgp_get_mac_handle(&netapi_get_global()->nwal_context, iface_no );\r
-    if(!ifHandle) \r
-            {*err = NETAPI_ERR_BAD_INPUT; return ;}\r
-    *err =0;\r
-    \r
-    //get a transaction id\r
-    pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-    if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}\r
-    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;\r
-    pTransInfo->netapi_handle = h;\r
-    //issue request\r
-    ret = nwal_delMacIface(\r
-                ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                trans_id,\r
-                ifHandle);\r
-    if(ret !=  nwal_OK)\r
-    {\r
-        *err = NETAPI_ERR_NWAL_ERR0;\r
-        printf (">netcp cfg - ERROR: nwal_delMacIface returned Error Code %d\n",\r
-                    ret);\r
-        pTransInfo->inUse = nwal_FALSE;\r
-        return ;\r
-    }\r
-    //wait here until its done since scheduler isn't running yet most likely..\r
-    // todo:  make this handled by scheduler poll later ??\r
-    if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-        n->nwal_local.numPendingCfg++;\r
-        while ((volatile) n->nwal_local.numPendingCfg)\r
-        {\r
-            // if response is there, then this poll squirts out in the CTl poll callback, \r
-            // which handles the rest (including decrmenting #pending!!\r
-            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-        }\r
-    }\r
-    printf (">netcp cfg: MAC i/f %d deleted\n",iface_no);\r
-    pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-    pTransInfo->inUse = nwal_FALSE;\r
-    //zap the entry\r
-    netcp_cfgp_delete_mac(&netapi_get_global()->nwal_context,  iface_no);\r
-    return ;\r
-}\r
-\r
-\r
-/*****************************************************************/\r
-/***************Add IP to MAC interface (internal)****************/\r
-/*****************************************************************/\r
-static NETCP_CFG_IP_T  netcp_cfgAddIpInternal(\r
-                  NETAPI_T  h,\r
-                  int  iface_no,\r
-                  nwal_IpType ipType,\r
-                  nwalIpAddr_t  * ip_addr,\r
-                  nwalIpOpt_t * ip_qualifiers,\r
-                  NETCP_CFG_ROUTE_HANDLE_T  route,  //NULL for default\r
-                  int * err,\r
-                  int  flag) //TRUE: add IP to iface.  False: add IP as part of classifier\r
-{\r
-NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-void * n_handle=NULL;\r
-nwalIpParam_t    nwalIpParam= {\r
-    pa_IPV4,      /* IP Type */\r
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */\r
-    { 0x0,0,0,0},/* IP Options */\r
-    NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */\r
-    NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */\r
-    CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */\r
-    QMSS_PARAM_NOT_SPECIFIED                     /* Use default queue configured to NWAL if packet is routed to host */\r
-};\r
-nwal_RetValue       retValue;\r
-NetapiNwalTransInfo_t *pTransInfo;\r
-nwal_TransID_t     trans_id;\r
-int ip_slot=-1;\r
-NETCP_CFG_IP_T ip_rule_id;\r
-NETCP_CFG_IP_T temp;\r
-\r
-     //verify that iface has been configured \r
-     if (iface_no != NETCP_CFG_NO_INTERFACE)\r
-     {\r
-     if ((iface_no<0) || (iface_no>= TUNE_NETAPI_MAX_INTERFACES)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}\r
-     }\r
-\r
-     if (iface_no != NETCP_CFG_NO_INTERFACE)\r
-     {\r
-     if(netapi_get_global()->nwal_context.interfaces[iface_no].in_use)\r
-     {\r
-       n_handle =  netapi_get_global()->nwal_context.interfaces[iface_no].nwal_handle;\r
-     }\r
-     else\r
-     {\r
-       *err = NETAPI_ERR_BAD_INPUT;\r
-       return -1;\r
-     }\r
-     }\r
-     if (flag) //if adding IP to MAC then reserve a slot to save info\r
-     {\r
-         //find free slot for IP & reserve\r
-         ip_slot= netcp_cfgp_find_ip_slot(&netapi_get_global()->nwal_context, \r
-                                   iface_no);\r
-         if (ip_slot <0) \r
-         {\r
-               *err= NETAPI_ERR_NOMEM;  //no room \r
-                return -1;\r
-          }\r
-     }\r
-\r
-     //get a transaction object for config action\r
-    pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-    if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return -1;}\r
-    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;\r
-    pTransInfo->netapi_handle = h;\r
-\r
-     //build nwalIpParam\r
-     memcpy(&nwalIpParam.locIpAddr,ip_addr, sizeof(nwalIpAddr_t));\r
-     nwalIpParam.ipType=ipType;\r
-     if(route)\r
-     {\r
-        netcp_cfgp_build_route(route,&nwalIpParam.appRxPktFlowId, &nwalIpParam.appRxPktQueue);\r
-     } \r
-     else{} //use nwal defaults\r
-     if (ip_qualifiers)\r
-       memcpy(&nwalIpParam.ipOpt,ip_qualifiers, sizeof(nwalIpOpt_t)); \r
-     else\r
-        memset(&nwalIpParam.ipOpt,0, sizeof(nwalIpOpt_t));\r
-\r
-     //build the rule id that will be returned when a packet matches \r
-     if (flag)\r
-       ip_rule_id = NETAPI_NETCP_MATCH_GENERIC_IP | iface_no | ((ip_slot&&0xff)<<8);\r
-     else\r
-        ip_rule_id = (NETAPI_NETCP_MATCH_CLASS_L3 | iface_no);\r
-\r
-     //perform config action\r
-     pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;\r
-     retValue = nwal_setIPAddr(   netapi_get_global()->nwal_context.nwalInstHandle,\r
-                                  trans_id,\r
-                                  (nwal_AppId) (ip_rule_id),\r
-                                  n_handle,\r
-                                  &nwalIpParam,\r
-                                  &pTransInfo->handle);\r
-\r
-    if(retValue !=  nwal_OK)\r
-    {\r
-        *err = NETAPI_ERR_NWAL_ERR0;\r
-        printf (">netcp cfg: nwal_setIP returned Error Code %d\n",\r
-                    retValue);\r
-        pTransInfo->inUse = nwal_FALSE;\r
-        //zap the entry\r
-        if (flag)\r
-        {\r
-               netcp_cfgp_delete_ip(&netapi_get_global()->nwal_context,\r
-                         iface_no,\r
-                         ip_slot);\r
-       }\r
-        return -1;\r
-    }\r
-    //wait here until its done since scheduler isn't running yet most likely..\r
-    // todo:  make this handled by scheduler poll later ??\r
-    if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-        n->nwal_local.numPendingCfg++;\r
-        while ((volatile) n->nwal_local.numPendingCfg)\r
-        {\r
-            // if response is there, then this poll squirts out in the CTl poll callback, \r
-            // which handles the rest (including decrmenting #pending!!\r
-            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-        }\r
-    }\r
-    if (flag)\r
-    {\r
-       printf (">netcp cfg: IP added to interface %d (slot%d)\n", iface_no, ip_slot);\r
-       netcp_cfgp_insert_ip(&netapi_get_global()->nwal_context, ipType, \r
-                          ip_addr, ip_qualifiers, iface_no, ip_slot,\r
-                          pTransInfo->handle);\r
-    }\r
-    pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-    temp = (NETCP_CFG_IP_T) pTransInfo->handle;\r
-    pTransInfo->inUse = nwal_FALSE;\r
-    return  (flag ? ip_rule_id:  temp);\r
-}\r
-/*****************************************************************/\r
-/***************Add IP to MAC interface **************************/\r
-/*****************************************************************/\r
-NETCP_CFG_IP_T  netcp_cfgAddIp(\r
-                  NETAPI_T  h,\r
-                  int  iface_no,\r
-                  nwal_IpType ipType,\r
-                  nwalIpAddr_t  * ip_addr,\r
-                  nwalIpOpt_t * ip_qualifiers,\r
-                  NETCP_CFG_ROUTE_HANDLE_T  route,  //NULL for default\r
-                  int * err\r
-                  )\r
-{\r
-       return netcp_cfgAddIpInternal(\r
-               h, iface_no, ipType, ip_addr, ip_qualifiers, route, err, \r
-                1);\r
-}\r
-\r
-/*****************************************************************/\r
-/***************Delete an attached IP*****************************/\r
-/*****************************************************************/\r
-static void netcp_cfgDelIpInternal(NETAPI_T h, int iface_no,  nwal_IpType ipType,\r
-                  nwalIpAddr_t  * ip_addr,\r
-                  nwalIpOpt_t * ip_qualifiers, \r
-                  NETCP_CFG_IP_T  ip_rule_id,\r
-                  int *err, \r
-                  void * handle,   /* if flag==0, handle must be valid */\r
-                  int flag)        /* flag==0 => delete IP rule that was part of classifier, not interface */\r
-{\r
-    nwal_RetValue ret;\r
-    NetapiNwalTransInfo_t *pTransInfo;\r
-    nwal_TransID_t     trans_id;\r
-    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-    void * ifHandle;\r
-    int ip_slot = (ip_rule_id>>8)&0xff;\r
-\r
-    //get the nwal handle assoicated with this ip   \r
-    if (flag)\r
-    {\r
-       ifHandle = netcp_cfgp_get_ip_handle(\r
-                 &netapi_get_global()->nwal_context, iface_no,\r
-                 ip_slot );\r
-    }\r
-    else \r
-    {\r
-       ifHandle = handle;\r
-    }\r
-    if(!ifHandle)\r
-            {*err = NETAPI_ERR_BAD_INPUT; return ;}\r
-    *err =0;\r
-\r
-    //get a transaction id\r
-    pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-    if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}\r
-    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;\r
-    pTransInfo->netapi_handle = h;\r
-    //issue request\r
-    ret = nwal_delIPAddr(\r
-                ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                trans_id,\r
-                ifHandle);\r
-    if(ret !=  nwal_OK)\r
-    {\r
-        *err = NETAPI_ERR_NWAL_ERR0;\r
-        printf (">netcp cfg - ERROR: nwal_delMacIface returned Error Code %d\n",\r
-                    ret);\r
-        pTransInfo->inUse = nwal_FALSE;\r
-        return ;\r
-    }\r
-    //wait here until its done since scheduler isn't running yet most likely..\r
-    // todo:  make this handled by scheduler poll later ??\r
-    if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-       n->nwal_local.numPendingCfg++;\r
-        while ((volatile) n->nwal_local.numPendingCfg)\r
-        {\r
-            // if response is there, then this poll squirts out in the CTl poll callback, \r
-            // which handles the rest (including decrmenting #pending!!\r
-            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-        }\r
-    }\r
-    if (flag)\r
-       printf (">netcp cfg: attached IP deleted\n");\r
-    else\r
-       printf (">netcp cfg: Classifier IP rule deleted\n");\r
-    pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-    pTransInfo->inUse = nwal_FALSE;\r
-\r
-    //zap the entry\r
-    if (flag)\r
-       netcp_cfgp_delete_ip(&netapi_get_global()->nwal_context,  \r
-                         iface_no,\r
-                         ip_slot);\r
-    return ;\r
-}\r
-\r
-/*****************************************************************/\r
-/***************Delete an attached IP*****************************/\r
-/*****************************************************************/\r
-void netcp_cfgDelIp(NETAPI_T h, int iface_no,  nwal_IpType ipType,\r
-                  nwalIpAddr_t  * ip_addr,\r
-                  nwalIpOpt_t * ip_qualifiers,\r
-                  NETCP_CFG_IP_T  ip_rule_id,\r
-                  int *err)\r
-{\r
-       netcp_cfgDelIpInternal( h, iface_no, ipType,\r
-                  ip_addr, ip_qualifiers, ip_rule_id,\r
-                  err, NULL, 1);\r
-       return;\r
-}\r
-\r
-\r
-/**\r
- * @def netcp_cfgAddClass\r
- * @brief  add a classifier rule into NETCP\r
- **/\r
-NETCP_CFG_CLASS_T netcp_cfgAddClass(NETAPI_T h,\r
-                                      NETCP_CFG_CLASSIFIER_T *p_class,\r
-                                      NETCP_CFG_ROUTE_HANDLE_T route,\r
-                                      int action, int * err)\r
-{\r
-NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-void * l3_handle=NULL;  //ip handle\r
-nwal_RetValue       retValue;\r
-NetapiNwalTransInfo_t *pTransInfo;\r
-nwal_TransID_t     trans_id;\r
-int class_slot=-1;\r
-int iface_no;\r
-int ip_slot=-1;\r
-NETCP_CFG_CLASS_T  classHandle;  //returned by us\r
-nwal_appProtoType_t proto;\r
-nwalLocConnCfg_t tempCfg={\r
-0,  //nwal_handle: to be filled in\r
-{0}, // l4 ports: to be filled in\r
-0,  //core id (NA)\r
-0, //action\r
-CPPI_PARAM_NOT_SPECIFIED, //flow id\r
-QMSS_PARAM_NOT_SPECIFIED, //dest queue\r
-};\r
-\r
-if(!p_class) { *err=NETAPI_ERR_BAD_INPUT; return -1;}\r
-switch(p_class->classType)\r
-{\r
-default:\r
-       printf(">netcp_cfg : classifier type %d not supported\n",p_class->classType);\r
-       break;\r
-case(NETCP_CFG_CLASS_TYPE_L3_L4):\r
-case(NETCP_CFG_CLASS_TYPE_L4):\r
-       //assume just type l4 only (L2, L3 defined by iface, l3 id )\r
-        iface_no = p_class->u.c_l4.iface;\r
-        if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)\r
-        { \r
-               ip_slot = (p_class->u.c_l4.ip>>8)&0xff;\r
-       }\r
-\r
-         //verify that iface has been configured \r
-        if (iface_no != NETCP_CFG_NO_INTERFACE)\r
-        {\r
-        if(!netapi_get_global()->nwal_context.interfaces[iface_no].in_use)\r
-       {\r
-               *err = NETAPI_ERR_BAD_INPUT;\r
-               return -1;\r
-       }\r
-        }\r
-\r
-        if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)\r
-        {\r
-                    //verify that ip has been configured and get its handle\r
-             l3_handle = netcp_cfgp_get_ip_handle(\r
-                          &netapi_get_global()->nwal_context, iface_no,\r
-                          ip_slot );\r
-        }\r
-        else\r
-        {\r
-            nwalIpParam_t tempParam={\r
-    pa_IPV4,      /* IP Type */\r
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */\r
-    { 0x0,0,0,0},/* IP Options */\r
-    NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */\r
-    NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */\r
-    CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */\r
-    QMSS_PARAM_NOT_SPECIFIED                     /* Use default queue configured to NWAL if packet is routed to host */\r
-       };\r
-               //build nwalIpParam\r
-               memcpy(&tempParam.locIpAddr,p_class->u.c_l3_l4.ip_addr, sizeof(nwalIpAddr_t));\r
-               tempParam.ipType=p_class->u.c_l3_l4.ipType;\r
-            //use nwal defauls for route\r
-           if (p_class->u.c_l3_l4.ip_qualifiers)\r
-                       memcpy(&tempParam.ipOpt,p_class->u.c_l3_l4.ip_qualifiers, sizeof(nwalIpOpt_t));\r
-            else\r
-                       memset(&tempParam.ipOpt,0, sizeof(nwalIpOpt_t));\r
-\r
-\r
-            //find if we have a matching L3 handle for IP classifier; if not create it\r
-             retValue =  nwal_getIPAddr (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                                &tempParam,\r
-                                netcp_cfgp_get_mac_handle(&netapi_get_global()->nwal_context, iface_no ),\r
-                                &l3_handle); \r
-             if (retValue != nwal_TRUE) \r
-             {\r
-                int ret;\r
-                //**NEW IP RULE  \r
-               //need to attach this IP RULE to the MAC\r
-               l3_handle= (void *) netcp_cfgAddIpInternal(\r
-                  h, iface_no, \r
-                  p_class->u.c_l3_l4.ipType,\r
-                  p_class->u.c_l3_l4.ip_addr,\r
-                  p_class->u.c_l3_l4.ip_qualifiers,\r
-                 p_class->u.c_l3_l4.p_fail_route,\r
-                 &ret,\r
-                  FALSE);\r
-                if(!ret)\r
-                 {\r
-                       l3_handle=NULL;\r
-                 }\r
-             }\r
-        }         \r
-        if(!l3_handle)\r
-            {*err = NETAPI_ERR_BAD_INPUT; return -1 ;}\r
-\r
-\r
-        //find free slot for CLASS & reserve\r
-        class_slot= netcp_cfgp_find_class_slot(&netapi_get_global()->nwal_context);\r
-        if(class_slot<0) {*err = NETAPI_ERR_NOMEM; return -1;}\r
-        classHandle = NETAPI_NETCP_MATCH_CLASS | (class_slot<<8) | (iface_no&0xff);\r
-        //build request from template\r
-        tempCfg.inHandle=l3_handle;\r
-        if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)\r
-        { \r
-               memcpy(&tempCfg.appProto,&p_class->u.c_l4.appProto,sizeof(nwalAppProto_t));\r
-               proto = p_class->u.c_l4.proto;\r
-        }\r
-        else\r
-       {\r
-               memcpy(&tempCfg.appProto,&p_class->u.c_l3_l4.appProto,sizeof(nwalAppProto_t));\r
-               proto = p_class->u.c_l3_l4.proto;\r
-       }\r
-        \r
-        tempCfg.matchAction = (action==NETCP_CFG_ACTION_TO_SW)  ? NWAL_MATCH_ACTION_HOST : NWAL_MATCH_ACTION_DISCARD;\r
-       if (route)\r
-        {\r
-               netcp_cfgp_build_route(route,&tempCfg.appRxPktFlowId, &tempCfg.appRxPktQueue);\r
-       }\r
-\r
-        //get a transaction id\r
-        pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-        if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return -1 ;}\r
-        pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP; /* todo: fix this to TRANS_L4*/\r
-        pTransInfo->netapi_handle = h;\r
-        //issue request\r
-        retValue = nwal_addConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                            trans_id,\r
-                           (nwal_AppId) classHandle,\r
-                            proto,\r
-                            &tempCfg,\r
-                            NULL,\r
-                            &pTransInfo->handle);\r
-        if(retValue !=  nwal_OK)\r
-        {\r
-            *err = NETAPI_ERR_NWAL_ERR0;\r
-            printf (">netcp cfg - ERROR: nwal_addConn returned Error Code %d\n",\r
-                    retValue);\r
-            pTransInfo->inUse = nwal_FALSE;\r
-            netcp_cfgp_delete_class(&netapi_get_global()->nwal_context, class_slot);\r
-            return -1;\r
-        }\r
-        //wait here until its done since scheduler isn't running yet most likely..\r
-        // todo:  make this handled by scheduler poll later ??\r
-        if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-        {\r
-             n->nwal_local.numPendingCfg++;\r
-             while ((volatile) n->nwal_local.numPendingCfg)\r
-             {\r
-                // if response is there, then this poll squirts out in the CTl poll callback, \r
-                // which handles the rest (including decrmenting #pending!!\r
-                nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-             }\r
-         }\r
-         printf (">netcp cfg: L4 Classifer added to interface %d ip %d (slot%d)\n", iface_no, ip_slot, class_slot);\r
-         netcp_cfgp_insert_class(&netapi_get_global()->nwal_context, \r
-                                   class_slot,\r
-                                 p_class->classType, \r
-                                 NULL,  //L2 we have\r
-                                 (p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4? l3_handle : NULL),\r
-                                  pTransInfo->handle);\r
-         pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-         return classHandle;\r
-} //end switch\r
-return -1;\r
-}\r
-\r
-//delete classifier\r
-void netcp_cfgDelClass(NETAPI_T h,\r
-                         NETCP_CFG_CLASS_T classId,\r
-                         int *err)\r
-{\r
-NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;\r
-void * L4_handle;  //class handle -> L4\r
-void * L3_handle;  //class handle -> L3\r
-nwal_RetValue       retValue;\r
-NetapiNwalTransInfo_t *pTransInfo;\r
-nwal_TransID_t     trans_id;\r
-int class_slot=-1;\r
-//int iface;\r
-//int ip_slot;\r
-\r
-       class_slot = (classId>>8)&0xffff;\r
-        L4_handle=netcp_cfgp_get_l4_handle(\r
-                       &netapi_get_global()->nwal_context,\r
-                       class_slot );\r
-        if(!L4_handle)  {*err = NETAPI_ERR_BAD_INPUT; return ;}\r
-        L3_handle = netcp_cfgp_get_l3_handle(\r
-                        &netapi_get_global()->nwal_context,\r
-                        class_slot );\r
-        /* l3 handle might be NULL,, depending on type of classifier */\r
-\r
-       netcp_cfgp_delete_class(\r
-                        &netapi_get_global()->nwal_context,\r
-                        class_slot );\r
-        //get a transaction id\r
-        pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);\r
-        if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return  ;}\r
-        pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;\r
-        pTransInfo->netapi_handle = h;\r
-        //issue request for L4\r
-        retValue = nwal_delConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,\r
-                            trans_id,\r
-                            L4_handle);\r
-        if(retValue !=  nwal_OK)\r
-        {\r
-            *err = NETAPI_ERR_NWAL_ERR0;\r
-            printf (">netcp cfg - ERROR: nwal_delConn returned Error Code %d\n",\r
-                    retValue);\r
-            pTransInfo->inUse = nwal_FALSE;\r
-            return ;  /* todo: what about the L3? */\r
-        }\r
-        //wait here until its done since scheduler isn't running yet most likely..\r
-        // todo:  make this handled by scheduler poll later ??\r
-        if(trans_id != NWAL_TRANSID_SPIN_WAIT)\r
-        {\r
-             n->nwal_local.numPendingCfg++;\r
-             while ((volatile) n->nwal_local.numPendingCfg)\r
-             {\r
-                // if response is there, then this poll squirts out in the CTl poll callback, \r
-                // which handles the rest (including decrmenting #pending!!\r
-                nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);\r
-             }\r
-         }\r
-         printf (">netcp cfg: Classifer deleted\n");\r
-         pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-         pTransInfo->inUse = nwal_FALSE;\r
-\r
-         /* delete L3 if we have to */\r
-         if (L3_handle)\r
-         {\r
-             netcp_cfgDelIpInternal( h, 0, 0,\r
-                  NULL, NULL, 0,\r
-                  err, L3_handle,  0);\r
-         }\r
-         return ;\r
-}\r
-\r
-\r
-/*--------------flow management--------*/\r
-// ADD A Flow\r
-NETCP_CFG_FLOW_HANDLE_T netcp_cfgAddFlow(NETAPI_T h,\r
-                                            int n,\r
-                                            Pktlib_HeapHandle handles[],\r
-                                            int sizes[],\r
-                                            int byte_offset,\r
-                                            int * err )\r
-{\r
-  Cppi_RxFlowCfg  rxFlowCfg;\r
-  Uint8           isAlloc;\r
-  Qmss_QueueHnd   rxBufQ[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];\r
-  Uint32          rxBufSize[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];\r
-  int             i;\r
-  Cppi_FlowHnd FlowHnd;\r
-  int  slot;\r
-  NETCP_CFG_FLOW_HANDLE_T retVal;\r
-\r
-  *err= 0;  /* ok */\r
-  //get a slot to save new flow\r
-  slot = netcp_cfgp_find_flow_slot(&netapi_get_global()->nwal_context);\r
-  if (slot<0) { *err= NETAPI_ERR_NOMEM;  return NULL; }\r
-\r
-  //configure flow\r
-  memset(&rxFlowCfg,0,sizeof(Cppi_RxFlowCfg));\r
-  for (i = 0; i < TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW; i++)\r
-  {\r
-      if (i >= n)\r
-      {\r
-          rxBufQ[i] = 0;\r
-          rxBufSize[i] = 0;\r
-      } else\r
-      {\r
-          rxBufQ[i] =   Pktlib_getInternalHeapQueue(handles[i]);\r
-          //todo: verity sizes< heapsize\r
-         //todo: verify order\r
-          rxBufSize[i]= sizes[i];\r
-      }\r
-      if (i && (rxBufQ[i] <= 0))\r
-      {\r
-          rxBufQ[i] = rxBufQ[i-1];\r
-          rxBufSize[i] = 0;\r
-      }\r
-  }\r
-  /* Configure Rx flow */\r
-  rxFlowCfg.flowIdNum      = CPPI_PARAM_NOT_SPECIFIED;\r
-  rxFlowCfg.rx_dest_qnum   = 100;   //DANGEROUS>  TODO PUT VALID Q HERE\r
-  rxFlowCfg.rx_dest_qmgr   = 0;\r
-  rxFlowCfg.rx_sop_offset  = byte_offset;\r
-  rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;\r
-  rxFlowCfg.rx_desc_type   = Cppi_DescType_HOST;\r
-  rxFlowCfg.rx_error_handling = 0;\r
-\r
-  rxFlowCfg.rx_psinfo_present = 1;\r
-  rxFlowCfg.rx_einfo_present  = 1;\r
-\r
-  rxFlowCfg.rx_dest_tag_lo = 0;\r
-  rxFlowCfg.rx_dest_tag_hi = 0;\r
-  rxFlowCfg.rx_src_tag_lo  = 0;\r
-  rxFlowCfg.rx_src_tag_hi  = 0;\r
-\r
-  rxFlowCfg.rx_size_thresh0_en = rxBufSize[1] ? 1 : 0;\r
-  rxFlowCfg.rx_size_thresh1_en = rxBufSize[2] ? 1 : 0;\r
-  rxFlowCfg.rx_size_thresh2_en = rxBufSize[3] ? 1 : 0;\r
-\r
-  rxFlowCfg.rx_dest_tag_lo_sel = 0;\r
-  rxFlowCfg.rx_dest_tag_hi_sel = 0;\r
-  rxFlowCfg.rx_src_tag_lo_sel  = 0;\r
-  rxFlowCfg.rx_src_tag_hi_sel  = 0;\r
-\r
-  rxFlowCfg.rx_fdq1_qnum = rxBufQ[1];\r
-  rxFlowCfg.rx_fdq1_qmgr = 0;\r
-  rxFlowCfg.rx_fdq2_qnum = rxBufQ[2];\r
-\r
-  rxFlowCfg.rx_fdq2_qmgr = 0;\r
-  rxFlowCfg.rx_fdq3_qnum = rxBufQ[3];\r
-\r
-  rxFlowCfg.rx_fdq3_qmgr = 0;\r
-\r
-  rxFlowCfg.rx_size_thresh0 = rxBufSize[1] ? rxBufSize[0] : 0;\r
-  rxFlowCfg.rx_size_thresh1 = rxBufSize[2] ? rxBufSize[1] : 0;\r
-  rxFlowCfg.rx_size_thresh2 = rxBufSize[3] ? rxBufSize[2] : 0;\r
-\r
-  rxFlowCfg.rx_fdq0_sz0_qnum = rxBufQ[0];\r
-  rxFlowCfg.rx_fdq0_sz0_qmgr = 0;\r
-  rxFlowCfg.rx_fdq0_sz1_qnum = rxBufQ[1];\r
-  rxFlowCfg.rx_fdq0_sz1_qmgr = 0;\r
-  rxFlowCfg.rx_fdq0_sz2_qnum = rxBufQ[2];\r
-  rxFlowCfg.rx_fdq0_sz2_qmgr = 0;\r
-  rxFlowCfg.rx_fdq0_sz3_qnum = rxBufQ[3];\r
-  rxFlowCfg.rx_fdq0_sz3_qmgr = 0;\r
-\r
- {\r
-  //todo: replace this with a nwal call to get global cntx info\r
-  Cppi_CpDmaInitCfg cpdmaCfg;\r
-  memset(&cpdmaCfg,0,sizeof(Cppi_CpDmaInitCfg));\r
-  cpdmaCfg.dmaNum   = Cppi_CpDma_PASS_CPDMA;\r
-  FlowHnd =\r
-      Cppi_configureRxFlow (Cppi_open (&cpdmaCfg), &rxFlowCfg, &isAlloc);\r
-}\r
-  if (FlowHnd == NULL)\r
-  {\r
-      *err= NETAPI_ERR_NORES;\r
-      netcp_cfgp_delete_flow(&netapi_get_global()->nwal_context, slot);\r
-      return (NULL);\r
-  }\r
-\r
-  //update slot\r
-  retVal = netcp_cfgp_insert_flow(&netapi_get_global()->nwal_context, slot, (void*) FlowHnd);\r
-  printf(">netcp cfg:  flow %d created\n",  ((NETCP_CFG_FLOW_T *) retVal)->flowid);\r
-  return ( retVal);\r
-\r
-\r
-\r
-}\r
-\r
-//Delete a flow\r
-void netcp_cfgDelFlow(NETAPI_T h , NETCP_CFG_FLOW_HANDLE_T f , int * err)\r
-{\r
-       int slot;\r
-       void * handle;\r
-       *err=0;\r
-        /* find entry */\r
-        slot = netcp_cfgp_find_flow(&netapi_get_global()->nwal_context, ((NETCP_CFG_FLOW_T *) f) ->flowid, &handle);\r
-       if (slot<0) {*err = NETAPI_ERR_BAD_INPUT; return;}\r
-\r
-       Cppi_closeRxFlow( (Cppi_FlowHnd) handle);\r
-        netcp_cfgp_delete_flow(&netapi_get_global()->nwal_context, slot);\r
-        printf(">netcp cfg:  flow %d deleted\n",  ((NETCP_CFG_FLOW_T *) f)->flowid);\r
-        return;\r
-}\r
-\r
-\r
-/*************************************************************************/\r
-/*********************************INTERNAL*******************************/\r
-/************************************************************************/\r
-\r
-/***************************************************************\r
- ********************METCP CMD Reply Callback******************\r
- ***************************************************************/\r
-void netapi_NWALCmdCallBack (nwal_AppId        appHandle,\r
-                          uint16_t            trans_id,\r
-                          nwal_RetValue     ret)\r
-{\r
-    NetapiNwalTransInfo_t * p_trans;\r
-    NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;\r
-\r
-    if(trans_id == NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-        netapi_get_global()->nwal_context.numBogusTransIds++;\r
-        return;\r
-    }\r
-\r
-    p_trans= &netapi_get_global()->nwal_context.transInfos[trans_id];\r
-    p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;\r
-\r
-    if(ret != nwal_OK)\r
-    {\r
-        printf (">netcp cfg : NWALCmdCallBack returned Error Code %d\n",\r
-                    ret);\r
-       //todo: atomic inc\r
-        netapi_get_global()->nwal_context.numCmdFail++;\r
-    }\r
-    else\r
-    {\r
-       //todo: atomic inc\r
-        netapi_get_global()->nwal_context.numCmdPass++;\r
-        switch(p_trans->transType)\r
-        {\r
-            case NETAPI_NWAL_HANDLE_TRANS_MAC:\r
-            {\r
-                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;\r
-                }\r
-                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-                }\r
-                break;\r
-            }\r
-            case NETAPI_NWAL_HANDLE_TRANS_IP:\r
-            {\r
-                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;\r
-                }\r
-                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-                }\r
-                break;\r
-            }\r
-            case NETAPI_NWAL_HANDLE_TRANS_PORT:\r
-            {\r
-                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;\r
-                }\r
-                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-                }\r
-                break;\r
-            }\r
-            case NETAPI_NWAL_HANDLE_TRANS_SA:\r
-            {\r
-                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;\r
-                }\r
-                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-                }\r
-                break;\r
-            }\r
-           case NETAPI_NWAL_HANDLE_TRANS_SA_POLICY:\r
-            {\r
-                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;\r
-                }\r
-                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)\r
-                {\r
-                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;\r
-                }\r
-                break;\r
-            }\r
-            default:\r
-            {\r
-                printf ("netcp cfg> Invalid transaction type %d for trans_id: %d\n",\r
-                    p_trans->transType,trans_id);\r
-                break;\r
-            }\r
-        }\r
-    }\r
-\r
-    p_local->numPendingCfg--;\r
-\r
-    if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_IDLE)\r
-    {\r
-        p_trans->inUse = nwal_FALSE;\r
-    }\r
-\r
-}\r
-\r
-\r
-/*******************************************************/\r
-/**************stats reply callback**********************/\r
-/*******************************************************/\r
-void netapi_NWALCmdPaStatsReply (nwal_AppId        appHandle,\r
-                              nwal_TransID_t    trans_id,\r
-                              paSysStats_t      *stats)\r
-{\r
-    NetapiNwalTransInfo_t * p_trans;\r
-    NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;\r
-  \r
-    if(trans_id == NWAL_TRANSID_SPIN_WAIT)\r
-    {\r
-        netapi_get_global()->nwal_context.numBogusTransIds++;\r
-        return;\r
-    }\r
-\r
-    p_trans= &netapi_get_global()->nwal_context.transInfos[trans_id];\r
-    p_trans->inUse = nwal_FALSE;\r
-    p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;\r
-\r
-    //save a local copy  of some stuff*/\r
-    p_local->numL2PktsRecvd=stats->classify1.nPackets;\r
-    p_local->numL3PktsRecvd=stats->classify1.nIpv4Packets;\r
-#if 0\r
-    p_local->numL4PktsRecvd=stats->;\r
-    p_local->numL4PktsSent=stats->;\r
-    p_local->TxErrDrop=stats->;\r
-#endif\r
-    //callout result to application !!\r
-    if (p_local->stats_cb) (*p_local->stats_cb)(p_trans->netapi_handle,stats);\r
-    \r
-} \r
-\r
+/**********************************************************
+ * file: netcp_cfg.c
+ * purpose: netcp configurations routines
+ **************************************************************
+ * FILE: netcp_cfg.c
+ * 
+ * DESCRIPTION:  netcp configuration main source file for user space transport
+ *               library
+ * 
+ * REVISION HISTORY:
+ *
+ *  Copyright (c) Texas Instruments Incorporated 2013
+ * 
+ *  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"
+
+extern NETAPI_SHM_T* pnetapiShm;
+
+/******************************************************************
+ ********************Netapi internal*************************************
+*******************************************************************/
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get a free transaction id
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to get a free transaction id.
+ ********************************************************************/
+NetapiNwalTransInfo_t * netapip_getFreeTransInfo(NETAPI_HANDLE_T *p_handle,
+                                                 NETAPI_PROC_GLOBAL_T *p_proc_global,
+                                                 nwal_TransID_t *pTransId)
+{
+    uint16_t    count=0;
+
+    count=0;
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    while(count < TUNE_NETAPI_MAX_NUM_TRANS)
+    {
+        if((p_proc_global->nwal_context.transInfos[count].inUse) != nwal_TRUE)
+        {
+            p_proc_global->nwal_context.transInfos[count].inUse = nwal_TRUE;
+            *pTransId = count;
+            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return(&p_proc_global->nwal_context.transInfos[count]);
+        }
+        count++;
+    }
+    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    /* trouble.  need to wait for one to free up*/
+    /* to do: handle this by forcing a poll of cntrl queue*/
+    netapi_Log(">netcp_cfg: trying to get free transaction slot but all full!!\n");
+    return NULL;
+
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to free a transaction id
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to free a transaction id
+ ********************************************************************/
+void netapip_freeTransInfo(NetapiNwalTransInfo_t *pTransInfo)
+{
+    pTransInfo->inUse = nwal_FALSE;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_NONE;
+}
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to build a route
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to build a route
+ ********************************************************************/
+void netapip_netcpCfgBuildRoute(NETCP_CFG_ROUTE_T * p_route,
+                                int16_t *p_flow,
+                                Qmss_QueueHnd *p_q,
+                                nwalRouteType_t *p_type)
+{
+    if (!p_route) return;
+    if (p_route->p_flow)  *p_flow= p_route->p_flow->flowid;
+    else *p_flow = CPPI_PARAM_NOT_SPECIFIED;
+
+    if (p_route->p_dest_q) *p_q = netapi_pktioGetQ(p_route->p_dest_q);
+    else *p_q=QMSS_PARAM_NOT_SPECIFIED;
+
+    *p_type = p_route->routeType;
+}
+
+
+/******************************************************/
+/*----------------database management stuff           */
+/******************************************************/
+
+/*=====================POLICIES=============================*/
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a free slot for an SA
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to find a free slot for an SA
+ ********************************************************************/
+int netapip_netcpCfgFindPolicySlot(NETAPI_HANDLE_T *p_handle,
+                                   NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                   int tunnel)
+{
+    int i;
+    if ((tunnel <0 ) || (tunnel >=TUNE_NETAPI_MAX_SA))
+        return -1;
+
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    //find a free entry
+    for(i=0;i<TUNE_NETAPI_MAX_POLICY;i++)
+    {
+        if (!p->policy[i].in_use)
+        {
+            p->policy[i].in_use = 2; //pending
+            p->policy[i].tunnel= tunnel; //save tunnel this is linked to
+            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return i;
+        }
+    }
+    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    return -1;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to delete a policy from policy list
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to delete a policy from policy list
+ ********************************************************************/
+void netapip_netcpCfgDeletePolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                  int policy_slot)
+{
+    if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
+    {
+        return ;
+    }
+    p->policy[policy_slot].in_use=0;
+    return;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to insert a policy to the policy list
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to insert a policy to the policy list
+ ********************************************************************/
+void netapip_netcpCfgInsertPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                  int policy_slot,
+                                  void * handle,
+                                  void * user_data)
+{
+    p->policy[policy_slot].in_use=1;
+    p->policy[policy_slot].nwal_handle = handle;
+    p->policy[policy_slot].user_data = user_data;
+    return;
+}
+
+/************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function which returns NWAL handle for a policy
+ ************************************************************************
+ * DESCRIPTION:  Netapi internal function which returns NWAL handle for a policy
+ ************************************************************************/
+void *netapip_netcpCfgGetPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                int policy_slot)
+{
+    if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
+        return NULL;
+    if (!p->policy[policy_slot].in_use)
+        return NULL;
+    return p->policy[policy_slot].nwal_handle;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a free slot in SA list for a SA
+ ********************************************************************
+ * DESCRIPTION:  Netapi internal function to find a free slot in SA list for an SA
+ ********************************************************************/
+int netapip_netcpCfgFindSaSlot(NETAPI_HANDLE_T *p_handle,
+                               NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                               int iface)
+{                                    
+   int i;
+   if (iface != NETCP_CFG_NO_INTERFACE)
+   {
+   if ((iface <0 ) || (iface >=TUNE_NETAPI_MAX_NUM_MAC)) return -1;
+   }
+   p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+   //find a free entry
+   for(i=0;i<TUNE_NETAPI_MAX_SA;i++)
+   {                       
+       if (!p->tunnel[i].in_use)
+       {
+           p->tunnel[i].in_use = 2; //pending
+           p->tunnel[i].iface= iface; //save iface
+           p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+           return i;
+       }
+   }
+   p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+   return -1;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to delete an SA from SA list
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to delete an SA from SA list 
+ ********************************************************************/
+void netapip_netcpCfgDeleteSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                              int sa_slot)
+{
+    if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
+    {
+        return ;
+    }
+    p->tunnel[sa_slot].in_use=0;
+    return;
+}
+
+
+/****************************************************************************
+ * FUNCTION PURPOSE:  Internal function to retrieve SB command info template
+ **************************************************************************
+ * DESCRIPTION:  Internal function to retrieve SB command info template
+ ***************************************************************************/
+nwalTxDmPSCmdInfo_t* netapip_netcpCfgGetSaSBInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                                 NETCP_CFG_SA_T    sa_app_id)
+{
+     int sa_slot = netapi_cfgGetMatchId(sa_app_id);
+    if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
+    {
+        return NULL;
+    }
+    return (&p->tunnel[sa_slot].dmPSCmdInfo);
+}
+
+/****************************************************************************
+ * FUNCTION PURPOSE:  Internal function to retrieve Inflow mode 
+ *                    software information required to transmit packet
+ **************************************************************************
+ * DESCRIPTION:  Internal function to retrieve Inflow mode 
+ *                    software information required to transmit packet
+ ***************************************************************************/
+int netapip_netcpCfgGetSaInflowInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                    NETCP_CFG_SA_T    sa_app_id,
+                                    uint32_t *swInfo0,
+                                    uint32_t *swInfo1)
+{
+    int sa_slot = netapi_cfgGetMatchId(sa_app_id);
+    if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
+    {
+        return 0;
+    }
+    *swInfo0 = p->tunnel[sa_slot].swInfo0;
+    *swInfo1 = p->tunnel[sa_slot].swInfo1;
+    return 1;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to insert an SA to the SA list
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to insert an SA to the SA list 
+ ********************************************************************/
+void netapip_netcpCfgInsertSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                              int sa_slot,
+                              int dir,
+                              int mode,
+                              void * temp1,
+                              void * temp2,
+                              void * handle_inflow,
+                              void * handle_sideband,
+                              nwalTxDmPSCmdInfo_t *dmPSCmdInfo,
+                              uint32_t swInfo0,
+                              uint32_t swInfo1,
+                              void* user_data)
+{
+    p->tunnel[sa_slot].in_use=1;
+    p->tunnel[sa_slot].inbound = dir;
+    p->tunnel[sa_slot].sa_mode = mode;
+    p->tunnel[sa_slot].sa_handle_inflow = handle_inflow;
+    p->tunnel[sa_slot].sa_handle_sideband = handle_sideband;
+    p->tunnel[sa_slot].swInfo0 = swInfo0;
+    p->tunnel[sa_slot].swInfo1 = swInfo1;
+    p->tunnel[sa_slot].user_data = user_data;
+    //netapi_Log("netapip_netcpCfgInsertSa: swInfo0 0x%x, swInfo1: 0x%x, user data: %d\n",
+//        p->tunnel[sa_slot].swInfo0, p->tunnel[sa_slot].swInfo1, (uint32_t)p->tunnel[sa_slot].user_data);
+
+    if (dmPSCmdInfo)
+    {
+        memcpy(&p->tunnel[sa_slot].dmPSCmdInfo, dmPSCmdInfo, sizeof(nwalTxDmPSCmdInfo_t));
+    }
+    return;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to return NWAL handles for an SA
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to return NWAL handles for an SA
+ ********************************************************************/
+ void *netapip_netcpCfgGetSaHandles(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                    int sa_slot,
+                                    void ** p_sideband)
+{
+    if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
+        return NULL;
+    if (!p->tunnel[sa_slot].in_use)
+        return NULL;
+    *p_sideband = p->tunnel[sa_slot].sa_handle_sideband;
+    return p->tunnel[sa_slot].sa_handle_inflow;
+}
+
+
+/*==============================FLOWS=============================*/
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a free slot for a flow
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to find a free slot for a flow
+ ********************************************************************/
+static int netapip_netcpCfgFindFlowSlot(NETAPI_HANDLE_T *p_handle,
+                                        NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
+{
+    int i;
+    //find a free entry
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
+    {
+        if (!p->flows[i].in_use)
+        {
+            p->flows[i].in_use = 2; /* pending */
+            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return i;
+        }
+    }
+   p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    return -1;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find delete a flow from flow list
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to find delete a flow from flow list
+ ********************************************************************/
+static void netapip_netcpCfgDeleteFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                       int slot)
+{
+    if ((slot >=0 ) && (slot < TUNE_NETAPI_MAX_FLOWS))
+    {
+        p->flows[slot].in_use = 0;
+    }
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to  insert a flow to the  flow list
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to  delete a flow from flow list
+ ********************************************************************/
+static NETCP_CFG_FLOW_HANDLE_T netapip_netcpCfgInsertFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                                          int slot,
+                                                          int dma_engine,
+                                                          void * handle)
+{
+    p->flows[slot].in_use=1;
+    p->flows[slot].handle = handle;
+    p->flows[slot].flow.flowid  = Cppi_getFlowId(handle);
+    p->flows[slot].flow.dma_engine  = dma_engine;
+        return (NETCP_CFG_FLOW_HANDLE_T) &p->flows[slot].flow;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find entry matching the flowid
+ ********************************************************************
+ * DESCRIPTION: Netapi internal function to find entry matching the flowid. Returns
+ * the slot number and the cPPI handle.
+ ********************************************************************/
+static int netapip_netcpCfgFindFlow(NETAPI_HANDLE_T *p_handle,
+                                    NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                    int flowid,  
+                                    int dma_engine,
+                                    void ** handle) 
+{
+    int i;
+    *handle=NULL;
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
+    {
+       if ((p->flows[i].in_use)&&
+           (p->flows[i].flow.flowid == flowid)&&
+           (p->flows[i].flow.dma_engine == dma_engine))
+        {
+            *handle = p->flows[i].handle;
+             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return i;
+        }
+    }
+    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    return -1;
+}
+
+
+
+/*============================IP ADDRESSES==========================*/
+
+/***************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a free slot for IP rule in IP slot list
+ ***************************************************************************
+ * DESCRIPTION: NNetapi internal function to find a free slot for IP rule in IP slot list
+ ***************************************************************************/
+static int netapip_netcpCfgFindIpSlot(NETAPI_HANDLE_T *p_handle,
+                                      NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                      int iface_no)
+{
+    int i;
+
+    //find a free entry
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    for(i=0;i<TUNE_NETAPI_MAX_NUM_IP;i++)
+    {
+        if (!p->ips[i].in_use)
+        {
+            p->ips[i].in_use = 2; //pending
+            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return i;
+        }
+    }
+    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    return -1;
+}
+
+/***************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to insert an IP address into interface
+ ***************************************************************************
+ * DESCRIPTION: Netapi internal function to insert an IP address into interface
+ ***************************************************************************/
+static void netapip_netcpCfgInsertIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, 
+                                     nwal_IpType ipType,
+                                     nwalIpAddr_t *ip_addr, 
+                                     nwalIpOpt_t *ip_qualifiers, 
+                                     int iface_no,
+                                     int ip_slot,
+                                     void * handle,
+                                     void * user_data)
+{
+    p->ips[ip_slot].in_use=1;
+    memcpy(&p->ips[ip_slot].ip_addr, ip_addr, sizeof(nwalIpAddr_t));
+    if(ip_qualifiers)
+    {
+        memcpy(&p->ips[ip_slot].ip_qualifiers, ip_qualifiers, sizeof(nwalIpOpt_t));
+    }
+    else
+    {
+        memset(&p->ips[ip_slot].ip_qualifiers, 0, sizeof(nwalIpOpt_t));
+    }
+    p->ips[ip_slot].ip_type = ipType;
+    p->ips[ip_slot].nwal_handle = handle;
+    p->ips[ip_slot].user_data = user_data;
+}
+
+/***************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to free IP slot associated with IP address
+ ***************************************************************************
+ * DESCRIPTION: Netapi internal function to free IP slot associated with IP address
+ ***************************************************************************/
+static void netapip_netcpCfgDeleteIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                     int iface_no,
+                                     int ip_slot)
+{
+    if ((ip_slot >=0) &&(ip_slot < TUNE_NETAPI_MAX_NUM_IP))
+    {
+        p->ips[ip_slot].in_use=0;
+    }
+}
+
+/***************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get IP handle associated with IP address
+ ***************************************************************************
+ * DESCRIPTION: Netapi internal function to get IP handle associated with IP address
+ ***************************************************************************/
+static void *netapip_netcpCfgGetIpHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                         int iface_no,
+                                         int ip_slot)
+{
+    if ((ip_slot <0)||(ip_slot>=TUNE_NETAPI_MAX_NUM_IP))
+        return NULL;
+    if (!p->ips[ip_slot].in_use)
+        return NULL;
+    return (void *) p->ips[ip_slot].nwal_handle;
+}
+
+/*==========================MAC INTERFACES======================*/
+
+
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to insert an interface to the interface list
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to insert an interface to the interface list
+ *******************************************************************************/
+static void netapip_netcpCfgInsertMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                      unsigned char * p_mac,
+                                      int iface_no, 
+                                      int state, NETCP_CFG_VLAN_T vlan, 
+                                      void * handle)
+{
+    if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
+    {
+        memset(&p->interfaces[iface_no],0,sizeof(NETCP_INTERFACE_T));
+        p->interfaces[iface_no].in_use = 1;
+        memcpy(&p->interfaces[iface_no].mac[0], p_mac,6);
+        p->interfaces[iface_no].state = state;
+        //todo p->interfaces[iface_no].vlan = vlan;
+        p->interfaces[iface_no].nwal_handle = handle; //save handle assoicated with this rule
+        netapi_Log("netapip_netcpCfgInsertMac, global context 0x%x\n", p);
+    }
+    else 
+        netapi_Log(">netapip_netcpCfgInsertMac insert interface # out of range %d\n",iface_no);
+
+}
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get handle associated with interface
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to get handle associated with interface
+ *******************************************************************************/
+void* netapip_netcpCfgGetMacHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                   int iface_no)
+{
+    if (iface_no == NETCP_CFG_NO_INTERFACE)
+    {
+        return NULL;
+    }
+    if ((iface_no <0 ) || (iface_no >= TUNE_NETAPI_MAX_NUM_MAC))
+    {
+        return NULL;
+    }
+    else if ( p->interfaces[iface_no].in_use)
+    {
+      return (void *) p->interfaces[iface_no].nwal_handle;
+    }
+    //no valid entry in slot
+    return NULL;
+}
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to delete interface from interface list
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to delete interface from interface list
+ *******************************************************************************/
+static void netapip_netcpCfgDeleteMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                      int iface_no)
+{
+    if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
+    {
+        p->interfaces[iface_no].in_use = 0;
+    }
+}
+
+/*========================CLASSIFIERS==========================*/
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a free slot for classifier rule
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to find a free slot for classifier rule
+ *******************************************************************************/
+static int netapip_netcpCfgFindClassSlot(NETAPI_HANDLE_T *p_handle,
+                                         NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
+{
+    int i;
+    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
+    for(i=0;i<TUNE_NETAPI_MAX_CLASSIFIERS;i++)
+    {
+        if (!p->classi[i].in_use)
+        {
+            p->classi[i].in_use = 2; //pending
+            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+            return i;
+        }
+    }
+    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
+    return -1;
+}
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a delete a classifer from classifer list
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to find a delete a classifer from classifer list
+ *******************************************************************************/
+static void netapip_netcpCfgDeleteClass(
+         NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+         int class_slot )
+{
+    if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
+    {
+        return;
+    }
+    p->classi[class_slot].in_use=0;
+}
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to find a insert a classifer to classifer list
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to find a insert a classifer to classifer list
+ *******************************************************************************/
+static void netapip_netcpCfgInsertClass(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                        int class_slot,
+                                        int class_type,
+                                        void * L2_handle,
+                                        void * L3_handle,
+                                        void * L4_handle,
+                                        void * user_data)
+{
+    if ((class_slot >=0 ) && (class_slot < TUNE_NETAPI_MAX_CLASSIFIERS))
+    {
+        p->classi[class_slot].in_use=1;
+        p->classi[class_slot].nwal_L2_handle = L2_handle;
+        p->classi[class_slot].nwal_L3_handle = L3_handle;
+        p->classi[class_slot].nwal_L4_handle = L4_handle;
+        p->classi[class_slot].class_type = class_type;
+        p->classi[class_slot].user_data = user_data;
+    }
+}
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get L4 nwal handle for classifier
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to get L4 nwal handle for classifier
+ *******************************************************************************/
+static void *netapip_netcpCfgGetL4Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                         int class_slot)
+{
+    if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
+    {
+        return NULL;
+    }
+    if (!p->classi[class_slot].in_use)
+    {
+        return NULL;
+    }
+    return p->classi[class_slot].nwal_L4_handle;
+}
+
+
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get L3 nwal handle for classifier
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to get L3 nwal handle for classifier
+ *******************************************************************************/
+static int cfgOkToDeleteL3ClassiHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                         void*  l3_handle)
+{
+    int i;
+    int count=0;
+
+    if(l3_handle == NULL)
+        return NETAPI_FALSE;
+    for(i=0; i< TUNE_NETAPI_MAX_CLASSIFIERS;i++)
+    {
+        if (!p->classi[i].in_use)
+        {
+            continue;
+        }
+        if (l3_handle == p->classi[i].nwal_L3_handle)
+        {
+            count++;
+        }
+    }
+    if (count > 0)
+        return NETAPI_FALSE;
+
+    return NETAPI_TRUE;
+}
+
+/*******************************************************************************
+ * FUNCTION PURPOSE:  Netapi internal function to get L3 nwal handle for classifier
+ *******************************************************************************
+ * DESCRIPTION:  Netapi internal function to get L3 nwal handle for classifier
+ *******************************************************************************/
+static void *netapip_netcpCfgGetL3Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
+                                         int class_slot)
+{
+    if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
+    {
+        return NULL;
+    }
+    if (!p->classi[class_slot].in_use)
+    {
+        return NULL;
+    }
+    return p->classi[class_slot].nwal_L3_handle;
+}
+
+
+/***********************************************************************************/
+/****************************************API****************************************/
+/***********************************************************************************/
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to request statistics from NETCP
+ ********************************************************************
+ * DESCRIPTION:  API to request statistics from NETCP
+ ********************************************************************/
+void netapi_netcpCfgReqStats(NETAPI_T  h, 
+                             NETCP_CFG_STATS_CB cb,
+                             int doClear,
+                             int *err)
+{
+    nwal_RetValue ret;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     transId;
+
+    paSysStats_t netcp_stats;
+    if ((!n) || (!cb))
+    {
+        *err = NETAPI_ERR_BAD_INPUT;
+        return ;
+    }
+    *err =0;
+
+    pTransInfo = netapip_getFreeTransInfo(n,
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &transId);
+    if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_STAT_REQUEST;
+    pTransInfo->netapi_handle = h;
+    n->nwal_local.stats_cb = cb;
+
+    memset(&netcp_stats, 0, sizeof(paSysStats_t));
+    ret = nwal_getPAStats( ((NETAPI_GLOBAL_T *) n->global)->nwal_context.nwalInstHandle,
+                              transId,
+                              &netcp_stats,
+                              doClear);
+    if(ret !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_BUSY;  //no resources??
+        netapi_Log("> netapi_netcpCfg reqStats failed, err=%d\n",ret);
+        netapip_freeTransInfo(pTransInfo);
+        return;
+    }
+#if defined(DEVICE_K2E) || defined(DEVICE_K2L)
+    if (cb)
+    {
+        cb(h, &netcp_stats);
+    }
+#endif
+    netapip_freeTransInfo(pTransInfo);
+}
+/********************************************************************
+ * FUNCTION PURPOSE:  API to create a MAC interface
+ ********************************************************************
+ * DESCRIPTION:  API to create a MAC interface
+ ********************************************************************/
+NETCP_CFG_MACIF_T  netapi_netcpCfgCreateMacInterface(NETAPI_T  h,
+                                                     uint8_t *p_mac,
+                                                     uint8_t *p_mac_remote,
+                                                     int  iface_no, 
+                                                     int switch_port, 
+                                                     NETCP_CFG_ROUTE_HANDLE_T  route,
+                                                     NETCP_CFG_VLAN_T  vlan,  //future
+                                                     uint16_t etherType,
+                                                     int state,  //0=down, 1=up  //ignored
+                                                     int * err)
+{
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    nwalMacParam_t   macInfo=
+    {
+        0,      /* validParams */
+        0,      /* ifNum */
+        0,      /* vlanId      */
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Local mac */
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Remote mac */
+        NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
+        NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
+        CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
+        QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
+        0,
+        0
+    };
+
+    nwal_RetValue       retValue;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+
+    if ((!n) || (!p_mac)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
+    *err =0;
+
+    pTransInfo = netapip_getFreeTransInfo(n,
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &trans_id);
+    if (!pTransInfo)
+    {
+        *err =  NETAPI_ERR_BUSY;
+        return -1;
+    }
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
+    pTransInfo->inUse = nwal_TRUE;
+    pTransInfo->netapi_handle = h;
+
+    /* set up MacInfo */
+    memcpy(&macInfo.macAddr,p_mac,6);
+    if(p_mac_remote)
+    {
+        macInfo.validParams |=  NWAL_SET_MAC_VALID_PARAM_REMOTE_MAC;
+        memcpy(&macInfo.remMacAddr,p_mac_remote,6);
+    }
+    /* todo: vlan */
+    if (switch_port)
+    {
+        macInfo.validParams |= NWAL_SET_MAC_VALID_PARAM_IFNUM ;
+        macInfo.ifNum = switch_port;
+    }
+
+    if(etherType)
+    {
+        macInfo.validParams |= NWAL_SET_MAC_VALID_PARAM_ETHER_TYPE;
+        macInfo.etherType = etherType;
+    }
+
+    if (route != NULL)
+    {
+        if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
+            NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
+        {
+           macInfo.validParams |= 
+                    NWAL_SET_MAC_VALID_PARAM_ROUTE_TYPE;
+        }
+        netapip_netcpCfgBuildRoute(route,
+                                   &macInfo.appRxPktFlowId,
+                                   &macInfo.appRxPktQueue,
+                                   &macInfo.routeType);
+    }
+    retValue = nwal_setMacIface( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                                  trans_id,
+                                  (nwal_AppId) (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no),
+                                  &macInfo,
+                                  &pTransInfo->handle);
+    if(retValue !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_NWAL_ERR0;
+        netapi_Log ("netapi_netcpCfg - ERROR: nwal_setMacIface returned Error Code %d\n",
+                    retValue);
+        netapip_freeTransInfo(pTransInfo);
+        return -1;
+    }
+
+    //wait here until its done since scheduler isn't running yet most likely..
+    // todo:  make this handled by scheduler poll later ??
+    if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+    {
+        n->nwal_local.numPendingCfg++;
+        while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+                (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
+        {
+            // if response is there, then this poll squirts out in the CTl poll callback, 
+            // which handles the rest (including decrmenting #pending!!
+            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+        }
+        if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+        {
+            netapip_freeTransInfo(pTransInfo);
+            *err = NETAPI_ERR_PA_FW;
+            netapi_Log (">netapi_netcpCfgCreateMacInterface - ERROR returned by NETCP PA firmware %d\n",
+                    *err);
+            return -1;
+        }
+
+    }
+    netapi_Log ("netapi_netcpCfg: MAC i/f %d added\n", iface_no);
+    netapip_netcpCfgInsertMac(&netapi_get_global()->nwal_context, 
+                          p_mac, iface_no, state,vlan,
+                          (void *) pTransInfo->handle);
+    netapip_freeTransInfo(pTransInfo);
+    return  (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no);
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to delete MAC  interface
+ ********************************************************************
+ * DESCRIPTION:  API to delete MAC  interface
+ ********************************************************************/
+void netapi_netcpCfgDelMac(NETAPI_T h,
+                           int iface_no,
+                           int *err)
+{
+    nwal_RetValue ret;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    void * ifHandle;
+
+    //get the nwal handle assoicated with this iface
+    ifHandle = netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no );
+    if(!ifHandle) 
+    {
+        *err = NETAPI_ERR_BAD_INPUT; return ;
+    }
+    *err =0;
+
+    //get a transaction id
+    pTransInfo = netapip_getFreeTransInfo(n,
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &trans_id);
+    if (!pTransInfo)
+    {
+        *err =  NETAPI_ERR_BUSY;
+        return ;
+    }
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
+    pTransInfo->inUse = nwal_TRUE;
+    pTransInfo->netapi_handle = h;
+
+    //issue request
+    ret = nwal_delMacIface(
+                ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                trans_id,
+                ifHandle);
+    if(ret !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_NWAL_ERR0;
+        netapi_Log ("netapi_netcpCfg - ERROR: nwal_delMacIface returned Error Code %d\n",
+                    ret);
+        netapip_freeTransInfo(pTransInfo);
+        return;
+    }
+    //wait here until its done since scheduler isn't running yet most likely..
+    // todo:  make this handled by scheduler poll later ??
+    if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+    {
+        n->nwal_local.numPendingCfg++;
+        while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+                (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
+        {
+            // if response is there, then this poll squirts out in the CTl poll callback, 
+            // which handles the rest (including decrmenting #pending!!
+            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+        }
+        if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+        {
+            netapip_freeTransInfo(pTransInfo);
+            *err = NETAPI_ERR_PA_FW;
+            netapi_Log (">netapi_netcpCfgCreateMacInterface - ERROR returned by NETCP PA firmware %d\n",
+                    *err);
+            netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
+            return;
+        }
+    }
+    netapi_Log ("netapi_netcpCfg: MAC i/f %d deleted\n",iface_no);
+    netapip_freeTransInfo(pTransInfo);
+    //zap the entry
+    netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
+    return ;
+}
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  NETAPi internal function to Add IP to MAC interface
+ ********************************************************************
+ * DESCRIPTION:  NETAPi internal function to Add IP to MAC interface
+ ********************************************************************/
+static NETCP_CFG_IP_T  netapip_netcpCfgAddIpInternal(NETAPI_T  h,
+                                                     int  iface_no,
+                                                     nwal_IpType ipType,
+                                                     nwalIpAddr_t  * ip_addr,
+                                                     nwalIpAddr_t  *ip_rem_addr,
+                                                     nwalIpOpt_t * ip_qualifiers,
+                                                     NETCP_CFG_ROUTE_HANDLE_T  route,/*NULL for default*/
+                                                     void * user_data,
+                                                     int * err,
+                                                     int  flag) /*TRUE: add IP to iface,
+                                                     FALSE: add IP as part of classifier */
+{
+    static unsigned char zeroIP6[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    void * n_handle=NULL;
+    nwalIpParam_t    nwalIpParam= {
+    0,
+    pa_IPV4,      /* IP Type */
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
+    { 0x0,0,0,0},/* IP Options */
+    NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
+    NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
+    CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
+    QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
+    0
+};
+    nwal_RetValue       retValue;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+    int ip_slot=-1;
+    NETCP_CFG_IP_T ip_rule_id;
+    NETCP_CFG_IP_T temp;
+
+    //verify that iface has been configured 
+    if (iface_no != NETCP_CFG_NO_INTERFACE)
+    {
+        if ((iface_no<0) || (iface_no>= TUNE_NETAPI_MAX_NUM_MAC)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
+    }
+
+    if (iface_no != NETCP_CFG_NO_INTERFACE)
+    {
+        netapi_Log("netapip_netcpCfgAddIpInternal, in_use %d\n", netapi_get_global()->nwal_context.interfaces[iface_no].in_use);
+        netapi_Log("netapip_netcpCfgAddIpInternal, p 0x%x\n", &netapi_get_global()->nwal_context);
+        if(netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
+        {
+            n_handle =  netapi_get_global()->nwal_context.interfaces[iface_no].nwal_handle;
+        }
+        else
+        {
+            *err = NETAPI_ERR_BAD_INPUT;
+            return -1;
+        }
+    }
+    if (flag) //if adding IP to MAC then reserve a slot to save info
+    {
+        //find free slot for IP & reserve
+         ip_slot= netapip_netcpCfgFindIpSlot(n,
+                                             &netapi_get_global()->nwal_context, 
+                                             iface_no);
+        if (ip_slot <0) 
+        {
+            *err= NETAPI_ERR_NOMEM;  //no room 
+            return -1;
+        }
+    }
+
+    //get a transaction object for config action
+    pTransInfo = netapip_getFreeTransInfo(n, 
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &trans_id);
+    if (!pTransInfo)
+    {
+        *err =  NETAPI_ERR_BUSY;
+        if (flag)
+        {
+            netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
+                         iface_no,
+                         ip_slot);
+        }
+        return -1;
+    }
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
+    pTransInfo->inUse = nwal_TRUE;
+    pTransInfo->netapi_handle = h;
+
+    //build nwalIpParam
+    memcpy(&nwalIpParam.locIpAddr,ip_addr, sizeof(nwalIpAddr_t));
+    if (ip_rem_addr)
+    {
+        if (ipType == nwal_IPV4)
+        {
+            if(memcmp(ip_rem_addr, zeroIP6, sizeof(nwalIpv4Addr_t)))
+            {
+                nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
+                memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
+            }
+        }
+        else
+        {
+            if(memcmp(ip_rem_addr, zeroIP6, sizeof(nwalIpv6Addr_t)))
+            {
+                nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
+                memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
+            }
+        }
+    }
+    nwalIpParam.ipType=ipType;
+    if(route)
+    {
+        if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
+            NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
+        {
+           nwalIpParam.validParams |= 
+                    NWAL_SET_IP_VALID_PARAM_ROUTE_TYPE;
+        }
+        netapip_netcpCfgBuildRoute(route,
+                                   &nwalIpParam.appRxPktFlowId,
+                                   &nwalIpParam.appRxPktQueue,
+                                   &nwalIpParam.routeType);
+    }
+    else{} //use nwal defaults
+
+    if (ip_qualifiers)
+        memcpy(&nwalIpParam.ipOpt,ip_qualifiers, sizeof(nwalIpOpt_t)); 
+    else
+        memset(&nwalIpParam.ipOpt,0, sizeof(nwalIpOpt_t));
+
+    //build the rule id that will be returned when a packet matches 
+    if (flag)
+        ip_rule_id = NETAPI_NETCP_MATCH_GENERIC_IP | iface_no | ((ip_slot&& NETAPI_NETCP_MATCH_ID_MASK) << NETAPI_NETCP_MATCH_ID_SHIFT);
+    else
+        ip_rule_id = (NETAPI_NETCP_MATCH_CLASS_L3 | iface_no);
+
+    retValue = nwal_setIPAddr(   netapi_get_global()->nwal_context.nwalInstHandle,
+                                  trans_id,
+                                  (nwal_AppId) (ip_rule_id),
+                                  n_handle,
+                                  &nwalIpParam,
+                                  &pTransInfo->handle);
+
+    if(retValue !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_NWAL_ERR0;
+        netapi_Log ("netcp_cfg: nwal_setIP returned Error Code %d\n",
+                    retValue);
+        netapip_freeTransInfo(pTransInfo);
+        //zap the entry
+        if (flag)
+        {
+            netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
+                         iface_no,
+                         ip_slot);
+        }
+        return -1;
+    }
+    //wait here until its done since scheduler isn't running yet most likely..
+    // todo:  make this handled by scheduler poll later ??
+    if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+    {
+        n->nwal_local.numPendingCfg++;
+        while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+        (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
+        {
+            // if response is there, then this poll squirts out in the CTl poll callback, 
+            // which handles the rest (including decrmenting #pending!!
+            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+        }
+        if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+        {
+            netapip_freeTransInfo(pTransInfo);
+            *err = NETAPI_ERR_PA_FW;
+            netapi_Log ("netapip_netcpCfgAddIpInternal - ERROR returned by NETCP PA firmware %d\n", *err);
+            return -1;
+        }
+    }
+    if (flag)
+    {
+        netapi_Log ("netcp_cfg: IP added to interface %d (slot%d)\n", iface_no, ip_slot);
+        netapip_netcpCfgInsertIp(&netapi_get_global()->nwal_context,
+                                 ipType, 
+                                 ip_addr,
+                                 ip_qualifiers,
+                                 iface_no,
+                                 ip_slot,
+                                 pTransInfo->handle,
+                                 user_data);
+    }
+
+    temp = (NETCP_CFG_IP_T) pTransInfo->handle;
+    netapip_freeTransInfo(pTransInfo);
+    return  (flag ? ip_rule_id:  temp);
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to Add IP to MAC interface
+ ********************************************************************
+ * DESCRIPTION:  API to Add IP to MAC interface
+ ********************************************************************/
+NETCP_CFG_IP_T  netapi_netcpCfgAddIp(NETAPI_T                  h,
+                                     int                       iface_no,
+                                     nwal_IpType               ipType,
+                                     nwalIpAddr_t*             ip_addr,
+                                     nwalIpAddr_t*             ip_rem_addr,
+                                     nwalIpOpt_t*              ip_qualifiers,
+                                     NETCP_CFG_ROUTE_HANDLE_T  route,  //NULL for default
+                                     void*                     user_data,
+                                     int*                      err)
+{
+    return netapip_netcpCfgAddIpInternal(h,
+                                         iface_no,
+                                         ipType,
+                                         ip_addr,
+                                         ip_rem_addr,
+                                         ip_qualifiers, 
+                                         route, 
+                                         user_data,
+                                         err,
+                                         1);
+}
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  NETAPI internal function to detach IP from MAC interface
+ ********************************************************************
+ * DESCRIPTION:  NETAPI internal function to detach IP from MAC interface
+ ********************************************************************/
+static void netapip_netcpCfgDelIpInternal(NETAPI_T h, 
+                                          int iface_no,
+                                          nwal_IpType ipType,
+                                          nwalIpAddr_t  * ip_addr,
+                                          nwalIpOpt_t * ip_qualifiers, 
+                                          NETCP_CFG_IP_T  ip_rule_id,
+                                          int *err, 
+                                          void * handle,   /* if flag==0, handle must be valid */
+                                          int flag)        /* flag==0 => delete IP rule that was part of classifier, not interface */
+{
+    nwal_RetValue ret;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    void * ifHandle;
+    int ip_slot = netapi_cfgGetMatchId(ip_rule_id);
+    /* get the nwal handle assoicated with this ip */
+    if (flag)
+    {
+        ifHandle = netapip_netcpCfgGetIpHandle(&netapi_get_global()->nwal_context,
+                                                iface_no,
+                                                ip_slot);
+    }
+    else 
+    {
+        ifHandle = handle;
+    }
+    if(!ifHandle)
+    {
+        *err = NETAPI_ERR_BAD_INPUT;
+        return ;
+    }
+    *err =0;
+
+    //get a transaction id
+    pTransInfo = netapip_getFreeTransInfo(n,
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &trans_id);
+    if (!pTransInfo)
+    {
+        *err =  NETAPI_ERR_BUSY;
+        return;
+    }
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
+    pTransInfo->inUse = nwal_TRUE;
+    pTransInfo->netapi_handle = h;
+    //issue request
+    ret = nwal_delIPAddr(
+                ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                trans_id,
+                ifHandle);
+    if(ret !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_NWAL_ERR0;
+        netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n",
+                    ret);
+        netapip_freeTransInfo(pTransInfo);
+        return ;
+    }
+    //wait here until its done since scheduler isn't running yet most likely..
+    // todo:  make this handled by scheduler poll later ??
+    if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+    {
+        n->nwal_local.numPendingCfg++;
+        while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+                (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
+        {
+            // if response is there, then this poll squirts out in the CTl poll callback, 
+            // which handles the rest (including decrmenting #pending!!
+            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+        }
+        if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+        {
+            netapip_freeTransInfo(pTransInfo);
+            *err = NETAPI_ERR_PA_FW;
+            netapi_Log ("netapip_netcpCfgDelIpInternal - ERROR returned by NETCP PA firmware %d\n", *err);
+            return;
+        }
+    }
+
+    netapip_freeTransInfo(pTransInfo);
+
+    //zap the entry
+    if (flag)
+        netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,  
+                         iface_no,
+                         ip_slot);
+    return ;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to detach IP from MAC interface
+ ********************************************************************
+ * DESCRIPTION:  API  to detach IP from MAC interface
+ ********************************************************************/
+void netapi_netcpCfgDelIp(NETAPI_T              h,
+                          int                   iface_no,
+                          nwal_IpType           ipType,
+                          nwalIpAddr_t*         ip_addr,
+                          nwalIpOpt_t*          ip_qualifiers,
+                          NETCP_CFG_IP_T        ip_rule_id,
+                          int*                  err)
+{
+    netapip_netcpCfgDelIpInternal( h, iface_no, ipType,
+                  ip_addr, ip_qualifiers, ip_rule_id,
+                  err, NULL, 1);
+    return;
+}
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to attach a classifier rule to NETCP
+ ********************************************************************
+ * DESCRIPTION:  API to attach a classifier rule to NETCP
+ ********************************************************************/
+NETCP_CFG_CLASS_T netapi_netcpCfgAddClass(NETAPI_T                  h,
+                                          NETCP_CFG_CLASSIFIER_T*   p_class,
+                                          NETCP_CFG_ROUTE_HANDLE_T  route,
+                                          int                       action, 
+                                          void*                     user_data, 
+                                          int*                      err)
+{
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    void * l3_handle=NULL;  //ip handle
+    nwal_RetValue       retValue;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+    int class_slot=-1;
+    int iface_no;
+    int ip_slot=-1;
+    NETCP_CFG_CLASS_T  classHandle;  //returned by us
+    nwal_appProtoType_t proto;
+    nwalRxConnCfg_t tempCfg=
+    {
+        0,  //nwal_handle: to be filled in
+        0, // l4 ports: to be filled in
+        0,  //core id (NA)
+        0, //action
+        CPPI_PARAM_NOT_SPECIFIED, //flow id
+        QMSS_PARAM_NOT_SPECIFIED, //dest queue
+        0,
+        0, // l4 ports: to be filled in
+    };
+
+    *err = NETAPI_ERR_OK;
+
+    if(!p_class)
+    {
+        *err=NETAPI_ERR_BAD_INPUT;
+        return -1;
+    }
+    switch(p_class->classType)
+    {
+        default:
+            netapi_Log(">netapi_netcpCfg : classifier type %d not supported\n",p_class->classType);
+            break;
+        case(NETCP_CFG_CLASS_TYPE_L3_L4):
+            n->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+        case(NETCP_CFG_CLASS_TYPE_L4):
+            //assume just type l4 only (L2, L3 defined by iface, l3 id )
+            iface_no = p_class->u.c_l4.iface;
+            if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
+            {
+                ip_slot = netapi_cfgGetMatchId(p_class->u.c_l4.ip);
+            }
+
+            //verify that iface has been configured 
+            if (iface_no != NETCP_CFG_NO_INTERFACE)
+            {
+                if(!netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
+                {
+                    *err = NETAPI_ERR_BAD_INPUT;
+                    if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
+                        n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                    return -1;
+                }
+            }
+
+            if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
+            {
+                //verify that ip has been configured and get its handle
+                l3_handle = netapip_netcpCfgGetIpHandle(
+                      &netapi_get_global()->nwal_context, iface_no,
+                      ip_slot );
+            }
+            else
+            {
+                nwalIpParam_t tempParam=
+                {
+                    0,
+                    pa_IPV4,      /* IP Type */
+                    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
+                    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
+                    { 0x0,0,0,0},/* IP Options */
+                    NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
+                    NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
+                    CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
+                    QMSS_PARAM_NOT_SPECIFIED,                    /* Use default queue configured to NWAL if packet is routed to host */
+                    0
+                };
+                //build nwalIpParam
+                memcpy(&tempParam.locIpAddr,p_class->u.c_l3_l4.ip_addr, sizeof(nwalIpAddr_t));
+                tempParam.ipType=p_class->u.c_l3_l4.ipType;
+                //use nwal defauls for route
+                if (p_class->u.c_l3_l4.ip_qualifiers)
+                    memcpy(&tempParam.ipOpt,p_class->u.c_l3_l4.ip_qualifiers, sizeof(nwalIpOpt_t));
+                else
+                    memset(&tempParam.ipOpt,0, sizeof(nwalIpOpt_t));
+
+                //find if we have a matching L3 handle for IP classifier; if not create it
+                retValue =  nwal_getIPAddr (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                            &tempParam,
+                            netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no ),
+                            &l3_handle); 
+                if (retValue != nwal_TRUE) 
+                {
+                    int ret;
+                    //**NEW IP RULE  
+                    //need to attach this IP RULE to the MAC
+                    l3_handle= (void *) netapip_netcpCfgAddIpInternal(
+                                      h, iface_no, 
+                                      p_class->u.c_l3_l4.ipType,
+                                      p_class->u.c_l3_l4.ip_addr,
+                                      NULL,
+                                      p_class->u.c_l3_l4.ip_qualifiers,
+                                      p_class->u.c_l3_l4.p_fail_route,
+                                      user_data,
+                                      &ret,
+                                      NETAPI_FALSE);
+                    if(!ret)
+                    {
+                        l3_handle=NULL;
+                    }
+                }
+            }
+            if(!l3_handle)
+            {
+                *err = NETAPI_ERR_BAD_INPUT; 
+                if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
+                        n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                return -1 ;
+            }
+
+            //find free slot for CLASS & reserve
+            class_slot= netapip_netcpCfgFindClassSlot(n,
+                                                      &netapi_get_global()->nwal_context);
+            if(class_slot<0) 
+            {
+                *err = NETAPI_ERR_NOMEM;
+                if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
+                        n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                return -1;
+                }
+            classHandle = NETAPI_NETCP_MATCH_CLASS |
+                          (class_slot << NETAPI_NETCP_MATCH_ID_SHIFT) | 
+                          (iface_no & NETAPI_NETCP_MATCH_LOGICAL_MAC_IFACE_MASK);
+            //build request from template
+            tempCfg.inHandle=l3_handle;
+            if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
+            {
+                memcpy(&tempCfg.appProto,&p_class->u.c_l4.appProto,sizeof(nwalAppProto_t));
+                proto = p_class->u.c_l4.proto;
+            }
+            else
+            {
+                memcpy(&tempCfg.appProto,&p_class->u.c_l3_l4.appProto,sizeof(nwalAppProto_t));
+                proto = p_class->u.c_l3_l4.proto;
+            }
+
+            tempCfg.matchAction = (action==NETCP_CFG_ACTION_TO_SW)  ? NWAL_MATCH_ACTION_HOST : NWAL_MATCH_ACTION_DISCARD;
+            if (route)
+            {
+                if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
+                    NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
+                {
+                    tempCfg.validParams |= 
+                        NWAL_SET_CONN_VALID_PARAM_ROUTE_TYPE;
+                }
+                netapip_netcpCfgBuildRoute(route,
+                                           &tempCfg.appRxPktFlowId,
+                                           &tempCfg.appRxPktQueue,
+                                           &tempCfg.routeType);
+            }
+
+
+            //get a transaction id
+            pTransInfo = netapip_getFreeTransInfo(n,
+                                                  (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                                  &trans_id);
+            if (!pTransInfo)
+            {
+                *err =  NETAPI_ERR_BUSY;
+                if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
+                    n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                return -1;
+            }
+            pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
+            pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
+            pTransInfo->inUse = nwal_TRUE;
+            pTransInfo->netapi_handle = h;
+                //issue request
+            retValue = nwal_addConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                            trans_id,
+                            (nwal_AppId) classHandle,
+                            proto,
+                            &tempCfg,
+                            NULL,
+                            &pTransInfo->handle);
+            if(retValue !=  nwal_OK)
+            {
+                *err = NETAPI_ERR_NWAL_ERR0;
+                netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n",
+                        retValue);
+                netapip_freeTransInfo(pTransInfo);
+                netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
+                if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
+                    n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                return -1;
+            }
+            //wait here until its done since scheduler isn't running yet most likely..
+           // todo:  make this handled by scheduler poll later ??
+            if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+            {
+                n->nwal_local.numPendingCfg++;
+                while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+                    (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
+                {
+                    // if response is there, then this poll squirts out in the CTl poll callback, 
+                    // which handles the rest (including decrmenting #pending!!
+                    nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+                }
+                if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+                {
+                    netapip_freeTransInfo(pTransInfo);
+                    *err = NETAPI_ERR_PA_FW;
+                    netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
+                    netapi_Log (">netcp_cfgAddClass - ERROR returned by NETCP PA firmware %d\n", *err);
+                    if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
+                        n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+                    return -1;
+                }
+            }
+            netapi_Log ("netcp_cfg: L4 Classifer added to interface %d ip %d (slot%d)\n", iface_no, ip_slot, class_slot);
+            netapip_netcpCfgInsertClass(&netapi_get_global()->nwal_context, 
+                                   class_slot,
+                                 p_class->classType, 
+                                NULL,  //L2 we have
+                                (p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4? l3_handle : NULL),
+                                  pTransInfo->handle,
+                                  user_data);
+
+            netapip_freeTransInfo(pTransInfo);
+            if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
+                n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+            return classHandle;
+    } //end switch
+
+return -1;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to delete a preconfigured classifier
+ ********************************************************************
+ * DESCRIPTION:  API to delete a preconfigured classifier
+ ********************************************************************/
+void netapi_netcpCfgDelClass(NETAPI_T           h,
+                             NETCP_CFG_CLASS_T  classId,
+                             int*               err)
+{
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    void *L4_handle = NULL;  //class handle -> L4
+    void *L3_handle = NULL;  //class handle -> L3
+    nwal_RetValue       retValue;
+    NetapiNwalTransInfo_t *pTransInfo;
+    nwal_TransID_t     trans_id;
+    int class_slot=-1;
+
+    class_slot = netapi_cfgGetMatchId(classId);
+    L4_handle=netapip_netcpCfgGetL4Handle(&netapi_get_global()->nwal_context, class_slot);
+    if(!L4_handle)
+    {
+        *err = NETAPI_ERR_BAD_INPUT; 
+        goto ERR_netapi_netcpCfgDelClass;
+    }
+    L3_handle = netapip_netcpCfgGetL3Handle( &netapi_get_global()->nwal_context,
+                                            class_slot);
+    /* l3 handle might be NULL, depending on type of classifier */
+
+    if(L3_handle)
+    {
+        // grab l3 lock
+        n->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+    }
+    netapip_netcpCfgDeleteClass(
+                        &netapi_get_global()->nwal_context,
+                        class_slot );
+    //get a transaction id
+    pTransInfo = netapip_getFreeTransInfo(n,
+                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
+                                          &trans_id);
+    if (!pTransInfo)
+    {
+        *err =  NETAPI_ERR_BUSY; 
+        goto ERR_netapi_netcpCfgDelClass;
+    }
+    pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
+    pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
+    pTransInfo->inUse = nwal_TRUE;
+    pTransInfo->netapi_handle = h;
+    //issue request for L4
+    retValue = nwal_delConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
+                                                 trans_id,
+                                                 L4_handle);
+    if(retValue !=  nwal_OK)
+    {
+        *err = NETAPI_ERR_NWAL_ERR0;
+         netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n", retValue);
+         netapip_freeTransInfo(pTransInfo);
+         goto ERR_netapi_netcpCfgDelClass;  /* todo: what about the L3? */
+    }
+    //wait here until its done since scheduler isn't running yet most likely..
+    // todo:  make this handled by scheduler poll later ??
+    if(trans_id != NWAL_TRANSID_SPIN_WAIT)
+    {
+        n->nwal_local.numPendingCfg++;
+        while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
+                (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
+        {
+            // if response is there, then this poll squirts out in the CTl poll callback, 
+            // which handles the rest (including decrmenting #pending!!
+            nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
+        }
+    }
+    if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
+    {
+        netapip_freeTransInfo(pTransInfo);
+        *err = NETAPI_ERR_PA_FW;
+         netapi_Log (">netapi_netcpCfgDelClass - ERROR returned by NETCP PA firmware %d\n", *err);
+         goto ERR_netapi_netcpCfgDelClass;
+    }
+    netapi_Log ("netcp_cfg: Classifer deleted\n");
+    pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;
+    pTransInfo->inUse = nwal_FALSE;
+
+    /* delete L3 if we have to */
+    if (cfgOkToDeleteL3ClassiHandle(h, L3_handle))
+    {
+        netapip_netcpCfgDelIpInternal(h,
+                                      0,
+                                      0,
+                                      NULL,
+                                      NULL,
+                                      0,
+                                      err,
+                                      L3_handle,
+                                      0);
+    }
+    netapip_freeTransInfo(pTransInfo);
+
+ERR_netapi_netcpCfgDelClass:
+    if(L3_handle)
+        n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
+
+    return;
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to add a flow
+ ********************************************************************
+ * DESCRIPTION:  API to add a flow
+ ********************************************************************/
+/*--------------flow management--------*/
+// ADD A Flow
+NETCP_CFG_FLOW_HANDLE_T netapi_netcpCfgAddFlow(NETAPI_T                 h,
+                                               int                      n,
+                                               Pktlib_HeapHandle        handles[],
+                                               int                      sizes[],
+                                               NETCP_CFG_FLOW_CONFIG_T* p_cfg,
+                                               int*                     err )
+{
+    Cppi_RxFlowCfg  rxFlowCfg;
+    Uint8           isAlloc;
+    Qmss_QueueHnd   rxBufQ[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
+    Uint32          rxBufSize[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
+    int             i;
+    Cppi_FlowHnd FlowHnd;
+    int  slot;
+    NETCP_CFG_FLOW_HANDLE_T retVal;
+    NETAPI_HANDLE_T * pHandle = (NETAPI_HANDLE_T *) h;
+    *err= 0;  /* ok */
+    if (!p_cfg)
+    {
+        *err= NETAPI_ERR_BAD_INPUT;
+        return NULL;
+    }
+    //get a slot to save new flow
+    slot = netapip_netcpCfgFindFlowSlot(pHandle,
+                                        &netapi_get_global()->nwal_context);
+
+    if (slot<0) { *err= NETAPI_ERR_NOMEM;  return NULL; }
+
+    //configure flow
+    memset(&rxFlowCfg,0,sizeof(Cppi_RxFlowCfg));
+    for (i = 0; i < TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW; i++)
+    {
+        if (i >= n)
+        {
+            rxBufQ[i] = 0;
+            rxBufSize[i] = 0;
+        }
+        else
+        {
+            rxBufQ[i] =   Pktlib_getInternalHeapQueue(handles[i]);
+            //todo: verity sizes< heapsize
+            //todo: verify order
+            rxBufSize[i]= sizes[i];
+        }
+       if (i && (rxBufQ[i] <= 0))
+       {
+            rxBufQ[i] = rxBufQ[i-1];
+            rxBufSize[i] = 0;
+       }
+    }
+
+    /* Configure Rx flow */
+    rxFlowCfg.flowIdNum      = p_cfg->flow_index;/*CPPI_PARAM_NOT_SPECIFIED*/;
+    rxFlowCfg.rx_dest_qnum   = netapi_pktioGetQ(p_cfg->p_dest_q);
+    rxFlowCfg.rx_dest_qmgr   = Qmss_getQueueNumber(rxFlowCfg.rx_dest_qnum).qMgr; 
+    rxFlowCfg.rx_sop_offset  = p_cfg->recv_offset;
+    rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;
+    rxFlowCfg.rx_desc_type   = Cppi_DescType_HOST;
+    rxFlowCfg.rx_error_handling = p_cfg->block;
+
+    rxFlowCfg.rx_psinfo_present = 1;
+    rxFlowCfg.rx_einfo_present  = 1;
+
+    rxFlowCfg.rx_dest_tag_lo = 0;
+    rxFlowCfg.rx_dest_tag_hi = 0;
+    rxFlowCfg.rx_src_tag_lo  = 0;
+    rxFlowCfg.rx_src_tag_hi  = 0;
+
+    rxFlowCfg.rx_size_thresh0_en = rxBufSize[1] ? 1 : 0;
+    rxFlowCfg.rx_size_thresh1_en = rxBufSize[2] ? 1 : 0;
+    rxFlowCfg.rx_size_thresh2_en = rxBufSize[3] ? 1 : 0;
+
+  if (p_cfg->dma_index==NETAPI_DMA_NETCP )
+    rxFlowCfg.rx_dest_tag_lo_sel =0;
+  else
+    rxFlowCfg.rx_dest_tag_lo_sel = 0x4;
+    rxFlowCfg.rx_dest_tag_hi_sel = 0;
+    rxFlowCfg.rx_src_tag_lo_sel  = 0;
+    rxFlowCfg.rx_src_tag_hi_sel  = 0;
+
+    rxFlowCfg.rx_fdq1_qnum = rxBufQ[1];
+    rxFlowCfg.rx_fdq1_qmgr = (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr: 0);
+    rxFlowCfg.rx_fdq2_qnum = rxBufQ[2];
+    rxFlowCfg.rx_fdq2_qmgr = (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr: 0);
+    rxFlowCfg.rx_fdq3_qnum = rxBufQ[3];
+    rxFlowCfg.rx_fdq3_qmgr = (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr: 0);
+
+    rxFlowCfg.rx_size_thresh0 = rxBufSize[1] ? rxBufSize[0] : 0;
+    rxFlowCfg.rx_size_thresh1 = rxBufSize[2] ? rxBufSize[1] : 0;
+    rxFlowCfg.rx_size_thresh2 = rxBufSize[3] ? rxBufSize[2] : 0;
+
+    rxFlowCfg.rx_fdq0_sz0_qnum = rxBufQ[0];
+    rxFlowCfg.rx_fdq0_sz0_qmgr =  (rxBufQ[0] ? Qmss_getQueueNumber(rxBufQ[0]).qMgr: 0);
+    rxFlowCfg.rx_fdq0_sz1_qnum = rxBufQ[1];
+    rxFlowCfg.rx_fdq0_sz1_qmgr =  (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr:0);
+    rxFlowCfg.rx_fdq0_sz2_qnum = rxBufQ[2];
+    rxFlowCfg.rx_fdq0_sz2_qmgr =  (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr:0);
+    rxFlowCfg.rx_fdq0_sz3_qnum = rxBufQ[3];
+    rxFlowCfg.rx_fdq0_sz3_qmgr =  (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr:0);
+    {
+        //todo: replace this with a nwal call to get global cntx info
+        Cppi_CpDmaInitCfg cpdmaCfg;
+        Cppi_Handle cppiHnd;
+        memset(&cpdmaCfg,0,sizeof(Cppi_CpDmaInitCfg));
+        cpdmaCfg.dmaNum   = (p_cfg->dma_index==NETAPI_DMA_NETCP ) ?Cppi_CpDma_PASS_CPDMA: Cppi_CpDma_QMSS_CPDMA;
+        cppiHnd= Cppi_open (&cpdmaCfg);
+        if (cppiHnd == NULL)
+        {
+              netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
+              *err= NETAPI_ERR_NORES;
+              return NULL;
+        }
+        FlowHnd = Cppi_configureRxFlow (cppiHnd, &rxFlowCfg, &isAlloc);
+    }
+    if (FlowHnd == NULL)
+    {
+        *err= NETAPI_ERR_NORES;
+        netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
+        return (NULL);
+    }
+
+    //update slot
+    retVal = netapip_netcpCfgInsertFlow(&netapi_get_global()->nwal_context,
+                                        slot,
+                                        p_cfg->dma_index,
+                                        (void*) FlowHnd);
+    netapi_Log(">netcp cfg:  flow %d created in dma index %d\n",
+        ((NETCP_CFG_FLOW_T *) retVal)->flowid, p_cfg->dma_index);
+    return (retVal);
+}
+
+/********************************************************************
+ * FUNCTION PURPOSE:  API to delete a flow
+ ********************************************************************
+ * DESCRIPTION:  API to delete a flow
+ ********************************************************************/
+void netapi_netcpCfgDelFlow(NETAPI_T                h,
+                            NETCP_CFG_FLOW_HANDLE_T f,
+                            int*                    err)
+{
+    int slot;
+    void * handle;
+    *err=0;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    /* find entry */
+        slot = netapip_netcpCfgFindFlow(n,
+                                        &netapi_get_global()->nwal_context,
+                                        ((NETCP_CFG_FLOW_T *) f) ->flowid,
+                                        ((NETCP_CFG_FLOW_T *) f) ->dma_engine,
+                                        &handle);
+    if (slot<0)
+    {
+        *err = NETAPI_ERR_BAD_INPUT;
+        return;
+    }
+    if ((Cppi_closeRxFlow( (Cppi_FlowHnd) handle)) == 0)
+    {
+        netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context,
+                               slot);
+    }
+    return;
+}
+
+/******************************************************************************
+ * FUNCTION PURPOSE:  API to configure NETCP with global rules for exception packet handling
+ ******************************************************************************
+ * DESCRIPTION:  API to configure NETCP with global rules for exception packet handling
+ *****************************************************************************/
+NETCP_CFG_EXCEPTION_PKT_T netapi_netcpCfgExceptions(NETAPI_T                    h,
+                                                    int                         exception_id,
+                                                    nwal_matchAction_t          action,
+                                                    NETCP_CFG_ROUTE_HANDLE_T    p_route)
+{
+    nwalCtlInfo_t   ctrl;
+    NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
+    nwal_RetValue retVal = 0;
+    memset(&ctrl, 0, sizeof(nwalCtlInfo_t));
+
+    if (p_route != NULL)
+    {
+        if((p_route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
+            NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
+        {
+           ctrl.validParams |= 
+                    NWAL_CONTROL_VALID_PARAM_ROUTE_TYPE;
+           ctrl.routeType = p_route->routeType;
+        }
+        netapip_netcpCfgBuildRoute(p_route,
+                                   &ctrl.appRxPktFlowId,
+                                   &ctrl.appRxPktQueue,
+                                   &ctrl.routeType);
+    }
+    else
+    {
+        ctrl.appRxPktFlowId = NWAL_FLOW_NOT_SPECIFIED;
+        ctrl.appRxPktQueue = NWAL_QUEUE_NOT_SPECIFIED;
+    }
+
+    ctrl.appId = (void*)(NETAPI_NETCP_CFG_MATCH_EXCEPTION | exception_id);
+
+    ctrl.matchAction = action;
+
+    if (exception_id == NETCP_CFG_ALL_EXCEPTIONS)
+    {
+        ctrl.pktCtl = NWAL_CTRL_CFG_ALL_EXCEPTIONS;
+    }
+    else
+    {
+            ctrl.pa_EROUTE_Id = exception_id;
+            ctrl.pktCtl = NWAL_CTRL_CFG_SINGLE_EXCEPTION;
+    }
+
+    retVal = nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &ctrl);
+
+
+    return (NETCP_CFG_EXCEPTION_PKT_T) ctrl.appId;
+}
+
+/*************************************************************************/
+/*********************************INTERNAL*******************************/
+/************************************************************************/
+
+/********************************************************************
+ * FUNCTION PURPOSE:  NETAPI internal function, NETCP command reply callback
+ ********************************************************************
+ * DESCRIPTION:  NETAPI internal function, NETCP command reply callback
+ ********************************************************************/
+void netapip_netcpCfgNWALCmdCallBack(nwal_AppId        appHandle,
+                            uint16_t            trans_id,
+                            nwal_RetValue     ret)
+{
+    NetapiNwalTransInfo_t * p_trans;
+    NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
+
+    if(trans_id == NWAL_TRANSID_SPIN_WAIT)
+    {
+        netapi_get_proc_global()->nwal_context.numBogusTransIds++;
+        return;
+    }
+
+    p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
+    p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
+
+    if(ret != nwal_OK)
+    {
+        netapi_Log ("netcp_cfg : netapip_netcpCfgNWALCmdCallBack returned Error Code %d for trans_id %d\n",
+                    ret, trans_id);
+        // update error code that is fialed  in p_trans */
+        //todo: atomic inc
+        p_trans->state = NETAPI_NWAL_HANDLE_STATE_ERR;
+        netapi_get_proc_global()->nwal_context.numCmdFail++;
+    }
+    else
+    {
+        //todo: atomic inc
+        netapi_get_proc_global()->nwal_context.numCmdPass++;
+        switch(p_trans->transType)
+        {
+            case NETAPI_NWAL_HANDLE_TRANS_MAC:
+            {
+                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
+                }
+                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
+                }
+                break;
+            }
+            case NETAPI_NWAL_HANDLE_TRANS_IP:
+            {
+                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
+                {
+                    p_trans->state = NETAPI_NWAL_HANDLE_STATE_OPEN;
+                }
+                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
+                }
+                break;
+            }
+            case NETAPI_NWAL_HANDLE_TRANS_PORT:
+            {
+                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
+                }
+                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
+                }
+                break;
+            }
+            case NETAPI_NWAL_HANDLE_TRANS_SA:
+            {
+                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
+                }
+                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
+                }
+                break;
+            }
+            case NETAPI_NWAL_HANDLE_TRANS_SA_POLICY:
+            {
+                if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
+                }
+                else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
+                {
+                    p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
+                }
+                break;
+            }
+            default:
+            {
+                netapi_Log ("netcp cfg> Invalid transaction type %d for trans_id: %d\n",
+                    p_trans->transType,trans_id);
+                break;
+            }
+        }
+    }
+
+    p_local->numPendingCfg--;
+
+    if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_IDLE)
+    {
+        p_trans->inUse = nwal_FALSE;
+    }
+}
+
+
+/********************************************************************
+ * FUNCTION PURPOSE:  NETAPI internal function, PA stats reply callback
+ ********************************************************************
+ * DESCRIPTION:  NETAPI internal function, PA stats reply callback
+ ********************************************************************/
+void netapip_netcpCfgNWALCmdPaStatsReply(nwal_AppId        appHandle,
+                                nwal_TransID_t    trans_id,
+                                paSysStats_t      *stats)
+{
+    NetapiNwalTransInfo_t * p_trans;
+    NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
+
+    if(trans_id == NWAL_TRANSID_SPIN_WAIT)
+    {
+        netapi_get_proc_global()->nwal_context.numBogusTransIds++;
+        return;
+    }
+
+    p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
+    p_trans->inUse = nwal_FALSE;
+    p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
+
+    //save a local copy  of some stuff*/
+    p_local->numL2PktsRecvd=stats->classify1.nPackets;
+    p_local->numL3PktsRecvd=stats->classify1.nIpv4Packets;
+
+    //callout result to application !!
+    if (p_local->stats_cb)
+    {
+        (*p_local->stats_cb)(p_trans->netapi_handle,stats);
+    }
+}
+