aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rpc.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-08-06 10:56:22 -0700
committerAnders Broman <a.broman58@gmail.com>2015-08-07 08:57:42 +0000
commitfd19aafbe6ae39dc07c16ebf565d916ec6da33a4 (patch)
treef63839dc26ea32e3aa42d05b9918b83854955e99 /epan/dissectors/packet-rpc.c
parent0c9998ddfdb425fef2a43badb09690ef2a8e73ce (diff)
Add ONC RPC program stats.
Convert ONC RPC program stats to the stat_tap API. Add a "user_data" member to the stat_tap_table_item_type struct. Change-Id: I5cbf000a447ff93d30fa7f098124bdcbc34f2935 Reviewed-on: https://code.wireshark.org/review/9904 Petri-Dish: Gerald Combs <gerald@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'epan/dissectors/packet-rpc.c')
-rw-r--r--epan/dissectors/packet-rpc.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/epan/dissectors/packet-rpc.c b/epan/dissectors/packet-rpc.c
index d192f0d81d..69702e1254 100644
--- a/epan/dissectors/packet-rpc.c
+++ b/epan/dissectors/packet-rpc.c
@@ -33,6 +33,7 @@
#include <epan/prefs.h>
#include <epan/reassemble.h>
#include <epan/tap.h>
+#include <epan/stat_tap_ui.h>
#include <epan/srt_table.h>
#include <epan/strutil.h>
#include <epan/show_exception.h>
@@ -3810,6 +3811,149 @@ rpc_cleanup_protocol(void)
g_hash_table_destroy(rpc_reassembly_table);
}
+/* Tap statistics */
+typedef enum
+{
+ PROGRAM_NAME_COLUMN,
+ PROGRAM_NUM_COLUMN,
+ VERSION_COLUMN,
+ CALLS_COLUMN,
+ MIN_SRT_COLUMN,
+ MAX_SRT_COLUMN,
+ AVG_SRT_COLUMN
+} rpc_prog_stat_columns;
+
+static stat_tap_table_item rpc_prog_stat_fields[] = {
+ {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "Program", "%-25s"},
+ {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Program Num", "%u"},
+ {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Version", "%u"},
+ {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Calls", "%u"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Min SRT (s)", "%.2f"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Max SRT (s)", "%.2f"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Avg SRT (s)", "%.2f"}
+};
+
+void rpc_prog_stat_init(new_stat_tap_ui* new_stat, new_stat_tap_gui_init_cb gui_callback, void* gui_data)
+{
+ int num_fields = sizeof(rpc_prog_stat_fields)/sizeof(stat_tap_table_item);
+ new_stat_tap_table* table;
+
+ table = new_stat_tap_init_table("ONC-RPC Program Statistics", num_fields, 0, NULL, gui_callback, gui_data);
+ new_stat_tap_add_table(new_stat, table);
+
+}
+
+static gboolean
+rpc_prog_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rciv_ptr)
+{
+ new_stat_data_t* stat_data = (new_stat_data_t*)tapdata;
+ const rpc_call_info_value *ri = (const rpc_call_info_value *)rciv_ptr;
+ int num_fields = sizeof(rpc_prog_stat_fields)/sizeof(stat_tap_table_item);
+ nstime_t delta;
+ double delta_s = 0.0;
+ guint call_count;
+ guint element;
+ gboolean found = FALSE;
+ new_stat_tap_table* table;
+ stat_tap_table_item_type* item_data;
+
+ table = g_array_index(stat_data->new_stat_tap_data->tables, new_stat_tap_table*, 0);
+
+ for (element = 0; element < table->num_elements; element++)
+ {
+ stat_tap_table_item_type *program_data, *version_data;
+ program_data = new_stat_tap_get_field_data(table, element, PROGRAM_NUM_COLUMN);
+ version_data = new_stat_tap_get_field_data(table, element, VERSION_COLUMN);
+
+ if ((ri->prog == program_data->value.uint_value) && (ri->vers == version_data->value.uint_value)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Add a new row */
+ stat_tap_table_item_type items[sizeof(rpc_prog_stat_fields)/sizeof(stat_tap_table_item)];
+ memset(items, 0, sizeof(items));
+
+ items[PROGRAM_NAME_COLUMN].type = TABLE_ITEM_STRING;
+ items[PROGRAM_NAME_COLUMN].value.string_value = g_strdup(rpc_prog_name(ri->prog));
+ items[PROGRAM_NUM_COLUMN].type = TABLE_ITEM_UINT;
+ items[PROGRAM_NUM_COLUMN].value.uint_value = ri->prog;
+ items[VERSION_COLUMN].type = TABLE_ITEM_UINT;
+ items[VERSION_COLUMN].value.uint_value = ri->vers;
+ items[CALLS_COLUMN].type = TABLE_ITEM_UINT;
+ items[MIN_SRT_COLUMN].type = TABLE_ITEM_FLOAT;
+ items[MAX_SRT_COLUMN].type = TABLE_ITEM_FLOAT;
+ items[AVG_SRT_COLUMN].type = TABLE_ITEM_FLOAT;
+
+ new_stat_tap_init_table_row(table, element, num_fields, items);
+ }
+
+ /* we are only interested in reply packets */
+ if (ri->request) {
+ return FALSE;
+ }
+
+ item_data = new_stat_tap_get_field_data(table, element, CALLS_COLUMN);
+ item_data->value.uint_value++;
+ call_count = item_data->value.uint_value;
+ new_stat_tap_set_field_data(table, element, CALLS_COLUMN, item_data);
+
+ /* calculate time delta between request and reply */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &ri->req_time);
+ delta_s = nstime_to_sec(&delta);
+
+ item_data = new_stat_tap_get_field_data(table, element, MIN_SRT_COLUMN);
+ if (item_data->value.float_value == 0.0 || delta_s < item_data->value.float_value) {
+ item_data->value.float_value = delta_s;
+ new_stat_tap_set_field_data(table, element, MIN_SRT_COLUMN, item_data);
+ }
+
+ item_data = new_stat_tap_get_field_data(table, element, MAX_SRT_COLUMN);
+ if (item_data->value.float_value == 0.0 || delta_s > item_data->value.float_value) {
+ item_data->value.float_value = delta_s;
+ new_stat_tap_set_field_data(table, element, MAX_SRT_COLUMN, item_data);
+ }
+
+ item_data = new_stat_tap_get_field_data(table, element, AVG_SRT_COLUMN);
+ item_data->user_data.float_value += delta_s;
+ item_data->value.float_value = item_data->user_data.float_value / call_count;
+ new_stat_tap_set_field_data(table, element, AVG_SRT_COLUMN, item_data);
+
+ return TRUE;
+}
+
+static void
+rpc_prog_stat_reset(new_stat_tap_table* table)
+{
+ guint element;
+ stat_tap_table_item_type* item_data;
+
+ for (element = 0; element < table->num_elements; element++)
+ {
+ item_data = new_stat_tap_get_field_data(table, element, CALLS_COLUMN);
+ item_data->value.uint_value = 0;
+ new_stat_tap_set_field_data(table, element, CALLS_COLUMN, item_data);
+ item_data = new_stat_tap_get_field_data(table, element, MIN_SRT_COLUMN);
+ item_data->value.float_value = 0.0;
+ new_stat_tap_set_field_data(table, element, MIN_SRT_COLUMN, item_data);
+ item_data = new_stat_tap_get_field_data(table, element, MAX_SRT_COLUMN);
+ item_data->value.float_value = 0.0;
+ new_stat_tap_set_field_data(table, element, MAX_SRT_COLUMN, item_data);
+ item_data = new_stat_tap_get_field_data(table, element, AVG_SRT_COLUMN);
+ item_data->value.float_value = 0.0;
+ new_stat_tap_set_field_data(table, element, AVG_SRT_COLUMN, item_data);
+ }
+}
+
+static void
+rpc_prog_stat_free_table_item(new_stat_tap_table* table _U_, guint row _U_, guint column, stat_tap_table_item_type* field_data)
+{
+ if (column != PROGRAM_NAME_COLUMN) return;
+ g_free((char*)field_data->value.string_value);
+}
+
/* will be called once from register.c at startup time */
void
proto_register_rpc(void)
@@ -4076,6 +4220,25 @@ proto_register_rpc(void)
module_t *rpc_module;
expert_module_t* expert_rpc;
+ static tap_param rpc_prog_stat_params[] = {
+ { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
+ };
+
+ static new_stat_tap_ui rpc_prog_stat_table = {
+ REGISTER_STAT_GROUP_UNSORTED,
+ "ONC-RPC Programs",
+ "rpc",
+ "rpc,programs",
+ rpc_prog_stat_init,
+ rpc_prog_stat_packet,
+ rpc_prog_stat_reset,
+ rpc_prog_stat_free_table_item,
+ NULL,
+ sizeof(rpc_prog_stat_fields)/sizeof(stat_tap_table_item), rpc_prog_stat_fields,
+ sizeof(rpc_prog_stat_params)/sizeof(tap_param), rpc_prog_stat_params,
+ NULL
+ };
+
proto_rpc = proto_register_protocol("Remote Procedure Call", "RPC", "rpc");
subdissector_call_table = register_custom_dissector_table("rpc.call", "RPC Call Functions", rpc_proc_hash, rpc_proc_equal);
@@ -4121,6 +4284,7 @@ proto_register_rpc(void)
rpc_tap = register_tap("rpc");
register_srt_table(proto_rpc, NULL, 1, rpcstat_packet, rpcstat_init, rpcstat_param);
+ register_new_stat_tap_ui(&rpc_prog_stat_table);
/*
* Init the hash tables. Dissectors for RPC protocols must