e282b1229c302cf27458dc1ee342c4324e7a94d4
[keystone-rtos/netapi.git] / ti / runtime / netapi / demo / src / navl_wrapper.c
1 #define __STDC_FORMAT_MACROS
2 #include <inttypes.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <signal.h>
7 #include <getopt.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <stdarg.h>
11 #include "ti/runtime/hplib/hplib.h"
12 #include "navl_wrapper.h"
13 /* timing */
15 #define netapi_timing_start hplib_mUtilGetPmuCCNT
17 extern int malloc_inst;
20 navl_wrapper_cfg_info_t *pNavlCfg;
21 void* pShmBase;
22 void *pShmEntry;
24 int free_inst=0;
25 extern int malloc_bytes;
26 static unsigned long long malloc_cycles;
27 static unsigned long long free_cycles;
28 static int n_ops=0;
29 static int n_class=0;
30 static unsigned long min_time=100000000;
31 static unsigned long max_time=0;
32 static unsigned long long timing=0LL;
33 static unsigned long n_err=0;
34 static char last_url[256];
35 int class=0;
36 void clear_pkt_stats();
37 void navl_clear_stats(void)
38 {
39     n_ops=0;
40     timing=0LL;
41     n_class=0;
42     min_time=100000000;
43     max_time=0;
44     n_err=0;
45     malloc_inst=0; free_inst=0; free_cycles=0LL; malloc_cycles=0LL;
46     clear_pkt_stats();
47 }
48 void navl_return_stats(int * Pn_ops, int * Pn_class, unsigned long * Pmin_time, unsigned long * Pmax_time, unsigned long long *Ptiming, int * Pmalloc_inst, int *Pmalloc_bytes, int * Pn_err, int *Pfree_inst, unsigned long *Pmalloc_cycles, unsigned long *Pfree_cycles)
49 {
50     *Pn_ops=n_ops;
51     *Pn_class=n_class;
52     *Pmin_time=min_time;
53     *Pmax_time=max_time;
54     *Ptiming=timing;
55     *Pmalloc_inst = malloc_inst;
56     *Pmalloc_bytes= malloc_bytes;
57     *Pn_err=n_err;
58     *Pfree_inst = free_inst; 
59     *Pmalloc_cycles= malloc_inst ? malloc_cycles/malloc_inst: 0;
60     *Pfree_cycles= free_inst? free_cycles/free_inst : 0;
61 }
63 //#define MAX_BIN 10
64 static long bins[MAX_BIN]={10000, 12500, 15000,17500,20000, 25000,30000,35000,40000,50000};
65 static char* binStr[MAX_BIN]={"10K", "12.5K", "15K","17.5K","20K","25K","30K","35K","40K","50K"};
67 void add2bin(long cycles, long p_bins[])
68 {
69     int i;
70     for(i=0;i<MAX_BIN-1;i++)
71       if (cycles<bins[i]) {p_bins[i]+=1;return;}
72      p_bins[MAX_BIN-1] += 1; //max
73 }
75 #if 0
76 /* for tracking packet stats */
77 typedef struct
78 {
79     uint64_t packets;
80     uint64_t bytes;
81     char name[12];
82     uint64_t cycles;
83     uint64_t cycles_nomem;
84     long cycles_nomem_max;
85     long cycles_nomem_min;
86     uint64_t class; //# packets classified
87     long bin_cycles[MAX_BIN];
88 } navl_wrapper_pkt_stat_t;
92 /* for tracking packets per thread/core basis */
93 typedef struct 
94 {
95     navl_wrapper_cfg_info_t     navl_cfg;
96     navl_wrapper_pkt_stat_t     stats_pkt[2];
97 } navl_wrapper_shm_pkt_stats_t;
102 /* for tracking memory stats */
103 typedef struct
105     int64_t curr;
106     int64_t peak;
107     int64_t fail;
108 } navl_wrapper_stat_t;
113 /* instance variables */
114 typedef struct {
115 /* handles */
116     navl_handle_t           navl;
118     /* configuration */
119     const char             *config_capfile;
120     const char             *config_plugins;
121     int                     config_num_proto;
122     int                     config_conn_id_attr;
123     int                     config_http_attr;
124     int                     config_num_memctx;
125     int                     config_num_memobj;
127     /* options */
128     int                     option_dpi;
129     int                     option_simple;
130     int                     option_track_memory;
131     int                     option_limit_memory;
132     int                     option_tunnel;
133     int                     option_realtime_mode;
134     int                     option_verbose;
136     /* diagnostics */
137     int                     error_navl;
139     /* statistics */
140 #define NUM_MEM_CTX 50
141 #define NUM_MEM_OBJ 50
142     navl_wrapper_stat_t    stats_mem[NUM_MEM_CTX][NUM_MEM_OBJ];
143     char                    ctx_name[NUM_MEM_CTX][64];
144     char                    obj_name[NUM_MEM_OBJ][64];
145     navl_wrapper_pkt_stat_t *stats_pkt[2];
146     uint64_t                stats_conns;
148     /* misc vars */
149     int                     running;
150     int64_t                 alloc_curr;
151     int64_t                 alloc_peak;
152 } navl_mcb_t;
153 #endif
156 navl_mcb_t *g_reader = NULL;
157 const char *g_exename = NULL;
159 static int  navl_wrapper_init(int argc, char *argv[]);
160 static void *navl_wrapper_malloc(size_t);
161 static void  navl_wrapper_free(void *);
162 static int   navl_wrapper_log_message(const char *level, const char *func, const char *format, ...);
164 static int navl_classify_callback(navl_handle_t handle, navl_result_t result, navl_state_t state, navl_conn_t conn, void *arg, int error);
166 static void  navl_wrapper_mem_stat_print();
168 /* external definitions */
169 void bind_navl_externals();
171 void navl_set_verbose(void)
173     g_reader->option_verbose=!g_reader->option_verbose;
174     printf(">**DPI Now in %s mode\n",g_reader->option_verbose?"verbose":"nonverbose");
176 void navl_dump_conn_info()
178 navl_diag(g_reader->navl, "TCP", NULL);
182 #define navl_wrapper_error() \
183 do { \
184     fprintf(stderr, "%s failed in %s:%u", g_exename, __FUNCTION__, __LINE__); \
185     if (g_reader) { \
186     if (g_reader->error_navl) \
187     fprintf(stderr, " with navl error %s", get_error_string(navl_error_get(g_reader->navl))); \
188     } \
189     fprintf(stderr, "\n"); \
190 } while (0)
192 int navl_setup(void)
194     return (navl_wrapper_init(0, NULL));
195     //return 1;
199 static const char *
200 get_state_string(navl_state_t state)
202 switch (state)
203     {
204         case NAVL_STATE_INSPECTING:
205             return "INSPECTING";
206         case NAVL_STATE_MONITORING:
207             return "MONITORING";
208         case NAVL_STATE_CLASSIFIED:
209             return "CLASSIFIED";
210         case NAVL_STATE_TERMINATED:
211             return "TERMINATED";
212         default:
213             return "UNKNOWN";
214     }
217 static const char *
218 get_confidence_string(int confidence)
220     switch (confidence)
221     {
222         case 50:
223             return "PORT";
224         case 100:
225             return "DPI";
226         default:
227             return "NONE";
228     }
231 static const char *
232 get_error_string(int error)
234     switch (error)
235     {
236         case 0:
237             return "None";
238         case ENOMEM:
239             return "No memory available";
240         case EPROTO:
241             return "Protocol error";
242         case ENOTCONN:
243             return "No connection allocated";
244         case EEXIST:
245             return "Object exists";
246         case EINVAL:
247             return "Invalid parameter";
248         case ECANCELED:
249             return "Operation cancelled";
250         case ENOENT:
251             return "No such file or directory";
252         case EPROTONOSUPPORT:
253             return "Protocol not supported";
254         default:
255             return "Unknown";
256     }
259 static int
260 navl_wrapper_init(int argc, char *argv[])
262     static navl_mcb_t reader;
264     int ret;
266     g_reader = &reader;
268     g_reader->navl = -1;
270     g_reader->config_capfile = NULL;
271     g_reader->config_plugins = "plugins";
272     g_reader->config_num_proto = 0;
273     g_reader->config_conn_id_attr = 0;
274     g_reader->config_http_attr = 0;
275     g_reader->config_num_memctx = NUM_MEM_CTX;
276     g_reader->config_num_memobj = NUM_MEM_OBJ;
278     g_reader->option_dpi = 1;
279     g_reader->option_simple = 0;
280     g_reader->option_track_memory = 1;
281     g_reader->option_limit_memory = 0;
282     g_reader->option_realtime_mode = 1;
283     g_reader->option_verbose = 0;
285     g_reader->error_navl = 0;
287     g_reader->stats_pkt[0] = NULL;
288     g_reader->stats_pkt[1] = NULL;
289     
290     g_reader->stats_conns = 0;
292     g_reader->running = 1;
293     g_reader->alloc_curr = 0;
294     g_reader->alloc_peak = 0;
296     g_exename = "dpi_demo";
298     /* EXTERNAL BINDINGS GO HERE */
299     {
300         /* Bind the platform specific functions. */
301         bind_navl_externals();
303         /* Private overrides for this example application. */
304         navl_log_message = navl_wrapper_log_message;
305         if (g_reader->option_track_memory)
306         {
307             navl_malloc_local = navl_wrapper_malloc;
308             navl_free_local = navl_wrapper_free;
309             navl_malloc_shared = navl_wrapper_malloc;
310             navl_free_shared = navl_wrapper_free;
312             memset(g_reader->stats_mem, 0, sizeof(g_reader->stats_mem));
313         }
314     }
316     /* open the navl library */
317     if ((g_reader->navl = navl_open(g_reader->config_plugins)) == -1)
318         navl_wrapper_error();
320     /* set logging level to "error | fatal" */
321     if (navl_config_set(g_reader->navl, "system.loglevel", "48") == -1)
322         navl_wrapper_error();
324     /* determine the max protocol index */
325     if ((ret = navl_proto_max_index(g_reader->navl)) == -1)
326     {
327         printf("navl_proto_max_index error\n");
328         navl_wrapper_error();
329     }
331     /* the number of protocols is the max + 1 */
332     g_reader->config_num_proto = (ret + 1);
336     /* allocate segment for shared memory for packet stats */
337      /* allocate packet statistics */
338     pShmBase = hplib_shmOpen();
339     if (pShmBase)
340     {
341         if (hplib_shmAddEntry(pShmBase,
342                           sizeof(navl_wrapper_pkt_stat_t)
343                          * g_reader->config_num_proto *NUM_FP_PROCS + sizeof(navl_wrapper_cfg_info_t),
344                          APP_ENTRY_1) != hplib_OK)
345         {
346             printf("navl_per_thread_init failure\n");
347             navl_wrapper_error();
348             return -1;
349         }
350         else
351         {
352             printf("navl_wrapper_init: num proto %d\n", g_reader->config_num_proto);
353             pShmEntry = hplib_shmGetEntry(pShmBase, APP_ENTRY_1);
354             pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;
355             memset(pNavlCfg,
356                    0,
357                    sizeof(navl_wrapper_pkt_stat_t) * g_reader->config_num_proto *NUM_FP_PROCS+ sizeof(navl_wrapper_cfg_info_t));
358             pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;
359             pNavlCfg->num_protocols = g_reader->config_num_proto;
360             g_reader->stats_pkt[0] = pShmEntry + sizeof(navl_wrapper_cfg_info_t);
362         
363             g_reader->stats_pkt[1] = pShmEntry + sizeof(navl_wrapper_cfg_info_t) +
364                     (sizeof(navl_wrapper_pkt_stat_t)*g_reader->config_num_proto); 
366             printf("navl_wrapper_init:  address: 0x%x\n", pShmEntry);
368             printf("navl_wrapper_init: stats 0 address: 0x%x\n", &g_reader->stats_pkt[0]);
370             printf("navl_wrapper_init: stats 1 address: 0x%x\n", &g_reader->stats_pkt[1]);
372         }
373     }
374     return ;
377 //per thread init. Call this in worker thread context
378 int navl_per_thread_init(uint32_t thread_num)
380     int  ret;
381     int c;
383      /* initialize this thread for classification */
384     if (navl_init(g_reader->navl))
385     {
386         printf("navl_init error\n");
387         navl_wrapper_error();
388     }
389 #if 0
390         /* enable connection tracking */
391         if (navl_attr_enable(g_reader->navl, "conn.id", 1) == -1)
392                 navl_wrapper_error();
394 #ifdef HTTP_ATTRIB
395         /* enable http url */
396         if (navl_attr_enable(g_reader->navl, "http.request.url",1) == -1)
397                 navl_wrapper_error();
398 #endif
400         /* lookup the key for conn.id */
401         if ((g_reader->config_conn_id_attr = navl_attr_key_get(g_reader->navl, "conn.id")) == -1)
402                 navl_wrapper_error();
403 #ifdef HTTP_ATTRIB
404         /* lookup the key for http.request.host */
405         if ((g_reader->config_http_attr = navl_attr_key_get(g_reader->navl, "http.request.url")) == -1)
406                 navl_wrapper_error();
407 #endif
408 #endif
409     /* simulated realtime */
410     if (g_reader->option_realtime_mode == 2)
411         navl_clock_set_mode(g_reader->navl, 1);
414 #if 0
415     /* determine the max protocol index */
416     if ((ret = navl_proto_max_index(g_reader->navl)) == -1)
417     {
418         printf("navl_proto_max_index error\n");
419         navl_wrapper_error();
420     }
422     /* the number of protocols is the max + 1 */
423     g_reader->config_num_proto = (ret + 1);
424 #endif
426 #if 0
427     if ((g_reader->stats_pkt = 
428         (navl_wrapper_pkt_stat_t *)malloc(sizeof(*g_reader->stats_pkt)
429     * (g_reader->config_num_proto))) == NULL)
430     {
431         navl_wrapper_error();
432     }
433     memset(g_reader->stats_pkt, 0, sizeof(*g_reader->stats_pkt) * (g_reader->config_num_proto) * 2);
434 #endif
435     /* now fetch all the protocol name ahead of time do we don't have to lookup them up on each packet */
436     for (ret = 0; ret != g_reader->config_num_proto; ret++)
437         navl_proto_get_name(g_reader->navl, ret,
438                             g_reader->stats_pkt[thread_num-1][ret].name,
439                             sizeof(g_reader->stats_pkt[thread_num-1][ret].name));
442  /* fetch all the memory tag names */
443     for (c = 0; c < NUM_MEM_CTX; c++)
444         navl_memory_ctx_name(g_reader->navl, c, g_reader->ctx_name[c], sizeof(g_reader->ctx_name[c]));
445     for (c = 0; c < NUM_MEM_OBJ; c++)
446         navl_memory_obj_name(g_reader->navl, c, g_reader->obj_name[c], sizeof(g_reader->obj_name[c]));
448     return 1;
452 static uint64_t
453 msec_time(struct timeval *tv)
455     return ((uint64_t)tv->tv_sec * 1000) + (tv->tv_usec / 1000);
458 static void
459 msec_delay(uint64_t msecs)
461     struct timeval tv = { msecs / 1000, (msecs % 1000) * 1000 };
462     select(0, 0, 0, 0, &tv);
465 #if 1
466 typedef struct
468     const uint8_t *data;
469     uint32_t       size;
470     uint32_t       sequence;
471     int32_t        appidx;
472     uint64_t       connid;
473 } navl_wrapper_packet_t;
474 #else
475 typedef struct
477         const uint8_t    *data;
478         uint32_t          size;
479         uint32_t          sequence;
480         int32_t           appidx;
481         int32_t           num_cb;
482 } navl_wrapper_packet_t;
483 #endif
486 #if 1
487 static int
488 navl_classify_callback(navl_handle_t handle,
489                             navl_result_t result,
490                             navl_state_t state,
491                             navl_conn_t conn,
492                             void *arg,
493                             int error)
495     int idx, protoid = 0, confidence = 0;
496     char buf[256] = {0};
497     navl_iterator_t it;
498     navl_wrapper_packet_t *packet = (navl_wrapper_packet_t *)arg;
499     int threadId =Osal_nwalGetProcId();
501     packet->appidx = navl_app_get(g_reader->navl, result, &confidence);
502     if((state==NAVL_STATE_CLASSIFIED) ||
503        (state==NAVL_STATE_TERMINATED) ||
504        (state==NAVL_STATE_MONITORING))
505     {
506         n_class+=1;
507         class =1;
508     }
509         else class=0;
510 #if 0
511     if (navl_proto_find_index(g_reader->navl, "HTTP") == packet->appidx)
512     {
513         it = navl_proto_find(g_reader->navl, result, navl_proto_find_index(g_reader->navl, "HTTP"));
514         if (navl_proto_valid(g_reader->navl, it))
515             navl_attr_get(g_reader->navl,
516             it, 
517             g_reader->config_http_attr, 
518             &last_url,
519             sizeof(last_url));
520     }
521 #endif
522     if (g_reader->option_verbose)
523     {
524         /* Build the stack string */
525         for (idx = 0, it = navl_proto_first(g_reader->navl, result); navl_proto_valid(g_reader->navl, it); navl_proto_next(g_reader->navl, it))
526         {
527             protoid = navl_proto_get_index(g_reader->navl, it);
528             if (!packet->connid)
529             {
530                 if (navl_proto_find_index(g_reader->navl, "IP") == protoid)
531                 {
532 #if 0
533                     navl_attr_get(g_reader->navl, it, g_reader->config_conn_id_attr, &packet->connid, sizeof(packet->connid));
534                     if (packet->connid > g_reader->stats_conns)
535                     g_reader->stats_conns = packet->connid;
536 #endif
537                 }
538             }
539             idx += sprintf(&buf[idx], "/%s", g_reader->stats_pkt[threadId -1][protoid].name);
540         }
541         printf(" Pkt: %u (%u bytes), Conn: %" PRIu64 ", App: %s (%s), State: %s, Stack: %s, Error: %s\n", packet->sequence
542         , packet->size, packet->connid, g_reader->stats_pkt[threadId -1][packet->appidx].name
543         , get_confidence_string(confidence), get_state_string(state), buf, get_error_string(error));
544     }
546     /* Continue tracking the flow */
547     return 0;
549 #else
550 static int
551 navl_classify_callback(navl_handle_t handle,
552                             navl_result_t result,
553                             navl_state_t state,
554                             navl_conn_t conn,
555                             void *arg,
556                             int error)
558         int idx, protoid = 0, confidence = 0;
559         char buf[256] = {0};
560         navl_iterator_t it;
561         navl_conn_id_t conn_id = navl_conn_id_get(handle, conn);
562         navl_wrapper_packet_t *packet = (navl_wrapper_packet_t *)arg;
564         /* Always display the outer packet; optionally display encapsulated data */
565         if (!packet->num_cb || g_reader->option_tunnel)
566         {
567                 packet->appidx = navl_app_get(g_reader->navl, result, &confidence);
569                 if (g_reader->option_verbose)
570                 {
571                         if (conn_id > g_reader->stats_conns)
572                                 g_reader->stats_conns = conn_id;
574                         /* Build the stack string */
575                         for (idx = 0, it = navl_proto_first(g_reader->navl, result); navl_proto_valid(g_reader->navl, it); navl_proto_next(g_reader->navl, it))
576                         {
577                                 protoid = navl_proto_get_index(g_reader->navl, it);
578                                 idx += sprintf(&buf[idx], "/%s", g_reader->stats_pkt[threadId -1][protoid].name);
579                         }
581                         printf(" Pkt: %u (%u bytes), Conn: %" PRIu64 ", App: %s (%s), State: %s, Stack: %s, Error: %s\n"
582                                 , packet->sequence, packet->size, conn_id, g_reader->stats_pkt[threadId -1][packet->appidx].name
583                                 , get_confidence_string(confidence), get_state_string(state), buf, get_error_string(error));
584                 }
585         }
587         packet->num_cb++;
589         /* Continue tracking the flow */
590         return 0;
592 #endif
594 //process the packet
595 __thread navl_wrapper_packet_t packet = { NULL, 0, 0 };
596 int navl_process_pkt(unsigned char *p_pkt, int len)
598     volatile unsigned long v1;
599     volatile unsigned long v2;
600     unsigned long temp;
601     uint64_t last = 0;
602     uint64_t next = 0;
603     unsigned long long mf1;
604     unsigned long long mf2;
605     mf1= malloc_cycles+free_cycles;
606     v1 = netapi_timing_start();
607     int threadId =Osal_nwalGetProcId();
609 /* update the current packet */
610     packet.sequence++;
611     packet.size = len;
612     packet.appidx = 0;
613     //packet.connid = 0;
614     packet.data=p_pkt;
616     /* "real" realtime */
617     if (g_reader->option_realtime_mode == 1)
618     {
619         //next = msec_time(0LL);//dal -> get ts here
620         next=0LL;
621         if (last)
622         msec_delay(next - last);
623         last = next;
624     }
625     if (navl_classify(g_reader->navl,
626                       NAVL_ENCAP_ETH,
627                       packet.data,
628                       packet.size,
629                       NULL,
630                       0,
631                       navl_classify_callback,
632                       &packet) == -1)
633     printf(" Pkt: %u (%u bytes), Error: %s\n", packet.sequence,
634                                                packet.size,
635                 get_error_string(navl_error_get(g_reader->navl)));
637     /* Update the stats. If classification was not enabled, then the appidx will be 0 and all packets
638      * captured will be accumulated there */
639     g_reader->stats_pkt[threadId -1][packet.appidx].packets++;
640     g_reader->stats_pkt[threadId -1][packet.appidx].bytes += packet.size;
641     if(class)  g_reader->stats_pkt[threadId -1][packet.appidx].class++;
642     //update timing
643     v2 = netapi_timing_start();
644     temp=v2-v1;
645     mf2= malloc_cycles+free_cycles;
646     timing+= (unsigned long long) temp;
647     g_reader->stats_pkt[threadId -1][packet.appidx].cycles += (unsigned long long) temp;
648     g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem += ((unsigned long long) temp - (mf2-mf1));
650     if (g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem_min > (temp - (unsigned long)(mf2-mf1)))
651         g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem_min = (temp - (unsigned long)(mf2-mf1));
653     if (g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem_max < (temp - (unsigned long)(mf2-mf1)) )
654         g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem_max = (temp - (unsigned long)(mf2-mf1));
656     add2bin((temp - (unsigned long)(mf2-mf1)),&g_reader->stats_pkt[threadId -1][packet.appidx].bin_cycles[0]); 
657     n_ops+=1;
658     if (temp>max_time) max_time=temp;
659     if (temp<min_time) min_time=temp;
660     return 1;
663 int navl_done(void)
665     navl_fini(g_reader->navl);
666     navl_close(g_reader->navl);
667     return 1;
670 void navl_results(int threadId)
672     int idx;
673     int i;
674     uint64_t total_packets, total_bytes;
675     void* pShmEntry;
678     total_packets = 0;
679     total_bytes = 0;
681     //if (g_reader->option_dpi)
682     {
683         printf("\n NAVL DPI stats for CORE ID %d\n", threadId);
684         printf("\n AppProto    Packets  Class   Bytes        Cycles/Pkt      Cyclesnomem/Pkt  (min)  (max) ");
685         for(i=0;i<MAX_BIN;i++)
686             printf("<%s ",binStr[i]);
687         printf("\n ----------------------------------------------------------------------------------------------------------------------------------------------------\n");
688     }
690     //for (idx = 0; idx < g_reader->config_num_proto; idx++)
691     for (idx = 0; idx < pNavlCfg->num_protocols; idx++)
692     {
693         //if (g_reader->option_dpi)
694         {
695             if (g_reader->stats_pkt[threadId -1][idx].packets)
696             {
697                 /* We need to provide protocol definitions */   
698                 printf(" %-12s%-12" PRIu64 " %" PRIu64 " %" PRIu64 "      %" PRIu64 "       %" PRIu64 "    %ld    %ld .. " , 
699                         g_reader->stats_pkt[threadId -1][idx].name,
700                         g_reader->stats_pkt[threadId -1][idx].packets, 
701                         g_reader->stats_pkt[threadId -1][idx].class, 
702                         g_reader->stats_pkt[threadId -1][idx].bytes,
703                         g_reader->stats_pkt[threadId -1][idx].cycles/g_reader->stats_pkt[threadId -1][idx].packets, 
704                         g_reader->stats_pkt[threadId -1][idx].cycles_nomem/g_reader->stats_pkt[threadId -1][idx].packets,
705                         g_reader->stats_pkt[threadId -1][idx].cycles_nomem_min,
706                         g_reader->stats_pkt[threadId -1][idx].cycles_nomem_max);
707                 for(i=0;i<MAX_BIN;i++) printf("%ld ",g_reader->stats_pkt[threadId -1][idx].bin_cycles[i]);
708                 printf("\n");
709             }
710         }
712         total_packets += g_reader->stats_pkt[threadId -1][idx].packets;
713         total_bytes += g_reader->stats_pkt[threadId -1][idx].bytes;
714     }
716     if (!total_packets)
717         printf("\n No packets captured.\n");
718     else
719         printf("\n %" PRIu64 " packets captured (%" PRIu64 " bytes)\n", total_packets, total_bytes);
721     if (g_reader->stats_conns)
722         printf(" %" PRIu64 " connections tracked\n", g_reader->stats_conns);
724     printf("\n");
725     if (g_reader->option_track_memory)
726         navl_wrapper_mem_stat_print();
728     if (g_reader->alloc_curr != 0)
729         printf("Bytes not freed: %" PRIi64 "\n", g_reader->alloc_curr);
731     if (g_reader->alloc_peak != 0)
732            printf("Peak allocated: %" PRIi64 "\n", g_reader->alloc_peak);
734     printf("attr test: last http utl= %s\n",last_url);
738 static void 
739 navl_wrapper_mem_stat_print()
741     int i, j;
742     navl_wrapper_stat_t *stat;
743     char *name;
745     printf("                                          Curr      Peak      Fail   \n");
746     printf("-----------------------------------------------------------------------");
748     for (i = 0; i < g_reader->config_num_memctx; i++)
749     {
750         stat = &g_reader->stats_mem[i][0];
751         if (stat->peak == 0)
752         continue;
754         printf("\n\t%s\n", g_reader->ctx_name[i]);
756         for (j = g_reader->config_num_memobj - 1; j >= 0; j--)
757         {
758             navl_wrapper_stat_t *stat = &g_reader->stats_mem[i][j];
759             if (stat->peak == 0)
760             continue;
762             name = j ? g_reader->obj_name[j] : (char *)"other";
764             if (stat->peak || stat->fail)
765             printf("\t\t%-20s%10" PRIu64 "%10" PRIu64 "%10" PRIu64 "\n", name, stat->curr, stat->peak, stat->fail);
766         }
767     }
768     printf("\n\n");
771 /* Private memory stamp type for tracking memory with navl_wrapper_malloc/free */
772 typedef struct
774     size_t      size;       /* size of allocation */
775     short       ctx_tag;    /* ctx axis */
776     short       obj_tag;    /* obj axis */
777     char        mem[0];
778 } memstamp_t;
780 static void *navl_wrapper_malloc(size_t size)
782     navl_handle_t handle;
783     navl_wrapper_stat_t *stat_mem;
784     int tag;
785     int ctx_tag, obj_tag;
786     unsigned long t1;
787     unsigned long t2;
788     malloc_inst+=1;
789     malloc_bytes+=size;
790     t1=netapi_timing_start();
792     assert(size);
794     /* In this context, the handle should be read using navl_handle_get() since
795      * the application cached handle (in this case g_reader->navl) will not be set
796      * until navl_open() returns. For this simple test we just assert that the handle
797      * is infact valid. */
798     handle = navl_handle_get();
799     assert(handle != 0);
801     /* Fetch the tags associated with this allocation. They will be used below to record
802      * statistics about allocations within the library on 2 axis. The upper 16 bits contain
803      * a memory obj tag and the lower 16 bits contain the allocation context tag. These
804      * tags are indices, the upper of which is available through navl_memory_ctx_num()
805      * and navl_memory_obj_num() resp. They are generated dynamically and may differ  between
806      * configurations. These total number of indices are available ONLY AFTER navl_open() 
807      * returns.
808      */
809     tag = navl_memory_tag_get(handle);
810     obj_tag = (tag >> 16);
811     ctx_tag = (tag & 0x0000FFFF);
813     /* You could do something better here and reallocate the matrix */
814     if (ctx_tag >= g_reader->config_num_memctx || obj_tag >= g_reader->config_num_memobj)
815     {
816         assert(0);
817         return NULL;
818     }
820     stat_mem = &g_reader->stats_mem[ctx_tag][obj_tag];
822     /* check limits */
823     if (!g_reader->option_limit_memory || (g_reader->alloc_curr + size < g_reader->option_limit_memory))
824     {
825         memstamp_t *ptr = (memstamp_t *)malloc(size + sizeof(memstamp_t));
826         if (ptr)
827         {
828             /* track peak values */
829             if ((g_reader->alloc_curr += size) > g_reader->alloc_peak)
830             g_reader->alloc_peak = g_reader->alloc_curr;
832             if ((stat_mem->curr += size) > stat_mem->peak)
833             stat_mem->peak = stat_mem->curr;
835             ptr->size = size;
836             ptr->ctx_tag = ctx_tag;
837             ptr->obj_tag = obj_tag;
838             t2=netapi_timing_start();
839             malloc_cycles += (unsigned long long)  (t2-t1);
840             return ptr->mem;
841         }
842     }
843     stat_mem->fail += size;
844     return NULL;
847 static void 
848 navl_wrapper_free(void *p)
850     unsigned long t1;
851     unsigned long t2;
852     free_inst += 1;
853     t1=netapi_timing_start();
854     if (!p)
855         return;
857     memstamp_t *ptr = (memstamp_t *)((char *)p - offsetof(memstamp_t, mem));
858     navl_wrapper_stat_t *stat_mem = &g_reader->stats_mem[ptr->ctx_tag][ptr->obj_tag];
860     assert(p == ptr->mem);
862     stat_mem->curr -= ptr->size;
863     g_reader->alloc_curr -= ptr->size;
865     free(ptr);
866     t2=netapi_timing_start();
867     free_cycles += (unsigned long long)  (t2-t1);
870 static int
871 navl_wrapper_log_message(const char *level, const char *func, const char *format, ... )
873     int res = 0;
874     char buf[4096];
875     va_list va;
876     va_start(va, format);
878     res = snprintf(buf, 4096, "%s: %s: ", level, func);
879     res += vsnprintf(buf + res, 4096 - res, format, va);
880     printf("%s\n", buf);
881     va_end(va);
882     return res;
885 //clear stats
886 void clear_pkt_stats()
888     int ret;
889     int threadId =Osal_nwalGetProcId();
890      memset(g_reader->stats_pkt, 0, sizeof(*g_reader->stats_pkt) * (g_reader->config_num_proto)*2);
891     /* now fetch all the protocol name ahead of time do we don't have to lookup them up on each packet */
892     for (ret = 0; ret != g_reader->config_num_proto; ret++)
893     {
894         navl_proto_get_name(g_reader->navl, ret, g_reader->stats_pkt[threadId -1][ret].name, sizeof(g_reader->stats_pkt[threadId -1][ret].name));
895         g_reader->stats_pkt[threadId -1][ret].cycles_nomem_min=10000000;
896     }