]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blob - ti/runtime/netapi/src/pktio.c
Implemented multi-core/thread protections, implemented changes to have each core...
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / pktio.c
1 /*********************************
2  * FILE: pktio.c
3  * PURPOSE: pktio library for NETAPI
4  **************************************************************
5  * FILE:  pktio.c
6  * 
7  * DESCRIPTION:  pktio source file for user space transport
8  *               library
9  * 
10  * REVISION HISTORY:  rev 0.0.1 
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2010-2011
13  * 
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  ********************************/
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include "netapi.h"
48 #include "pktio.h"
49 #include "netapi_util.h"
54 static hplib_spinLock_T pktio_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
56 /*--------------------Utilites-----------------*/
59 static PKTIO_HANDLE_T * pktiop_get_free_channel_slot(NETAPI_T n)
60 {
61         PKTIO_HANDLE_T ** pp = (PKTIO_HANDLE_T **) netapi_get_pktio_list(n);
62         int i;
63         for(i=0;i<NETAPI_MAX_PKTIO;i++)
64         {
65                 if (pp[i]->inuse != PKTIO_INUSE)
66                 {
67                         pp[i]->inuse = PKTIO_INUSE;
68                     return  pp[i];
69                 }
70         }
71         return NULL;
72 }
75 /*-----------------------------------------------------*/
76 /*          optimized send/rcv functions              */
77 /*----------------------------------------------------*/
79 //********************************************
80 //send pkt via ipc queue 
81 //********************************************
82 static int pktio_send_ipc(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
83 {
84         PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
85         *err=0;
86 #ifdef PKTIO_GET_BENCHMARK
87         p->vv8p=netapi_timing_stop();
88 #endif
89         Qmss_queuePushDesc (p->q, (void*)pkt);
91 #ifdef PKTIO_GET_BENCHMARK
92         p->vv9p=netapi_timing_stop();
93 #endif
94         return 1;
95 }
96 //********************************************
97 //send pkt to NETCP via NWAL
98 //********************************************
99 static int pktio_send_nwal(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
101         PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
102         nwalTxPktInfo_t * pPktInfo=m->u.tx_meta;
103         nwal_RetValue res;
104         *err=0;
105         pPktInfo->pPkt = pkt;
106 #ifdef PKTIO_GET_BENCHMARK
107         p->vv11p=netapi_timing_stop();
108 #endif
109         res=nwal_send(p->nwalInstanceHandle, m->sa_handle,pPktInfo);
110 #ifdef PKTIO_GET_BENCHMARK
111         p->vv12p=netapi_timing_stop();
112 #endif
113         if (res != nwal_OK) {  *err = NETAPI_ERR_NWAL_TX_ERR -res;}
114         return 1;
116 //********************************************
117 //send to SA via SB queue
118 //********************************************
119 static int pktio_send_sb(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
121         PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
122         nwalDmTxPayloadInfo_t *pPktInfoSB =  m->u.tx_sb_meta;
123         nwal_RetValue res;
124         *err=0;
125         pPktInfoSB->pPkt = pkt;
126         res=nwal_sendDM(p->nwalInstanceHandle, m->sa_handle,pPktInfoSB);
127         if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
128         return 1;
130 //********************************************
131 //dummy.  return err
132 //********************************************
133 static int pktio_send_dummy(struct PKTIO_HANDLE_tag * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
135         *err =  NETAPI_ERR_BAD_INPUT;
136         return -1;
137
138 //*******************************************
139 //dummy poll
140 //*******************************************
141 static int pktio_poll_dummy(struct PKTIO_HANDLE_tag * p, PKTIO_POLL_T * p_poll_cfg,  int * err)
143         *err= NETAPI_ERR_BAD_INPUT;
144         return 0;
146 //********************************************
147 //poll IPC queue
148 //********************************************
149 static int pktio_poll_ipc(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg,  int * err)
151 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
152 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
153 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
154 int r=0;
155 int n;
156 Ti_Pkt * temp;
157 *err=0;
158 n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV;
159 for(r=0;r<n;r++)
161 #ifdef PKTIO_GET_BENCHMARK
162       if (r==0) p->vv7p=netapi_timing_stop();
163 #endif
164       temp=(Ti_Pkt*)(Cppi_HostDesc*)QMSS_DESC_PTR(Qmss_queuePop(p->q));
166 #ifdef PKTIO_GET_BENCHMARK
167       if (r==0) p->vv10p=netapi_timing_stop();
168 #endif
169       if(!temp) break;
170          /* process meta data */
171          pkt_list[r]= temp;
172          meta_s[r].flags1=0x1;
173       }
174       if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL);
175       return r;
177 //********************************************
178 //poll nwal data queues for pkts from netcp
179 //********************************************
180 static int pktio_poll_nwal(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg,  int * err)
182 int r=0;
183 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
184 *err=0;
185         /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are
186          set.. optimizaion maybe? */
187 #ifdef PKTIO_GET_BENCHMARK
188         p->vv13p=netapi_timing_stop();
189 #endif
190         r=nwal_pollPkt(p->nwalInstanceHandle,
191                    p->poll_flags,
192                    (uint32_t) p,
193                    p->max_n,
194                    QMSS_PARAM_NOT_SPECIFIED,
195                    (void*) NULL);
196         return r;
198 //********************************************
199 //poll nwal sideband queues for pkts from SA
200 //********************************************
201 static int  pktio_poll_sb(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg,  int * err)
203 int r=0;
204 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
205 *err=0;
206       r=nwal_pollDm(p->nwalInstanceHandle,
207                     nwal_POLL_DM_DEF_SB_SA_Q,
208                      (uint32_t) p,
209                      p->max_n,
210                      QMSS_PARAM_NOT_SPECIFIED,
211                      (void *) NULL);
212       return r;
215 //********************************************
216 //poll app-provided netcp rx queue
217 //********************************************
218 static int pktio_poll_nwal_adj(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg,  int * err)
220 int r=0;
221 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
222 *err=0;
223         /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are
224          set.. optimizaion maybe? */
225 #ifdef PKTIO_GET_BENCHMARK
226         p->vv14p=netapi_timing_stop();
227 #endif
228         r=nwal_pollPkt(p->nwalInstanceHandle,
229                      nwal_POLL_APP_MANAGED_PKT_Q,
230                      (uint32_t) p,
231                      p->max_n,
232                      p->q,
233                      (void *)  NULL);
234         return r;
237 //********************************************
238 //poll app-defined sideband queues for pkts from SA
239 //********************************************
240 static int  pktio_poll_sb_adj(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg,  int * err)
242 int r=0;
243 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
244 *err=0;
245       r=nwal_pollDm(p->nwalInstanceHandle,
246                      nwal_POLL_DM_APP_MANAGED_Q,
247                      (uint32_t) p,
248                      p->max_n,
249                      p->q,
250                      (void *)  NULL);
251       return r;
254 /*-----------------------MAIN API----------------------*/
255 /* create a channel */
256 PKTIO_HANDLE_T * pktio_create(NETAPI_T n, char * name,
257                               PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err)
259 int r = 0;
260 PKTIO_HANDLE_T *p;
261 uint8_t         isAllocated;
263 *err=0;
265 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
266 if ((p_cfg->flags2 & PKTIO_PKT) &&(p_cfg->flags1& PKTIO_W)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;};
267 if ((p_cfg->flags2 & PKTIO_SB) &&(p_cfg->flags1& PKTIO_W)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;};
269 /* get a free channel handle */
270 p=pktiop_get_free_channel_slot(n);
272 if (!p) {*err = PKTIO_NOMEM; return (p); }
274 /* p->inuse= PKTIO_INUSE;   moved to pktiop_get_free_channel_slot */
275 p->back = n;
276 p->cb = cb;
277 p->max_n = p_cfg->max_n;
278 p->_poll=pktio_poll_dummy;
279 p->_send=pktio_send_dummy;
280 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
282     /* create a  general queue (for now). todo: allow qnum to be passed in */
283      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
284                        QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
285     if (p->q == (Qmss_QueueHnd) NULL)
286     {
287         printf(">pktio_create:  queueOpen failed\n");
288         p->inuse=0;
289         *err= NETAPI_ERR_QLLD;  ///queue lld error
290         return NULL;
291     }
292     p->qInfo = Qmss_getQueueNumber(p->q);
293     if (p_cfg->flags2 & PKTIO_PKT)
294     {
295        p->use_nwal = PKTIO_4_ADJ_NWAL;
296        p->_poll=pktio_poll_nwal_adj;
297        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n);
298     }
299     else if (p_cfg->flags2 & PKTIO_SB)
300     {
301        p->use_nwal = PKTIO_4_ADJ_SB;
302        p->_poll=pktio_poll_sb_adj;
303        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n);
304     }
305     else
306     {
307         p->use_nwal=0;
308         if (p_cfg->flags1& PKTIO_W) p->_send=pktio_send_ipc;
309         if (p_cfg->flags1& PKTIO_R) p->_poll=pktio_poll_ipc;
310     }
312     /* save name */ 
313     strncpy(p->name,name,
314        strlen(name)<PKTIO_MAX_NAME ?
315                strlen(name):PKTIO_MAX_NAME);   
317     /* add name, qnum to global name list */
318    if ((strcmp(name,NETCP_RX)) && (strcmp(name,NETCP_TX)) && 
319        (strcmp(name,NETCP_SB_RX)) &&
320        (strcmp(name,NETCP_SB_TX)) &&
321        (p_cfg->flags1 & PKTIO_GLOBAL) )
322    {
323          //todo: make sure this succeeds..
324         hplib_mSpinLockLock(&pktio_lock);
325         r=netapi_add_global_pktio(n, name, &p->qInfo);
326         hplib_mSpinLockUnlock(&pktio_lock);
327     }
329   ((NETAPI_HANDLE_T *)n )->n_pktios+=1;
330    return p;
334 /***********************************************************/
335 /************** open an existing channel.  *****************/
336 /***********************************************************/
337 PKTIO_HANDLE_T * pktio_open(NETAPI_T  n, char *name,
338                             PKTIO_CB cb,  PKTIO_CFG_T * p_cfg, int * err)
340 int r=0;
341 PKTIO_HANDLE_T *p, *p2;
342 uint8_t         isAllocated;
343 *err=0;
344 Qmss_Queue *p_qnum;
346 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
348 /* get a free channel handle */
350 p=pktiop_get_free_channel_slot(n);
352 if (!p) {*err = PKTIO_NOMEM; return (p); }
353 ((NETAPI_HANDLE_T *)n)->n_pktios+=1;
355 p->inuse= PKTIO_INUSE;
356 p->back = n;
357 p->cb = cb;
358 p->max_n = p_cfg->max_n;
359 p->_poll=pktio_poll_dummy;
360 p->_send=pktio_send_dummy;
361 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
363 /* special handling of NETCP_RX, NETCP_TX */
364 if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) )
366     printf("pktio_open: trace 1\n");
367    /* these have already been opened internally, so don't search in global list */
368     p->use_nwal = PKTIO_DEF_NWAL;
369     p->q = 0;  
370     p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n);
371     printf("pktio_open1: nwalInstanceHandle 0x%x\n", p->nwalInstanceHandle);
372     if (!strcmp(name,NETCP_RX)) 
373     {
374         p->_poll=pktio_poll_nwal; 
375         p->poll_flags= nwal_POLL_DEFAULT_GLOB_PKT_Q|  nwal_POLL_DEFAULT_PER_PROC_PKT_Q;
376     }
377     if (!strcmp(name,NETCP_TX)) p->_send=pktio_send_nwal;
379 else if( (!strcmp(name, NETCP_SB_RX)) || (!strcmp(name,NETCP_SB_TX)) )
381    /* these have already been opened internally, so don't search in global list */
382     p->use_nwal =  PKTIO_DEF_SB;
383     p->q = 0;
384     p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n);
385     if (!strcmp(name,NETCP_SB_RX)) p->_poll=pktio_poll_sb;
386     if (!strcmp(name,NETCP_SB_TX)) p->_send=pktio_send_sb;
388 else
390     hplib_mSpinLockLock(&pktio_lock); 
391     /* find queue in global list */
392     p_qnum = netapi_find_global_pktio(n, name);
393      printf("pktio_open: trace 2\n");
394     
395     hplib_mSpinLockUnlock(&pktio_lock);
396  if (!p_qnum ) 
397   {
398         printf(">pktio_open: can't find %s\n",name);
399         p->inuse=0;
400        *err= NETAPI_ERR_NOTFOUND;  ///queue lld error
401         return NULL;
402   }
404  /* open a  general queue (for now). use qnum that was just found */
405      p->q  = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
406                        p_qnum->qNum , &isAllocated);
407     if (p->q == (Qmss_QueueHnd) NULL)
408     {
409         printf(">pktio_create:  queueOpen failed\n");
410         p->inuse=0;
411         *err= NETAPI_ERR_QLLD;  ///queue lld error
412         return NULL;
413     }
414     p->qInfo = Qmss_getQueueNumber(p->q);
415     printf("pktio_open: queueMgr %d\,  queueNum; %d\n", p->qInfo.qMgr, p->qInfo.qNum);
416     if (p_cfg->flags2 & PKTIO_PKT)
417     {
418        p->use_nwal = PKTIO_4_ADJ_NWAL;  //additonal RX q for nwal
419        p->_poll = pktio_poll_nwal_adj;
420        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n); 
421        printf("pktio_open: nwalInstanceHandle 0x%x\n", p->nwalInstanceHandle);
422     } 
423     else if (p_cfg->flags2 & PKTIO_SB)
424     {
425        p->use_nwal = PKTIO_4_ADJ_SB;  //additional RX q for sideband with NWAL
426        p->_poll = pktio_poll_sb_adj;
427        p->nwalInstanceHandle = netapi_return_nwal_instance_handle(n);
428     } 
429     else 
430     {
431        p->use_nwal=0; //not handled by nwal
432         if (p_cfg->flags1& PKTIO_W) p->_send=pktio_send_ipc;
433         if (p_cfg->flags1& PKTIO_R) p->_poll=pktio_poll_ipc;
434     }
437     /* save name */
438     strncpy(p->name,name,
439        strlen(name)<PKTIO_MAX_NAME ?
440                strlen(name):PKTIO_MAX_NAME);
443     printf("pktio_open: returning with sucess for name %s\n", p->name);
444 return p;
447 /***********************************************************/
448 /************** control the channel ****************/
449 /***********************************************************/
450 void pktio_control(PKTIO_HANDLE_T * p,
451                    PKTIO_CB cb,
452                    PKTIO_CFG_T * p_cfg,
453                    PKTIO_CONTROL_T * p_control,
454                    int *err)
456         if (!p) { *err=1; return;}
457         if (cb) 
458         {
459                 p->cb = cb;
460         }
461         if (p_control)
462         {
463                 /* todo: check for validity, eg don't allow clear of NETCP TX queues */
464                 /* todo: implement divert */
465                 switch(p_control->op)
466                 {
467                         //clear the queue
468                         case(PKTIO_SET_POLL_FLAGS):
469                                 p->poll_flags=p_control->poll_flags;
470                                 break;
471                         case(PKTIO_CLEAR):
472                                 netapi_zapQ(p->q);
473                                 break;
474                         case(PKTIO_DIVERT):
475                         default:
476                                 printf(">pktio_control: pktio_control op %d not implemented\n",p_control->op);
477                                 *err= NETAPI_ERR_NOT_IMPLEMENTED;
478                                 break;
479                 }
480         }
481         //all we configure is max_n.  Can't change type of queue, rx/tx, etc
482         if (p_cfg)
483         {
484                 p->max_n = p_cfg->max_n;
485         }
486         *err=0;
487         return;
490 /***********************************************************/
491 /*****************close ***************************/
492 /***********************************************************/
493 void pktio_close(PKTIO_HANDLE_T * p, int * err)
495         if(!p) { *err=1; return;}
496         *err=0;
497         if (p->q) Qmss_queueClose(p->q); //LLD keeps reference count
498         p->q=-1;
499         p->inuse=0;
500         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
501         return;
504 /***********************************************************/
505 /*****************Delete***************************/
506 /***********************************************************/
507 void pktio_delete(PKTIO_HANDLE_T * p, int * err)
509         if(!p) { *err=1; return;}
510         *err=0;
511         /* remove from name list */
512     hplib_mSpinLockLock(&pktio_lock);
513         netapi_del_global_pktio((NETAPI_HANDLE_T *)p->back, p->name);
514     hplib_mSpinLockUnlock(&pktio_lock);
515         if((p->use_nwal != PKTIO_DEF_NWAL) && (p->use_nwal != PKTIO_DEF_SB)) 
516         {
517                 netapi_zapQ(p->q);   //since we are deleting, zap the queue 
518                 Qmss_queueClose(p->q);
519         }
520         p->q=-1;
521         p->inuse=0;
522         ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
523         return ;
527 /***********************************************************/
528 /*****************send *************************/
529 /***********************************************************/
530 int pktio_send_genric(PKTIO_HANDLE_T * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
532     nwalTxPktInfo_t * pPktInfo=m->u.tx_meta;
533     nwal_RetValue res;
534     *err=0;
535     if(! (p->cfg.flags1&PKTIO_W)) return 0;
536     if ((p->use_nwal== PKTIO_DEF_NWAL) )
537     {
538         pPktInfo->pPkt = pkt;
539 #ifdef PKTIO_GET_BENCHMARK
540         p->vv11p=netapi_timing_stop();
541 #endif
542         res=nwal_send(p->nwalInstanceHandle, m->sa_handle,pPktInfo);
543 #ifdef PKTIO_GET_BENCHMARK
544         p->vv12p=netapi_timing_stop();
545 #endif
546         if (res != nwal_OK) { printf("nwal send err= %d (%x)\n", res, res);  *err = NETAPI_ERR_NWAL_TX_ERR -res;}
547     }
548         else if ((p->use_nwal== PKTIO_DEF_SB) )
549         {
550                 nwalDmTxPayloadInfo_t *pPktInfoSB =  m->u.tx_sb_meta;
551                 pPktInfoSB->pPkt = pkt;
552                 res=nwal_sendDM(p->nwalInstanceHandle, m->sa_handle,pPktInfoSB);
553                 if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
554         }
555     else
556     {
557                 /* tod: meta data for non netcp xfers */
558             /* process meta data */
559 #ifdef PKTIO_GET_BENCHMARK
560         p->vv8p=netapi_timing_stop();
561 #endif
562         Qmss_queuePushDesc (p->q, (void*)pkt);
564 #ifdef PKTIO_GET_BENCHMARK
565         p->vv9p=netapi_timing_stop();
566 #endif
567     }
568     return 1;
571 /***********************************************************/
572 /*******************send multiple**************************/
573 /***********************************************************/
574 int pktio_sendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err)
576         nwal_RetValue res;
577         int r=0;
578         *err=0;
579         if(! p->cfg.flags1&PKTIO_W) return 0;
580         if ((p->use_nwal== PKTIO_DEF_NWAL) )
581         {
582                 for(r=0;r<np;r++)
583                 {
584                         nwalTxPktInfo_t  *pPktInfo= m[r]->u.tx_meta;
585                         pPktInfo->pPkt = pkt[r];
586                         res=nwal_send(p->nwalInstanceHandle,m[r]->sa_handle,pPktInfo);
587                         if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
588                 }
589         }
590         else if ((p->use_nwal== PKTIO_DEF_SB) )
591         {
592                 for(r=0;r<np;r++)
593                 {
594                         nwalDmTxPayloadInfo_t *pPktInfoSB  =m[r]->u.tx_sb_meta;
595                         pPktInfoSB->pPkt = pkt[r];
596                         res=nwal_sendDM(p->nwalInstanceHandle, m[r]->sa_handle,pPktInfoSB);
597                         if (res != nwal_OK) *err = NETAPI_ERR_NWAL_TX_ERR -res;
598                 }
599         }
600         else
601         {
602                 for(r=0;r<np;r++)
603                 {
604                         /* process meta data */
605                         Qmss_queuePushDesc(p->q, (void*) pkt[r]);
606                 }
607         }       
608         return r;
611 /***********************************************************/
612 /******************* polling **********************/
613 /***********************************************************/
615 /* poll a particular channel */
616 int pktio_poll_generic(PKTIO_HANDLE_T * p, PKTIO_POLL_T * p_poll_cfg,  int * err)
618 int r=0;
619 int n;
620 Ti_Pkt * temp;
621 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
622 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
623 //uint64_t ts= netapi_getTimestamp();  //get_ts
624 uint64_t ts=0LL;
626         if(! p->cfg.flags1&PKTIO_R) return 0;
628         /** poll the netcp default RX queue we squirt out below */
629         if (p->use_nwal==PKTIO_DEF_NWAL)
630         {
631                 /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are
632                    set.. optimizaion maybe? */
633 #ifdef PKTIO_GET_BENCHMARK
634             p->vv13p=netapi_timing_stop();
635 #endif
636                 r=nwal_pollPkt(p->nwalInstanceHandle,
637                      p->poll_flags,
638                      (uint32_t) p,
639                      p->max_n,
640                      QMSS_PARAM_NOT_SPECIFIED,
641                      (void*) NULL);
642         }
643         /** poll a netcp RX queue. we squirt out below */
644         else if (p->use_nwal==PKTIO_4_ADJ_NWAL)
645         {
646                 /* Poll an additional NETCP RX queue */
647 #ifdef PKTIO_GET_BENCHMARK
648                p->vv14p=netapi_timing_stop();
649 #endif
650                r=nwal_pollPkt(p->nwalInstanceHandle,
651                      nwal_POLL_APP_MANAGED_PKT_Q,
652                      (uint32_t) p,
653                      p->max_n,
654                      p->q,
655                      (void *)  NULL);
656         }
657         /** poll the NETCP default SideBand (data mode -dm) return queue **/
658         else if(p->use_nwal==PKTIO_DEF_SB)
659         {
660                  r=nwal_pollDm(p->nwalInstanceHandle,
661                      nwal_POLL_DM_DEF_SB_SA_Q,
662                      (uint32_t) p,
663                      p->max_n,
664                      QMSS_PARAM_NOT_SPECIFIED,
665                      (void *)  NULL);
667         }
668         /** poll an app define SideBand (data mode -dm) return queue **/
669         else if (p->use_nwal==PKTIO_4_ADJ_SB)
670         {            
671                  r=nwal_pollDm(p->nwalInstanceHandle,
672                      nwal_POLL_DM_APP_MANAGED_Q,
673                      (uint32_t) p,
674                      p->max_n,
675                      p->q,
676                      (void *)  NULL);
677         }
679         /* poll an IPC queue */
680         else 
681         {
682                 *err=0;
683                 n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV;
684                 for(r=0;r<n;r++)
685                 {
686 #ifdef PKTIO_GET_BENCHMARK
687             if (r==0) p->vv7p=netapi_timing_stop();
688 #endif
689                         temp=(Ti_Pkt*)(Cppi_HostDesc*)QMSS_DESC_PTR(Qmss_queuePop(p->q));
691 #ifdef PKTIO_GET_BENCHMARK
692             if (r==0) p->vv10p=netapi_timing_stop();
693 #endif
694                         if(!temp) break;
695                          /* process meta data */
696                         pkt_list[r]= temp;
697                         meta_s[r].flags1=0x1;
698                 }       
699                 if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, ts);
700         }
701         return r;
704 /***********************************************************/
705 /** poll all channels attached to this handle */
706 /***********************************************************/
707 int pktio_pollAll(NETAPI_T  handle, PKTIO_POLL_T * p_poll_cfg, int *err)
709 int i=0;
710 int r=0;
711 int err2;
712 int cnt=0;
713 PKTIO_HANDLE_T **pp =( PKTIO_HANDLE_T **)  netapi_get_pktio_list(handle);
714  
715 *err=0;
716 for(i=0;i<NETAPI_MAX_PKTIO && cnt < ((NETAPI_HANDLE_T *)handle)->n_pktios;i++)
718     if (pp[i]->inuse != PKTIO_INUSE) continue;
719     if(!(pp[i]->cfg.flags1&PKTIO_R)) continue;
720     r+=pktio_poll(pp[i],  p_poll_cfg,  &err2); cnt+=1;
721     if (err2) { *err = err2; break;}
723 return r;
727 /***** this is the callback we registered with NWAL for pkt reception *****/
728 /* appcookie -> pktio handle */
729 void netapi_NWALRxPktCallback     (uint32_t            appCookie,
730                                 uint16_t             numPkts,
731                                 nwalRxPktInfo_t*    pPktInfo,
732                                 uint64_t            timestamp,
733                                 nwal_Bool_t*        pFreePkt)
735 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;
736 int r=0;
737 int n;
738 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
739 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
741 #ifdef PKTIO_GET_BENCHMARK
742     p->vv15p=netapi_timing_stop();
743 #endif
744     for(r=0;r<numPkts;r++)
745     {
746          pkt_list[r] = pPktInfo[r].pPkt;
747          meta_s[r].flags1 = PKTIO_META_RX;
748          meta_s[r].u.rx_meta = &pPktInfo[r];
749     }
750     if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, timestamp);
754 /***** this is the callback we registered with NWAL for crypto callbcak *****/
755 /* appcookie -> pktio handle */
756 void netapi_NWALSBPktCallback     (uint32_t            appCookie,
757                                 uint16_t             numPkts,
758                                 nwalDmRxPayloadInfo_t*  pDmRxPktInfo,
759                                 nwal_Bool_t*        pFreePkt)
761 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;
762 int r=0;
763 int n;
764 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
765 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
766     for(r=0;r<numPkts;r++)
767     {
768          pkt_list[r] = pDmRxPktInfo[r].pPkt;
769          meta_s[r].flags1 =  PKTIO_META_SB_RX;
770          meta_s[r].u.rx_sb_meta = &pDmRxPktInfo[r];
771     }
772     if (r) p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL);
776