diff options
-rw-r--r-- | doc/tshark.pod | 5 | ||||
-rw-r--r-- | docbook/release-notes.asciidoc | 5 | ||||
-rw-r--r-- | epan/dissectors/packet-hpfeeds.c | 99 | ||||
-rw-r--r-- | ui/gtk/main_menubar.c | 2 | ||||
-rw-r--r-- | ui/qt/main_window.h | 1 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 9 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 5 |
7 files changed, 126 insertions, 0 deletions
diff --git a/doc/tshark.pod b/doc/tshark.pod index c7b79e61cc..a3c7e305af 100644 --- a/doc/tshark.pod +++ b/doc/tshark.pod @@ -1111,6 +1111,11 @@ and IPv6 addresses are dumped by default. Addresses are collected from a number of sources, including standard "hosts" files and captured traffic. +=item B<-z> hpfeeds,tree[,I<filter>] + +Calculate statistics for HPFEEDS traffic such as publish per channel, and opcode +distribution. + =item B<-z> http,stat, Calculate the HTTP statistics distribution. Displayed values are diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc index 621ea50c2f..1453de9c96 100644 --- a/docbook/release-notes.asciidoc +++ b/docbook/release-notes.asciidoc @@ -44,6 +44,11 @@ field and shows a description in the status bar. (min, max, avg) for values such as query name length or DNS payload. +* HPFEEDS stats: + + A new stats tree has been added to the statistics menu. Now it + is possible to collect stats per channel (messages count and payload + size), and opcode distribution. + The following features are new (or have been significantly updated) since version 1.12.0: diff --git a/epan/dissectors/packet-hpfeeds.c b/epan/dissectors/packet-hpfeeds.c index 2656aeae9b..7a08be509d 100644 --- a/epan/dissectors/packet-hpfeeds.c +++ b/epan/dissectors/packet-hpfeeds.c @@ -32,9 +32,33 @@ #include <epan/packet.h> #include <epan/prefs.h> #include <epan/expert.h> +#include <epan/tap.h> +#include <epan/stats_tree.h> +#include <epan/wmem/wmem_list.h> #include "packet-tcp.h" +struct HpfeedsTap { + guint payload_size; + guint8* channel; + guint8 opcode; +}; + +static int hpfeeds_tap = -1; + +static const guint8* st_str_channels_payload = "Payload size per channel"; +static const guint8* st_str_opcodes = "Opcodes"; + +static int st_node_channels_payload = -1; +static int st_node_opcodes = -1; + +static wmem_list_t* channels_list; + +struct channel_node { + guint8* channel; + guint st_node_channel_payload; +}; + void proto_register_hpfeeds(void); void proto_reg_handoff_hpfeeds(void); @@ -130,6 +154,25 @@ dissect_hpfeeds_auth_pdu(tvbuff_t *tvb, proto_tree *tree, guint offset) offset, -1, ENC_NA); } +static guint8* +hpfeeds_get_channel_name(tvbuff_t* tvb, guint offset) +{ + guint8 len = tvb_get_guint8(tvb, offset); + offset += len + 1; + len = tvb_get_guint8(tvb, offset); + offset += 1; + return tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII); +} + +static guint +hpfeeds_get_payload_size(tvbuff_t* tvb, guint offset) +{ + guint message_len = tvb_get_ntohl(tvb, offset); + guint ident_len = tvb_get_guint8(tvb, offset + 5); + guint channel_len = tvb_get_guint8(tvb, offset + 6 + ident_len); + return (message_len - 2 - ident_len - 1 - channel_len); +} + static void dissect_hpfeeds_publish_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) @@ -166,6 +209,48 @@ dissect_hpfeeds_publish_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree_add_item(tree, hf_hpfeeds_payload, tvb, offset, -1, ENC_NA); } +static void hpfeeds_stats_tree_init(stats_tree* st) +{ + st_node_channels_payload = stats_tree_create_node(st, st_str_channels_payload, 0, TRUE); + st_node_opcodes = stats_tree_create_pivot(st, st_str_opcodes, 0); + + channels_list = wmem_list_new(wmem_epan_scope()); +} + +static int hpfeeds_stats_tree_packet(stats_tree* st _U_, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) +{ + struct HpfeedsTap *pi = (struct HpfeedsTap *)p; + wmem_list_frame_t* head = wmem_list_head(channels_list); + wmem_list_frame_t* cur = head; + struct channel_node* ch_node; + + if (pi->opcode == OP_PUBLISH) { + /* search an existing channel node and create it if it does not */ + while(cur != NULL) { + ch_node = (struct channel_node*)wmem_list_frame_data(cur); + if (strncmp(ch_node->channel, pi->channel, strlen(pi->channel)) == 0) { + break; + } + cur = wmem_list_frame_next(cur); + } + + if (cur == NULL) { + ch_node = (struct channel_node*)wmem_alloc0(wmem_file_scope(), sizeof(struct channel_node)); + ch_node->channel = wmem_strdup(wmem_file_scope(), pi->channel); + ch_node->st_node_channel_payload = stats_tree_create_node(st, ch_node->channel, + st_node_channels_payload, FALSE); + wmem_list_append(channels_list, ch_node); + } + + avg_stat_node_add_value(st, st_str_channels_payload, 0, FALSE, pi->payload_size); + avg_stat_node_add_value(st, ch_node->channel, 0, FALSE, pi->payload_size); + } + + stats_tree_tick_pivot(st, st_node_opcodes, + val_to_str(pi->opcode, opcode_vals, "Unknown opcode (%d)")); + return 1; +} + static void dissect_hpfeeds_subscribe_pdu(tvbuff_t *tvb, proto_tree *tree, guint offset) { @@ -198,6 +283,8 @@ get_hpfeeds_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) static int dissect_hpfeeds_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { + struct HpfeedsTap *hpfeeds_stats; + /* We have already parsed msg length we need to skip to opcode offset */ guint offset = 0; @@ -252,6 +339,15 @@ dissect_hpfeeds_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d } } + /* In publish, generate stats every packet, even not in tree */ + hpfeeds_stats = wmem_new0(wmem_file_scope(), struct HpfeedsTap); + if (opcode == OP_PUBLISH) { + hpfeeds_stats->channel = hpfeeds_get_channel_name(tvb, offset); + hpfeeds_stats->payload_size = hpfeeds_get_payload_size(tvb, 0); + } + + hpfeeds_stats->opcode = opcode; + tap_queue_packet(hpfeeds_tap, pinfo, hpfeeds_stats); return tvb_captured_length(tvb); } @@ -391,6 +487,8 @@ proto_register_hpfeeds(void) "Try heuristic sub-dissectors", "Try to decode the payload using an heuristic sub-dissector", &try_heuristic); + + hpfeeds_tap = register_tap("hpfeeds"); } void @@ -402,6 +500,7 @@ proto_reg_handoff_hpfeeds(void) if (!hpfeeds_prefs_initialized) { hpfeeds_handle = new_create_dissector_handle(dissect_hpfeeds, proto_hpfeeds); + stats_tree_register("hpfeeds", "hpfeeds", "HPFEEDS", 0, hpfeeds_stats_tree_packet, hpfeeds_stats_tree_init, NULL); hpfeeds_prefs_initialized = TRUE; } else { diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index 630dcb13cd..dbff56869a 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -1048,6 +1048,7 @@ static const char *ui_desc_menubar = " <menuitem name= 'DNS' action='/Statistics/dns'/>\n" " <menuitem name='FlowGraph' action='/Statistics/FlowGraph'/>\n" " <menuitem name='HART-IP' action='/Statistics/hart_ip'/>\n" +" <menuitem name= 'Hpfeeds' action='/Statistics/hpfeeds'/>\n" " <menu name= 'HTTPMenu' action='/Statistics/HTTP'>\n" " <menuitem name='http' action='/Statistics/HTTP/http'/>\n" " <menuitem name='http_req' action='/Statistics/HTTP/http_req'/>\n" @@ -1481,6 +1482,7 @@ static const GtkActionEntry main_menu_bar_entries[] = { { "/Statistics/dns", NULL, "DNS", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) }, { "/Statistics/FlowGraph", WIRESHARK_STOCK_FLOW_GRAPH, "Flo_w Graph...", NULL, NULL, G_CALLBACK(flow_graph_launch) }, { "/Statistics/hart_ip", NULL, "HART-IP", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) }, + { "/Statistics/hpfeeds", NULL, "HPFEEDS", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) }, { "/Statistics/HTTP", NULL, "HTTP", NULL, NULL, NULL }, { "/Statistics/HTTP/http", NULL, "Packet Counter", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) }, { "/Statistics/HTTP/http_req", NULL, "Requests", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) }, diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index b254f4214e..d1fedbeaa1 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -423,6 +423,7 @@ private slots: void on_actionStatisticsSametime_triggered(); void on_actionStatisticsDNS_triggered(); void actionStatisticsPlugin_triggered(); + void on_actionStatisticsHpfeeds_triggered(); void openVoipCallsDialog(bool all_flows = false); void on_actionTelephonyVoipCalls_triggered(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 2502f8cfa5..0e1888faed 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -427,6 +427,7 @@ <addaction name="actionStatisticsDNS"/> <addaction name="actionStatisticsFlowGraph"/> <addaction name="actionStatisticsHART_IP"/> + <addaction name="actionStatisticsHpfeeds"/> <addaction name="menuHTTP"/> <addaction name="actionStatisticsSametime"/> <addaction name="menuTcpStreamGraphs"/> @@ -1569,6 +1570,14 @@ <string>HART-IP statistics</string> </property> </action> + <action name="actionStatisticsHpfeeds"> + <property name="text"> + <string>HPFEEDS</string> + </property> + <property name="toolTip"> + <string>hpfeeds statistics</string> + </property> + </action> <action name="actionStatisticsHTTPPacketCounter"> <property name="text"> <string>Packet Counter</string> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index d53e9545bd..dad5df9943 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1593,6 +1593,11 @@ void MainWindow::on_actionFileExportObjectsDICOM_triggered() new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom); } +void MainWindow::on_actionStatisticsHpfeeds_triggered() +{ + openStatisticsTreeDialog("hpfeeds"); +} + void MainWindow::on_actionFileExportObjectsHTTP_triggered() { new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http); |