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)
100 {
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;
115 }
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)
120 {
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;
129 }
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)
134 {
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)
142 {
143 *err= NETAPI_ERR_BAD_INPUT;
144 return 0;
145 }
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)
150 {
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++)
160 {
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;
176 }
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)
181 {
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;
197 }
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)
202 {
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;
213 }
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)
219 {
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;
235 }
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)
241 {
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;
252 }
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)
258 {
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;
331 }
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)
339 {
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)) )
365 {
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;
378 }
379 else if( (!strcmp(name, NETCP_SB_RX)) || (!strcmp(name,NETCP_SB_TX)) )
380 {
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;
387 }
388 else
389 {
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");
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 }
435 }
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;
445 }
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)
455 {
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;
488 }
490 /***********************************************************/
491 /*****************close ***************************/
492 /***********************************************************/
493 void pktio_close(PKTIO_HANDLE_T * p, int * err)
494 {
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;
502 }
504 /***********************************************************/
505 /*****************Delete***************************/
506 /***********************************************************/
507 void pktio_delete(PKTIO_HANDLE_T * p, int * err)
508 {
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 ;
524 }
527 /***********************************************************/
528 /*****************send *************************/
529 /***********************************************************/
530 int pktio_send_genric(PKTIO_HANDLE_T * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err)
531 {
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;
569 }
571 /***********************************************************/
572 /*******************send multiple**************************/
573 /***********************************************************/
574 int pktio_sendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err)
575 {
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;
609 }
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)
617 {
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;
702 }
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)
708 {
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);
715 *err=0;
716 for(i=0;i<NETAPI_MAX_PKTIO && cnt < ((NETAPI_HANDLE_T *)handle)->n_pktios;i++)
717 {
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;}
722 }
723 return r;
725 }
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)
734 {
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);
752 }
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)
760 {
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);
774 }