/********************************* * FILE: pktio.c * PURPOSE: pktio library for NETAPI ************************************************************** * FILE: pktio.c * * DESCRIPTION: pktio 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" /*--------------------Utilites-----------------*/ static PKTIO_HANDLE_T * pktiop_get_free_channel_slot(NETAPI_T n) { PKTIO_HANDLE_T * pp = (PKTIO_HANDLE_T*) netapi_get_pktio_list(n); int i; for(i=0;iinuse != PKTIO_INUSE) { return pp; } pp+=1; } return NULL; } /*-----------------------MAIN API----------------------*/ /* create a channel */ PKTIO_HANDLE_T * pktio_create(NETAPI_T n, char * name, PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err) { int r = 0; PKTIO_HANDLE_T *p; uint8_t isAllocated; *err=0; if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;} /* get a free channel handle */ p=pktiop_get_free_channel_slot(n); if (!p) {*err = PKTIO_NOMEM; return (p); } p->inuse= PKTIO_INUSE; p->back = n; p->cb = cb; p->max_n = p_cfg->max_n; memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T)); /* create a general queue (for now). TODO: allow qnum to be passed in */ p->q = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated); if (p->q == (Qmss_QueueHnd) NULL) { printf("pktio_create: queueOpen failed\n"); p->inuse=0; *err= NETAPI_ERR_QLLD; ///queue lld error return NULL; } p->qInfo = Qmss_getQueueNumber(p->q); if (p->cfg.flags2 & PKTIO_PKT) { p->use_nwal =1; p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); } else p->use_nwal=0; /* save name */ strncpy(p->name,name, strlen(name)flags1 & PKTIO_GLOBAL) ) { //todo: make sure this succeeds.. netapi_add_global_pktio(n, name, &p->qInfo); } ((NETAPI_HANDLE_T *)n )->n_pktios+=1; return p; } /***********************************************************/ /************** open an existing channel. *****************/ /***********************************************************/ PKTIO_HANDLE_T * pktio_open(NETAPI_T n, char *name, PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p, *p2; uint8_t isAllocated; *err=0; Qmss_Queue *p_qnum; if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;} /* get a free channel handle */ p=pktiop_get_free_channel_slot(n); if (!p) {*err = PKTIO_NOMEM; return (p); } ((NETAPI_HANDLE_T *)n)->n_pktios+=1; p->inuse= PKTIO_INUSE; p->back = n; p->cb = cb; p->max_n = p_cfg->max_n; memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T)); /* special handling of NETCP_RX, NETCP_TX */ if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) ) { /* these have already been opened internally, so don't search in global list */ p->use_nwal = 2; p->q = 0; p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); } else { /* find queue in global list */ p_qnum = netapi_find_global_pktio(n, name); if (!p_qnum ) { printf("pktio_open: can't find %s\n",name); p->inuse=0; *err= NETAPI_ERR_NOTFOUND; ///queue lld error return NULL; } /* open a general queue (for now). use qnum that was just found */ p->q = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE, p_qnum->qNum , &isAllocated); if (p->q == (Qmss_QueueHnd) NULL) { printf("pktio_create: queueOpen failed\n"); p->inuse=0; *err= NETAPI_ERR_QLLD; ///queue lld error return NULL; } p->qInfo = Qmss_getQueueNumber(p->q); if (p_cfg->flags2 & PKTIO_PKT) { p->use_nwal =1; p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); } else p->use_nwal=0; } /* save name */ strncpy(p->name,name, strlen(name)cb = cb; } if (p_control) { } if (p_cfg) { p->max_n = p_cfg->max_n; memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T)); } *err=0; return; } /***********************************************************/ /*****************close ***************************/ /***********************************************************/ void pktio_close(PKTIO_HANDLE_T * p, int * err) { if(!p) { *err=1; return;} *err=0; //Qmss_queueClose(p->q); p->q=-1; p->inuse=0; ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1; return; } /***********************************************************/ /*****************Delete***************************/ /***********************************************************/ void pktio_delete(PKTIO_HANDLE_T * p, int * err) { if(!p) { *err=1; return;} *err=0; /* todo remove from name list */ if(p->use_nwal !=2) { Qmss_queueClose(p->q); } p->q=-1; p->inuse=0; ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1; return ; } /***********************************************************/ /*****************send *************************/ /***********************************************************/ int pktio_send(PKTIO_HANDLE_T * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { nwalTxPktInfo_t * pPktInfo=m->u.tx_meta; nwal_RetValue res; *err=0; if(! (p->cfg.flags1&PKTIO_W)) return 0; if (p->use_nwal) { pPktInfo->pPkt = pkt; //todo metadata res=nwal_send(p->nwalInstanceHandle, nwal_HANDLE_INVALID,pPktInfo); if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res; } else { /* process meta data */ Qmss_queuePushDesc (p->q, (void*)pkt); } return 1; } /***********************************************************/ /*******************send multiple**************************/ /***********************************************************/ int pktio_sendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err) { int r=0; *err=0; if(! p->cfg.flags1&PKTIO_W) return 0; if (p->use_nwal) { for(r=0;ru.tx_meta; nwal_RetValue res; pPktInfo->pPkt = pkt[r]; res=nwal_send(p->nwalInstanceHandle,nwal_HANDLE_INVALID,pPktInfo); if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res; } } else { for(r=0;rq, (void*) pkt[r]); } } return r; } /***********************************************************/ /******************* polling **********************/ /***********************************************************/ /* poll a particular channel */ int pktio_poll(PKTIO_HANDLE_T * p, PKTIO_POLL_T * p_poll_cfg, int * err) { int r=0; int n; Ti_Pkt * temp; Ti_Pkt * pkt_list[PKTIO_MAX_RECV]; PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV]; uint64_t ts= netapi_getTimestamp(); //get_ts if(! p->cfg.flags1&PKTIO_R) return 0; /** poll the netcp default RX queue we squirt out below */ if (p->use_nwal==2) { /* Poll for common L2/L3 packets */ nwal_pollPkt(p->nwalInstanceHandle, nwal_POLL_DEFAULT_GLOB_PKT_Q, (uint32_t) p, p->max_n, QMSS_PARAM_NOT_SPECIFIED, (void*) NULL); } /** poll a netcp RX queue. we squirt out below */ else if (p->use_nwal==1) { /* Poll an additional NETCP RX queue */ nwal_pollPkt(p->nwalInstanceHandle, nwal_POLL_APP_MANAGED_PKT_Q, (uint32_t) p, p->max_n, p->q, (void *) NULL); } /* poll an IPC queue */ else { *err=0; n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV; for(r=0;rq)); if(!temp) break; /* process meta data */ pkt_list[r]= temp; meta_s[r].flags1=0x1; } if (r) p->cb(p, pkt_list, &meta_s[0], r, ts); } return r; } /***********************************************************/ /** poll all channels attached to this handle */ /***********************************************************/ int pktio_pollAll(NETAPI_T handle, PKTIO_POLL_T * p_poll_cfg, int *err) { int i=0; int r=0; int err2; int cnt=0; PKTIO_HANDLE_T *pp =( PKTIO_HANDLE_T *) netapi_get_pktio_list(handle); *err=0; for(i=0;in_pktios;i++,pp+=1) { if (pp->inuse != PKTIO_INUSE) continue; if(!(pp->cfg.flags1&PKTIO_R)) continue; r+=pktio_poll(pp, p_poll_cfg, &err2); cnt+=1; if (err2) { *err = err2; break;} } return r; } /***** this is the callback we registered with NWAL for pkt reception *****/ /* appcookie -> pktio handle */ void netapi_NWALRxPktCallback (uint32_t appCookie, uint8_t numPkts, nwalRxPktInfo_t* pPktInfo, uint64_t timestamp, nwal_Bool_t* pFreePkt) { PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie; int r=0; int n; Ti_Pkt * pkt_list[PKTIO_MAX_RECV]; PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV]; for(r=0;rcb(p, pkt_list, &meta_s[0], r, timestamp); }