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
104 {
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)
172 {
173 g_reader->option_verbose=!g_reader->option_verbose;
174 printf(">**DPI Now in %s mode\n",g_reader->option_verbose?"verbose":"nonverbose");
175 }
176 void navl_dump_conn_info()
177 {
178 navl_diag(g_reader->navl, "TCP", NULL);
179 }
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)
193 {
194 return (navl_wrapper_init(0, NULL));
195 //return 1;
196 }
199 static const char *
200 get_state_string(navl_state_t state)
201 {
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 }
215 }
217 static const char *
218 get_confidence_string(int confidence)
219 {
220 switch (confidence)
221 {
222 case 50:
223 return "PORT";
224 case 100:
225 return "DPI";
226 default:
227 return "NONE";
228 }
229 }
231 static const char *
232 get_error_string(int error)
233 {
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 }
257 }
259 static int
260 navl_wrapper_init(int argc, char *argv[])
261 {
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;
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);
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 ;
375 }
377 //per thread init. Call this in worker thread context
378 int navl_per_thread_init(uint32_t thread_num)
379 {
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;
449 }
452 static uint64_t
453 msec_time(struct timeval *tv)
454 {
455 return ((uint64_t)tv->tv_sec * 1000) + (tv->tv_usec / 1000);
456 }
458 static void
459 msec_delay(uint64_t msecs)
460 {
461 struct timeval tv = { msecs / 1000, (msecs % 1000) * 1000 };
462 select(0, 0, 0, 0, &tv);
463 }
465 #if 1
466 typedef struct
467 {
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
476 {
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)
494 {
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;
548 }
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)
557 {
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;
591 }
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)
597 {
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;
661 }
663 int navl_done(void)
664 {
665 navl_fini(g_reader->navl);
666 navl_close(g_reader->navl);
667 return 1;
668 }
670 void navl_results(int threadId)
671 {
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);
736 }
738 static void
739 navl_wrapper_mem_stat_print()
740 {
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");
769 }
771 /* Private memory stamp type for tracking memory with navl_wrapper_malloc/free */
772 typedef struct
773 {
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)
781 {
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;
845 }
847 static void
848 navl_wrapper_free(void *p)
849 {
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);
868 }
870 static int
871 navl_wrapper_log_message(const char *level, const char *func, const char *format, ... )
872 {
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;
883 }
885 //clear stats
886 void clear_pkt_stats()
887 {
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 }
897 }