[H248 3GPP] Add dissection of IP transport package.
[metze/wireshark/wip.git] / ui / io_graph_item.h
1 /* io_graph_item.h
2  * Definitions and functions for IO graph items
3  *
4  * Copied from gtk/io_stat.c, (c) 2002 Ronnie Sahlberg
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #ifndef __IO_GRAPH_ITEM_H__
26 #define __IO_GRAPH_ITEM_H__
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif /* __cplusplus */
31
32 typedef enum {
33     IOG_ITEM_UNIT_FIRST,
34     IOG_ITEM_UNIT_PACKETS = IOG_ITEM_UNIT_FIRST,
35     IOG_ITEM_UNIT_BYTES,
36     IOG_ITEM_UNIT_BITS,
37     IOG_ITEM_UNIT_CALC_SUM,
38     IOG_ITEM_UNIT_CALC_FRAMES,
39     IOG_ITEM_UNIT_CALC_FIELDS,
40     IOG_ITEM_UNIT_CALC_MAX,
41     IOG_ITEM_UNIT_CALC_MIN,
42     IOG_ITEM_UNIT_CALC_AVERAGE,
43     IOG_ITEM_UNIT_CALC_LOAD,
44     IOG_ITEM_UNIT_LAST = IOG_ITEM_UNIT_CALC_LOAD,
45     NUM_IOG_ITEM_UNITS
46 } io_graph_item_unit_t;
47
48 typedef struct _io_graph_item_t {
49     guint32  frames;            /* always calculated, will hold number of frames*/
50     guint64  bytes;             /* always calculated, will hold number of bytes*/
51     guint64  fields;
52     gint64   int_max;
53     gint64   int_min;
54     gint64   int_tot;
55     /* XXX - Why do we always use 64-bit ints but split floats between
56      * gfloat and gdouble?
57      */
58     gfloat   float_max;
59     gfloat   float_min;
60     gfloat   float_tot;
61     gdouble  double_max;
62     gdouble  double_min;
63     gdouble  double_tot;
64     nstime_t time_max;
65     nstime_t time_min;
66     nstime_t time_tot;
67     guint32  first_frame_in_invl;
68     guint32  last_frame_in_invl;
69 } io_graph_item_t;
70
71 /** Reset (zero) an io_graph_item_t.
72  *
73  * @param items [in,out] Array containing the items to reset.
74  * @param count [in] The number of items in the array.
75  */
76 static inline void
77 reset_io_graph_items(io_graph_item_t *items, gsize count) {
78     io_graph_item_t *item;
79     gsize i;
80
81     for (i = 0; i < count; i++) {
82         item = &items[i];
83
84         item->frames     = 0;
85         item->bytes      = 0;
86         item->fields     = 0;
87         item->int_max    = 0;
88         item->int_min    = 0;
89         item->int_tot    = 0;
90         item->float_max  = 0;
91         item->float_min  = 0;
92         item->float_tot  = 0;
93         item->double_max = 0;
94         item->double_min = 0;
95         item->double_tot = 0;
96         nstime_set_zero(&item->time_max);
97         nstime_set_zero(&item->time_min);
98         nstime_set_zero(&item->time_tot);
99         item->first_frame_in_invl = 0;
100         item->last_frame_in_invl  = 0;
101     }
102 }
103
104 /** Get the interval (array index) for a packet
105  *
106  * It is up to the caller to determine if the return value is valid.
107  *
108  * @param [in] pinfo Packet of interest.
109  * @param [in] interval Time interval in milliseconds.
110  * @return Array index on success, -1 on failure.
111  */
112 int get_io_graph_index(packet_info *pinfo, int interval);
113
114 /** Check field and item unit compatibility
115  *
116  * @param field_name [in] Header field name to check
117  * @param hf_index [out] Assigned the header field index corresponding to field_name if valid.
118  *                       Can be NULL.
119  * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
120  * @return NULL if compatible, otherwise an error string. The string must
121  *         be freed by the caller.
122  */
123 GString *check_field_unit(const char *field_name, int *hf_index, io_graph_item_unit_t item_unit);
124
125 /** Update the values of an io_graph_item_t.
126  *
127  * Frame and byte counts are always calculated. If edt is non-NULL advanced
128  * statistics are calculated using hfindex.
129  *
130  * @param items [in,out] Array containing the item to update.
131  * @param idx [in] Index of the item to update.
132  * @param pinfo [in] Packet containing update information.
133  * @param edt [in] Dissection information for advanced statistics. May be NULL.
134  * @param hf_index [in] Header field index for advanced statistics.
135  * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
136  * @param interval [in] Timing interval in ms.
137  * @return TRUE if the update was successful, otherwise FALSE.
138  */
139 static inline gboolean
140 update_io_graph_item(io_graph_item_t *items, int idx, packet_info *pinfo, epan_dissect_t *edt, int hf_index, int item_unit, guint32 interval) {
141     io_graph_item_t *item = &items[idx];
142
143     /* Set the first and last frame num in current interval matching the target field+filter  */
144     if (item->first_frame_in_invl == 0) {
145         item->first_frame_in_invl = pinfo->num;
146     }
147     item->last_frame_in_invl = pinfo->num;
148
149     if (edt && hf_index >= 0) {
150         GPtrArray *gp;
151         guint i;
152
153         gp = proto_get_finfo_ptr_array(edt->tree, hf_index);
154         if (!gp) {
155             return FALSE;
156         }
157
158         /* Update the appropriate counters. If fields == 0, this is the first seen
159          *  value so set any min/max values accordingly. */
160         for (i=0; i < gp->len; i++) {
161             int new_int;
162             gint64 new_int64;
163             float new_float;
164             double new_double;
165             nstime_t *new_time;
166
167             switch (proto_registrar_get_ftype(hf_index)) {
168             case FT_UINT8:
169             case FT_UINT16:
170             case FT_UINT24:
171             case FT_UINT32:
172                 new_int = fvalue_get_uinteger(&((field_info *)gp->pdata[i])->value);
173
174                 if ((new_int > item->int_max) || (item->fields == 0)) {
175                     item->int_max = new_int;
176                 }
177                 if ((new_int < item->int_min) || (item->fields == 0)) {
178                     item->int_min = new_int;
179                 }
180                 item->int_tot += new_int;
181                 item->fields++;
182                 break;
183             case FT_INT8:
184             case FT_INT16:
185             case FT_INT24:
186             case FT_INT32:
187                 new_int = fvalue_get_sinteger(&((field_info *)gp->pdata[i])->value);
188                 if ((new_int > item->int_max) || (item->fields == 0)) {
189                     item->int_max = new_int;
190                 }
191                 if ((new_int < item->int_min) || (item->fields == 0)) {
192                     item->int_min = new_int;
193                 }
194                 item->int_tot += new_int;
195                 item->fields++;
196                 break;
197             case FT_UINT40:
198             case FT_UINT48:
199             case FT_UINT56:
200             case FT_UINT64:
201                 new_int64 = fvalue_get_uinteger64(&((field_info *)gp->pdata[i])->value);
202                 if ((new_int64 > item->int_max) || (item->fields == 0)) {
203                     item->int_max = new_int64;
204                 }
205                 if ((new_int64 < item->int_min) || (item->fields == 0)) {
206                     item->int_min = new_int64;
207                 }
208                 item->int_tot += new_int64;
209                 item->fields++;
210                 break;
211             case FT_INT40:
212             case FT_INT48:
213             case FT_INT56:
214             case FT_INT64:
215                 new_int64 = fvalue_get_sinteger64(&((field_info *)gp->pdata[i])->value);
216                 if ((new_int64 > item->int_max) || (item->fields == 0)) {
217                     item->int_max = new_int64;
218                 }
219                 if ((new_int64 < item->int_min) || (item->fields == 0)) {
220                     item->int_min = new_int64;
221                 }
222                 item->int_tot += new_int64;
223                 item->fields++;
224                 break;
225             case FT_FLOAT:
226                 new_float = (gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
227                 if ((new_float > item->float_max) || (item->fields == 0)) {
228                     item->float_max = new_float;
229                 }
230                 if ((new_float < item->float_min) || (item->fields == 0)) {
231                     item->float_min = new_float;
232                 }
233                 item->float_tot += new_float;
234                 item->fields++;
235                 break;
236             case FT_DOUBLE:
237                 new_double = fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
238                 if ((new_double > item->double_max) || (item->fields == 0)) {
239                     item->double_max = new_double;
240                 }
241                 if ((new_double < item->double_min) || (item->fields == 0)) {
242                     item->double_min = new_double;
243                 }
244                 item->double_tot += new_double;
245                 item->fields++;
246                 break;
247             case FT_RELATIVE_TIME:
248                 new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
249
250                 switch (item_unit) {
251                 case IOG_ITEM_UNIT_CALC_LOAD:
252                 {
253                     guint64 t, pt; /* time in us */
254                     int j;
255                     /*
256                      * Add the time this call spanned each interval according to its contribution
257                      * to that interval.
258                      */
259                     t = new_time->secs;
260                     t = t * 1000000 + new_time->nsecs / 1000;
261                     j = idx;
262                     /*
263                      * Handle current interval
264                      */
265                     pt = pinfo->rel_ts.secs * 1000000 + pinfo->rel_ts.nsecs / 1000;
266                     pt = pt % (interval * 1000);
267                     if (pt > t) {
268                         pt = t;
269                     }
270                     while (t) {
271                         io_graph_item_t *load_item;
272
273                         load_item = &items[j];
274                         load_item->time_tot.nsecs += (int) (pt * 1000);
275                         if (load_item->time_tot.nsecs > 1000000000) {
276                             load_item->time_tot.secs++;
277                             load_item->time_tot.nsecs -= 1000000000;
278                         }
279
280                         if (j == 0) {
281                             break;
282                         }
283                         j--;
284                         t -= pt;
285                         if (t > (guint64) interval * 1000) {
286                             pt = (guint64) interval * 1000;
287                         } else {
288                             pt = t;
289                         }
290                     }
291                     break;
292                 }
293                 default:
294                     if ( (new_time->secs > item->time_max.secs)
295                          || ( (new_time->secs == item->time_max.secs)
296                               && (new_time->nsecs > item->time_max.nsecs))
297                          || (item->fields == 0)) {
298                         item->time_max = *new_time;
299                     }
300                     if ( (new_time->secs<item->time_min.secs)
301                          || ( (new_time->secs == item->time_min.secs)
302                               && (new_time->nsecs < item->time_min.nsecs))
303                          || (item->fields == 0)) {
304                         item->time_min = *new_time;
305                     }
306                     nstime_add(&item->time_tot, new_time);
307                     item->fields++;
308                 }
309                 break;
310             default:
311                 if ((item_unit == IOG_ITEM_UNIT_CALC_FRAMES) ||
312                     (item_unit == IOG_ITEM_UNIT_CALC_FIELDS)) {
313                     /*
314                      * It's not an integeresque type, but
315                      * all we want to do is count it, so
316                      * that's all right.
317                      */
318                     item->fields++;
319                 }
320                 else {
321                     /*
322                      * "Can't happen"; see the "check that the
323                      * type is compatible" check in
324                      * filter_callback().
325                      */
326                     g_assert_not_reached();
327                 }
328                 break;
329             }
330         }
331     }
332
333     item->frames++;
334     item->bytes += pinfo->fd->pkt_len;
335
336     return TRUE;
337 }
338
339
340 #ifdef __cplusplus
341 }
342 #endif /* __cplusplus */
343
344 #endif /* __IO_GRAPH_ITEM_H__ */
345
346 /*
347  * Editor modelines
348  *
349  * Local Variables:
350  * c-basic-offset: 4
351  * tab-width: 8
352  * indent-tabs-mode: nil
353  * End:
354  *
355  * ex: set shiftwidth=4 tabstop=8 expandtab:
356  * :indentSize=4:tabSize=8:noTabs=true:
357  */