2 * Definitions and functions for I/O graph items
4 * Copied from gtk/io_stat.c, (c) 2002 Ronnie Sahlberg
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/epan_dissect.h>
18 #include <wsutil/application_flavor.h>
20 #include "ui/io_graph_item.h"
22 // XXX - constant defined elsewhere, any benefit to store it in a global .h ?
23 #define MICROSECS_PER_SEC 1000000
25 int64_t get_io_graph_index(packet_info
*pinfo
, int interval
) {
28 ws_return_val_if(interval
<= 0, -1);
31 * Find in which interval this is supposed to go and store the interval index as idx
33 time_delta
= pinfo
->rel_ts
;
34 if (time_delta
.nsecs
<0) {
36 time_delta
.nsecs
+= 1000000000;
38 if (time_delta
.secs
<0) {
41 return ((time_delta
.secs
*INT64_C(1000000) + time_delta
.nsecs
/1000) / interval
);
44 GString
*check_field_unit(const char *field_name
, int *hf_index
, io_graph_item_unit_t item_unit
)
46 GString
*err_str
= NULL
;
47 if (item_unit
>= IOG_ITEM_UNIT_CALC_SUM
) {
48 header_field_info
*hfi
;
50 const char *item_unit_names
[NUM_IOG_ITEM_UNITS
+1] = {
65 if (application_flavor_is_stratoshark()) {
66 item_unit_names
[0] = "Events";
69 /* There was no field specified */
70 if ((field_name
== NULL
) || (field_name
[0] == 0)) {
71 err_str
= g_string_new("You didn't specify a field name.");
75 /* The field could not be found */
76 hfi
= proto_registrar_get_byname(field_name
);
78 err_str
= g_string_new("");
79 g_string_printf(err_str
, "There is no field named '%s'.", field_name
);
83 if (hf_index
) *hf_index
= hfi
->id
;
85 /* Check that the type is compatible */
99 /* These values support all calculations except LOAD */
101 case IOG_ITEM_UNIT_CALC_LOAD
:
102 err_str
= g_string_new("LOAD is only supported for relative-time fields.");
106 /* These types support all calculations */
108 case FT_RELATIVE_TIME
:
109 /* This type only supports COUNT, MAX, MIN, AVG */
111 case IOG_ITEM_UNIT_CALC_SUM
:
112 case IOG_ITEM_UNIT_CALC_FRAMES
:
113 case IOG_ITEM_UNIT_CALC_FIELDS
:
114 case IOG_ITEM_UNIT_CALC_MAX
:
115 case IOG_ITEM_UNIT_CALC_MIN
:
116 case IOG_ITEM_UNIT_CALC_AVERAGE
:
117 case IOG_ITEM_UNIT_CALC_THROUGHPUT
:
118 case IOG_ITEM_UNIT_CALC_LOAD
:
121 ws_assert(item_unit
< NUM_IOG_ITEM_UNITS
);
122 err_str
= g_string_new("");
123 g_string_printf(err_str
, "\"%s\" is a relative-time field. %s calculations are not supported on it.",
125 item_unit_names
[item_unit
]);
129 if ((item_unit
!= IOG_ITEM_UNIT_CALC_FRAMES
) &&
130 (item_unit
!= IOG_ITEM_UNIT_CALC_FIELDS
)) {
131 err_str
= g_string_new("");
132 g_string_printf(err_str
, "\"%s\" doesn't have integral or float values. %s calculations are not supported on it.",
134 item_unit_names
[item_unit
]);
142 // Adapted from get_it_value in gtk/io_stat.c.
143 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_
, bool asAOT
)
145 double value
= 0; /* FIXME: loss of precision, visible on the graph for small values */
147 const io_graph_item_t
*item
;
150 ws_return_val_if(idx
< 0, 0);
155 // XXX - Should we divide these counted values by the interval
156 // so that they measure rates (as done with LOAD)? That might be
157 // more meaningful and consistent.
158 switch (val_units_
) {
159 case IOG_ITEM_UNIT_PACKETS
:
160 return asAOT
? MICROSECS_PER_SEC
*item
->frames
/interval_
: item
->frames
;
161 case IOG_ITEM_UNIT_BYTES
:
162 return (double)(asAOT
? MICROSECS_PER_SEC
*item
->bytes
/interval_
: item
->bytes
);
163 case IOG_ITEM_UNIT_BITS
:
164 return (double)(asAOT
? MICROSECS_PER_SEC
*item
->bytes
*8/interval_
: item
->bytes
*8);
165 case IOG_ITEM_UNIT_CALC_FRAMES
:
167 case IOG_ITEM_UNIT_CALC_FIELDS
:
168 return (double) item
->fields
;
170 /* If it's COUNT_TYPE_ADVANCED but not one of the
171 * generic ones we'll get it when we switch on the
180 adv_type
= proto_registrar_get_ftype(hf_index_
);
191 switch (val_units_
) {
192 case IOG_ITEM_UNIT_CALC_SUM
:
193 value
= item
->double_tot
;
195 case IOG_ITEM_UNIT_CALC_MAX
:
196 value
= (double)item
->int_max
;
198 case IOG_ITEM_UNIT_CALC_MIN
:
199 value
= (double)item
->int_min
;
201 case IOG_ITEM_UNIT_CALC_THROUGHPUT
:
202 value
= item
->double_tot
*MICROSECS_PER_SEC
/interval_
;
204 case IOG_ITEM_UNIT_CALC_AVERAGE
:
206 value
= item
->double_tot
/ item
->fields
;
224 switch (val_units_
) {
225 case IOG_ITEM_UNIT_CALC_SUM
:
226 value
= item
->double_tot
;
228 case IOG_ITEM_UNIT_CALC_MAX
:
229 value
= (double)item
->uint_max
;
231 case IOG_ITEM_UNIT_CALC_MIN
:
232 value
= (double)item
->uint_min
;
234 case IOG_ITEM_UNIT_CALC_THROUGHPUT
:
235 value
= item
->double_tot
*MICROSECS_PER_SEC
/interval_
;
237 case IOG_ITEM_UNIT_CALC_AVERAGE
:
239 value
= item
->double_tot
/ item
->fields
;
251 switch (val_units_
) {
252 case IOG_ITEM_UNIT_CALC_SUM
:
253 value
= item
->double_tot
;
255 case IOG_ITEM_UNIT_CALC_MAX
:
256 value
= item
->double_max
;
258 case IOG_ITEM_UNIT_CALC_MIN
:
259 value
= item
->double_min
;
261 case IOG_ITEM_UNIT_CALC_AVERAGE
:
263 value
= item
->double_tot
/ item
->fields
;
273 case FT_RELATIVE_TIME
:
274 switch (val_units_
) {
275 case IOG_ITEM_UNIT_CALC_MAX
:
276 value
= nstime_to_sec(&item
->time_max
);
278 case IOG_ITEM_UNIT_CALC_MIN
:
279 value
= nstime_to_sec(&item
->time_min
);
281 case IOG_ITEM_UNIT_CALC_SUM
:
282 value
= nstime_to_sec(&item
->time_tot
);
284 case IOG_ITEM_UNIT_CALC_AVERAGE
:
286 value
= nstime_to_sec(&item
->time_tot
) / item
->fields
;
291 case IOG_ITEM_UNIT_CALC_LOAD
:
292 // "LOAD graphs plot the QUEUE-depth of the connection over time"
293 // (for response time fields such as smb.time, rpc.time, etc.)
294 // This interval is expressed in microseconds.
295 if (idx
== cur_idx_
&& cap_file
) {
296 // If this is the last interval, it may not be full width.
297 uint64_t start_us
= (uint64_t)interval_
* idx
;
298 nstime_t timediff
= NSTIME_INIT_SECS_USECS(start_us
/ 1000000, start_us
% 1000000);
299 nstime_delta(&timediff
, &cap_file
->elapsed_time
, &timediff
);
300 interval
= (uint32_t)(1000*nstime_to_msec(&timediff
) + 0.5);
302 interval
= interval_
;
304 value
= (1000 * nstime_to_msec(&item
->time_tot
)) / interval
;