/src/wireshark/epan/dissectors/packet-componentstatus.c
Line | Count | Source |
1 | | /* packet-componentstatus.c |
2 | | * Routines for the Component Status Protocol of the |
3 | | * RSPLIB RSerPool implementation |
4 | | * https://www.uni-due.de/~be0001/rserpool/ |
5 | | * |
6 | | * Copyright 2006-2021 by Thomas Dreibholz <dreibh [AT] iem.uni-due.de> |
7 | | * |
8 | | * Wireshark - Network traffic analyzer |
9 | | * By Gerald Combs <gerald@wireshark.org> |
10 | | * Copyright 1998 Gerald Combs |
11 | | * |
12 | | * Copied from README.developer |
13 | | * |
14 | | * SPDX-License-Identifier: GPL-2.0-or-later |
15 | | */ |
16 | | |
17 | | #include "config.h" |
18 | | |
19 | | #include <epan/packet.h> |
20 | | #include <epan/stat_tap_ui.h> |
21 | | #include <epan/tfs.h> |
22 | | #include <wsutil/array.h> |
23 | | #include "packet-sctp.h" |
24 | | #include <epan/iana-info.h> |
25 | | |
26 | | |
27 | | void proto_register_componentstatusprotocol(void); |
28 | | void proto_reg_handoff_componentstatusprotocol(void); |
29 | | |
30 | | static dissector_handle_t componentstatusprotocol_handle; |
31 | | |
32 | | /* Initialize the protocol and registered fields */ |
33 | | static int proto_componentstatusprotocol; |
34 | | static int tap_componentstatusprotocol = -1; |
35 | | |
36 | | /* Initialize the subtree pointers */ |
37 | | static int ett_componentstatusprotocol; |
38 | | static int ett_message_flags; |
39 | | static int ett_message_sender_id; |
40 | | static int ett_cspreport_association_receiver_id; |
41 | | static int ett_association; |
42 | | |
43 | | |
44 | 16 | #define COMPONENTSTATUSPROTOCOL_PORT 2960 /* Not IANA registered */ |
45 | 0 | #define COMPONENTSTATUSPROTOCOL_VERSION 0x0200 |
46 | | |
47 | | static int hf_message_type; |
48 | | static int hf_message_flags; |
49 | | static int hf_message_flags_final_bit; |
50 | | static int hf_message_length; |
51 | | static int hf_message_version; |
52 | | static int hf_message_sender_id; |
53 | | static int hf_message_sender_id_group; |
54 | | static int hf_message_sender_id_object; |
55 | | static int hf_message_sender_timestamp; |
56 | | |
57 | | static uint64_t componentstatusprotocol_total_msgs; |
58 | | static uint64_t componentstatusprotocol_total_bytes; |
59 | | |
60 | | |
61 | 0 | #define COMPONENTSTATUS_REPORT 0x01 |
62 | | |
63 | | static const value_string message_type_values[] = { |
64 | | { COMPONENTSTATUS_REPORT, "ComponentStatus Report" }, |
65 | | { 0, NULL } |
66 | | }; |
67 | | |
68 | | |
69 | | static int hf_cspreport_report_interval; |
70 | | static int hf_cspreport_location; |
71 | | static int hf_cspreport_status; |
72 | | static int hf_cspreport_workload; |
73 | | static int hf_cspreport_associations; |
74 | | |
75 | | #define CSPF_FINAL (1 << 0) |
76 | | static const true_false_string message_flags_final_bit = { |
77 | | "Final message", |
78 | | "Not final message" |
79 | | }; |
80 | | |
81 | | #define CID_GROUP_UNKNOWN 0x0000 |
82 | | #define CID_GROUP_REGISTRAR 0x0001 |
83 | | #define CID_GROUP_POOLELEMENT 0x0002 |
84 | | #define CID_GROUP_POOLUSER 0x0003 |
85 | | #define CID_GROUP(id) (((uint64_t) id >> 56) & (0xffffULL) |
86 | | #define CID_OBJECT(id) (((uint64_t) id & 0xffffffffffffffULL) |
87 | | static const value_string group_values[] = { |
88 | | { CID_GROUP_UNKNOWN, "Unknown" }, |
89 | | { CID_GROUP_REGISTRAR, "Registrar" }, |
90 | | { CID_GROUP_POOLELEMENT, "Pool Element" }, |
91 | | { CID_GROUP_POOLUSER, "Pool User" }, |
92 | | { 0, NULL } |
93 | | }; |
94 | | |
95 | 0 | #define CSR_GET_WORKLOAD(w) ((w == 0xffff) ? -1.0 : (float)(w / (float)0xfffe)) |
96 | | |
97 | | static int hf_cspreport_association_receiver_id; |
98 | | static int hf_cspreport_association_receiver_id_group; |
99 | | static int hf_cspreport_association_receiver_id_object; |
100 | | static int hf_cspreport_association_duration; |
101 | | static int hf_cspreport_association_flags; |
102 | | static int hf_cspreport_association_protocolid; |
103 | | static int hf_cspreport_association_ppid; |
104 | | |
105 | | |
106 | | /* Setup list of header fields */ |
107 | | static hf_register_info hf[] = { |
108 | | { &hf_message_type, { "Type", "componentstatusprotocol.message_type", FT_UINT8, BASE_DEC, VALS(message_type_values), 0x0, NULL, HFILL } }, |
109 | | { &hf_message_flags, { "Flags", "componentstatusprotocol.message_flags", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
110 | | { &hf_message_flags_final_bit, { "F-Bit", "componentstatusprotocol.message_final_bit", FT_BOOLEAN, 8, TFS(&message_flags_final_bit), CSPF_FINAL, NULL, HFILL } }, |
111 | | { &hf_message_length, { "Length", "componentstatusprotocol.message_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
112 | | { &hf_message_version, { "Version", "componentstatusprotocol.message_version", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
113 | | { &hf_message_sender_id, { "SenderID", "componentstatusprotocol.message_sender_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
114 | | { &hf_message_sender_id_group, { "Group", "componentstatusprotocol.message_sender_id.group", FT_UINT16, BASE_HEX, VALS(group_values), 0x0, NULL, HFILL } }, |
115 | | { &hf_message_sender_id_object, { "Object", "componentstatusprotocol.message_sender_id.object", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
116 | | { &hf_message_sender_timestamp, { "SenderTimeStamp", "componentstatusprotocol.message_sendertimestamp", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
117 | | |
118 | | { &hf_cspreport_report_interval, { "ReportInterval", "componentstatusprotocol.componentstatusreport_reportinterval", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
119 | | { &hf_cspreport_location, { "Location", "componentstatusprotocol.componentstatusreport_location", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
120 | | { &hf_cspreport_status, { "Status", "componentstatusprotocol.componentstatusreport_status", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
121 | | { &hf_cspreport_workload, { "Workload", "componentstatusprotocol.componentstatusreport_workload", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
122 | | { &hf_cspreport_associations, { "Associations", "componentstatusprotocol.componentstatusreport_associations", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
123 | | |
124 | | { &hf_cspreport_association_receiver_id, { "ReceiverID", "componentstatusprotocol.componentassociation_receiver_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
125 | | { &hf_cspreport_association_receiver_id_group, { "Group", "componentstatusprotocol.componentassociation_receiver_id.group", FT_UINT16, BASE_HEX, VALS(group_values), 0x0, NULL, HFILL } }, |
126 | | { &hf_cspreport_association_receiver_id_object, { "Object", "componentstatusprotocol.componentassociation_receiver_id.object", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
127 | | { &hf_cspreport_association_duration, { "Duration", "componentstatusprotocol.componentassociation_duration", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
128 | | { &hf_cspreport_association_flags, { "Flags", "componentstatusprotocol.componentassociation_flags", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
129 | | { &hf_cspreport_association_protocolid, { "ProtocolID", "componentstatusprotocol.componentassociation_protocolid", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ipproto_val_ext, 0x0, NULL, HFILL } }, |
130 | | { &hf_cspreport_association_ppid, { "PPID", "componentstatusprotocol.componentassociation_ppid", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sctpppid_val_ext, 0x0, NULL, HFILL } }, |
131 | | }; |
132 | | |
133 | | |
134 | | typedef struct _tap_componentstatusprotocol_rec_t { |
135 | | uint8_t type; |
136 | | uint16_t size; |
137 | | const char* type_string; |
138 | | } tap_componentstatusprotocol_rec_t; |
139 | | |
140 | | |
141 | | static void |
142 | | dissect_componentstatusprotocol_cspreport_association(tvbuff_t *message_tvb, proto_tree *message_tree) |
143 | 0 | { |
144 | 0 | proto_item* receiver_id_item; |
145 | 0 | proto_tree* receiver_id_tree; |
146 | 0 | uint64_t timestamp; |
147 | 0 | nstime_t t; |
148 | |
|
149 | 0 | receiver_id_item = proto_tree_add_item(message_tree, hf_cspreport_association_receiver_id, message_tvb, 0, 8, ENC_BIG_ENDIAN); |
150 | 0 | receiver_id_tree = proto_item_add_subtree(receiver_id_item, ett_cspreport_association_receiver_id); |
151 | 0 | proto_tree_add_item(receiver_id_tree, hf_cspreport_association_receiver_id_group, message_tvb, 0, 1, ENC_BIG_ENDIAN); |
152 | 0 | proto_tree_add_item(receiver_id_tree, hf_cspreport_association_receiver_id_object, message_tvb, 1, 7, ENC_BIG_ENDIAN); |
153 | |
|
154 | 0 | timestamp = tvb_get_ntoh64(message_tvb, 8); |
155 | 0 | t.secs = (time_t)(timestamp / 1000000); |
156 | 0 | t.nsecs = (int)((timestamp - 1000000 * t.secs) * 1000); |
157 | 0 | if(timestamp == 0xffffffffffffffffULL) { |
158 | 0 | proto_tree_add_time_format_value(message_tree, hf_cspreport_association_duration, message_tvb, 8, 8, &t, "Unknown"); |
159 | 0 | } |
160 | 0 | else { |
161 | 0 | proto_tree_add_time(message_tree, hf_cspreport_association_duration, message_tvb, 8, 8, &t); |
162 | 0 | } |
163 | |
|
164 | 0 | proto_tree_add_item(message_tree, hf_cspreport_association_flags, message_tvb, 16, 2, ENC_BIG_ENDIAN); |
165 | 0 | proto_tree_add_item(message_tree, hf_cspreport_association_protocolid, message_tvb, 18, 2, ENC_BIG_ENDIAN); |
166 | 0 | proto_tree_add_item(message_tree, hf_cspreport_association_ppid, message_tvb, 20, 4, ENC_BIG_ENDIAN); |
167 | 0 | } |
168 | | |
169 | | |
170 | | static void |
171 | | dissect_componentstatusprotocol_cspreport_message(tvbuff_t *message_tvb, proto_tree *message_tree) |
172 | 0 | { |
173 | 0 | tvbuff_t *association_tvb; |
174 | 0 | proto_tree *association_tree; |
175 | 0 | int association; |
176 | 0 | int offset; |
177 | 0 | float workload; |
178 | 0 | uint64_t interval; |
179 | 0 | nstime_t t; |
180 | |
|
181 | 0 | interval = tvb_get_ntohl(message_tvb, 24); |
182 | 0 | t.secs = (time_t)(interval / 1000000); |
183 | 0 | t.nsecs = (int)((interval - 1000000 * t.secs) * 1000); |
184 | 0 | proto_tree_add_time(message_tree, hf_cspreport_report_interval, message_tvb, 24, 4, &t); |
185 | 0 | proto_tree_add_item(message_tree, hf_cspreport_location, message_tvb, 28, 128, ENC_UTF_8); |
186 | 0 | proto_tree_add_item(message_tree, hf_cspreport_status, message_tvb, 156, 128, ENC_UTF_8); |
187 | |
|
188 | 0 | workload = (float)(100.0 * CSR_GET_WORKLOAD(tvb_get_ntohs(message_tvb, 284))); |
189 | 0 | if(workload < 0.0) { /* Special value 0xffff -> -1.0 means "no load provided"! */ |
190 | 0 | proto_tree_add_float_format_value(message_tree, hf_cspreport_workload, message_tvb, 284, 2, |
191 | 0 | workload, "N/A"); |
192 | 0 | } |
193 | 0 | else { |
194 | 0 | proto_tree_add_float_format_value(message_tree, hf_cspreport_workload, message_tvb, 284, 2, |
195 | 0 | workload, "%1.2f%%", workload); |
196 | 0 | } |
197 | 0 | proto_tree_add_item(message_tree, hf_cspreport_associations, message_tvb, 286, 2, ENC_BIG_ENDIAN); |
198 | |
|
199 | 0 | association = 1; |
200 | 0 | offset = 288; |
201 | 0 | while(tvb_reported_length_remaining(message_tvb, offset) >= 24) { |
202 | 0 | association_tree = proto_tree_add_subtree_format(message_tree, message_tvb, offset, 24, |
203 | 0 | ett_association, NULL, "Association #%d", association++); |
204 | 0 | association_tvb = tvb_new_subset_length(message_tvb, offset, 24); |
205 | |
|
206 | 0 | dissect_componentstatusprotocol_cspreport_association(association_tvb, association_tree); |
207 | 0 | offset += 24; |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | |
212 | | static void |
213 | | dissect_componentstatusprotocol_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *componentstatusprotocol_tree) |
214 | 0 | { |
215 | 0 | proto_item* flags_item; |
216 | 0 | proto_tree* flags_tree; |
217 | 0 | proto_item* sender_id_item; |
218 | 0 | proto_tree* sender_id_tree; |
219 | 0 | uint64_t timestamp; |
220 | 0 | nstime_t t; |
221 | |
|
222 | 0 | tap_componentstatusprotocol_rec_t* tap_rec = wmem_new0(pinfo->pool, tap_componentstatusprotocol_rec_t); |
223 | 0 | tap_rec->type = tvb_get_uint8(message_tvb, 0); |
224 | 0 | tap_rec->size = tvb_get_ntohs(message_tvb, 2); |
225 | 0 | tap_rec->type_string = val_to_str_const(tap_rec->type, message_type_values, "Unknown ComponentStatusProtocol message type"); |
226 | 0 | tap_queue_packet(tap_componentstatusprotocol, pinfo, tap_rec); |
227 | |
|
228 | 0 | proto_tree_add_item(componentstatusprotocol_tree, hf_message_type, message_tvb, 0, 1, ENC_BIG_ENDIAN); |
229 | 0 | flags_item = proto_tree_add_item(componentstatusprotocol_tree, hf_message_flags, message_tvb, 1, 1, ENC_BIG_ENDIAN); |
230 | 0 | flags_tree = proto_item_add_subtree(flags_item, ett_message_flags); |
231 | 0 | proto_tree_add_item(flags_tree, hf_message_flags_final_bit, message_tvb, 1, 1, ENC_BIG_ENDIAN); |
232 | 0 | proto_tree_add_item(componentstatusprotocol_tree, hf_message_length, message_tvb, 2, 2, ENC_BIG_ENDIAN); |
233 | |
|
234 | 0 | proto_tree_add_item(componentstatusprotocol_tree, hf_message_version, message_tvb, 4, 4, ENC_BIG_ENDIAN); |
235 | 0 | sender_id_item = proto_tree_add_item(componentstatusprotocol_tree, hf_message_sender_id, message_tvb, 8, 8, ENC_BIG_ENDIAN); |
236 | 0 | sender_id_tree = proto_item_add_subtree(sender_id_item, ett_message_sender_id); |
237 | 0 | proto_tree_add_item(sender_id_tree, hf_message_sender_id_group, message_tvb, 8, 1, ENC_BIG_ENDIAN); |
238 | 0 | proto_tree_add_item(sender_id_tree, hf_message_sender_id_object, message_tvb, 9, 7, ENC_BIG_ENDIAN); |
239 | |
|
240 | 0 | timestamp = tvb_get_ntoh64(message_tvb, 16); |
241 | 0 | t.secs = (time_t)(timestamp / 1000000); |
242 | 0 | t.nsecs = (int)((timestamp - 1000000 * t.secs) * 1000); |
243 | 0 | proto_tree_add_time(componentstatusprotocol_tree, hf_message_sender_timestamp, message_tvb, 16, 8, &t); |
244 | |
|
245 | 0 | switch (tap_rec->type) { |
246 | 0 | case COMPONENTSTATUS_REPORT: |
247 | 0 | dissect_componentstatusprotocol_cspreport_message(message_tvb, componentstatusprotocol_tree); |
248 | 0 | break; |
249 | 0 | } |
250 | 0 | } |
251 | | |
252 | | |
253 | | static int |
254 | | dissect_componentstatusprotocol(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
255 | 0 | { |
256 | 0 | proto_item *componentstatusprotocol_item; |
257 | 0 | proto_tree *componentstatusprotocol_tree; |
258 | 0 | int8_t type; |
259 | 0 | int32_t version; |
260 | |
|
261 | 0 | if (tvb_reported_length(message_tvb) < 4 + 4) |
262 | 0 | return 0; |
263 | | |
264 | | /* Check, if this packet really contains a ComponentStatusProtocol message */ |
265 | 0 | type = tvb_get_uint8(message_tvb, 0); |
266 | 0 | if (type != COMPONENTSTATUS_REPORT) { |
267 | 0 | return 0; |
268 | 0 | } |
269 | 0 | version = tvb_get_ntohl(message_tvb, 4); |
270 | 0 | if (version != COMPONENTSTATUSPROTOCOL_VERSION) { |
271 | 0 | return 0; |
272 | 0 | } |
273 | | |
274 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ComponentStatusProtocol"); |
275 | | |
276 | | /* create the componentstatusprotocol protocol tree */ |
277 | 0 | componentstatusprotocol_item = proto_tree_add_item(tree, proto_componentstatusprotocol, message_tvb, 0, -1, ENC_NA); |
278 | 0 | componentstatusprotocol_tree = proto_item_add_subtree(componentstatusprotocol_item, ett_componentstatusprotocol); |
279 | | |
280 | | /* dissect the message */ |
281 | 0 | dissect_componentstatusprotocol_message(message_tvb, pinfo, componentstatusprotocol_tree); |
282 | 0 | return tvb_reported_length(message_tvb); |
283 | 0 | } |
284 | | |
285 | | |
286 | | /* TAP STAT INFO */ |
287 | | typedef enum |
288 | | { |
289 | | MESSAGE_TYPE_COLUMN = 0, |
290 | | MESSAGES_COLUMN, |
291 | | MESSAGES_SHARE_COLUMN, |
292 | | BYTES_COLUMN, |
293 | | BYTES_SHARE_COLUMN, |
294 | | FIRST_SEEN_COLUMN, |
295 | | LAST_SEEN_COLUMN, |
296 | | INTERVAL_COLUMN, |
297 | | MESSAGE_RATE_COLUMN, |
298 | | BYTE_RATE_COLUMN |
299 | | } componentstatusprotocol_stat_columns; |
300 | | |
301 | | static stat_tap_table_item componentstatusprotocol_stat_fields[] = { |
302 | | { TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "ComponentStatusProtocol Message Type", "%-25s" }, |
303 | | { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Messages ", "%u" }, |
304 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Messages Share (%)" , "%1.3f %%" }, |
305 | | { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes (B)", "%u" }, |
306 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Bytes Share (%) ", "%1.3f %%" }, |
307 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "First Seen (s)", "%1.6f" }, |
308 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Last Seen (s)", "%1.6f" }, |
309 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Interval (s)", "%1.6f" }, |
310 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Message Rate (Msg/s)", "%1.2f" }, |
311 | | { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Byte Rate (B/s)", "%1.2f" } |
312 | | }; |
313 | | |
314 | | static void componentstatusprotocol_stat_init(stat_tap_table_ui* new_stat) |
315 | 0 | { |
316 | 0 | const char *table_name = "ComponentStatusProtocol Statistics"; |
317 | 0 | int num_fields = array_length(componentstatusprotocol_stat_fields); |
318 | 0 | stat_tap_table *table; |
319 | 0 | int i = 0; |
320 | 0 | stat_tap_table_item_type items[array_length(componentstatusprotocol_stat_fields)]; |
321 | |
|
322 | 0 | table = stat_tap_find_table(new_stat, table_name); |
323 | 0 | if (table) { |
324 | 0 | if (new_stat->stat_tap_reset_table_cb) { |
325 | 0 | new_stat->stat_tap_reset_table_cb(table); |
326 | 0 | } |
327 | 0 | return; |
328 | 0 | } |
329 | | |
330 | 0 | table = stat_tap_init_table(table_name, num_fields, 0, NULL); |
331 | 0 | stat_tap_add_table(new_stat, table); |
332 | |
|
333 | 0 | memset(items, 0x0, sizeof(items)); |
334 | | /* Add a row for each value type */ |
335 | 0 | while (message_type_values[i].strptr) { |
336 | 0 | items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING; |
337 | 0 | items[MESSAGE_TYPE_COLUMN].value.string_value = message_type_values[i].strptr; |
338 | 0 | items[MESSAGES_COLUMN].type = TABLE_ITEM_UINT; |
339 | 0 | items[MESSAGES_COLUMN].value.uint_value = 0; |
340 | 0 | items[MESSAGES_SHARE_COLUMN].type = TABLE_ITEM_NONE; |
341 | 0 | items[MESSAGES_SHARE_COLUMN].value.float_value = -1.0; |
342 | 0 | items[BYTES_COLUMN].type = TABLE_ITEM_UINT; |
343 | 0 | items[BYTES_COLUMN].value.uint_value = 0; |
344 | 0 | items[BYTES_SHARE_COLUMN].type = TABLE_ITEM_NONE; |
345 | 0 | items[BYTES_SHARE_COLUMN].value.float_value = -1.0; |
346 | 0 | items[FIRST_SEEN_COLUMN].type = TABLE_ITEM_NONE; |
347 | 0 | items[FIRST_SEEN_COLUMN].value.float_value = DBL_MAX; |
348 | 0 | items[LAST_SEEN_COLUMN].type = TABLE_ITEM_NONE; |
349 | 0 | items[LAST_SEEN_COLUMN].value.float_value = DBL_MIN; |
350 | 0 | items[INTERVAL_COLUMN].type = TABLE_ITEM_NONE; |
351 | 0 | items[INTERVAL_COLUMN].value.float_value = -1.0; |
352 | 0 | items[MESSAGE_RATE_COLUMN].type = TABLE_ITEM_NONE; |
353 | 0 | items[MESSAGE_RATE_COLUMN].value.float_value = -1.0; |
354 | 0 | items[BYTE_RATE_COLUMN].type = TABLE_ITEM_NONE; |
355 | 0 | items[BYTE_RATE_COLUMN].value.float_value = -1.0; |
356 | 0 | stat_tap_init_table_row(table, i, num_fields, items); |
357 | 0 | i++; |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | | static tap_packet_status |
362 | | componentstatusprotocol_stat_packet(void* tapdata, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* data, tap_flags_t flags _U_) |
363 | 0 | { |
364 | 0 | stat_data_t* stat_data = (stat_data_t*)tapdata; |
365 | 0 | const tap_componentstatusprotocol_rec_t* tap_rec = (const tap_componentstatusprotocol_rec_t*)data; |
366 | 0 | stat_tap_table* table; |
367 | 0 | stat_tap_table_item_type* msg_data; |
368 | 0 | int idx; |
369 | 0 | uint64_t messages; |
370 | 0 | uint64_t bytes; |
371 | 0 | int i = 0; |
372 | 0 | double firstSeen = -1.0; |
373 | 0 | double lastSeen = -1.0; |
374 | |
|
375 | 0 | idx = str_to_val_idx(tap_rec->type_string, message_type_values); |
376 | 0 | if (idx < 0) |
377 | 0 | return TAP_PACKET_DONT_REDRAW; |
378 | | |
379 | 0 | table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0); |
380 | | |
381 | | /* Update packets counter */ |
382 | 0 | componentstatusprotocol_total_msgs++; |
383 | 0 | msg_data = stat_tap_get_field_data(table, idx, MESSAGES_COLUMN); |
384 | 0 | msg_data->value.uint_value++; |
385 | 0 | messages = msg_data->value.uint_value; |
386 | 0 | stat_tap_set_field_data(table, idx, MESSAGES_COLUMN, msg_data); |
387 | | |
388 | | /* Update bytes counter */ |
389 | 0 | componentstatusprotocol_total_bytes += tap_rec->size; |
390 | 0 | msg_data = stat_tap_get_field_data(table, idx, BYTES_COLUMN); |
391 | 0 | msg_data->value.uint_value += tap_rec->size; |
392 | 0 | bytes = msg_data->value.uint_value; |
393 | 0 | stat_tap_set_field_data(table, idx, BYTES_COLUMN, msg_data); |
394 | | |
395 | | /* Update messages and bytes share */ |
396 | 0 | while (message_type_values[i].strptr) { |
397 | 0 | msg_data = stat_tap_get_field_data(table, i, MESSAGES_COLUMN); |
398 | 0 | const unsigned m = msg_data->value.uint_value; |
399 | 0 | msg_data = stat_tap_get_field_data(table, i, BYTES_COLUMN); |
400 | 0 | const unsigned b = msg_data->value.uint_value; |
401 | |
|
402 | 0 | msg_data = stat_tap_get_field_data(table, i, MESSAGES_SHARE_COLUMN); |
403 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
404 | 0 | msg_data->value.float_value = 100.0 * m / (double)componentstatusprotocol_total_msgs; |
405 | 0 | stat_tap_set_field_data(table, i, MESSAGES_SHARE_COLUMN, msg_data); |
406 | |
|
407 | 0 | msg_data = stat_tap_get_field_data(table, i, BYTES_SHARE_COLUMN); |
408 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
409 | 0 | msg_data->value.float_value = componentstatusprotocol_total_bytes ? 100.0 * b / (double)componentstatusprotocol_total_bytes : 0.0; |
410 | 0 | stat_tap_set_field_data(table, i, BYTES_SHARE_COLUMN, msg_data); |
411 | 0 | i++; |
412 | 0 | } |
413 | | |
414 | | /* Update first seen time */ |
415 | 0 | if (pinfo->presence_flags & PINFO_HAS_TS) { |
416 | 0 | msg_data = stat_tap_get_field_data(table, idx, FIRST_SEEN_COLUMN); |
417 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
418 | 0 | msg_data->value.float_value = MIN(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts)); |
419 | 0 | firstSeen = msg_data->value.float_value; |
420 | 0 | stat_tap_set_field_data(table, idx, FIRST_SEEN_COLUMN, msg_data); |
421 | 0 | } |
422 | | |
423 | | /* Update last seen time */ |
424 | 0 | if (pinfo->presence_flags & PINFO_HAS_TS) { |
425 | 0 | msg_data = stat_tap_get_field_data(table, idx, LAST_SEEN_COLUMN); |
426 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
427 | 0 | msg_data->value.float_value = MAX(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts)); |
428 | 0 | lastSeen = msg_data->value.float_value; |
429 | 0 | stat_tap_set_field_data(table, idx, LAST_SEEN_COLUMN, msg_data); |
430 | 0 | } |
431 | |
|
432 | 0 | if ((lastSeen - firstSeen) > 0.0) { |
433 | | /* Update interval */ |
434 | 0 | msg_data = stat_tap_get_field_data(table, idx, INTERVAL_COLUMN); |
435 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
436 | 0 | msg_data->value.float_value = lastSeen - firstSeen; |
437 | 0 | stat_tap_set_field_data(table, idx, INTERVAL_COLUMN, msg_data); |
438 | | |
439 | | /* Update message rate */ |
440 | 0 | msg_data = stat_tap_get_field_data(table, idx, MESSAGE_RATE_COLUMN); |
441 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
442 | 0 | msg_data->value.float_value = messages / (lastSeen - firstSeen); |
443 | 0 | stat_tap_set_field_data(table, idx, MESSAGE_RATE_COLUMN, msg_data); |
444 | | |
445 | | /* Update byte rate */ |
446 | 0 | msg_data = stat_tap_get_field_data(table, idx, BYTE_RATE_COLUMN); |
447 | 0 | msg_data->type = TABLE_ITEM_FLOAT; |
448 | 0 | msg_data->value.float_value = bytes / (lastSeen - firstSeen); |
449 | 0 | stat_tap_set_field_data(table, idx, BYTE_RATE_COLUMN, msg_data); |
450 | 0 | } |
451 | |
|
452 | 0 | return TAP_PACKET_REDRAW; |
453 | 0 | } |
454 | | |
455 | | static void |
456 | | componentstatusprotocol_stat_reset(stat_tap_table* table) |
457 | 0 | { |
458 | 0 | unsigned element; |
459 | 0 | stat_tap_table_item_type* item_data; |
460 | |
|
461 | 0 | for (element = 0; element < table->num_elements; element++) { |
462 | 0 | item_data = stat_tap_get_field_data(table, element, MESSAGES_COLUMN); |
463 | 0 | item_data->value.uint_value = 0; |
464 | 0 | stat_tap_set_field_data(table, element, MESSAGES_COLUMN, item_data); |
465 | |
|
466 | 0 | item_data = stat_tap_get_field_data(table, element, MESSAGES_SHARE_COLUMN); |
467 | 0 | item_data->type = TABLE_ITEM_NONE; |
468 | 0 | item_data->value.float_value = -1.0; |
469 | 0 | stat_tap_set_field_data(table, element, MESSAGES_SHARE_COLUMN, item_data); |
470 | |
|
471 | 0 | item_data = stat_tap_get_field_data(table, element, BYTES_COLUMN); |
472 | 0 | item_data->value.uint_value = 0; |
473 | 0 | stat_tap_set_field_data(table, element, BYTES_COLUMN, item_data); |
474 | |
|
475 | 0 | item_data = stat_tap_get_field_data(table, element, BYTES_SHARE_COLUMN); |
476 | 0 | item_data->type = TABLE_ITEM_NONE; |
477 | 0 | item_data->value.float_value = -1.0; |
478 | 0 | stat_tap_set_field_data(table, element, BYTES_SHARE_COLUMN, item_data); |
479 | |
|
480 | 0 | item_data = stat_tap_get_field_data(table, element, FIRST_SEEN_COLUMN); |
481 | 0 | item_data->type = TABLE_ITEM_NONE; |
482 | 0 | item_data->value.float_value = DBL_MAX; |
483 | 0 | stat_tap_set_field_data(table, element, FIRST_SEEN_COLUMN, item_data); |
484 | |
|
485 | 0 | item_data = stat_tap_get_field_data(table, element, LAST_SEEN_COLUMN); |
486 | 0 | item_data->type = TABLE_ITEM_NONE; |
487 | 0 | item_data->value.float_value = DBL_MIN; |
488 | 0 | stat_tap_set_field_data(table, element, LAST_SEEN_COLUMN, item_data); |
489 | |
|
490 | 0 | item_data = stat_tap_get_field_data(table, element, INTERVAL_COLUMN); |
491 | 0 | item_data->type = TABLE_ITEM_NONE; |
492 | 0 | item_data->value.float_value = -1.0; |
493 | 0 | stat_tap_set_field_data(table, element, INTERVAL_COLUMN, item_data); |
494 | |
|
495 | 0 | item_data = stat_tap_get_field_data(table, element, MESSAGE_RATE_COLUMN); |
496 | 0 | item_data->type = TABLE_ITEM_NONE; |
497 | 0 | item_data->value.float_value = -1.0; |
498 | 0 | stat_tap_set_field_data(table, element, MESSAGE_RATE_COLUMN, item_data); |
499 | |
|
500 | 0 | item_data = stat_tap_get_field_data(table, element, BYTE_RATE_COLUMN); |
501 | 0 | item_data->type = TABLE_ITEM_NONE; |
502 | 0 | item_data->value.float_value = -1.0; |
503 | 0 | stat_tap_set_field_data(table, element, BYTE_RATE_COLUMN, item_data); |
504 | 0 | } |
505 | 0 | componentstatusprotocol_total_msgs = 0; |
506 | 0 | componentstatusprotocol_total_bytes = 0; |
507 | 0 | } |
508 | | |
509 | | |
510 | | /* Register the protocol with Wireshark */ |
511 | | void |
512 | | proto_register_componentstatusprotocol(void) |
513 | 16 | { |
514 | | /* Setup protocol subtree array */ |
515 | 16 | static int *ett[] = { |
516 | 16 | &ett_componentstatusprotocol, |
517 | 16 | &ett_message_flags, |
518 | 16 | &ett_message_sender_id, |
519 | 16 | &ett_cspreport_association_receiver_id, |
520 | 16 | &ett_association |
521 | 16 | }; |
522 | | |
523 | 16 | static tap_param componentstatusprotocol_stat_params[] = { |
524 | 16 | { PARAM_FILTER, "filter", "Filter", NULL, true } |
525 | 16 | }; |
526 | | |
527 | 16 | static stat_tap_table_ui componentstatusprotocol_stat_table = { |
528 | 16 | REGISTER_STAT_GROUP_RSERPOOL, |
529 | 16 | "ComponentStatusProtocol Statistics", |
530 | 16 | "componentstatusprotocol", |
531 | 16 | "componentstatusprotocol,stat", |
532 | 16 | componentstatusprotocol_stat_init, |
533 | 16 | componentstatusprotocol_stat_packet, |
534 | 16 | componentstatusprotocol_stat_reset, |
535 | 16 | NULL, |
536 | 16 | NULL, |
537 | 16 | array_length(componentstatusprotocol_stat_fields), componentstatusprotocol_stat_fields, |
538 | 16 | array_length(componentstatusprotocol_stat_params), componentstatusprotocol_stat_params, |
539 | 16 | NULL, |
540 | 16 | 0 |
541 | 16 | }; |
542 | | |
543 | | /* Register the protocol name and description */ |
544 | 16 | proto_componentstatusprotocol = proto_register_protocol("Component Status Protocol", "ComponentStatusProtocol", "componentstatusprotocol"); |
545 | | |
546 | | /* Required function calls to register the header fields and subtrees used */ |
547 | 16 | proto_register_field_array(proto_componentstatusprotocol, hf, array_length(hf)); |
548 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
549 | 16 | tap_componentstatusprotocol = register_tap("componentstatusprotocol"); |
550 | | |
551 | | /* Register the dissector */ |
552 | 16 | componentstatusprotocol_handle = register_dissector("componentstatusprotocol", dissect_componentstatusprotocol, proto_componentstatusprotocol); |
553 | | |
554 | 16 | register_stat_tap_table_ui(&componentstatusprotocol_stat_table); |
555 | 16 | } |
556 | | |
557 | | void |
558 | | proto_reg_handoff_componentstatusprotocol(void) |
559 | 16 | { |
560 | 16 | dissector_add_uint_with_preference("udp.port", COMPONENTSTATUSPROTOCOL_PORT, componentstatusprotocol_handle); |
561 | 16 | } |
562 | | |
563 | | /* |
564 | | * Editor modelines |
565 | | * |
566 | | * Local Variables: |
567 | | * c-basic-offset: 2 |
568 | | * tab-width: 8 |
569 | | * indent-tabs-mode: nil |
570 | | * End: |
571 | | * |
572 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
573 | | * :indentSize=2:tabSize=8:noTabs=true: |
574 | | */ |