Updates for stats collection across processes
[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 "ti/runtime/netapi/netapi_types.h"
13 #include "navl_wrapper.h"
14 /* timing */
16 #define netapi_timing_start hplib_mUtilGetPmuCCNT
18 navl_wrapper_cfg_info_t *pNavlCfg;
19 navl_global_dpi_stats *pDpiStats;
20 void* pShmBase;
21 void *pShmEntry;
23 //int free_inst=0;
25 static unsigned long long timing=0LL;
27 static char last_url[256];
28 int class=0;
29 void clear_pkt_stats();
30 void navl_clear_stats(void)
31 {
32     memset(pDpiStats, 0, sizeof(navl_global_dpi_stats));
33     pDpiStats->min_time=100000000;
34     clear_pkt_stats();
35 }
36 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)
37 {
38     *Pn_ops=pDpiStats->n_ops;
39     *Pn_class=pDpiStats->n_class;
40     *Pmin_time=pDpiStats->min_time;
41     *Pmax_time=pDpiStats->max_time;
42     *Ptiming=timing;
43     *Pmalloc_inst = pDpiStats->malloc_inst;
44     *Pmalloc_bytes= pDpiStats->malloc_bytes;
45     *Pn_err=pDpiStats->n_err;
46     *Pfree_inst = pDpiStats->free_inst; 
47     *Pmalloc_cycles= pDpiStats->malloc_inst ? pDpiStats->malloc_cycles/pDpiStats->malloc_inst: 0;
48     *Pfree_cycles= pDpiStats->free_inst? pDpiStats->free_cycles/pDpiStats->free_inst : 0;
49 }
51 //#define MAX_BIN 10
52 static long bins[MAX_BIN]={10000, 12500, 15000,17500,20000, 25000,30000,35000,40000,50000};
53 static char* binStr[MAX_BIN]={"10K", "12.5K", "15K","17.5K","20K","25K","30K","35K","40K","50K"};
55 void add2bin(long cycles, long p_bins[])
56 {
57     int i;
58     for(i=0;i<MAX_BIN-1;i++)
59       if (cycles<bins[i]) {p_bins[i]+=1;return;}
60      p_bins[MAX_BIN-1] += 1; //max
61 }
65 navl_mcb_t *g_reader = NULL;
66 const char *g_exename = NULL;
68 static int  navl_wrapper_init(int argc, char *argv[]);
69 static void *navl_wrapper_malloc(size_t);
70 static void  navl_wrapper_free(void *);
71 static int   navl_wrapper_log_message(const char *level, const char *func, const char *format, ...);
73 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);
75 static void  navl_wrapper_mem_stat_print();
77 /* external definitions */
78 void bind_navl_externals();
80 void navl_set_verbose(void)
81 {
82     g_reader->option_verbose=!g_reader->option_verbose;
83     printf(">**DPI Now in %s mode\n",g_reader->option_verbose?"verbose":"nonverbose");
84 }
85 void navl_dump_conn_info()
86 {
87 navl_diag(g_reader->navl, "TCP", NULL);
88 }
91 #define navl_wrapper_error() \
92 do { \
93     fprintf(stderr, "%s failed in %s:%u", g_exename, __FUNCTION__, __LINE__); \
94     if (g_reader) { \
95     if (g_reader->error_navl) \
96     fprintf(stderr, " with navl error %s", get_error_string(navl_error_get(g_reader->navl))); \
97     } \
98     fprintf(stderr, "\n"); \
99 } while (0)
101 int navl_setup(void)
103     return (navl_wrapper_init(0, NULL));
107 static const char *
108 get_state_string(navl_state_t state)
110 switch (state)
111     {
112         case NAVL_STATE_INSPECTING:
113             return "INSPECTING";
114         case NAVL_STATE_MONITORING:
115             return "MONITORING";
116         case NAVL_STATE_CLASSIFIED:
117             return "CLASSIFIED";
118         case NAVL_STATE_TERMINATED:
119             return "TERMINATED";
120         default:
121             return "UNKNOWN";
122     }
125 static const char *
126 get_confidence_string(int confidence)
128     switch (confidence)
129     {
130         case 50:
131             return "PORT";
132         case 100:
133             return "DPI";
134         default:
135             return "NONE";
136     }
139 static const char *
140 get_error_string(int error)
142     switch (error)
143     {
144         case 0:
145             return "None";
146         case ENOMEM:
147             return "No memory available";
148         case EPROTO:
149             return "Protocol error";
150         case ENOTCONN:
151             return "No connection allocated";
152         case EEXIST:
153             return "Object exists";
154         case EINVAL:
155             return "Invalid parameter";
156         case ECANCELED:
157             return "Operation cancelled";
158         case ENOENT:
159             return "No such file or directory";
160         case EPROTONOSUPPORT:
161             return "Protocol not supported";
162         default:
163             return "Unknown";
164     }
167 static int
168 navl_wrapper_init(int argc, char *argv[])
170     static navl_mcb_t reader;
172     int ret;
173     int i;
175     g_reader = &reader;
177     g_reader->navl = -1;
179     g_reader->config_capfile = NULL;
180     g_reader->config_plugins = "plugins";
181     g_reader->config_num_proto = 0;
182     g_reader->config_conn_id_attr = 0;
183     g_reader->config_http_attr = 0;
184     g_reader->config_num_memctx = NUM_MEM_CTX;
185     g_reader->config_num_memobj = NUM_MEM_OBJ;
187     g_reader->option_dpi = 1;
188     g_reader->option_simple = 0;
189     g_reader->option_track_memory = 1;
190     g_reader->option_limit_memory = 0;
191     g_reader->option_realtime_mode = 1;
192     g_reader->option_verbose = 0;
194     g_reader->error_navl = 0;
196     g_reader->stats_pkt[0] = NULL;
197     g_reader->stats_pkt[1] = NULL;
198     
199     g_reader->stats_conns = 0;
201     g_reader->running = 1;
202     g_reader->alloc_curr = 0;
203     g_reader->alloc_peak = 0;
205     g_exename = "dpi_demo";
208     /* allocate segment for shared memory for packet stats */
209      /* allocate packet statistics */
210     pShmBase = hplib_shmOpen();
211     if (pShmBase)
212     {
213         pShmEntry = hplib_shmGetEntry(pShmBase, APP_ENTRY_1);
214         pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;
215         memset(pNavlCfg,
216                0,
217                sizeof(navl_wrapper_pkt_stat_t) * MAX_PROTOCOLS *NUM_FP_PROCS+ sizeof(navl_wrapper_cfg_info_t));
218         pNavlCfg =  (navl_wrapper_cfg_info_t*)pShmEntry;
219         pNavlCfg->num_protocols = g_reader->config_num_proto;
220         g_reader->stats_pkt[0] = pShmEntry + sizeof(navl_wrapper_cfg_info_t);
222         g_reader->stats_pkt[1] = pShmEntry + sizeof(navl_wrapper_cfg_info_t) +
223                 (sizeof(navl_wrapper_pkt_stat_t)*MAX_PROTOCOLS); 
225         for(i=0;i< MAX_PROTOCOLS;i++)
226         {
227             g_reader->stats_pkt[0][i].cycles_min=10000000;
228             g_reader->stats_pkt[1][i].cycles_min=10000000;
229             g_reader->stats_pkt[0][i].cycles_max=0;
230             g_reader->stats_pkt[1][i].cycles_max=0;
231         }
233         pShmEntry = hplib_shmGetEntry(pShmBase, APP_ENTRY_2);
234         pDpiStats = (navl_global_dpi_stats*) pShmEntry;
235     }
236     else
237     {
238         printf("navl_wrapper_init: hplib_shmOpen failure\n");
239         return NETAPI_ERR_NOMEM;
240     }
242     /* EXTERNAL BINDINGS GO HERE */
243     {
244         /* Bind the platform specific functions. */
245         bind_navl_externals();
247         /* Private overrides for this example application. */
248         navl_log_message = navl_wrapper_log_message;
249         if (g_reader->option_track_memory)
250         {
251             navl_malloc_local = navl_wrapper_malloc;
252             navl_free_local = navl_wrapper_free;
253             navl_malloc_shared = navl_wrapper_malloc;
254             navl_free_shared = navl_wrapper_free;
256             memset(g_reader->stats_mem, 0, sizeof(g_reader->stats_mem));
257         }
258     }
260     /* open the navl library */
261     if ((g_reader->navl = navl_open(g_reader->config_plugins)) == -1)
262         navl_wrapper_error();
264     /* set logging level to "error | fatal" */
265     if (navl_config_set(g_reader->navl, "system.loglevel", "48") == -1)
266         navl_wrapper_error();
268     /* determine the max protocol index */
269     if ((ret = navl_proto_max_index(g_reader->navl)) == -1)
270     {
271         printf("navl_proto_max_index error\n");
272         navl_wrapper_error();
273     }
275     /* the number of protocols is the max + 1 */
276     g_reader->config_num_proto = (ret + 1);
277     pNavlCfg->num_protocols = g_reader->config_num_proto;
279     return NETAPI_ERR_OK;
282 //per thread init. Call this in worker thread context
283 int navl_per_thread_init(uint32_t thread_num)
285     int  ret;
286     int c;
288      /* initialize this thread for classification */
289     if (navl_init(g_reader->navl))
290     {
291         printf("navl_init error\n");
292         navl_wrapper_error();
293     }
294 #if 0
295         /* enable connection tracking */
296         if (navl_attr_enable(g_reader->navl, "conn.id", 1) == -1)
297                 navl_wrapper_error();
299 #ifdef HTTP_ATTRIB
300         /* enable http url */
301         if (navl_attr_enable(g_reader->navl, "http.request.url",1) == -1)
302                 navl_wrapper_error();
303 #endif
305         /* lookup the key for conn.id */
306         if ((g_reader->config_conn_id_attr = navl_attr_key_get(g_reader->navl, "conn.id")) == -1)
307                 navl_wrapper_error();
308 #ifdef HTTP_ATTRIB
309         /* lookup the key for http.request.host */
310         if ((g_reader->config_http_attr = navl_attr_key_get(g_reader->navl, "http.request.url")) == -1)
311                 navl_wrapper_error();
312 #endif
313 #endif
314     /* simulated realtime */
315     if (g_reader->option_realtime_mode == 2)
316         navl_clock_set_mode(g_reader->navl, 1);
319 #if 0
320     /* determine the max protocol index */
321     if ((ret = navl_proto_max_index(g_reader->navl)) == -1)
322     {
323         printf("navl_proto_max_index error\n");
324         navl_wrapper_error();
325     }
327     /* the number of protocols is the max + 1 */
328     g_reader->config_num_proto = (ret + 1);
329 #endif
332     /* now fetch all the protocol name ahead of time do we don't have to lookup them up on each packet */
333     for (ret = 0; ret != g_reader->config_num_proto; ret++)
334         navl_proto_get_name(g_reader->navl, ret,
335                             g_reader->stats_pkt[thread_num-1][ret].name,
336                             sizeof(g_reader->stats_pkt[thread_num-1][ret].name));
339  /* fetch all the memory tag names */
340     for (c = 0; c < NUM_MEM_CTX; c++)
341         navl_memory_ctx_name(g_reader->navl, c, g_reader->ctx_name[c], sizeof(g_reader->ctx_name[c]));
342     for (c = 0; c < NUM_MEM_OBJ; c++)
343         navl_memory_obj_name(g_reader->navl, c, g_reader->obj_name[c], sizeof(g_reader->obj_name[c]));
345     return 1;
349 static uint64_t
350 msec_time(struct timeval *tv)
352     return ((uint64_t)tv->tv_sec * 1000) + (tv->tv_usec / 1000);
355 static void
356 msec_delay(uint64_t msecs)
358     struct timeval tv = { msecs / 1000, (msecs % 1000) * 1000 };
359     select(0, 0, 0, 0, &tv);
362 #if 1
363 typedef struct
365     const uint8_t *data;
366     uint32_t       size;
367     uint32_t       sequence;
368     int32_t        appidx;
369     uint64_t       connid;
370 } navl_wrapper_packet_t;
371 #else
372 typedef struct
374         const uint8_t    *data;
375         uint32_t          size;
376         uint32_t          sequence;
377         int32_t           appidx;
378         int32_t           num_cb;
379 } navl_wrapper_packet_t;
380 #endif
383 #if 1
384 static int
385 navl_classify_callback(navl_handle_t handle,
386                             navl_result_t result,
387                             navl_state_t state,
388                             navl_conn_t conn,
389                             void *arg,
390                             int error)
392     int idx, protoid = 0, confidence = 0;
393     char buf[256] = {0};
394     navl_iterator_t it;
395     navl_wrapper_packet_t *packet = (navl_wrapper_packet_t *)arg;
396     int threadId =Osal_nwalGetProcId();
398     packet->appidx = navl_app_get(g_reader->navl, result, &confidence);
399     if((state==NAVL_STATE_CLASSIFIED) ||
400        (state==NAVL_STATE_TERMINATED) ||
401        (state==NAVL_STATE_MONITORING))
402     {
403         pDpiStats->n_class+=1;
404         class =1;
405     }
406     else
407         class=0;
408 #if 0
409     if (navl_proto_find_index(g_reader->navl, "HTTP") == packet->appidx)
410     {
411         it = navl_proto_find(g_reader->navl, result, navl_proto_find_index(g_reader->navl, "HTTP"));
412         if (navl_proto_valid(g_reader->navl, it))
413             navl_attr_get(g_reader->navl,
414             it, 
415             g_reader->config_http_attr, 
416             &last_url,
417             sizeof(last_url));
418     }
419 #endif
420     if (g_reader->option_verbose)
421     {
422         /* Build the stack string */
423         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))
424         {
425             protoid = navl_proto_get_index(g_reader->navl, it);
426             if (!packet->connid)
427             {
428                 if (navl_proto_find_index(g_reader->navl, "IP") == protoid)
429                 {
430 #if 0
431                     navl_attr_get(g_reader->navl, it, g_reader->config_conn_id_attr, &packet->connid, sizeof(packet->connid));
432                     if (packet->connid > g_reader->stats_conns)
433                     g_reader->stats_conns = packet->connid;
434 #endif
435                 }
436             }
437             idx += sprintf(&buf[idx], "/%s", g_reader->stats_pkt[threadId -1][protoid].name);
438         }
439         printf(" Pkt: %u (%u bytes), Conn: %" PRIu64 ", App: %s (%s), State: %s, Stack: %s, Error: %s\n", packet->sequence
440         , packet->size, packet->connid, g_reader->stats_pkt[threadId -1][packet->appidx].name
441         , get_confidence_string(confidence), get_state_string(state), buf, get_error_string(error));
442     }
444     /* Continue tracking the flow */
445     return 0;
447 #else
448 static int
449 navl_classify_callback(navl_handle_t handle,
450                             navl_result_t result,
451                             navl_state_t state,
452                             navl_conn_t conn,
453                             void *arg,
454                             int error)
456         int idx, protoid = 0, confidence = 0;
457         char buf[256] = {0};
458         navl_iterator_t it;
459         navl_conn_id_t conn_id = navl_conn_id_get(handle, conn);
460         navl_wrapper_packet_t *packet = (navl_wrapper_packet_t *)arg;
462         /* Always display the outer packet; optionally display encapsulated data */
463         if (!packet->num_cb || g_reader->option_tunnel)
464         {
465                 packet->appidx = navl_app_get(g_reader->navl, result, &confidence);
467                 if (g_reader->option_verbose)
468                 {
469                         if (conn_id > g_reader->stats_conns)
470                                 g_reader->stats_conns = conn_id;
472                         /* Build the stack string */
473                         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))
474                         {
475                                 protoid = navl_proto_get_index(g_reader->navl, it);
476                                 idx += sprintf(&buf[idx], "/%s", g_reader->stats_pkt[threadId -1][protoid].name);
477                         }
479                         printf(" Pkt: %u (%u bytes), Conn: %" PRIu64 ", App: %s (%s), State: %s, Stack: %s, Error: %s\n"
480                                 , packet->sequence, packet->size, conn_id, g_reader->stats_pkt[threadId -1][packet->appidx].name
481                                 , get_confidence_string(confidence), get_state_string(state), buf, get_error_string(error));
482                 }
483         }
485         packet->num_cb++;
487         /* Continue tracking the flow */
488         return 0;
490 #endif
492 //process the packet
493 __thread navl_wrapper_packet_t packet = { NULL, 0, 0 };
494 int navl_process_pkt(unsigned char *p_pkt, int len)
496     volatile unsigned long v1;
497     volatile unsigned long v2;
498     unsigned long temp=0;
499     uint64_t last = 0;
500     uint64_t next = 0;
501     unsigned long long mf1;
502     unsigned long long mf2;
503     int threadId =Osal_nwalGetProcId();
504     mf1= pDpiStats->malloc_cycles+pDpiStats->free_cycles;
505     
506     v1 = netapi_timing_start();
507     
508 /* update the current packet */
509     packet.sequence++;
510     packet.size = len;
511     packet.appidx = 0;
512     //packet.connid = 0;
513     packet.data=p_pkt;
515     /* "real" realtime */
516     if (g_reader->option_realtime_mode == 1)
517     {
518         //next = msec_time(0LL);//dal -> get ts here
519         next=0LL;
520         if (last)
521         msec_delay(next - last);
522         last = next;
523     }
524     if (navl_classify(g_reader->navl,
525                       NAVL_ENCAP_ETH,
526                       packet.data,
527                       packet.size,
528                       NULL,
529                       0,
530                       navl_classify_callback,
531                       &packet) == -1)
532     printf(" Pkt: %u (%u bytes), Error: %s\n", packet.sequence,
533                                                packet.size,
534                 get_error_string(navl_error_get(g_reader->navl)));
536     /* Update the stats. If classification was not enabled, then the appidx will be 0 and all packets
537      * captured will be accumulated there */
538     g_reader->stats_pkt[threadId -1][packet.appidx].packets++;
539     g_reader->stats_pkt[threadId -1][packet.appidx].bytes += packet.size;
540     if(class)
541         g_reader->stats_pkt[threadId -1][packet.appidx].class++;
542     //update timing
543     v2 = netapi_timing_start();
544     temp=v2-v1;
545     mf2= pDpiStats->malloc_cycles + pDpiStats->free_cycles;
546     timing+= (unsigned long long) temp;
547     g_reader->stats_pkt[threadId -1][packet.appidx].cycles += (unsigned long long) temp;
548     g_reader->stats_pkt[threadId -1][packet.appidx].cycles_nomem += ((unsigned long long) temp - (mf2-mf1));
550     if (g_reader->stats_pkt[threadId -1][packet.appidx].cycles_min > temp)
551         g_reader->stats_pkt[threadId -1][packet.appidx].cycles_min = temp;
553     if (g_reader->stats_pkt[threadId -1][packet.appidx].cycles_max  < temp)
554     {
555         g_reader->stats_pkt[threadId -1][packet.appidx].cycles_max = temp;
557     }
558     
560     add2bin((temp - (unsigned long)(mf2-mf1)),&g_reader->stats_pkt[threadId -1][packet.appidx].bin_cycles[0]); 
561     pDpiStats->n_ops+=1;
562     if (temp > pDpiStats->max_time) pDpiStats->max_time = temp;
563     if (temp< pDpiStats->min_time) pDpiStats->min_time = temp;
564     return 1;
567 int navl_done(void)
569     navl_fini(g_reader->navl);
570     navl_close(g_reader->navl);
571     return 1;
574 void navl_results(int threadId)
576     int idx;
577     int i;
578     uint64_t total_packets, total_bytes;
579     void* pShmEntry;
581     total_packets = 0;
582     total_bytes = 0;
584     if (g_reader->option_dpi)
585     {
586         printf("\n NAVL DPI stats for CORE ID %d\n", threadId);
587         printf("\n AppProto    Packets  Class   Bytes        Cycles/Pkt      Cyclesnomem/Pkt  (min)  (max) ");
588         for(i=0;i<MAX_BIN;i++)
589             printf("<%s ",binStr[i]);
590         printf("\n ----------------------------------------------------------------------------------------------------------------------------------------------------\n");
591     }
593     //for (idx = 0; idx < g_reader->config_num_proto; idx++)
594     for (idx = 0; idx < pNavlCfg->num_protocols; idx++)
595     {
596         if (g_reader->option_dpi)
597         {
598             if (g_reader->stats_pkt[threadId -1][idx].packets)
599             {
600                 /* We need to provide protocol definitions */   
601                 printf(" %-12s%-12" PRIu64 " %" PRIu64 " %" PRIu64 "      %" PRIu64 "       %" PRIu64 "    %ld    %ld    " , 
602                         g_reader->stats_pkt[threadId -1][idx].name,
603                         g_reader->stats_pkt[threadId -1][idx].packets, 
604                         g_reader->stats_pkt[threadId -1][idx].class, 
605                         g_reader->stats_pkt[threadId -1][idx].bytes,
606                         g_reader->stats_pkt[threadId -1][idx].cycles/g_reader->stats_pkt[threadId -1][idx].packets, 
607                         g_reader->stats_pkt[threadId -1][idx].cycles_nomem/g_reader->stats_pkt[threadId -1][idx].packets,
608                         g_reader->stats_pkt[threadId -1][idx].cycles_min,
609                         g_reader->stats_pkt[threadId -1][idx].cycles_max);
610                 for(i=0;i<MAX_BIN;i++) printf("%ld ",g_reader->stats_pkt[threadId -1][idx].bin_cycles[i]);
611                 printf("\n");
612             }
613         }
615         total_packets += g_reader->stats_pkt[threadId -1][idx].packets;
616         total_bytes += g_reader->stats_pkt[threadId -1][idx].bytes;
617     }
619     if (!total_packets)
620         printf("\n No packets captured.\n");
621     else
622         printf("\n %" PRIu64 " packets captured (%" PRIu64 " bytes)\n", total_packets, total_bytes);
624     if (g_reader->stats_conns)
625         printf(" %" PRIu64 " connections tracked\n", g_reader->stats_conns);
627     printf("\n");
628     if (g_reader->option_track_memory)
629         navl_wrapper_mem_stat_print();
632     if (pNavlCfg->alloc_curr != 0)
633         printf("Bytes not freed: %" PRIi64 "\n", pNavlCfg->alloc_curr);
635     if (g_reader->alloc_peak != 0)
636            printf("Peak allocated: %" PRIi64 "\n", g_reader->alloc_peak);
638     printf("attr test: last http utl= %s\n",last_url);
641 static void 
642 navl_wrapper_mem_stat_print()
644     int i, j;
645     navl_wrapper_stat_t *stat;
646     char *name;
648     printf("                                          Curr      Peak      Fail   \n");
649     printf("-----------------------------------------------------------------------");
651     for (i = 0; i < g_reader->config_num_memctx; i++)
652     {
653         stat = &g_reader->stats_mem[i][0];
654         if (stat->peak == 0)
655         continue;
657         printf("\n\t%s\n", g_reader->ctx_name[i]);
659         for (j = g_reader->config_num_memobj - 1; j >= 0; j--)
660         {
661             navl_wrapper_stat_t *stat = &g_reader->stats_mem[i][j];
662             if (stat->peak == 0)
663             continue;
665             name = j ? g_reader->obj_name[j] : (char *)"other";
667             if (stat->peak || stat->fail)
668             printf("\t\t%-20s%10" PRIu64 "%10" PRIu64 "%10" PRIu64 "\n", name, stat->curr, stat->peak, stat->fail);
669         }
670     }
671     printf("\n\n");
675 void navl_results2(int threadId)
677     int idx;
678     int i;
679     uint64_t total_packets, total_bytes;
680     void* pShmEntry;
681     void* pShmBase;
682     void* pTemp;
683     navl_wrapper_cfg_info_t *pNavlCfg;
684     navl_wrapper_pkt_stat_t *pStats1;
685     navl_wrapper_pkt_stat_t *pStats2;
686     navl_mcb_t g_reader;
688     pShmBase = hplib_shmOpen();
689     if (pShmBase)
690     {
691         pTemp = hplib_shmGetEntry(pShmBase, APP_ENTRY_1);
692         pNavlCfg =  (navl_wrapper_cfg_info_t*)pTemp;
693     
694         g_reader.stats_pkt[0] = pTemp + sizeof(navl_wrapper_cfg_info_t);
695     
696     
697         g_reader.stats_pkt[1] = pTemp + sizeof(navl_wrapper_cfg_info_t) +
698                 (sizeof(navl_wrapper_pkt_stat_t)*pNavlCfg->num_protocols);
699     }
700     total_packets = 0;
701     total_bytes = 0;
703     //if (g_reader->option_dpi)
704     {
705         printf("\n NAVL DPI stats for CORE ID %d\n", threadId);
706         printf("\n AppProto    Packets  Class   Bytes        Cycles/Pkt      Cyclesnomem/Pkt  (min)  (max) ");
707         for(i=0;i<MAX_BIN;i++)
708             printf("<%s ",binStr[i]);
709         printf("\n ----------------------------------------------------------------------------------------------------------------------------------------------------\n");
710     }
712     //for (idx = 0; idx < g_reader->config_num_proto; idx++)
713     for (idx = 0; idx < pNavlCfg->num_protocols; idx++)
714     {
715         //if (g_reader->option_dpi)
716         {
717             if (g_reader.stats_pkt[threadId -1][idx].packets)
718             {
719                 /* We need to provide protocol definitions */   
720                 printf(" %-12s%-12" PRIu64 " %" PRIu64 " %" PRIu64 "      %" PRIu64 "       %" PRIu64 "    %ld    %ld    " , 
721                         g_reader.stats_pkt[threadId -1][idx].name,
722                         g_reader.stats_pkt[threadId -1][idx].packets, 
723                         g_reader.stats_pkt[threadId -1][idx].class, 
724                         g_reader.stats_pkt[threadId -1][idx].bytes,
725                         g_reader.stats_pkt[threadId -1][idx].cycles/g_reader.stats_pkt[threadId -1][idx].packets, 
726                         g_reader.stats_pkt[threadId -1][idx].cycles_nomem/g_reader.stats_pkt[threadId -1][idx].packets,
727                         g_reader.stats_pkt[threadId -1][idx].cycles_min,
728                         g_reader.stats_pkt[threadId -1][idx].cycles_max);
729                 for(i=0;i<MAX_BIN;i++) printf("%ld ",g_reader.stats_pkt[threadId -1][idx].bin_cycles[i]);
730                 printf("\n");
731             }
732         }
734         total_packets += g_reader.stats_pkt[threadId -1][idx].packets;
735         total_bytes += g_reader.stats_pkt[threadId -1][idx].bytes;
736     }
738     if (!total_packets)
739         printf("\n No packets captured.\n");
740     else
741         printf("\n %" PRIu64 " packets captured (%" PRIu64 " bytes)\n", total_packets, total_bytes);
743 #if 0
744     if (g_reader.stats_conns)
745         printf(" %" PRIu64 " connections tracked\n", g_reader.stats_conns);
747     printf("\n");
748     //if (g_reader.option_track_memory)
749         navl_wrapper_mem_stat_print();
751     if (pNavlCfg->alloc_curr != 0)
752         printf("Bytes not freed: %" PRIi64 "\n", pNavlCfg->alloc_curr);
754     if (g_reader.alloc_peak != 0)
755            printf("Peak allocated: %" PRIi64 "\n", g_reader.alloc_peak);
757     printf("attr test: last http utl= %s\n",last_url);
758 #endif
763 /* Private memory stamp type for tracking memory with navl_wrapper_malloc/free */
764 typedef struct
766     size_t      size;       /* size of allocation */
767     short       ctx_tag;    /* ctx axis */
768     short       obj_tag;    /* obj axis */
769     char        mem[0];
770 } memstamp_t;
772 static void *navl_wrapper_malloc(size_t size)
774     navl_handle_t handle;
775     navl_wrapper_stat_t *stat_mem;
776     int tag;
777     int ctx_tag, obj_tag;
778     unsigned long t1;
779     unsigned long t2;
780     pDpiStats->malloc_inst+=1;
781     pDpiStats->malloc_bytes+=size;
782     t1=netapi_timing_start();
784     assert(size);
786     /* In this context, the handle should be read using navl_handle_get() since
787      * the application cached handle (in this case g_reader->navl) will not be set
788      * until navl_open() returns. For this simple test we just assert that the handle
789      * is infact valid. */
790     handle = navl_handle_get();
791     assert(handle != 0);
793     /* Fetch the tags associated with this allocation. They will be used below to record
794      * statistics about allocations within the library on 2 axis. The upper 16 bits contain
795      * a memory obj tag and the lower 16 bits contain the allocation context tag. These
796      * tags are indices, the upper of which is available through navl_memory_ctx_num()
797      * and navl_memory_obj_num() resp. They are generated dynamically and may differ  between
798      * configurations. These total number of indices are available ONLY AFTER navl_open() 
799      * returns.
800      */
801     tag = navl_memory_tag_get(handle);
802     obj_tag = (tag >> 16);
803     ctx_tag = (tag & 0x0000FFFF);
805     /* You could do something better here and reallocate the matrix */
806     if (ctx_tag >= g_reader->config_num_memctx || obj_tag >= g_reader->config_num_memobj)
807     {
808         assert(0);
809         return NULL;
810     }
812     stat_mem = &g_reader->stats_mem[ctx_tag][obj_tag];
814     /* check limits */
815     if (!g_reader->option_limit_memory || (pNavlCfg->alloc_curr + size < g_reader->option_limit_memory))
816     {
817         memstamp_t *ptr = (memstamp_t *)malloc(size + sizeof(memstamp_t));
818         if (ptr)
819         {
820             /* track peak values */
821             if ((pNavlCfg->alloc_curr += size) > g_reader->alloc_peak)
822             g_reader->alloc_peak = pNavlCfg->alloc_curr;
824             if ((stat_mem->curr += size) > stat_mem->peak)
825             stat_mem->peak = stat_mem->curr;
827             ptr->size = size;
828             ptr->ctx_tag = ctx_tag;
829             ptr->obj_tag = obj_tag;
830             t2=netapi_timing_start();
831             pDpiStats->malloc_cycles += (unsigned long long)  (t2-t1);
832             return ptr->mem;
833         }
834     }
835     stat_mem->fail += size;
836     return NULL;
839 static void 
840 navl_wrapper_free(void *p)
842     unsigned long t1;
843     unsigned long t2;
844     pDpiStats->free_inst += 1;
845     t1=netapi_timing_start();
846     if (!p)
847         return;
849     memstamp_t *ptr = (memstamp_t *)((char *)p - offsetof(memstamp_t, mem));
850     navl_wrapper_stat_t *stat_mem = &g_reader->stats_mem[ptr->ctx_tag][ptr->obj_tag];
852     assert(p == ptr->mem);
854     stat_mem->curr -= ptr->size;
855     pNavlCfg->alloc_curr -= ptr->size;
857     free(ptr);
858     t2=netapi_timing_start();
859     pDpiStats->free_cycles += (unsigned long long)  (t2-t1);
862 static int
863 navl_wrapper_log_message(const char *level, const char *func, const char *format, ... )
865     int res = 0;
866     char buf[4096];
867     va_list va;
868     va_start(va, format);
870     res = snprintf(buf, 4096, "%s: %s: ", level, func);
871     res += vsnprintf(buf + res, 4096 - res, format, va);
872     printf("%s\n", buf);
873     va_end(va);
874     return res;
877 //clear stats
878 void clear_pkt_stats()
880     int ret, i;
881     memset(g_reader->stats_pkt[0], 0, (sizeof(navl_wrapper_pkt_stat_t)*MAX_PROTOCOLS));
882     memset(g_reader->stats_pkt[1], 0, (sizeof(navl_wrapper_pkt_stat_t)*MAX_PROTOCOLS));
884     for (i=0;i < NUM_FP_PROCS;i++)
885     {
886         /* now fetch all the protocol name ahead of time do we don't have to lookup them up on each packet */
887         for (ret = 0; ret != MAX_PROTOCOLS; ret++)
888         {
889             g_reader->stats_pkt[i][ret].cycles_min=10000000;
890         }
891     }