/********************************************************** * 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" /****************************************************************** ********************Netapi internal************************************* *******************************************************************/ static hplib_spinLock_T netapi_netcp_cfg_lock = hplib_spinLock_UNLOCKED_INITIALIZER; /******************************************************************** * 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_GLOBAL_T *p_global, nwal_TransID_t *pTransId) { uint16_t count=0; count=0; hplib_mSpinLockLock(&netapi_netcp_cfg_lock); while(count < TUNE_NETAPI_MAX_NUM_TRANS) { if((p_global->nwal_context.transInfos[count].inUse) != nwal_TRUE) { p_global->nwal_context.transInfos[count].inUse = nwal_TRUE; *pTransId = count; hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return(&p_global->nwal_context.transInfos[count]); } count++; } hplib_mSpinLockUnlock(&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) { 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 = pktio_get_q(p_route->p_dest_q); else *p_q=QMSS_PARAM_NOT_SPECIFIED; } /******************************************************/ /*----------------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_NWAL_GLOBAL_CONTEXT_T *p, int tunnel) { int i; if ((tunnel <0 ) || (tunnel >=TUNE_NETAPI_MAX_SA)) return -1; hplib_mSpinLockLock(&netapi_netcp_cfg_lock); //find a free entry for(i=0;ipolicy[i].in_use) { p->policy[i].in_use = 2; //pending p->policy[i].tunnel= tunnel; //save tunnel this is linked to hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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_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; } hplib_mSpinLockLock(&netapi_netcp_cfg_lock); //find a free entry for(i=0;itunnel[i].in_use) { p->tunnel[i].in_use = 2; //pending p->tunnel[i].iface= iface; //save iface hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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_NWAL_GLOBAL_CONTEXT_T *p) { int i; //find a free entry hplib_mSpinLockLock(&netapi_netcp_cfg_lock); for(i=0;iflows[i].in_use) { p->flows[i].in_use = 2; /* pending */ hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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, void * handle) { p->flows[slot].in_use=1; p->flows[slot].handle = handle; p->flows[slot].flow.flowid = Cppi_getFlowId(handle); 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_NWAL_GLOBAL_CONTEXT_T *p, int flowid, void ** handle) { int i; *handle=NULL; hplib_mSpinLockLock(&netapi_netcp_cfg_lock); for(i=0;iflows[i].in_use)&&(p->flows[i].flow.flowid == flowid)) { *handle = p->flows[i].handle; hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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_NWAL_GLOBAL_CONTEXT_T *p, int iface_no) { int i; //find a free entry hplib_mSpinLockLock(&netapi_netcp_cfg_lock); for(i=0;iips[i].in_use) { p->ips[i].in_use = 2; //pending hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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_NWAL_GLOBAL_CONTEXT_T *p) { int i; hplib_mSpinLockLock(&netapi_netcp_cfg_lock); for(i=0;iclassi[i].in_use) { p->classi[i].in_use = 2; //pending hplib_mSpinLockUnlock(&netapi_netcp_cfg_lock); return i; } } hplib_mSpinLockUnlock(&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 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; if ((!n) || (!cb)) { *err = NETAPI_ERR_BAD_INPUT; return ; } *err =0; pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->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; ret = nwal_getPAStats( ((NETAPI_GLOBAL_T *) n->global)->nwal_context.nwalInstHandle, transId, NULL, doClear); if(ret != nwal_OK) { //pTransInfo->inUse = nwal_FALSE; *err = NETAPI_ERR_BUSY; //no resources?? netapi_Log("> netapi_netcpCfg reqStats failed, err=%d\n",ret); } 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, int iface_no, int switch_port, NETCP_CFG_ROUTE_HANDLE_T route, NETCP_CFG_VLAN_T vlan, //future 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 */ 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 */ }; 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((NETAPI_GLOBAL_T *) n->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); /* todo: vlan */ MacInfo.ifNum = switch_port; /* todo: check for 0/1 relative*/ if (route != NULL) { netapip_netcpCfgBuildRoute(route,&MacInfo.appRxPktFlowId, &MacInfo.appRxPktQueue); } 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((NETAPI_GLOBAL_T *) n->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, 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 */ { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; void * n_handle=NULL; nwalIpParam_t nwalIpParam= { pa_IPV4, /* IP Type */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Dest 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 */ }; 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("netcp-cfgAddIpInternal, 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(&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((NETAPI_GLOBAL_T *) n->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)); nwalIpParam.ipType=ipType; if(route) { netapip_netcpCfgBuildRoute(route,&nwalIpParam.appRxPktFlowId, &nwalIpParam.appRxPktQueue); } 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, 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_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((NETAPI_GLOBAL_T *) n->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 }; 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): 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; 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= { pa_IPV4, /* IP Type */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Dest 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 */ }; //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, p_class->u.c_l3_l4.ip_qualifiers, p_class->u.c_l3_l4.p_fail_route, user_data, &ret, FALSE); if(!ret) { l3_handle=NULL; } } } if(!l3_handle) { *err = NETAPI_ERR_BAD_INPUT; return -1 ; } //find free slot for CLASS & reserve class_slot= netapip_netcpCfgFindClassSlot(&netapi_get_global()->nwal_context); if(class_slot<0) {*err = NETAPI_ERR_NOMEM; 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) { netapip_netcpCfgBuildRoute(route,&tempCfg.appRxPktFlowId, &tempCfg.appRxPktQueue); } //get a transaction id pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *err = NETAPI_ERR_BUSY; 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); 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); 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); 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; //class handle -> L4 void * L3_handle; //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 */ netapip_netcpCfgDeleteClass( &netapi_get_global()->nwal_context, class_slot ); //get a transaction id pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->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 (L3_handle) { netapip_netcpCfgDelIpInternal( h, 0, 0, NULL, NULL, 0, err, L3_handle, 0); } netapip_freeTransInfo(pTransInfo); ERR_netapi_netcpCfgDelClass: 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[], int byte_offset, 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; *err= 0; /* ok */ //get a slot to save new flow slot = netapip_netcpCfgFindFlowSlot(&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 = CPPI_PARAM_NOT_SPECIFIED; rxFlowCfg.rx_dest_qnum = 100; //DANGEROUS> TODO PUT VALID Q HERE rxFlowCfg.rx_dest_qmgr = 0; rxFlowCfg.rx_sop_offset = byte_offset; rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC; rxFlowCfg.rx_desc_type = Cppi_DescType_HOST; rxFlowCfg.rx_error_handling = 0; 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; rxFlowCfg.rx_dest_tag_lo_sel = 0; 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 = 0; rxFlowCfg.rx_fdq2_qnum = rxBufQ[2]; rxFlowCfg.rx_fdq2_qmgr = 0; rxFlowCfg.rx_fdq3_qnum = rxBufQ[3]; rxFlowCfg.rx_fdq3_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 = 0; rxFlowCfg.rx_fdq0_sz1_qnum = rxBufQ[1]; rxFlowCfg.rx_fdq0_sz1_qmgr = 0; rxFlowCfg.rx_fdq0_sz2_qnum = rxBufQ[2]; rxFlowCfg.rx_fdq0_sz2_qmgr = 0; rxFlowCfg.rx_fdq0_sz3_qnum = rxBufQ[3]; rxFlowCfg.rx_fdq0_sz3_qmgr = 0; { //todo: replace this with a nwal call to get global cntx info Cppi_CpDmaInitCfg cpdmaCfg; memset(&cpdmaCfg,0,sizeof(Cppi_CpDmaInitCfg)); cpdmaCfg.dmaNum = Cppi_CpDma_PASS_CPDMA; FlowHnd = Cppi_configureRxFlow (Cppi_open (&cpdmaCfg), &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, (void*) FlowHnd); netapi_Log("netcp_cfg: flow %d created\n", ((NETCP_CFG_FLOW_T *) retVal)->flowid); 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; /* find entry */ slot = netapip_netcpCfgFindFlow(&netapi_get_global()->nwal_context, ((NETCP_CFG_FLOW_T *) f) ->flowid, &handle); if (slot<0) { *err = NETAPI_ERR_BAD_INPUT; return; } Cppi_closeRxFlow( (Cppi_FlowHnd) handle); netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot); netapi_Log("netcp_cfg: flow %d deleted\n", ((NETCP_CFG_FLOW_T *) f)->flowid); 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) { netapip_netcpCfgBuildRoute(p_route, &ctrl.appRxPktFlowId,& ctrl.appRxPktQueue); } 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 netapi_NWALCmdCallBack(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_global()->nwal_context.numBogusTransIds++; return; } p_trans= &netapi_get_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 : netapi_NWALCmdCallBack 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_global()->nwal_context.numCmdFail++; } else { //todo: atomic inc netapi_get_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 netapi_NWALCmdPaStatsReply(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_global()->nwal_context.numBogusTransIds++; return; } p_trans= &netapi_get_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); } }