1 /******************************************
2 * File: net_test_router.c
3 * Purpose: net_test_router application
4 **************************************************************
5 * FILE: net_test_router.c
6 *
7 * DESCRIPTION: netapi user space transport
8 * library net_test_router application
9 *
10 * REVISION HISTORY:
11 *
12 * Copyright (c) Texas Instruments Incorporated 2013
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 *****************************************/
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <signal.h>
49 #include <pthread.h>
51 #include "net_test.h"
52 #include "trie.h"
53 #include "string.h"
55 #include <sys/resource.h>
57 #include <ti/drv/sa/salld.h>
58 #include <ti/drv/pa/pa.h>
60 #include "net_test_utils.h"
62 extern int QUIT;
64 /* Global definitions */
65 #ifdef MULTI_THREAD
66 cpu_set_t cpu_set;
67 #endif
69 netTestConfig_t netTestCfg;
70 static netTestConfigFile_t config_file;
72 char input_file_name[] = "net_test_config.txt";
74 nwal_RetValue nwalRetVal;
75 Pktlib_HeapHandle ourHeap;
77 PKTIO_HANDLE_T *netcp_tx_chan_no_crypto;
78 PKTIO_HANDLE_T *netcp_rx_chan;
79 PKTIO_HANDLE_T *netcp_tx_chan_esp;
80 PKTIO_HANDLE_T *netcp_tx_chan_ah;
85 PKTIO_CFG_T netcp_rx_cfg={PKTIO_RX, PKTIO_NA, PKTIO_NA, 8};
86 PKTIO_CFG_T netcp_tx_cfg={PKTIO_TX, PKTIO_NA, PKTIO_NA, 8};
90 NETCP_CFG_EXCEPTION_PKT_T expPkt_appid;
92 Trie *p_trie_sa_rx;
93 Trie *p_trie_sa_tx;
96 #include "router.c"
97 extern Trie * our_router;
98 extern OUR_ROUTE_T routes[];
100 unsigned int ip[MAX_ROUTES]={BE(0x0a0100c8),BE(0x0a00000a),BE(0x0a02000a),BE(0xc0a8010a),BE(0x9eda6719)};
102 void recv_cb_router(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
103 PKTIO_METADATA_T meta[], int n_pkts,
104 uint64_t ts );
107 extern STATS_T stats[TUNE_NETAPI_NUM_CORES];
108 extern paSysStats_t netcp_stats;
110 /*******************************************
111 *************NETAPI OBJECTS***************
112 *****************************************/
113 static NETAPI_CFG_T our_netapi_default_cfg=
114 {
115 TUNE_NETAPI_PERM_MEM_SZ,
116 128, //start of packet offset for hw to place data on rx for default flow
117 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
118 TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use
119 TUNE_NETAPI_DEFAULT_NUM_BUFFERS, //#descriptors+buffers in default heap
120 64, //#descriptors w/o buffers in default heap
121 TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128, //size of buffers in default heap
122 128 , //tail room
123 256 //extra room
124 };
128 void house(NETAPI_SCHED_HANDLE_T *s);
129 NETAPI_T netapi_handle;
130 NETAPI_SCHED_HANDLE_T * our_sched;
131 #ifdef MULTI_THREAD
132 NETAPI_SCHED_HANDLE_T * scheduler[TUNE_NETAPI_NUM_CORES];
133 #endif
134 NETAPI_SCHED_CONFIG_T our_sched_cfg={
135 NETAPI_SCHED_DURATION|NETAPI_SCHED_CBV, 0, house, 5000000 //every 5000000 poll loops
136 };
139 NETCP_CFG_IP_T ip_rule[NET_TEST_MAX_IP];
140 NETCP_CFG_MACIF_T mac[NET_TEST_MAX_MAC];
144 /* security objects. (for loopback mode) */
145 netTestSA_t sa_info[MAX_SEC_INDEX];
148 NETCP_CFG_IPSEC_POLICY_T rx_policy[MAX_SEC_INDEX];
153 /*************************END NETAPI OBJECTS***********************/
155 void update_header(HEAD_T * p_head, int len)
156 {
157 unsigned char *p = (unsigned char *) &p_head->udp[1];
158 len -= (20+14);
159 /* update ip checksum */
160 /* update udp checksum */
161 /* update length */
162 *p= (len&0xff00)>>8;
163 *(p+1) = len&0xff;
164 }
166 #ifdef MULTI_THREAD
167 /* Templates to build command labels at startup up time, required by open_pktio_tx_channels() */
168 nwalTxPktInfo_t txPktInfoESP =
169 {
170 NULL, /* p_pkt */
171 NWAL_TX_FLAG1_DO_IPSEC_ESP_CRYPTO| NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID, /* txFlags */
172 0, /* lpbackPass */
173 1, /* enetport */
174 0, /* msuSize */
175 0, /* startOffset */
176 netTest_MAC_HEADER_LEN + netTest_IP_HEADER_LEN, /* saOffBytes */
177 0, /* saPayLoadLen */
178 0 , /* saAhIcvOffBytes */
179 0, /* saAhMacSize */
180 0, /* etherLenOffBytes */
181 netTest_MAC_HEADER_LEN, /* ipOffBytes */
182 0, /* l4OffBytes */
183 0, /* l4HdrLen */
184 0, /* pseudoHdrChecksum */
185 0 /* pLoadLen */
186 };
189 nwalTxPktInfo_t txPktInfoAH =
190 {
191 NULL, /* p_pkt */
192 NWAL_TX_FLAG1_DO_IPSEC_AH_CRYPTO| NWAL_TX_FLAG1_DO_IPV4_CHKSUM | NWAL_TX_FLAG1_META_DATA_VALID, /* txFlags */
193 0, /* lpbackPass */
194 0, /* enetport */
195 0, /* msuSize */
196 0, /* startOffset */
197 netTest_MAC_HEADER_LEN + netTest_IP_HEADER_LEN, /* saOffBytes */
198 0, /* saPayLoadLen */
199 netTest_MAC_HEADER_LEN + netTest_IP_HEADER_LEN + netTest_IPSEC_AH_FIXED_HDR_SIZE, /* saAhIcvOffBytes */
200 12, /* saAhMacSize */
201 0, /* etherLenOffBytes */
202 netTest_MAC_HEADER_LEN, /* ipOffBytes */
203 0, /* l4OffBytes */
204 netTest_UDP_HEADER_LEN, /* l4HdrLen */
205 0, /* pseudoHdrChecksum */
206 0 /* pLoadLen */
207 };
209 nwalTxPktInfo_t txPktInfoNoCrypto =
210 {
211 NULL, /* p_pkt */
212 NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID, /* txFlags */
213 0, /* lpbackPass */
214 0, /* enetport */
215 0, /* msuSize */
216 0, /* startOffset */
217 0, /* saOffBytes */
218 0, /* saPayLoadLen */
219 0 , /* saAhIcvOffBytes */
220 0, /* saAhMacSize */
221 0, /* etherLenOffBytes */
222 netTest_MAC_HEADER_LEN, /* ipOffBytes */
223 netTest_MAC_HEADER_LEN +netTest_IP_HEADER_LEN, /* l4OffBytes */
224 netTest_UDP_HEADER_LEN, /* l4HdrLen */
225 0, /* pseudoHdrChecksum */
226 0 /* pLoadLen */
227 };
229 void close_pktio_channels(void)
230 {
231 int err;
232 netapi_pktioClose(netcp_tx_chan_no_crypto ,&err);
233 netapi_pktioClose(netcp_tx_chan_esp ,&err);
234 netapi_pktioClose(netcp_tx_chan_ah ,&err);
235 }
239 void open_pktio_tx_channels()
240 {
241 int err;
242 /* open netcp default TX channels */
243 netcp_tx_chan_no_crypto= netapi_pktioOpen(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg, &err);
244 if (!netcp_tx_chan_no_crypto)
245 {
246 netapi_Log("pktio open TX failed err=%d\n",err);
247 exit(1);
248 }
249 else
250 {
251 if(netTestCfg.ipsec_mode_tx == IPSEC_MODE_TX_INFLOW)
252 {
253 PKTIO_CONTROL_T control;
254 control.op = PKTIO_UPDATE_FAST_PATH;
255 PKTIO_CFG_T cfg;
256 cfg.fast_path_cfg.fp_send_option = PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT;
257 cfg.fast_path_cfg.txPktInfo= &txPktInfoNoCrypto;
258 //netapi_pktioControl(netcp_tx_chan_no_crypto, NULL, &cfg, &control, &err);
259 }
260 }
261 /* open netcp default TX for ESP packets */
262 netcp_tx_chan_esp= netapi_pktioOpen(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg, &err);
263 if (!netcp_tx_chan_esp)
264 {
265 netapi_Log("pktio open TX failed err=%d\n",err);
266 exit(1);
267 }
268 else
269 {
270 if(netTestCfg.ipsec_mode_tx == IPSEC_MODE_TX_INFLOW)
271 {
272 PKTIO_CONTROL_T control;
273 control.op = PKTIO_UPDATE_FAST_PATH;
274 PKTIO_CFG_T cfg;
275 cfg.fast_path_cfg.fp_send_option = PKTIO_FP_ESP_PORT;
276 cfg.fast_path_cfg.txPktInfo= &txPktInfoESP;
277 //netapi_pktioControl(netcp_tx_chan_esp, NULL, &cfg, &control, &err);
278 }
279 }
281 /*/* open netcp default TX for AH packets */
282 netcp_tx_chan_ah= netapi_pktioOpen(netapi_handle, NETCP_TX, NULL, &netcp_tx_cfg, &err);
283 if (!netcp_tx_chan_ah)
284 {
285 netapi_Log("pktio open TX failed err=%d\n",err);
286 exit(1);
287 }
288 else
289 {
290 if(netTestCfg.ipsec_mode_tx == IPSEC_MODE_TX_INFLOW)
291 {
292 PKTIO_CONTROL_T control;
293 control.op = PKTIO_UPDATE_FAST_PATH;
294 PKTIO_CFG_T cfg;
295 cfg.fast_path_cfg.fp_send_option = PKTIO_FP_AH_PORT;
296 cfg.fast_path_cfg.txPktInfo= &txPktInfoAH;
297 //netapi_pktioControl(netcp_tx_chan_ah, NULL, &cfg, &control, &err);
298 }
299 }
300 }
305 NETAPI_T worker_nh[TUNE_NETAPI_NUM_CORES];
306 void slow_path_thread(uint32_t thread_num)
307 {
308 int err,i;
309 PKTIO_HANDLE_T *rx_chan;
310 PKTIO_HANDLE_T *sb_tx_chan;
311 PKTIO_HANDLE_T *sb_rx_chan;
314 CPU_ZERO( &cpu_set);
315 #ifdef CORTEX_A15
316 for (i = netTestCfg.sp_proc_start[thread_num]; i <= netTestCfg.sp_proc_end[thread_num];i++)
317 {
318 printf("fast_path_thread: setting cpu %d to cpu_set\n", i);
319 CPU_SET( i, &cpu_set);
320 }
321 hplib_utilSetupCore(thread_num, &cpu_set);
322 #else
323 for (i = netTestCfg.sp_proc_start[thread_num]; i <= netTestCfg.sp_proc_end[thread_num];i++)
324 {
325 printf("fast_path_thread: setting cpu %d to cpu_set\n", i);
326 CPU_SET( i, &cpu_set);
327 }
328 hplib_utilSetupCore(thread_num, &cpu_set);
329 #endif
330 worker_nh[thread_num]=netapi_init(NETAPI_CORE_MASTER,NULL);
332 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) worker_nh[thread_num];
334 /* open netcp RX channel */
335 rx_chan = netapi_pktioOpen(worker_nh[thread_num], NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg, &err);
339 netapi_setCookie(worker_nh[thread_num],(void*) (thread_num | NET_TEST_SP_THREAD_MASK));
341 scheduler[thread_num] =netapi_schedOpen(worker_nh[thread_num],&our_sched_cfg, &err);
342 if (!scheduler[thread_num])
343 {
344 netapi_Log("sched create failed for core%d\n",thread_num);
345 exit(1);
346 }
347 scheduler[thread_num]->config.yield = FALSE;
348 scheduler[thread_num]->config.pollGarbageQ = TRUE;
349 scheduler[thread_num]->config.pollCtrlQ = TRUE;
350 /*********************************************/
351 /**************Entry point into scheduler ****/
352 /*********************************************/
353 netapi_schedRun(scheduler[thread_num], &err);
354 netapi_Log(">net_test: core %d worker thread done\n",thread_num);
356 netapi_pktioClose(rx_chan, &err);
357 netapi_shutdown(worker_nh[thread_num]);
358 }
361 void fast_path_thread(uint32_t thread_num)
362 {
363 int err,i;
364 PKTIO_HANDLE_T *rx_chan;
365 PKTIO_HANDLE_T *sb_tx_chan;
366 //PKTIO_HANDLE_T *sb_rx_chan;
368 #ifdef CORTEX_A15
369 for (i = netTestCfg.fp_proc_start[thread_num]; i <= netTestCfg.fp_proc_end[thread_num];i++)
370 {
371 printf("fast_path_thread: setting cpu %d to cpu_set\n", i);
372 CPU_SET( i, &cpu_set);
373 }
374 hplib_utilSetupCore(thread_num, &cpu_set);
375 #else
376 for (i = netTestCfg.fp_proc_start[thread_num]; i <= netTestCfg.fp_proc_end[thread_num];i++)
377 {
378 printf("fast_path_thread: setting cpu %d to cpu_set\n", i);
379 CPU_SET( i, &cpu_set);
380 }
381 hplib_utilSetupCore(thread_num, &cpu_set);
382 #endif
383 worker_nh[thread_num]=netapi_init(NETAPI_CORE_MASTER,NULL);
385 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) worker_nh[thread_num];
387 /* open netcp RX channel */
388 rx_chan = netapi_pktioOpen(worker_nh[thread_num], NETCP_RX, (PKTIO_CB) recv_cb_router, &netcp_rx_cfg, &err);
389 netapi_setCookie(worker_nh[thread_num],(void*)thread_num);
391 scheduler[thread_num] =netapi_schedOpen(worker_nh[thread_num],&our_sched_cfg, &err);
392 if (!scheduler[thread_num])
393 {
394 netapi_Log("sched create failed for core%d\n",thread_num);
395 exit(1);
396 }
398 /*********************************************/
399 /**************Entry point into scheduler ****/
400 /*********************************************/
401 scheduler[thread_num]->config.yield = FALSE;
402 scheduler[thread_num]->config.pollGarbageQ = FALSE;
403 scheduler[thread_num]->config.pollCtrlQ = FALSE;
404 //sleep(100000);
405 netapi_schedRun(scheduler[thread_num], &err);
406 netapi_Log(">net_test: core %d worker thread done\n",thread_num);
408 netapi_pktioClose(rx_chan, &err);
409 netapi_shutdown(worker_nh[thread_num]);
410 \r}
412 #endif
414 /***************************************
415 ********** test driver*****************
416 ***************************************/
417 int main(int argc, char **argv)
418 {
419 int err,i;
420 Pktlib_HeapCfg heapCfg;
421 rlim_t oss,ss = 1024*1024;
422 struct rlimit rl;
423 int32_t errCode;
424 Pktlib_HeapIfTable* pPktifTable;
425 /* Local Per Process default resourcese maintained at NWAL */
426 nwalLocCxtInfo_t nwalLocCxt;
428 FILE * fpr = NULL;
431 err= getrlimit(RLIMIT_STACK,&rl);
432 if (!err) netapi_Log(" stack limit = %d\n",rl.rlim_cur); else netapi_Log("getrlimit failed\n");
434 /* install signal handler for ^c */
435 signal(SIGINT,mysig);
437 if (argc == 2)
438 {
439 fpr = fopen(argv[1], "r");
440 }
441 else
442 {
443 fpr = fopen(input_file_name, "r");
444 }
445 if (fpr == NULL)
446 {
447 exit(1);
448 }
449 else
450 {
451 memset(&config_file, 0, sizeof(netTestConfigFile_t));
452 memset(&netTestCfg, 0, sizeof(netTestConfig_t));
453 parse_config_file(fpr,&config_file);
454 }
456 memset(&sa_info, 0, sizeof(sa_info));
458 #ifdef MULTI_THREAD
459 /* assign main net_test thread to run on core 0 */
460 CPU_ZERO( &cpu_set);
461 CPU_SET( 0, &cpu_set);
462 hplib_utilSetupCore(0, &cpu_set);
463 #endif
464 /* create netapi */
465 netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);
467 /* configure expection packet handling with netapi */
468 netapi_netcpCfgExceptions(netapi_handle, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_DISCARD, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
469 expPkt_appid = netapi_netcpCfgExceptions(netapi_handle, 7, NETCP_CFG_ACTION_TO_SW, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
471 /* open the main heap */
472 ourHeap = Pktlib_findHeapByName("netapi");
473 if (!ourHeap)
474 {
475 netapi_Log("Pktlib_findHeapByName() fail\n");
476 exit(1);
477 }
479 /* Open all required PKTIO TX channels */
480 open_pktio_tx_channels();
482 netapi_Log("net_test> %d bytes left in our CMA area\n", netapi_getBufMemRemainder());
483 /* create scheduler instance */
484 our_sched =netapi_schedOpen(netapi_handle,&our_sched_cfg, &err);
485 if (!our_sched) {netapi_Log("sched create failed\n"); exit(1);}
488 /*create net_test MAC interfaces, attach IP to created MAC interfaces */
489 create_interfaces();
491 /* Lookup Database for SA context, this is used by packet processing routines to get RX and TX SA information*/
492 p_trie_sa_rx = trie_new();
493 p_trie_sa_tx = trie_new();
494 if (!p_trie_sa_rx || !p_trie_sa_tx)
495 {netapi_Log("trie alloc for SA failed\n"); exit(1);}
497 /* Create RX SA's, RX Policy and TX SA's, all SA configuration parameters are read from net_test_config.txt file */
498 create_sec_associations();
501 #ifdef MULTI_THREAD
502 {
503 char c;
504 /* create and set affinity of slow path and fast path threads to
505 * specific CPU cores as specified in the net_test_config.txt file */
506 create_sp_fp_threads();
509 //this thread of execution (main) now just waits on user input
510 for(;;)
511 {
512 printf(">");
513 c=getchar();
514 if (c=='q') {QUIT=1;break;}
515 else if (c=='s') our_stats_cb(netapi_handle, &netcp_stats);
516 else if (c=='h') printf("'q' to quit, 's' for stats, 'h' for help\n");
517 }
519 }
520 #else
521 /*********************************************/
522 /**************Entry point into scheduler ****/
523 /*********************************************/
524 netapi_schedRun(our_sched, &err);
525 #endif
527 /* done */
528 our_stats_cb(netapi_handle, NULL);
532 /* cleanup*/
533 delete_sec_associations();
534 delete_interfaces();
536 /* close pktio channels we opened via open_pktio_tx_channels() */
537 close_pktio_channels();
538 }
540 static inline void send_it(Ti_Pkt *tip, int len, ROUTE_SEC_T * p_sec, int out_port)
541 {
542 unsigned long st1;
543 unsigned long st2;
544 int err=0;
545 PKTIO_METADATA_T meta2 = {PKTIO_META_TX,{0},0};
546 nwalTxPktInfo_t meta_tx2={0};
547 st1=hplib_mUtilGetPmuCCNT();
548 #ifdef MULTI_THREAD
549 int coreid=Osal_nwalGetProcId(); //who we are(thread local)
550 //int coreid = our_core;
551 #else
552 int coreid=0;
553 #endif
554 if (len<60)
555 {
556 unsigned int templen;
557 char * p_pkt;
558 len=60;
559 Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
560 Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
561 stats[coreid].tx_min+=1;
562 }
563 Pktlib_setPacketLen(tip,len);
564 meta_tx2.txFlag1 = (NWAL_TX_FLAG1_DO_IPV4_CHKSUM| NWAL_TX_FLAG1_META_DATA_VALID );
565 meta_tx2.startOffset = 0;
566 meta_tx2.ipOffBytes = netTest_MAC_HEADER_LEN;
567 meta_tx2.ploadLen = len ;
568 meta_tx2.enetPort=out_port;
569 if(p_sec)
570 {
571 meta_tx2.txFlag1 |= NWAL_TX_FLAG1_DO_IPSEC_ESP_CRYPTO ;
572 //meta2.sa_handle = (void*)p_sec->tx_tunnel;
573 meta2.sa_handle=p_sec->tx_inflow_mode_handle;
574 meta_tx2.saOffBytes=netTest_MAC_HEADER_LEN + netTest_IP_HEADER_LEN;
575 meta_tx2.saPayloadLen=len-netTest_MAC_HEADER_LEN - netTest_IP_HEADER_LEN; //don't include tag, mac and outer header
576 meta2.u.tx_meta=&meta_tx2;
577 pktio_send(netcp_tx_chan_esp,tip,&meta2,&err);
578 stats[coreid].sec_tx+=1;
579 }
580 else
581 {
582 meta2.u.tx_meta=&meta_tx2;
583 pktio_send(netcp_tx_chan_no_crypto,tip,&meta2,&err);
585 }
586 stats[coreid].tx +=1;
587 st2=hplib_mUtilGetPmuCCNT();
588 stats[coreid].send_cycles += (unsigned long long) (st2-st1);
589 }
590 void recv_cb_router(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
591 PKTIO_METADATA_T meta[], int n_pkts,
592 uint64_t ts )
593 {
594 int i;
595 int len;
596 int p;
597 Ti_Pkt * tip;
598 unsigned int templen;
599 char * p_pkt;
600 HEAD_T temp_head;
601 unsigned int appid;
602 IP_HEAD_T th;
603 ROUTE_SEC_T *sec_data=NULL;
604 unsigned long t1;
605 unsigned long t2;
606 unsigned long long ct1;
607 unsigned long long ct2;
608 unsigned short ip_pl;
609 unsigned long long n_c_ops;
610 int ifno;
611 int out_port;
612 #ifdef MULTI_THREAD
613 int coreid=Osal_nwalGetProcId(); //who we are(thread local)
614 //int coreid = our_core;
615 #else
616 int coreid=0;
617 #endif
618 t1=hplib_mUtilGetPmuCCNT();
619 ct1 =Osal_cache_op_measure(&n_c_ops);
620 for(i=0;i<n_pkts;i++)
621 {
622 ifno = ((unsigned int)meta[i].u.rx_meta->appId)&0xff;
623 if(coreid<TUNE_NETAPI_NUM_CORES) stats[coreid].rx+=1;
624 if (ifno < TUNE_NETAPI_MAX_NUM_MAC) stats[coreid].if_rx[ifno]+=1;
625 tip = p_recv[i];
626 Pktlib_getDataBuffer(tip,(uint8_t**)&p_pkt,&templen);//ignore templen
627 len = Pktlib_getPacketLen(tip)-4;//real length, subtract mac trailer
628 stats[coreid].rx+=1;
629 appid = ((unsigned int)meta[i].u.rx_meta->appId)&0xff000000;
630 switch(appid)
631 {
632 case(NETAPI_NETCP_MATCH_IPSEC):
633 case(NETAPI_NETCP_MATCH_IPSEC_POLICY):
634 {
635 int tailen=12+2;
636 memcpy(&temp_head,&p_pkt[14],sizeof(HEAD_T));
637 if (!check_header(&temp_head,&meta[i])) {
638 stats[coreid].n_bad+=1;
639 Pktlib_freePacket(tip);
640 continue;
641 }
642 tailen+=p_pkt[len-12-2]; //padding length (12)should come from sec_ptr
643 p_pkt = &p_pkt[8+16+20]; //16= iv len, should come from sec_ptr
644 len -= (8+16+20+tailen); //16= iv len should come from sec ptr
646 //now check inner headder.
647 memcpy(&th,&p_pkt[14],20);
648 if (!check_header(&temp_head,&meta[i])) {
649 stats[coreid].n_bad+=1;
650 Pktlib_freePacket(tip);
651 continue;
652 }
653 Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc *) tip, p_pkt,len);
654 Pktlib_setPacketLen(tip,len);
656 if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data,&out_port)<0)
657 {
658 stats[coreid].n_bad+=1;
659 Pktlib_freePacket(tip);
660 }
661 else
662 {
663 send_it(tip,len,sec_data,out_port);
664 }
665 break;
666 }
667 case(NETAPI_NETCP_MATCH_GENERIC_MAC):
668 if((p_pkt[12]!=0x8)||(p_pkt[13]!=0x00))
669 {
670 stats[coreid].n_new+=1;
671 Pktlib_freePacket(tip);
672 continue;
673 }
674 if (!check_header(&temp_head,&meta[i]))
675 {
676 stats[coreid].n_bad+=1;
677 Pktlib_freePacket(tip);
678 continue;
679 }
680 memcpy(&th,&p_pkt[14],20);
681 ip_pl= (((unsigned char *)&th.w1)[2]<<8) | ((unsigned char *)&th.w1)[3];
682 if ((ip_pl+14)<60)
683 {
684 len-= (60-(ip_pl+14));
685 stats[coreid].rx_min+=1;
686 }
687 Pktlib_setPacketLen(tip,len);
688 if (route_pkt(our_router, tip, &th, p_pkt, &len,&sec_data,&out_port)<0)
689 {
690 stats[coreid].n_bad+=1;
691 Pktlib_freePacket(tip);
692 }
693 else
694 {
695 send_it(tip,len,sec_data,out_port);
696 }
697 break;
698 case(NETAPI_NETCP_MATCH_GENERIC_IP):
699 Pktlib_freePacket(tip);
700 stats[coreid].n_new=1;
701 break;
702 default:
703 stats[coreid].n_new+=1;
704 Pktlib_freePacket(tip);
705 break;
706 }
707 }
708 t2=hplib_mUtilGetPmuCCNT();
709 ct2 =Osal_cache_op_measure(&n_c_ops);
710 stats[coreid].app_cycles += (unsigned long long) (t2-t1);
711 stats[coreid].tx_cache_cycles += (unsigned long long) (ct2-ct1);
712 return;
713 }
715 /* STUB functions required for compilation */
716 void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
717 PKTIO_METADATA_T meta[], int n_pkts,
718 uint64_t ts )
719 {
720 }
722 void recv_sb_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
723 PKTIO_METADATA_T meta[], int n_pkts,
724 uint64_t ts )
725 {
726 }