From fe04fb5e9879fd6c03fa60982964961bb87c8087 Mon Sep 17 00:00:00 2001 From: Thomas Dreibholz Date: Wed, 3 Mar 2021 10:42:16 +0100 Subject: Added ENRP statistics. --- epan/dissectors/packet-enrp.c | 205 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 1 deletion(-) (limited to 'epan') diff --git a/epan/dissectors/packet-enrp.c b/epan/dissectors/packet-enrp.c index 5b7f106ed0..6cb14267a3 100644 --- a/epan/dissectors/packet-enrp.c +++ b/epan/dissectors/packet-enrp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -32,6 +33,7 @@ void proto_register_enrp(void); void proto_reg_handoff_enrp(void); /* Initialize the protocol and registered fields */ +static int enrp_tap = -1; static int proto_enrp = -1; static int hf_cause_code = -1; static int hf_cause_length = -1; @@ -101,6 +103,12 @@ dissect_enrp(tvbuff_t *, packet_info *, proto_tree *, void*); #define ENRP_UDP_PORT 9901 #define ENRP_SCTP_PORT 9901 +typedef struct _enrp_tap_rec_t { + guint8 type; + guint16 size; + const char* type_string; +} enrp_tap_rec_t; + /* Dissectors for error causes. This is common for ASAP and ENRP. */ static void @@ -704,14 +712,22 @@ static const value_string message_type_values[] = { static void dissect_enrp_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *enrp_tree) { + enrp_tap_rec_t *tap_rec; proto_item *flags_item; proto_tree *flags_tree; guint8 type; type = tvb_get_guint8(message_tvb, MESSAGE_TYPE_OFFSET); /* pinfo is NULL only if dissect_enrp_message is called via dissect_error_cause */ - if (pinfo) + if (pinfo) { + tap_rec = wmem_new0(wmem_packet_scope(), enrp_tap_rec_t); + tap_rec->type = type; + tap_rec->size = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET); + tap_rec->type_string = val_to_str_const(tap_rec->type, message_type_values, "Unknown ENRP type"); + tap_queue_packet(enrp_tap, pinfo, tap_rec); + col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(type, message_type_values, "Unknown ENRP Type")); + } if (enrp_tree) { proto_tree_add_item(enrp_tree, hf_message_type, message_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, ENC_BIG_ENDIAN); @@ -775,6 +791,171 @@ dissect_enrp(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, void* return tvb_captured_length(message_tvb); } +/* TAP STAT INFO */ +typedef enum +{ + MESSAGE_TYPE_COLUMN = 0, + MESSAGES_COLUMN, + BYTES_COLUMN, + FIRST_SEEN_COLUMN, + LAST_SEEN_COLUMN, + INTERVAL_COLUMN, + RATE_COLUMN +} enrp_stat_columns; + +static stat_tap_table_item enrp_stat_fields[] = { + { TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "ENRP Message Type", "%-25s" }, + { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Messages ", "%u" }, + { TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes (B)", "%u" }, + { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "First Seen (s)", "%1.6f" }, + { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Last Seen (s)", "%1.6f" }, + { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Interval (s)", "%1.6f" }, + { TABLE_ITEM_FLOAT, TAP_ALIGN_LEFT, "Rate (1/s)", "%1.2f" } +}; + +static void enrp_stat_init(stat_tap_table_ui* new_stat) +{ + const char *table_name = "ENRP Statistics"; + int num_fields = sizeof(enrp_stat_fields)/sizeof(stat_tap_table_item); + stat_tap_table *table; + int i = 0; + stat_tap_table_item_type items[sizeof(enrp_stat_fields)/sizeof(stat_tap_table_item)]; + + table = stat_tap_find_table(new_stat, table_name); + if (table) { + if (new_stat->stat_tap_reset_table_cb) { + new_stat->stat_tap_reset_table_cb(table); + } + return; + } + + table = stat_tap_init_table(table_name, num_fields, 0, NULL); + stat_tap_add_table(new_stat, table); + + /* Add a row for each value type */ + while (message_type_values[i].strptr) { + items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING; + items[MESSAGE_TYPE_COLUMN].value.string_value = message_type_values[i].strptr; + items[MESSAGES_COLUMN].type = TABLE_ITEM_UINT; + items[MESSAGES_COLUMN].value.uint_value = 0; + items[BYTES_COLUMN].type = TABLE_ITEM_UINT; + items[BYTES_COLUMN].value.uint_value = 0; + items[FIRST_SEEN_COLUMN].type = TABLE_ITEM_NONE; + items[FIRST_SEEN_COLUMN].value.float_value = DBL_MAX; + items[LAST_SEEN_COLUMN].type = TABLE_ITEM_NONE; + items[LAST_SEEN_COLUMN].value.float_value = DBL_MIN; + items[INTERVAL_COLUMN].type = TABLE_ITEM_NONE; + items[INTERVAL_COLUMN].value.float_value = -1.0; + items[RATE_COLUMN].type = TABLE_ITEM_NONE; + items[RATE_COLUMN].value.float_value = -1.0; + stat_tap_init_table_row(table, i, num_fields, items); + i++; + } +} + +static tap_packet_status +enrp_stat_packet(void* tapdata, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* data) +{ + stat_data_t* stat_data = (stat_data_t*)tapdata; + const enrp_tap_rec_t* tap_rec = (const enrp_tap_rec_t*)data; + stat_tap_table* table; + stat_tap_table_item_type* msg_data; + gint idx; + guint messages = 0; + double firstSeen = -1.0; + double lastSeen = -1.0; + + idx = str_to_val_idx(tap_rec->type_string, message_type_values); + if (idx < 0) + return TAP_PACKET_DONT_REDRAW; + + table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0); + + /* Update packets counter */ + msg_data = stat_tap_get_field_data(table, idx, MESSAGES_COLUMN); + msg_data->value.uint_value++; + messages = msg_data->value.uint_value; + stat_tap_set_field_data(table, idx, MESSAGES_COLUMN, msg_data); + + /* Update bytes counter */ + msg_data = stat_tap_get_field_data(table, idx, BYTES_COLUMN); + msg_data->value.uint_value += tap_rec->size; + stat_tap_set_field_data(table, idx, BYTES_COLUMN, msg_data); + + /* Update first seen time */ + if (pinfo->presence_flags & PINFO_HAS_TS) { + msg_data = stat_tap_get_field_data(table, idx, FIRST_SEEN_COLUMN); + msg_data->type = TABLE_ITEM_FLOAT; + msg_data->value.float_value = MIN(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts)); + firstSeen = msg_data->value.float_value; + stat_tap_set_field_data(table, idx, FIRST_SEEN_COLUMN, msg_data); + } + + /* Update last seen time */ + if (pinfo->presence_flags & PINFO_HAS_TS) { + msg_data = stat_tap_get_field_data(table, idx, LAST_SEEN_COLUMN); + msg_data->type = TABLE_ITEM_FLOAT; + msg_data->value.float_value = MAX(msg_data->value.float_value, nstime_to_sec(&pinfo->rel_ts)); + lastSeen = msg_data->value.float_value; + stat_tap_set_field_data(table, idx, LAST_SEEN_COLUMN, msg_data); + } + + if ((lastSeen - firstSeen) > 0.0) { + /* Update interval */ + msg_data = stat_tap_get_field_data(table, idx, INTERVAL_COLUMN); + stat_tap_set_field_data(table, idx, INTERVAL_COLUMN, msg_data); + msg_data->type = TABLE_ITEM_FLOAT; + msg_data->value.float_value = lastSeen - firstSeen; + stat_tap_set_field_data(table, idx, INTERVAL_COLUMN, msg_data); + + /* Update message rate */ + msg_data = stat_tap_get_field_data(table, idx, RATE_COLUMN); + stat_tap_set_field_data(table, idx, INTERVAL_COLUMN, msg_data); + msg_data->type = TABLE_ITEM_FLOAT; + msg_data->value.float_value = messages / (lastSeen - firstSeen); + stat_tap_set_field_data(table, idx, RATE_COLUMN, msg_data); + } + + return TAP_PACKET_REDRAW; +} + +static void +enrp_stat_reset(stat_tap_table* table) +{ + stat_tap_table_item_type* item_data; + guint element; + + for (element = 0; element < table->num_elements; element++) { + item_data = stat_tap_get_field_data(table, element, MESSAGES_COLUMN); + item_data->value.uint_value = 0; + stat_tap_set_field_data(table, element, MESSAGES_COLUMN, item_data); + + item_data = stat_tap_get_field_data(table, element, BYTES_COLUMN); + item_data->value.uint_value = 0; + stat_tap_set_field_data(table, element, FIRST_SEEN_COLUMN, item_data); + + item_data = stat_tap_get_field_data(table, element, FIRST_SEEN_COLUMN); + item_data->type = TABLE_ITEM_NONE; + item_data->value.float_value = DBL_MAX; + stat_tap_set_field_data(table, element, FIRST_SEEN_COLUMN, item_data); + + item_data = stat_tap_get_field_data(table, element, LAST_SEEN_COLUMN); + item_data->type = TABLE_ITEM_NONE; + item_data->value.float_value = DBL_MIN; + stat_tap_set_field_data(table, element, LAST_SEEN_COLUMN, item_data); + + item_data = stat_tap_get_field_data(table, element, INTERVAL_COLUMN); + item_data->type = TABLE_ITEM_NONE; + item_data->value.float_value = -1.0; + stat_tap_set_field_data(table, element, INTERVAL_COLUMN, item_data); + + item_data = stat_tap_get_field_data(table, element, RATE_COLUMN); + item_data->type = TABLE_ITEM_NONE; + item_data->value.float_value = -1.0; + stat_tap_set_field_data(table, element, RATE_COLUMN, item_data); + } +} + /* Register the protocol with Wireshark */ void proto_register_enrp(void) @@ -843,13 +1024,35 @@ proto_register_enrp(void) &ett_enrp_flags, }; + static tap_param enrp_stat_params[] = { + { PARAM_FILTER, "filter", "Filter", NULL, TRUE } + }; + + static stat_tap_table_ui enrp_stat_table = { + REGISTER_STAT_GROUP_UNSORTED, + "ENRP Statistics", + "enrp", + "enrp,stat", + enrp_stat_init, + enrp_stat_packet, + enrp_stat_reset, + NULL, + NULL, + sizeof(enrp_stat_fields)/sizeof(stat_tap_table_item), enrp_stat_fields, + sizeof(enrp_stat_params)/sizeof(tap_param), enrp_stat_params, + NULL, + 0 + }; + /* Register the protocol name and description */ proto_enrp = proto_register_protocol("Endpoint Handlespace Redundancy Protocol", "ENRP", "enrp"); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_enrp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); + enrp_tap = register_tap("enrp"); + register_stat_tap_table_ui(&enrp_stat_table); } void -- cgit v1.2.3