Added HPFEEDS stats_tree.

Change-Id: I256fd5395b062fa954ebd60598721323ea1d7ff1
Bug: 10875
Reviewed-on: https://code.wireshark.org/review/6713
Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Dario Lombardo 2015-01-13 15:13:27 +01:00 committed by Michael Mann
parent c80aa10415
commit 9bbc337306
7 changed files with 126 additions and 0 deletions

View File

@ -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

View File

@ -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:

View File

@ -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 {

View File

@ -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) },

View File

@ -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();

View File

@ -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>

View File

@ -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);