aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>2001-03-22 23:54:47 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>2001-03-22 23:54:47 +0000
commit2218ce1220aba62c515952ac2d79844bccea1ba9 (patch)
tree270db3ea5620aa7ca4d307425c12db2caf72a9b8
parentc2b31166ed69b75a2a3eb535ccfe8700556bbb79 (diff)
Add a new tool which summarizes packet counts by protocols, but
organizes the protocols in the same hierarchical order in which they are found in the packet. The GUI needs some more refinement (placment of vertical scrollbar, style of GtkCTree, initial sizing of window). I need to add an option to honor/not honor the current display filter. svn path=/trunk/; revision=3162
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.nmake3
-rw-r--r--doc/ethereal.pod.template12
-rw-r--r--gtk/Makefile.am4
-rw-r--r--gtk/Makefile.nmake1
-rw-r--r--gtk/menu.c5
-rw-r--r--gtk/proto_hier_stats_dlg.c213
-rw-r--r--gtk/proto_hier_stats_dlg.h27
-rw-r--r--proto_hier_stats.c203
-rw-r--r--proto_hier_stats.h27
10 files changed, 495 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 92151a4bfe..cfbe9ebbdc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
-# $Id: Makefile.am,v 1.293 2001/03/18 03:34:22 guy Exp $
+# $Id: Makefile.am,v 1.294 2001/03/22 23:54:44 gram Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@@ -371,6 +371,8 @@ ethereal_SOURCES = \
filters.h \
globals.h \
menu.h \
+ proto_hier_stats.h \
+ proto_hier_stats.c \
simple_dialog.h \
summary.c \
summary.h \
diff --git a/Makefile.nmake b/Makefile.nmake
index 9f2307fcd8..d80e50ccc8 100644
--- a/Makefile.nmake
+++ b/Makefile.nmake
@@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
-# $Id: Makefile.nmake,v 1.87 2001/03/18 02:13:32 guy Exp $
+# $Id: Makefile.nmake,v 1.88 2001/03/22 23:54:44 gram Exp $
include config.nmake
@@ -207,6 +207,7 @@ ethereal_OBJECTS = \
capture.obj \
file.obj \
filters.obj \
+ proto_hier_stats.obj \
summary.obj \
tethereal_OBJECTS = \
diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template
index 803ce43496..e8b0ef08c5 100644
--- a/doc/ethereal.pod.template
+++ b/doc/ethereal.pod.template
@@ -401,6 +401,18 @@ packet is a TCP packet to port 12345, using this dialog you can
instruct Ethereal to decode all packets to or from that TCP port as
HTTP packets.
+=item Tools:Protocol Hierarchy Statistics
+
+This shows the number of packets, and the number of bytes
+in those packets, for each protocol in the trace. It
+organizes the protocols in the same hierarchy in which
+they were found in the trace. Besides counting the packets
+in which the protocol exists, a count is also made
+for packets in which the protocol is the last protocol in
+the stack. These "Last Protocol" counts show you how many packets
+(and the byte count associated with those packets) B<ended> in a particular
+protocol.
+
=head2 WINDOWS
=over 4
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index acf76f2947..68c3c5d768 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -1,7 +1,7 @@
# Makefile.am
# Automake file for the GTK interface routines for Ethereal
#
-# $Id: Makefile.am,v 1.33 2001/02/01 07:34:33 guy Exp $
+# $Id: Makefile.am,v 1.34 2001/03/22 23:54:47 gram Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@@ -82,6 +82,8 @@ libui_a_SOURCES = \
proto_dlg.h \
proto_draw.c \
proto_draw.h \
+ proto_hier_stats_dlg.h \
+ proto_hier_stats_dlg.c \
simple_dialog.c \
stream_prefs.c \
stream_prefs.h \
diff --git a/gtk/Makefile.nmake b/gtk/Makefile.nmake
index c69428bc5a..dfbbb83527 100644
--- a/gtk/Makefile.nmake
+++ b/gtk/Makefile.nmake
@@ -40,6 +40,7 @@ OBJECTS=capture_dlg.obj \
progress_dlg.obj \
proto_dlg.obj \
proto_draw.obj \
+ proto_hier_stats_dlg.obj \
simple_dialog.obj \
stream_prefs.obj \
summary_dlg.obj \
diff --git a/gtk/menu.c b/gtk/menu.c
index 443cd06cee..2083b29845 100644
--- a/gtk/menu.c
+++ b/gtk/menu.c
@@ -1,7 +1,7 @@
/* menu.c
* Menu routines
*
- * $Id: menu.c,v 1.49 2001/02/11 23:02:05 guy Exp $
+ * $Id: menu.c,v 1.50 2001/03/22 23:54:47 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -58,6 +58,7 @@
#include "decode_as_dlg.h"
#include "help_dlg.h"
#include "proto_dlg.h"
+#include "proto_hier_stats_dlg.h"
#include "keys.h"
#include "plugins.h"
@@ -150,6 +151,7 @@ static GtkItemFactoryEntry menu_items[] =
{"/Tools/_Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, NULL},
/* {"/Tools/Graph", NULL, NULL, 0, NULL}, future use */
{"/Tools/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, NULL},
+ {"/Tools/Protocol Hierarchy Statistics", NULL, GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL},
{"/_Help", NULL, NULL, 0, "<LastBranch>" },
{"/Help/_Help", NULL, GTK_MENU_FUNC(help_cb), 0, NULL},
{"/Help/<separator>", NULL, NULL, 0, "<Separator>"},
@@ -379,6 +381,7 @@ set_menus_for_captured_packets(gboolean have_captured_packets)
set_menu_sensitivity("/Display/Match Selected", have_captured_packets);
set_menu_sensitivity("/Display/Colorize Display...", have_captured_packets);
set_menu_sensitivity("/Tools/Summary", have_captured_packets);
+ set_menu_sensitivity("/Tools/Protocol Hierarchy Statistics", have_captured_packets);
}
/* Enable or disable menu items based on whether a packet is selected. */
diff --git a/gtk/proto_hier_stats_dlg.c b/gtk/proto_hier_stats_dlg.c
new file mode 100644
index 0000000000..aceec24b78
--- /dev/null
+++ b/gtk/proto_hier_stats_dlg.c
@@ -0,0 +1,213 @@
+/* proto_hier_stats_dlg.c
+ *
+ * $Id: proto_hier_stats_dlg.c,v 1.1 2001/03/22 23:54:47 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#include "proto_hier_stats.h"
+#include "dlg_utils.h"
+#include "main.h"
+
+#define NUM_STAT_COLUMNS 6
+
+typedef struct {
+
+ GtkCTree *tree;
+ GtkCTreeNode *parent;
+ ph_stats_t *ps;
+
+} draw_info_t;
+
+
+#define PCT(x,y) (100.0 * (float)(x) / (float)(y))
+
+static void
+fill_in_ctree_node(GNode *node, gpointer data)
+{
+ ph_stats_node_t *stats = node->data;
+ draw_info_t *di = data;
+
+ GtkCTree *tree = di->tree;
+ GtkCTreeNode *parent = di->parent;
+ ph_stats_t *ps = di->ps;
+
+ gchar *text[NUM_STAT_COLUMNS];
+ gboolean is_leaf;
+ GtkCTreeNode *new_node;
+
+ draw_info_t child_di;
+
+ if (g_node_n_children(node) > 0) {
+ is_leaf = FALSE;
+ }
+ else {
+ is_leaf = TRUE;
+ }
+
+ text[0] = stats->hfinfo->name;
+ text[1] = g_strdup_printf("%6.2f%%",
+ PCT(stats->num_pkts_total, ps->tot_packets));
+ text[2] = g_strdup_printf("%u", stats->num_pkts_total);
+ text[3] = g_strdup_printf("%u", stats->num_bytes_total);
+ text[4] = g_strdup_printf("%u", stats->num_pkts_last);
+ text[5] = g_strdup_printf("%u", stats->num_bytes_last);
+
+ new_node = gtk_ctree_insert_node(tree, parent, NULL, text,
+ 5, NULL, NULL, NULL, NULL,
+ is_leaf, TRUE);
+
+
+ g_free(text[1]);
+ g_free(text[2]);
+ g_free(text[3]);
+ g_free(text[4]);
+ g_free(text[5]);
+
+ child_di.tree = tree;
+ child_di.parent = new_node;
+ child_di.ps = ps;
+
+ g_node_children_foreach(node, G_TRAVERSE_ALL,
+ fill_in_ctree_node, &child_di);
+
+}
+
+
+
+static void
+fill_in_ctree(GtkWidget *tree, ph_stats_t *ps)
+{
+ draw_info_t di;
+
+ di.tree = GTK_CTREE(tree);
+ di.parent = NULL;
+ di.ps = ps;
+
+ g_node_children_foreach(ps->stats_tree, G_TRAVERSE_ALL,
+ fill_in_ctree_node, &di);
+}
+
+static void
+create_tree(GtkWidget *container)
+{
+ GtkWidget *sw, *tree;
+ ph_stats_t *ps;
+ int i, height;
+ gchar *column_titles[NUM_STAT_COLUMNS] = {
+ "Protocol",
+ "Percentage Packets",
+ "Packets",
+ "Bytes",
+ "Last-Protocol Packets",
+ "Last-Protocol Bytes",
+ };
+
+ ps = ph_stats_new();
+
+ /* Scrolled Window */
+ sw = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(container), sw);
+
+ tree = gtk_ctree_new_with_titles(NUM_STAT_COLUMNS, 0, column_titles);
+
+ /* XXX - get 'pos' to set vertical scroll-bar placement. */
+ /* XXX - set line style from preferences ???. */
+
+ /* The titel bars do nothing. */
+ gtk_clist_column_titles_passive(GTK_CLIST(tree));
+
+ /* Auto Resize all columns */
+ for (i = 0; i < NUM_STAT_COLUMNS; i++) {
+ gtk_clist_set_column_auto_resize(GTK_CLIST(tree), i, TRUE);
+ }
+
+
+ /* Right justify numeric columns */
+ for (i = 1; i <= 5; i++) {
+ gtk_clist_set_column_justification(GTK_CLIST(tree), i,
+ GTK_JUSTIFY_RIGHT);
+ }
+
+ /* Fill in the data. */
+ fill_in_ctree(tree, ps);
+
+ /* Try to size the CTree to a good initial size.
+ * 5 is a magic number that I pulled out off my hat.
+ * Using DEF_WIDTH is pretty bogus, too. */
+ height = GTK_CLIST(tree)->rows * (GTK_CLIST(tree)->row_height + 5);
+ gtk_widget_set_usize(tree, DEF_WIDTH, height);
+
+
+ gtk_container_add(GTK_CONTAINER(sw), tree);
+ ph_stats_free(ps);
+}
+
+void
+proto_hier_stats_cb(GtkWidget *w, gpointer d)
+{
+ GtkWidget *dlg, *bt, *vbox, *frame, *bbox;
+ const gchar *wname = "Protocol Hierarchy Statistics";
+
+ dlg = dlg_window_new(wname);
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 5);
+ gtk_container_add(GTK_CONTAINER(dlg), vbox);
+
+ frame = gtk_frame_new(wname);
+ /*gtk_container_add(GTK_CONTAINER(vbox), frame);*/
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
+
+
+ /* Data section */
+ create_tree(frame);
+
+ /* Button row. We put it in an HButtonBox to
+ * keep it from expanding to the width of the window. */
+ bbox = gtk_hbutton_box_new();
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
+ /*gtk_container_add(GTK_CONTAINER(vbox), bbox);*/
+ gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+
+ /* Close button */
+ bt = gtk_button_new_with_label("Close");
+ gtk_signal_connect_object(GTK_OBJECT(bt), "clicked",
+ GTK_SIGNAL_FUNC(gtk_widget_destroy),
+ GTK_OBJECT(dlg));
+ gtk_container_add(GTK_CONTAINER(bbox), bt);
+ GTK_WIDGET_SET_FLAGS(bt, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(bt);
+ dlg_set_cancel(dlg, bt);
+
+ gtk_widget_show_all(dlg);
+
+}
+
diff --git a/gtk/proto_hier_stats_dlg.h b/gtk/proto_hier_stats_dlg.h
new file mode 100644
index 0000000000..dc124ffec1
--- /dev/null
+++ b/gtk/proto_hier_stats_dlg.h
@@ -0,0 +1,27 @@
+/* proto_hier_stats_dlg.h
+ *
+ * $Id: proto_hier_stats_dlg.h,v 1.1 2001/03/22 23:54:47 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+void
+proto_hier_stats_cb(GtkWidget *w, gpointer d);
diff --git a/proto_hier_stats.c b/proto_hier_stats.c
new file mode 100644
index 0000000000..303d14ee6f
--- /dev/null
+++ b/proto_hier_stats.c
@@ -0,0 +1,203 @@
+/* proto_hier_stats.c
+ * Routines for calculating statistics based on protocol.
+ *
+ * $Id: proto_hier_stats.c,v 1.1 2001/03/22 23:54:44 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "globals.h"
+#include "proto_hier_stats.h"
+#include <wtap.h>
+
+#include <stdio.h>
+#include <glib.h>
+
+static GNode*
+find_stat_node(GNode *parent_node, header_field_info *needle_hfinfo)
+{
+ GNode *needle_node;
+ field_info *finfo;
+ ph_stats_node_t *stats;
+
+ needle_node = g_node_first_child(parent_node);
+
+ while (needle_node) {
+ finfo = needle_node->data;
+ if (finfo && finfo->hfinfo && finfo->hfinfo->id == needle_hfinfo->id) {
+ return needle_node;
+ }
+ needle_node = g_node_next_sibling(needle_node);
+ }
+
+ /* None found. Create one. */
+ stats = g_new(ph_stats_node_t, 1);
+
+ /* Intialize counters */
+ stats->hfinfo = needle_hfinfo;
+ stats->num_pkts_total = 0;
+ stats->num_pkts_last = 0;
+ stats->num_bytes_total = 0;
+ stats->num_bytes_last = 0;
+
+ needle_node = g_node_new(stats);
+ g_node_append(parent_node, needle_node);
+ return needle_node;
+}
+
+
+static void
+process_node(proto_item *proto_node, GNode *parent_stat_node, ph_stats_t *ps, guint pkt_len)
+{
+ field_info *finfo;
+ ph_stats_node_t *stats;
+ proto_item *proto_sibling_node;
+ GNode *stat_node;
+
+ finfo = proto_node->data;
+ g_assert(finfo);
+
+ stat_node = find_stat_node(parent_stat_node, finfo->hfinfo);
+
+ /* Assert that the finfo is related to a protocol, not a field. */
+ g_assert(finfo->hfinfo->parent == -1);
+
+ stats = stat_node->data;
+ stats->num_pkts_total++;
+ stats->num_bytes_total += pkt_len;
+
+ proto_sibling_node = g_node_next_sibling(proto_node);
+
+ if (proto_sibling_node) {
+ process_node(proto_sibling_node, stat_node, ps, pkt_len);
+ }
+ else {
+ stats->num_pkts_last++;
+ stats->num_bytes_last += pkt_len;
+ }
+}
+
+
+
+static void
+process_tree(proto_tree *protocol_tree, ph_stats_t* ps, guint pkt_len)
+{
+ proto_item *proto_node;
+
+ proto_node = g_node_first_child(protocol_tree);
+ if (!proto_node) {
+ return;
+ }
+
+ process_node(proto_node, ps->stats_tree, ps, pkt_len);
+}
+
+static void
+process_frame(frame_data *frame, ph_stats_t* ps)
+{
+ epan_dissect_t *edt;
+ union wtap_pseudo_header phdr;
+ proto_tree *protocol_tree;
+ guint8 pd[WTAP_MAX_PACKET_SIZE];
+
+ protocol_tree = proto_tree_create_root();
+
+ /* Load the frame from the capture file */
+ wtap_seek_read(cfile.wth, frame->file_off, &phdr,
+ pd, frame->cap_len);
+
+ /* Dissect the frame */
+ edt = epan_dissect_new(&phdr, pd, frame, protocol_tree);
+
+ /* Get stats from this protocol tree */
+ process_tree(protocol_tree, ps, frame->pkt_len);
+
+ /* Free our memory. */
+ epan_dissect_free(edt);
+ proto_tree_free(protocol_tree);
+}
+
+
+
+ph_stats_t*
+ph_stats_new(void)
+{
+ ph_stats_t *ps;
+ frame_data *frame;
+ guint tot_packets, tot_bytes;
+
+ /* Initialize the data */
+ ps = g_new(ph_stats_t, 1);
+ ps->tot_packets = 0;
+ ps->tot_bytes = 0;
+ ps->stats_tree = g_node_new(NULL);
+
+ frame = cfile.plist;
+ tot_packets = 0;
+ tot_bytes = 0;
+
+ while (frame) {
+ /* Skip frames that are hidden due to the display filter */
+ if (!frame->flags.passed_dfilter) {
+ continue;
+ }
+
+ process_frame(frame, ps);
+
+ tot_packets++;
+ tot_bytes += frame->pkt_len;
+
+ frame = frame->next;
+ }
+
+ ps->tot_packets = tot_packets;
+ ps->tot_bytes = tot_bytes;
+
+ return ps;
+}
+
+static gboolean
+stat_node_free(GNode *node, gpointer data)
+{
+ ph_stats_node_t *stats = node->data;
+
+ if (stats) {
+ g_free(stats);
+ }
+}
+
+void
+ph_stats_free(ph_stats_t *ps)
+{
+
+ if (ps->stats_tree) {
+ g_node_traverse(ps->stats_tree, G_IN_ORDER,
+ G_TRAVERSE_ALL, -1,
+ stat_node_free, NULL);
+ g_node_destroy(ps->stats_tree);
+ }
+
+ g_free(ps);
+}
diff --git a/proto_hier_stats.h b/proto_hier_stats.h
new file mode 100644
index 0000000000..257c9e19eb
--- /dev/null
+++ b/proto_hier_stats.h
@@ -0,0 +1,27 @@
+
+#ifndef PROTO_HIER_STATS_H
+#define PROTO_HIER_STATS_H
+
+#include "proto.h"
+
+typedef struct {
+ header_field_info *hfinfo;
+ guint num_pkts_total;
+ guint num_pkts_last;
+ guint num_bytes_total;
+ guint num_bytes_last;
+} ph_stats_node_t;
+
+
+typedef struct {
+ guint tot_packets;
+ guint tot_bytes;
+ GNode *stats_tree;
+} ph_stats_t;
+
+
+ph_stats_t* ph_stats_new(void);
+
+void ph_stats_free(ph_stats_t *ps);
+
+#endif