Wireshark  4.3.0
The Wireshark network protocol analyzer
io_graph_item.h
Go to the documentation of this file.
1 
14 #ifndef __IO_GRAPH_ITEM_H__
15 #define __IO_GRAPH_ITEM_H__
16 
17 #include "cfile.h"
18 #include <wsutil/ws_assert.h>
19 
20 #include <epan/epan_dissect.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif /* __cplusplus */
25 
26 typedef enum {
27  IOG_ITEM_UNIT_FIRST,
28  IOG_ITEM_UNIT_PACKETS = IOG_ITEM_UNIT_FIRST,
29  IOG_ITEM_UNIT_BYTES,
30  IOG_ITEM_UNIT_BITS,
31  IOG_ITEM_UNIT_CALC_SUM,
32  IOG_ITEM_UNIT_CALC_FRAMES,
33  IOG_ITEM_UNIT_CALC_FIELDS,
34  IOG_ITEM_UNIT_CALC_MAX,
35  IOG_ITEM_UNIT_CALC_MIN,
36  IOG_ITEM_UNIT_CALC_AVERAGE,
37  IOG_ITEM_UNIT_CALC_LOAD,
38  IOG_ITEM_UNIT_LAST = IOG_ITEM_UNIT_CALC_LOAD,
39  NUM_IOG_ITEM_UNITS
40 } io_graph_item_unit_t;
41 
42 typedef struct _io_graph_item_t {
43  uint32_t frames; /* always calculated, will hold number of frames*/
44  uint64_t bytes; /* always calculated, will hold number of bytes*/
45  uint64_t fields;
46  /* We use a double for totals because of overflow. For min and max,
47  * unsigned 64 bit integers larger than 2^53 cannot all be represented
48  * in a double, and this is useful for determining the frame with the
49  * min or max value, even though for plotting it will be converted to a
50  * double.
51  */
52  union {
53  nstime_t time_max;
54  double double_max;
55  int64_t int_max;
56  uint64_t uint_max;
57  };
58  union {
59  nstime_t time_min;
60  double double_min;
61  int64_t int_min;
62  uint64_t uint_min;
63  };
64  union {
65  nstime_t time_tot;
66  double double_tot;
67  };
68  uint32_t first_frame_in_invl;
69  uint32_t min_frame_in_invl;
70  uint32_t max_frame_in_invl;
71  uint32_t last_frame_in_invl;
73 
79 static inline void
80 reset_io_graph_items(io_graph_item_t *items, size_t count, int hf_index _U_) {
81  io_graph_item_t *item;
82  size_t i;
83 
84  for (i = 0; i < count; i++) {
85  item = &items[i];
86 
87  item->frames = 0;
88  item->bytes = 0;
89  item->fields = 0;
90  item->first_frame_in_invl = 0;
91  item->min_frame_in_invl = 0;
92  item->max_frame_in_invl = 0;
93  item->last_frame_in_invl = 0;
94 
95  nstime_set_zero(&item->time_max);
96  nstime_set_zero(&item->time_min);
97  nstime_set_zero(&item->time_tot);
98 
99 #if 0
100  /* XXX - On C, type punning is explicitly allowed since C99 so
101  * setting the nstime_t values to 0 is always sufficient.
102  * On C++ that appears technically to be undefined behavior (though
103  * I don't know of any compilers for which it doesn't work and I
104  * can't get UBSAN to complain about it) and this would be safer.
105  */
106  if (hf_index > 0) {
107 
108  switch (proto_registrar_get_ftype(hf_index)) {
109 
110  case FT_INT8:
111  case FT_INT16:
112  case FT_INT24:
113  case FT_INT32:
114  case FT_INT40:
115  case FT_INT48:
116  case FT_INT56:
117  case FT_INT64:
118  item->int_max = 0;
119  item->int_min = 0;
120  item->double_tot = 0;
121  break;
122 
123  case FT_UINT8:
124  case FT_UINT16:
125  case FT_UINT24:
126  case FT_UINT32:
127  case FT_UINT40:
128  case FT_UINT48:
129  case FT_UINT56:
130  case FT_UINT64:
131  item->uint_max = 0;
132  item->uint_min = 0;
133  item->double_tot = 0;
134  break;
135 
136  case FT_DOUBLE:
137  case FT_FLOAT:
138  item->double_max = 0;
139  item->double_min = 0;
140  item->double_tot = 0;
141  break;
142 
143  case FT_RELATIVE_TIME:
144  nstime_set_zero(&item->time_max);
145  nstime_set_zero(&item->time_min);
146  nstime_set_zero(&item->time_tot);
147  break;
148 
149  default:
150  break;
151  }
152  }
153 #endif
154  }
155 }
156 
169 int64_t get_io_graph_index(packet_info *pinfo, int interval);
170 
180 GString *check_field_unit(const char *field_name, int *hf_index, io_graph_item_unit_t item_unit);
181 
192 double get_io_graph_item(const io_graph_item_t *items, io_graph_item_unit_t val_units, int idx, int hf_index, const capture_file *cap_file, int interval, int cur_idx);
193 
208 static inline bool
209 update_io_graph_item(io_graph_item_t *items, int idx, packet_info *pinfo, epan_dissect_t *edt, int hf_index, int item_unit, uint32_t interval) {
210  io_graph_item_t *item = &items[idx];
211 
212  /* Set the first and last frame num in current interval matching the target field+filter */
213  if (item->first_frame_in_invl == 0) {
214  item->first_frame_in_invl = pinfo->num;
215  }
216  item->last_frame_in_invl = pinfo->num;
217 
218  if (edt && hf_index >= 0) {
219  GPtrArray *gp;
220  unsigned i;
221 
222  gp = proto_get_finfo_ptr_array(edt->tree, hf_index);
223  if (!gp) {
224  return false;
225  }
226 
227  /* Update the appropriate counters. If fields == 0, this is the first seen
228  * value so set any min/max values accordingly. */
229  for (i=0; i < gp->len; i++) {
230  int64_t new_int64;
231  uint64_t new_uint64;
232  float new_float;
233  double new_double;
234  const nstime_t *new_time;
235 
236  switch (proto_registrar_get_ftype(hf_index)) {
237  case FT_UINT8:
238  case FT_UINT16:
239  case FT_UINT24:
240  case FT_UINT32:
241  new_uint64 = fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
242 
243  if ((new_uint64 > item->uint_max) || (item->fields == 0)) {
244  item->uint_max = new_uint64;
245  item->max_frame_in_invl = pinfo->num;
246  }
247  if ((new_uint64 < item->uint_min) || (item->fields == 0)) {
248  item->uint_min = new_uint64;
249  item->min_frame_in_invl = pinfo->num;
250  }
251  item->double_tot += (double)new_uint64;
252  item->fields++;
253  break;
254  case FT_INT8:
255  case FT_INT16:
256  case FT_INT24:
257  case FT_INT32:
258  new_int64 = fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
259  if ((new_int64 > item->int_max) || (item->fields == 0)) {
260  item->int_max = new_int64;
261  item->max_frame_in_invl = pinfo->num;
262  }
263  if ((new_int64 < item->int_min) || (item->fields == 0)) {
264  item->int_min = new_int64;
265  item->min_frame_in_invl = pinfo->num;
266  }
267  item->double_tot += (double)new_int64;
268  item->fields++;
269  break;
270  case FT_UINT40:
271  case FT_UINT48:
272  case FT_UINT56:
273  case FT_UINT64:
274  new_uint64 = fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
275  if ((new_uint64 > item->uint_max) || (item->fields == 0)) {
276  item->uint_max = new_uint64;
277  item->max_frame_in_invl = pinfo->num;
278  }
279  if ((new_uint64 < item->uint_min) || (item->fields == 0)) {
280  item->uint_min = new_uint64;
281  item->min_frame_in_invl = pinfo->num;
282  }
283  item->double_tot += (double)new_uint64;
284  item->fields++;
285  break;
286  case FT_INT40:
287  case FT_INT48:
288  case FT_INT56:
289  case FT_INT64:
290  new_int64 = fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
291  if ((new_int64 > item->int_max) || (item->fields == 0)) {
292  item->int_max = new_int64;
293  item->max_frame_in_invl = pinfo->num;
294  }
295  if ((new_int64 < item->int_min) || (item->fields == 0)) {
296  item->int_min = new_int64;
297  item->min_frame_in_invl = pinfo->num;
298  }
299  item->double_tot += (double)new_int64;
300  item->fields++;
301  break;
302  case FT_FLOAT:
303  new_float = (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
304  if ((new_float > item->double_max) || (item->fields == 0)) {
305  item->double_max = new_float;
306  item->max_frame_in_invl = pinfo->num;
307  }
308  if ((new_float < item->double_min) || (item->fields == 0)) {
309  item->double_min = new_float;
310  item->min_frame_in_invl = pinfo->num;
311  }
312  item->double_tot += new_float;
313  item->fields++;
314  break;
315  case FT_DOUBLE:
316  new_double = fvalue_get_floating(((field_info *)gp->pdata[i])->value);
317  if ((new_double > item->double_max) || (item->fields == 0)) {
318  item->double_max = new_double;
319  item->max_frame_in_invl = pinfo->num;
320  }
321  if ((new_double < item->double_min) || (item->fields == 0)) {
322  item->double_min = new_double;
323  item->min_frame_in_invl = pinfo->num;
324  }
325  item->double_tot += new_double;
326  item->fields++;
327  break;
328  case FT_RELATIVE_TIME:
329  new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
330 
331  switch (item_unit) {
332  case IOG_ITEM_UNIT_CALC_LOAD:
333  {
334  uint64_t t, pt; /* time in us */
335  int j;
336  /*
337  * Add the time this call spanned each interval according to
338  * its contribution to that interval.
339  * If the call time is negative (unlikely, requires both an
340  * out of order capture file plus retransmission), ignore.
341  */
342  const nstime_t time_zero = NSTIME_INIT_ZERO;
343  if (nstime_cmp(new_time, &time_zero) < 0) {
344  break;
345  }
346  t = new_time->secs;
347  t = t * 1000000 + new_time->nsecs / 1000;
348  j = idx;
349  /*
350  * Handle current interval
351  * This cannot be negative, because get_io_graph_index
352  * returns an invalid interval if so.
353  */
354  pt = pinfo->rel_ts.secs * 1000000 + pinfo->rel_ts.nsecs / 1000;
355  pt = pt % interval;
356  if (pt > t) {
357  pt = t;
358  }
359  while (t) {
360  io_graph_item_t *load_item;
361 
362  load_item = &items[j];
363  load_item->time_tot.nsecs += (int) (pt * 1000);
364  if (load_item->time_tot.nsecs > 1000000000) {
365  load_item->time_tot.secs++;
366  load_item->time_tot.nsecs -= 1000000000;
367  }
368  load_item->fields++;
369 
370  if (j == 0) {
371  break;
372  }
373  j--;
374  t -= pt;
375  if (t > (uint64_t) interval) {
376  pt = (uint64_t) interval;
377  } else {
378  pt = t;
379  }
380  }
381  break;
382  }
383  default:
384  if ( (nstime_cmp(new_time, &item->time_max) > 0)
385  || (item->fields == 0)) {
386  item->time_max = *new_time;
387  item->max_frame_in_invl = pinfo->num;
388  }
389  if ( (nstime_cmp(new_time, &item->time_min) < 0)
390  || (item->fields == 0)) {
391  item->time_min = *new_time;
392  item->min_frame_in_invl = pinfo->num;
393  }
394  nstime_add(&item->time_tot, new_time);
395  item->fields++;
396  }
397  break;
398  default:
399  if ((item_unit == IOG_ITEM_UNIT_CALC_FRAMES) ||
400  (item_unit == IOG_ITEM_UNIT_CALC_FIELDS)) {
401  /*
402  * It's not an integeresque type, but
403  * all we want to do is count it, so
404  * that's all right.
405  */
406  item->fields++;
407  }
408  else {
409  /*
410  * "Can't happen"; see the "check that the
411  * type is compatible" check in
412  * filter_callback().
413  */
414  ws_assert_not_reached();
415  }
416  break;
417  }
418  }
419  }
420 
421  item->frames++;
422  item->bytes += pinfo->fd->pkt_len;
423 
424  return true;
425 }
426 
427 
428 #ifdef __cplusplus
429 }
430 #endif /* __cplusplus */
431 
432 #endif /* __IO_GRAPH_ITEM_H__ */
enum ftenum proto_registrar_get_ftype(const int n)
Definition: proto.c:11109
GPtrArray * proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
Definition: proto.c:11169
int64_t get_io_graph_index(packet_info *pinfo, int interval)
Definition: io_graph_item.c:22
double get_io_graph_item(const io_graph_item_t *items, io_graph_item_unit_t val_units, int idx, int hf_index, const capture_file *cap_file, int interval, int cur_idx)
Definition: io_graph_item.c:138
GString * check_field_unit(const char *field_name, int *hf_index, io_graph_item_unit_t item_unit)
Definition: io_graph_item.c:41
#define nstime_add(sum, a)
Definition: nstime.h:96
WS_DLL_PUBLIC void nstime_set_zero(nstime_t *nstime)
Definition: nstime.c:28
WS_DLL_PUBLIC int nstime_cmp(const nstime_t *a, const nstime_t *b)
Definition: nstime.c:138
Definition: cfile.h:67
Definition: io_graph_item.h:42
Definition: packet_info.h:44
nstime_t rel_ts
Definition: packet_info.h:50
guint32 num
Definition: packet_info.h:48
Definition: epan_dissect.h:28
Definition: proto.h:816
Definition: nstime.h:26