/********************************************************** * 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: rev 0.0.1 * * Copyright (c) Texas Instruments Incorporated 2010-2011 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************/ #include "netapi.h" #include "netcp_cfg.h" #include "netapi_loc.h" /****************************************************************** ********************Utility************************************* *******************************************************************/ //get a free transaction id static NetapiNwalTransInfo_t * netapi_GetFreeTransInfo(NETAPI_GLOBAL_T *p_global, nwal_TransID_t *pTransId) { uint16_t count=0; count=0; 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; return(&p_global->nwal_context.transInfos[count]); } count++; } /* trouble. need to wait for one to free up*/ /* to do: handle this by forcing a poll of cntrl queue*/ printf("netapi>> trying to get free transaction slot but all full!!\n"); return NULL; } //internal: insert an IP address into iface void netcp_cfgp_insert_ip(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, nwal_IpType ipType, nwalIpAddr_t *ip_addr, nwalIpOpt_t *ip_qualifiers, int iface_no, void * handle) { int i; for(i=0;iinterfaces[iface_no].ips[i].in_use) { p->interfaces[iface_no].ips[i].in_use=1; memcpy(&p->interfaces[iface_no].ips[i].ip_addr, ip_addr, sizeof(nwalIpAddr_t)); if(ip_qualifiers) memcpy(&p->interfaces[iface_no].ips[i].ip_qualifiers, ip_qualifiers, sizeof(nwalIpOpt_t)); else memset(&p->interfaces[iface_no].ips[i].ip_qualifiers, 0, sizeof(nwalIpOpt_t)); p->interfaces[iface_no].ips[i].ip_type = ipType; p->interfaces[iface_no].ips[i].nwal_handle = handle; return; } } printf("netcp_cfg> add ip: no room in table\n"); } //internal: instert interface info into global context void netcp_cfgp_insert_mac(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_INTERFACES)) { 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 } else printf("netcp_cfg> insert interface # out of range %d\n",iface_no); } //internal: clear inteface entry void netcp_cfgp_delete_mac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,int iface_no) { if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_INTERFACES)) { p->interfaces[iface_no].in_use = 0; } else printf("netcp_cfg> delete interface # out of range %d\n",iface_no); } //internal: /***********************************************************************************/ /****************************************API****************************************/ /***********************************************************************************/ /***************************************************************** * Queury Stats ****************************************************************/ void netcp_cfgReqStats(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 = netapi_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?? printf("reqStats-> failed, err=%d\n",ret); } } /***************************************************************** * CREATE A MAC INTERFACE ****************************************************************/ NETCP_CFG_MACIF_T netcp_cfgCreateMacInterface( 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 NULL;} *err =0; pTransInfo = netapi_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *err = NETAPI_ERR_BUSY; return NULL;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC; 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 0 //todo if (route != NULL) { MacInfo.appRxPktFlowId = ((NETCP_CFG_FLOW_T *)(route.flow))->flowid; MacInfo.appRxPktQueue = PKTIO_GET_Q(route->p_dest_q); //handle action ?? } #endif pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING; 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; printf ("ERROR: nwal_setMacIface returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; return NULL; } //pTransInfo->inUse = nwal_FALSE; printf ("MAC Open sent with trans_id: %d\n",trans_id); //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 ((volatile) n->nwal_local.numPendingCfg) { // 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); } } printf ("MAC i/f added\n"); netcp_cfgp_insert_mac(&netapi_get_global()->nwal_context, p_mac, iface_no, state,vlan, (void *) pTransInfo->handle); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; pTransInfo->inUse = nwal_FALSE; return (void *) (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no); } /*****************************************************************/ /***************Delete a mac interface****************************/ /*****************************************************************/ void netcp_cfgDelMac(NETAPI_T h,int iface_no, int *err) { *err =0; netcp_cfgp_delete_mac(&netapi_get_global()->nwal_context, iface_no); printf("netcp_cfg> del mac not fully implemented \n"); return; } /*****************************************************************/ /***************Add IP to MAC interface****************************/ /*****************************************************************/ NETCP_CFG_IP_T netcp_addIp( 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 int * err ) { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; void * n_handle; 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; //verify that iface has been configurred if ((iface_no<0) || (iface_no>= TUNE_NETAPI_MAX_INTERFACES)) {*err = NETAPI_ERR_BAD_INPUT; return NULL;} 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 NULL; } //get a transaction object for config action pTransInfo = netapi_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *err = NETAPI_ERR_BUSY; return NULL;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP; pTransInfo->netapi_handle = h; //build nwalIpParam memcpy(&nwalIpParam.locIpAddr,ip_addr, sizeof(nwalIpAddr_t)); nwalIpParam.ipType=ipType; if(route) { //todo: support app defined routes } else{} //use nwal defaults if (ip_qualifiers) memcpy(&nwalIpParam.ipOpt,ip_qualifiers, sizeof(nwalIpOpt_t)); else memset(&nwalIpParam.ipOpt,0, sizeof(nwalIpOpt_t)); //perform config action pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING; retValue = nwal_setIPAddr( netapi_get_global()->nwal_context.nwalInstHandle, trans_id, (nwal_AppId) (NETAPI_NETCP_MATCH_GENERIC_IP | iface_no), n_handle, &nwalIpParam, &pTransInfo->handle); if(retValue != nwal_OK) { *err = NETAPI_ERR_NWAL_ERR0; printf ("ERROR: nwal_setIP returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; return NULL; } //pTransInfo->inUse = nwal_FALSE; printf (" SeIPAddr sent with trans_id: %d\n",trans_id); //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 ((volatile) n->nwal_local.numPendingCfg) { // 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); } } printf ("IP added\n"); netcp_cfgp_insert_ip(&netapi_get_global()->nwal_context, ipType, ip_addr, ip_qualifiers, iface_no, pTransInfo->handle); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; pTransInfo->inUse = nwal_FALSE; return (void *) (NETAPI_NETCP_MATCH_GENERIC_IP | iface_no); } /*************************************************************************/ /*********************************INTERNAL*******************************/ /************************************************************************/ /*************************************************************** ********************METCP CMD 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) { printf("ERROR: callback found SPIN_WAIT transaction id. SO CANT FIND OUT WHO WE ARE]n"); 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) { printf ("ERROR: NWALCmdCallBack returned Error Code %d\n", ret); //todo: atomic inc 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; } #if 0 case TEST_NWAL_HANDLE_TRANS_PORT: { if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_OPEN_PENDING) { testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_OPEN; } else if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_CLOSE_PENDING) { testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_IDLE; } break; } case TEST_NWAL_HANDLE_TRANS_SEC_ASSOC: { if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_OPEN_PENDING) { testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_OPEN; } else if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_CLOSE_PENDING) { System_printf ("Set Security Assoc Close ACK received for trans_id: %d\n", testNwLocContext.transInfos[trans_id].transType,trans_id); nwal_SystemFlush(); testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_IDLE; } break; } case TEST_NWAL_HANDLE_TRANS_SEC_POLICY: { if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_OPEN_PENDING) { testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_OPEN; } else if(testNwLocContext.transInfos[trans_id].state == TEST_NWAL_HANDLE_STATE_CLOSE_PENDING) { System_printf ("Set Security Policy Close ACK received for trans_id: %d\n", testNwLocContext.transInfos[trans_id].transType,trans_id); nwal_SystemFlush(); testNwLocContext.transInfos[trans_id].state =TEST_NWAL_HANDLE_STATE_IDLE; } break; } #endif default: { printf ("ERROR: 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; } } /*******************************************************/ /**************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; printf("stats reply for transid %d\n", trans_id); if(trans_id == NWAL_TRANSID_SPIN_WAIT) { printf("ERROR: callback found SPIN_WAIT transaction id. SO CANT FIND OUT WHO WE ARE]n"); 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; #if 0 p_local->numL4PktsRecvd=stats->; p_local->numL4PktsSent=stats->; p_local->TxErrDrop=stats->; #endif //callout result to application !! if (p_local->stats_cb) (*p_local->stats_cb)(p_trans->netapi_handle,stats); }