b9fcc578a4004254e56f46fbf049daa8a531ed8b
1 /*******************************
2 * FILE: netapi.c
3 * Purpose: implementation of netapi startup/shutdown
4 **************************************************************
5 * FILE: netapi.c
6 *
7 * DESCRIPTION: netapi main 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"
49 typedef struct PRESET_Tag
50 {
51 #define KMAXQ 10
52 int kqinuse[KMAXQ];
53 //more..
54 } PRESET_T;
56 /*------------internal prototypes---------------*/
57 static uint8_t* netapiSharedMemoryMalloc(uint32_t size);
58 static void netapiSharedMemoryFree(uint8_t* ptr, uint32_t size);
59 static int system_init(NETAPI_HANDLE_T *);
60 static void get_presets(PRESET_T * p_preset);
61 static void netapi_cleanup_at_start(void);
64 /*------------globals-----------------*/
65 #define NUM_HOST_DESC (TUNE_NETAPI_NUM_LOCAL_DESC)
66 #define SIZE_LOCAL_DESC (TUNE_NETAPI_DESC_SIZE)
67 #define SIZE_SHARED_DESC (TUNE_NETAPI_DESC_SIZE)
69 #define CONFIG_BUFSIZE_PA_INST 256
70 #define CONFIG_BUFSIZE_L2_TABLE 1000
71 #define CONFIG_BUFSIZE_L3_TABLE 4000
73 static NETAPI_CFG_T netapi_default_cfg=
74 {
75 TUNE_NETAPI_PERM_MEM_SZ,
76 0, //start of packet offset for hw to place data on rx for default flow
77 TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
78 TUNE_NETAPI_NUM_GLOBAL_DESC, //total we will use
79 TUNE_NETAPI_DEFAULT_NUM_BUFFERS, //#descriptors+buffers in default heap
80 TUNE_NETAPI_DEFAULT_NUM_SOLO_DESCRIPTORS, //#descriptors w/o buffers in default heap
81 TUNE_NETAPI_DEFAULT_BUFFER_SIZE, //size of buffers in default heap
82 0,0
83 };
85 /* Global variablesto hold virtual address of various subsystems */
86 hplib_virtualAddrInfo_T netapi_VM_VirtAddr[HPLIB_MAX_MEM_POOLS];
87 /* Global variables which needs to be populated with memory pool attributes
88 which is passed to HPLIB for memory pool initialization*/
89 hplib_memPoolAttr_T netapi_VM_MempoolAttr[HPLIB_MAX_MEM_POOLS];
90 unsigned char *netapi_VM_QMemLocalDescRam;
91 unsigned char *netapi_VM_QMemGlobalDescRam;
92 unsigned char *netapi_VM_SaContextVaddr;
94 static Pktlib_HeapIfTable netapi_pktlib_ifTable;
95 static NETAPI_GLOBAL_T netapi_global;
96 NETAPI_GLOBAL_T * netapi_get_global(){ return &netapi_global;}
98 /* utility API for NETAPI user to get pktlib if table to use if he creates his own heap */
99 Pktlib_HeapIfTable *netapi_getPktlibIfTable(void) {return &netapi_pktlib_ifTable;}
101 //zap a queue
102 void netapi_zapQ(int queueNum);
103 /*-------------------------------------
104 * initialize NETAPI instance
105 *-------------------------------------*/
106 NETAPI_T netapi_init(int master, NETAPI_CFG_T * p_cfg)
107 {
108 int i;
109 int err;
110 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) calloc(1,sizeof(NETAPI_HANDLE_T));
111 NETAPI_HANDLE_T * p_master;
112 if (!p) return NULL;
113 p->master = master;
115 /* create space for our local pktios */
116 for(i=0;i<NETAPI_MAX_PKTIO; i++)
117 {
118 p->pktios[i] = calloc(1,sizeof(PKTIO_HANDLE_T));
119 if (!p->pktios[i]) return NULL;
120 }
122 #ifdef NETAPI_INCLUDE_SCHED
123 /* create space for scheduler */
124 p->p_sched = calloc(1,sizeof(NETAPI_SCHED_HANDLE_T));
125 #endif
128 /* global stuff (if master) */
129 if (master==NETAPI_SYS_MASTER)
130 {
131 if (p_cfg) memcpy(&netapi_global.cfg,p_cfg, sizeof(NETAPI_CFG_T));
132 else memcpy(&netapi_global.cfg,&netapi_default_cfg, sizeof(NETAPI_CFG_T));
133 for(i=0;i<NETAPI_MAX_PKTIO;i++)
134 {
135 netapi_global.pktios[i].qn.qNum=-1;
136 netapi_global.pktios[i].name[0]='\0';
137 }
138 }
139 //this goes to shared memory eventually
140 p->global = (void *) &netapi_global;
142 //dalmt: save master's handle back in global; else for slave retrieve p_master
143 if (master==NETAPI_SYS_MASTER)
144 {
145 netapi_global.p_master = p;
146 }
147 else
148 {
149 p_master=(NETAPI_HANDLE_T *)netapi_global.p_master;
150 }
152 /* system init */
153 if(master==NETAPI_SYS_MASTER)
154 {
155 err = system_init(p);
156 if (err<0)
157 {
158 //todo: cleanup
159 return NULL;
160 }
161 /* create pktio channels for tx,rx */
162 }
163 else if (master==NETAPI_NO_MASTER)
164 {
165 //dalmt ->simple trial. Just copy master's packetio list for now
166 p->n_pktios = p_master->n_pktios;
167 memcpy(&p->pktios[0],&p_master->pktios[0],NETAPI_MAX_PKTIO*sizeof(PKTIO_HANDLE_T));
168 p->nwal_local=p_master->nwal_local;
169 }
170 else
171 {
172 /*todo init for non-system cores/threads */
173 /* qm_start, */
174 /* attach to heaps */
175 /* nwal_start */
176 }
178 return (NETAPI_T) p;
179 }
181 /*-------------------------------
182 * Shut down netapi instance
183 *-------------------------------*/
184 void netapi_shutdown(NETAPI_T h)
185 {
186 int i;
187 NETAPI_HANDLE_T * p = (NETAPI_HANDLE_T *) h;
188 if (!p) return;
190 printf(">netapi: WARNING shutdown may not be fully implemented\n");
191 if (p->master)
192 {
193 /* close nwal */
194 nwal_delete(netapi_global.nwal_context.nwalInstHandle);
196 /* close heaps */
197 netapi_closeHeap(h, p->netcp_heap);
198 netapi_closeHeap(h, p->netcp_control_rx_heap);
199 netapi_closeHeap(h, p->netcp_control_tx_heap);
200 netapi_closeHeap(h, netapi_get_global()->nwal_context.pa2sa_heap);
201 netapi_closeHeap(h, netapi_get_global()->nwal_context.sa2pa_heap);
203 //loop over registered heaps
204 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
205 {
206 if (p->createdHeaps[i]) {netapi_closeHeap(h,p->createdHeaps[i]);p->createdHeaps[i]=NULL;}
207 }
208 netapi_cleanup_at_start(); //clear 1st 50 not-specified queues..
209 hplib_vmTeardown();
210 }
211 free(p);
212 return;
213 }
215 //exception crash
216 void netapi_err_teardown() { netapi_cleanup_at_start(); exit(-99); }
218 /*-------------------utilities-------------------*/
219 static uint8_t* netapiSharedMemoryMalloc(uint32_t size)
220 {
221 return (uint8_t *)hplib_vmMemAlloc(size +netapi_global.cfg.def_heap_extra_size , 128, 0);
222 }
224 static void netapiSharedMemoryFree(uint8_t* ptr, uint32_t size)
225 {
226 /* Do Nothing. */
227 printf(">netapi Unexpected. need to provide a free () for some reason!! \n");
228 return;
229 }
231 // initialization
232 static int system_init(NETAPI_HANDLE_T * handle)
233 {
234 int32_t result;
235 Pktlib_HeapHandle sharedHeapHandle;
236 Pktlib_HeapHandle controlRxHeapHandle,controlTxHeapHandle;
237 Pktlib_HeapCfg heapCfg;
238 int32_t errCode;
239 #ifdef NETAPI_USE_DDR
240 /* Init attributes for DDR */
241 netapi_VM_MempoolAttr[0].attr = HPLIB_ATTR_KM_CACHED0;
242 netapi_VM_MempoolAttr[0].phys_addr = 0;
243 netapi_VM_MempoolAttr[0].size = 0;
245 /* Init attributes for un-cached MSMC */
246 netapi_VM_MempoolAttr[1].attr = HPLIB_ATTR_UN_CACHED;
247 netapi_VM_MempoolAttr[1].phys_addr = CSL_MSMC_SRAM_REGS;
248 netapi_VM_MempoolAttr[1].size = TUNE_NETAPI_PERM_MEM_SZ;
249 #else
250 netapi_VM_MempoolAttr[1].attr = HPLIB_ATTR_KM_CACHED0;
251 netapi_VM_MempoolAttr[1].phys_addr = 0;
252 netapi_VM_MempoolAttr[1].size = 0;
254 /* Init attributes for un-cached MSMC */
255 netapi_VM_MempoolAttr[0].attr = HPLIB_ATTR_UN_CACHED;
256 netapi_VM_MempoolAttr[0].phys_addr = CSL_MSMC_SRAM_REGS;
257 netapi_VM_MempoolAttr[0].size = TUNE_NETAPI_PERM_MEM_SZ;
258 #endif
259 /* initialize all the memory we are going to use
260 - chunk for buffers, descriptors
261 - memory mapped peripherals we use, such as QMSS, PA, etc */
262 result = hplib_vmInit(&netapi_VM_VirtAddr[0], 2, &netapi_VM_MempoolAttr[0]);
263 /* TODO: at this point, we need to create the QM regions which need to moved out of the above
264 netapi_VM_memory_setup() call, also need to move out the SA context stuff */
266 if (result == hplib_OK) printf(">netapi: system init - memory set up OK\n");
267 else {printf(">netap: system init - memory set up failed\n"); return -1;}
270 #ifdef NETAPI_ENABLE_SECURITY
271 #define SEC_CONTEXT_SZ 384 //not tunable
272 /* allocate 2x number of tunnels since we need one for inflow and one for data mode */
273 netapi_VM_SaContextVaddr = hplib_vmMemAlloc((TUNE_NETAPI_MAX_NUM_IPSEC_CHANNELS*2 *
274 SEC_CONTEXT_SZ), 128, 0);
275 if (!netapi_VM_SaContextVaddr)
276 {
277 printf(">netapi ERROR: Failed to map SA context memory region\n");
278 return (-1);
279 }
280 printf(">hplib VM_SaContext: Memory mapped/allocated at address %p.\n", netapi_VM_SaContextVaddr);
281 // *netapi_VM_SaContextVaddr = 'x';
282 // printf(" system Init: value being read %c\n", netapi_VM_SaContextVaddr);
283 // *netapi_VM_SaContextVaddr = 0;
285 #else
286 netapi_VM_SaContextVaddr= (char *) NULL;
287 #endif
289 /* TODO: the QM regions is application specific and needs to be moved since number of regions created is appliction specific, put this in system_init */
290 /* (3) Allocate 2 QM regions from continguous chunk above */
291 netapi_VM_QMemGlobalDescRam =
292 (void *)hplib_vmMemAlloc((TUNE_NETAPI_NUM_GLOBAL_DESC *
293 TUNE_NETAPI_DESC_SIZE),
294 128, 0);
296 netapi_VM_QMemLocalDescRam =
297 (void *)hplib_vmMemAlloc((TUNE_NETAPI_NUM_LOCAL_DESC *
298 TUNE_NETAPI_DESC_SIZE),
299 128, 0);
300 printf("netapi local desc region=%x global desc region=%x\n", netapi_VM_QMemLocalDescRam, netapi_VM_QMemGlobalDescRam);
302 //get timer running
303 #ifdef CORTEX_A8
304 netapi_init_timer();
305 #endif
306 printf("system_init: returned from netapi_init_timer\n");
308 /* Initialize Queue Manager Sub System */
309 result = netapi_init_qm (netapi_global.cfg.def_max_descriptors);
311 if (result != 1)
312 {
313 printf("system_init: returned from netapi_init_qm with failure\n");
314 return -1;
315 }
317 /* Start the QMSS. */
318 if (netapi_start_qm() != 1)
319 {
320 printf("system_init: returned from netapi_start_qm with failure\n");
321 return -1;
322 }
325 //clean our old junk in 1st bunch of queues that will be allocated to us
326 netapi_cleanup_at_start();
327 printf("system_init: returned from netapi_cleanup_at_start\n");
328 /* Initialize the global descriptor memory region. */
329 result= netapi_qm_setup_mem_region(
330 netapi_global.cfg.def_tot_descriptors_for_us,
331 SIZE_SHARED_DESC,
332 (unsigned int *) netapi_VM_QMemGlobalDescRam,
333 NETAPI_GLOBAL_REGION);
334 if(result <0) {printf(">netapi; can't setup QM shared region\n"); return -1;}
336 printf(">system_init: returned from netapi_qm_setup_mem_region\n");
337 #if 0 //todo setup 2nd region
338 /* Initialize the local memory region configuration. */
339 result= netapi_qm_setup_mem_region(
340 NUM_HOST_DESC,
341 SIZE_LOCAL_DESC,
342 netapi_VM_QMemLocalDescRam,
343 NETAPI_LOCAL_REGION);
344 if(result <0) {printf("can't setup local region\n"); return -1;}
345 #endif
346 /* Initialize CPPI CPDMA */
348 result = netapi_init_cppi ();
349 printf(">system_init: returned from netapi_init_cppi\n");
350 if (result != 1)
351 {
352 printf (">netapi: Error initializing CPPI SubSystem error code : %d\n",result);
353 return -1;
354 }
356 /* CPPI and Queue Manager are initialized. */
357 printf (">netapi: Queue Manager and CPPI are initialized.\n");
359 /* create main pkt heap */
360 /* Initialize the Shared Heaps. */
361 Pktlib_sharedHeapInit();
362 printf(">system_init: returned from Pktlib_sharedHeapInit\n");
363 /* Populate the heap interface table. */
364 netapi_pktlib_ifTable.data_malloc = netapiSharedMemoryMalloc;
365 netapi_pktlib_ifTable.data_free = netapiSharedMemoryFree;
367 /* Initialize the heap configuration. */
368 memset ((void *)&heapCfg, 0, sizeof(Pktlib_HeapCfg));
369 /* Populate the heap configuration */
370 heapCfg.name = "netapi";
371 heapCfg.memRegion = NETAPI_GLOBAL_REGION;
372 heapCfg.sharedHeap = 1;
373 heapCfg.useStarvationQueue = 0;
374 heapCfg.dataBufferSize = netapi_global.cfg.def_heap_buf_size;
375 heapCfg.numPkts = netapi_global.cfg.def_heap_n_descriptors;
376 heapCfg.numZeroBufferPackets= netapi_global.cfg.def_heap_n_zdescriptors;
377 heapCfg.heapInterfaceTable.data_malloc = netapi_pktlib_ifTable.data_malloc;
378 heapCfg.heapInterfaceTable.data_free = netapi_pktlib_ifTable.data_free;
379 heapCfg.dataBufferPktThreshold = 0;
380 heapCfg.zeroBufferPktThreshold = 0;
382 /* Create Shared Heap with specified configuration. */
383 sharedHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
384 printf(">system_init: returned from Pktlib_createHeap1\n");
385 //todo -> cleanup on failure
386 if (!sharedHeapHandle) { printf(">'netapi' heap create failed, Error Code: %d\n",errCode); return -1;}
387 handle->netcp_heap= sharedHeapHandle;
390 /* Update for Control */
391 heapCfg.name = "netapi_control_rx";
392 heapCfg.sharedHeap = 1;
393 heapCfg.dataBufferSize = TUNE_NETAPI_CONFIG_MAX_CTL_RXTX_BUF_SIZE;
394 heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_RX_BUF;
395 heapCfg.numZeroBufferPackets= 0;
397 controlRxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
398 printf(">system_init: returned from Pktlib_createHeap2\n");
399 //todo -> cleanup on failure
400 if (!controlRxHeapHandle) { printf(">netapi -'netapi_control_rx' heap create failed, Error Code: %d\n",errCode); return -1;}
401 handle->netcp_control_rx_heap= controlRxHeapHandle;
404 heapCfg.name = "netapi_control_tx";
405 heapCfg.numPkts = TUNE_NETAPI_CONFIG_NUM_CTL_TX_BUF;
407 controlTxHeapHandle = Pktlib_createHeap(&heapCfg, &errCode);
408 printf(">system_init: returned from Pktlib_createHeap3\n");
409 //todo -> cleanup on failure
410 if (!controlTxHeapHandle) { printf(">netapi -'netapi_control_tx' heap create failed, Error Code: %d\n",errCode); return -1;}
411 handle->netcp_control_tx_heap= controlTxHeapHandle;
413 /* now NWAL */
414 result = netapi_init_nwal(
415 NETAPI_GLOBAL_REGION,
416 &netapi_pktlib_ifTable,
417 &netapi_global.nwal_context,
418 &netapi_global.cfg);
419 if (result<0) {printf(">netapi init_nwal() failed\n"); return -1; }
420 printf("system_init: returned from netapi_init_nwal\n");
421 /* start NWAL */
422 result = netapi_start_nwal(sharedHeapHandle,
423 controlRxHeapHandle,
424 controlTxHeapHandle,
425 &handle->nwal_local,
426 &netapi_global.cfg,
427 &netapi_global.nwal_context);
428 if (result<0) {printf("netapi start_nwal() failed\n"); return -1; }
429 printf("system_init: returned from netapi_start_nwal\n");
430 //** success **
433 return 0;
435 }
438 /*---------------
439 * get presets()
440 *---------------*/
441 static void get_presets(PRESET_T * p_preset)
442 {
443 /* read from kernel or overall config area */
444 /* for now hard code what kernel did */
445 }
448 /*************************************************************
449 ******************MISC INTERNAL******************************
450 **************************************************************/
451 /* poll the garbage queues of all registered heaps */
452 void netapi_pollHeapGarbage(NETAPI_T h)
453 {
454 int i;
455 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
456 Pktlib_garbageCollection(n->netcp_heap);
457 //no need to do garbage collection on other internal heaps
458 for(i=0;i<TUNE_NETAPI_MAX_HEAPS;i++)
459 {
460 if (n->createdHeaps[i]) Pktlib_garbageCollection(n->createdHeaps[i]);
461 }
462 }
464 /* poll NETCP control queue for responses */
465 void netapi_netcpPoll(NETAPI_T p)
466 {
467 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) p;
468 nwal_pollCtl( ((NETAPI_GLOBAL_T *) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
469 }
471 /****************************************************************
472 *****************Cleanup Functions******************************
473 *****************************************************************/
475 //clean up function for linux user space
476 void netapi_zapQ(int queueNum)
477 {
478 char * descPtr;
479 int i;
480 if (!queueNum) return;
481 for (i=0;;i+=1 )
482 {
483 /* Pop descriptor from source queue */
484 if ((descPtr = (char *)PKTIO_QMSS_QUEUE_POP_RAW (queueNum)) == NULL)
485 {
486 break;
487 }
488 else {/*printf("netapi qzap in play\n");*/}
489 }
490 if(i) printf(">netapi: @recovery - %d descriptors cleaned from qn %d\n",i, queueNum);
491 }
493 //defensive: clean out stuff hanging around
494 //
495 // open a bunch of free queues and zap them
496 #define NQUEUES2CLEAR 35
497 static Qmss_QueueHnd tempQH[NQUEUES2CLEAR];
498 static void netapi_cleanup_at_start(void)
499 {
500 int i;
501 uint8_t isAllocated;
503 for(i=0;i<NQUEUES2CLEAR;i++)
504 {
505 tempQH[i] = Qmss_queueOpen(Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
506 QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
507 netapi_zapQ(tempQH[i]);
508 }
510 for(i=0;i<NQUEUES2CLEAR;i++)
511 {
512 Qmss_queueClose(tempQH[i]);
513 }
515 }
517 /********************************
518 * clean up a pktlib heap
519 ***********************************/
520 int netapi_closeHeap(NETAPI_T h, Pktlib_HeapHandle p)
521 {
522 Qmss_QueueHnd q;
523 Pktlib_garbageCollection(p);
524 q = Pktlib_getZeroHeapQueue(p);
525 netapi_zapQ(q);
526 q= Pktlib_getInternalHeapQueue(p);
527 netapi_zapQ(q);
528 }
534 netapi_getBufMemRemainder(void)
535 {
536 hplib_vmGetMemPoolRemainder(0);
537 }
541 void netapi_dump_internal_heap_stats(void)
542 {
543 Pktlib_HeapStats pktLibHeapStats;
544 Pktlib_getHeapStats(netapi_get_global()->nwal_context.pa2sa_heap,&pktLibHeapStats);
545 printf("PA2SA(ingress) stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
546 pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
547 printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
548 pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
549 pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
550 #if 0
551 Pktlib_getHeapStats(netapi_get_global()->nwal_context.pa2saTX_heap,&pktLibHeapStats);
552 printf("PA2SA(egress) stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
553 pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
554 printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
555 pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
556 pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
557 #endif
558 Pktlib_getHeapStats(netapi_get_global()->nwal_context.sa2pa_heap,&pktLibHeapStats);
559 printf("SA2PA stats> #free=%d #zb=%d #garbage=%d\n", pktLibHeapStats.numFreeDataPackets,
560 pktLibHeapStats.numZeroBufferPackets, pktLibHeapStats.numPacketsinGarbage);
561 printf(" > #dataBufThreshStatus=%d #dataBufStarvCounter=%d #zBufThreshStatus=%d #zBufStarvCounter=%d \n",
562 pktLibHeapStats.dataBufferThresholdStatus,pktLibHeapStats.dataBufferStarvationCounter,
563 pktLibHeapStats.zeroDataBufferThresholdStatus, pktLibHeapStats.zeroDataBufferStarvationCounter);
565 }