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