wireshark/doc/README.stats_tree
John Thacker 46eb9a2c92 stats_tree: Update documentation
Clarify how the stats_tree flags are used. Some are for the entire
tree, some can be set on nodes, and some are internal use only. All
of them have to not overlap with the generic tapping system flags for
some reason.

Update the README for some recent changes adding tap flags to the
per packet routine and changing the directory separator to being a
double forward slash.

ST_FLG_SORT_DESC had backwards comment text, but has always indicated
that descending order was to be used (at least in the tshark CLI
tap, and in various functions, and in how the preference was interprted,
even if the Qt GUI didn't respect it previously.)

Also, packet-ltp was using the sort ordering incorrectly, and probably
didn't intend for counts to be ascending, so remove it. (It wasn't
doing anything other than actually requesting the tap columns, which
it didn't need, and the default order of descending count was used.)

Fix #20038
2025-02-25 22:13:28 +00:00

271 lines
10 KiB
Plaintext

tapping with stats_tree
Let's suppose that you want to write a tap only to keep counters, and you
don't want to get involved with GUI programming or maybe you'd like to make
it a plugin. A stats_tree might be the way to go. The stats_tree module takes
care of the representation (GUI for Wireshark and text for TShark) of the
tap data. So there's very little code to write to make a tap listener usable
from both Wireshark and TShark.
First, you should add the TAP to the dissector in question as described in
README.tapping .
Once the dissector in question is "tapped" you have to write the stats tree
code which is made of three parts:
The init callback routine:
which will be executed before any packet is passed to the tap. Here you
should create the "static" nodes of your tree. As well as initialize your
data.
The (per)packet callback routine:
As the tap_packet callback is going to be called for every packet, it
should be used to increment the counters.
The cleanup callback:
It is called at the destruction of the stats_tree and might be used to
free ....
Other than that the stats_tree should be registered.
If you want to make it a plugin, stats_tree_register() should be called by
plugin_register_tap_listener() read README.plugins for other information
regarding Wireshark plugins.
If you want it as part of the dissector stats_tree_register() can be called
either by proto_register_xxx() or if you prefer by proto_reg_handoff_xxx().
A small example of a very basic stats_tree plugin follows.
----- example stats_tree plugin ------
/* udpterm_stats_tree.c
* A small example of stats_tree plugin that counts udp packets by termination
* 2005, Luis E. G. Ontanon
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <gmodule.h>
#include <epan/stats_tree.h>
#include <epan/dissectors/udp.h>
static int st_udp_term;
static char* st_str_udp_term = "UDP terminations";
/* this one initializes the tree, creating the root nodes */
extern void udp_term_stats_tree_init(stats_tree* st) {
/* we create a node under which we'll add every termination */
st_udp_term = stats_tree_create_node(st, st_str_udp_term, 0, STAT_DT_INT, true);
}
/* this one will be called with every udp packet */
extern tap_packet_status
udp_term_stats_tree_packet(stats_tree *st, /* st as it was passed to us */
packet_info *pinfo, /* we'll fetch the addresses from here */
epan_dissect_t *edt _U_, /* unused */
const void *p, /* we'll use this to fetch the ports */
tap_flags_t flags _U_) /* unused */
{
static uint8_t str[128];
e_udphdr* udphdr = (e_udphdr*) p;
/* we increment by one (tick) the root node */
tick_stat_node(st, st_str_udp_term, 0, false);
/* we then tick a node for this src_addr:src_port
if the node doesn't exists it will be created */
snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_src),udphdr->sport);
tick_stat_node(st, str, st_udp_term, false);
/* same thing for dst */
snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_dst),udphdr->dport);
tick_stat_node(st, str, st_udp_term, false);
return 1;
}
WS_DLL_PUBLIC_DEF const char version[] = "0.0";
WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void) {
stats_tree_register_plugin("udp", /* the proto we are going to "tap" */
"udp_terms", /* the abbreviation for this tree (to be used as -z udp_terms,tree) */
st_str_udp_term, /* the name of the menu and window (use "//" for sub menus)*/
0, /* tap listener flags for per-packet callback */
udp_term_stats_tree_packet, /* the per packet callback */
udp_term_stats_tree_init, /* the init callback */
NULL ); /* the cleanup callback (in this case there isn't) */
}
----- END ------
the stats_tree API
==================
every stats_tree callback has a stats_tree* parameter (st), stats_tree is an obscure
data structure which should be passed to the api functions.
stats_tree_register(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
registers a new stats tree with default group REGISTER_STAT_GROUP_UNSORTED
stats_tree_register_plugin(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
registers a new stats tree from a plugin with the default group REGISTER_STAT_GROUP_UNSORTED
stats_tree_set_group(st_config, stat_group);
changes the menu statistics group for a stats tree
stats_tree_parent_id_by_name( st, parent_name)
returns the id of a candidate parent node given its name
flags
is a bitmask set of flags for the tap listener. Generic tap system flags
(TL_*) described in README.tapping can be used, along with stat tree specific
flags that control the default sorting, six for choosing the column and one
for the order:
ST_SORT_COL_NAME
Sort nodes by node names
ST_SORT_COL_COUNT
Sort nodes by node count
ST_SORT_COL_AVG
Sort nodes by node average
ST_SORT_COL_MIN
Sort nodes by minimum node value
ST_SORT_COL_MAX
Sort nodes by maximum node value
ST_SORT_COL_BURSTRATE
Sort nodes by burst rate
ST_FLG_SORT_DESC
Sort nodes in descending order using the chosen column
The default if only a column is given is to use ascending
order
The sort column flags need to be left shifted by ST_FLG_SRTCOL_SHIFT when
registering. If no sort columns flags are given, values from the preferences
(found in the "Statistics" module) are used for both column and order. The
default preferences are to sort in descending order of node count, i.e.,
(ST_SORT_COL_COUNT << ST_FLG_SRTCOL_SHIFT) | ST_FLG_SORT_DESC
Node functions
==============
All the functions that operate on nodes return a parent_id
stats_tree_create_node(st, name, parent_id, datatype, with_children)
Creates a node in the tree (to be used in the in init_cb)
name: the name of the new node
parent_id: the id of the parent_node (NULL for root)
datatype: datatype of the new node, STAT_DT_INT or STAT_DT_FLOAT. The only
methods implemented for floats are averages.
with_children: true if this node will have "dynamically created" children
(i.e. it will be a candidate parent)
stats_tree_create_node_by_pname(st, name, parent_name, datatype, with_children);
As before but creates a node using its parent's name
stats_tree_create_range_node(st, name, parent_id, ...)
stats_tree_create_range_node_string(st, name, parent_id, num_str_ranges, str_ranges)
stats_tree_range_node_with_pname(st, name, parent_name, ...)
Creates a node in the tree, that will contain a ranges list.
example:
stats_tree_create_range_node(st,name,parent_id,
"-99","100-199","200-299","300-399","400-", NULL);
stats_tree_tick_range(st, name, parent_id, value_in_range);
stats_tree_tick_range_by_pname(st, name, parent_name, value_in_range)
Increases by one the ranged node and the sub node to whose range the value belongs
stats_tree_create_pivot(st, name, parent_id);
stats_tree_create_pivot_by_pname(st, name, parent_name);
Creates a "pivot node"
stats_tree_tick_pivot(st, pivot_id, pivoted_string);
Each time a pivot node will be ticked it will get increased, and, it will
increase (or create) the children named as pivoted_string
the following will either increase or create a node (with value 1) when called
tick_stat_node(st, name, parent_id, with_children)
increases by one a stat_node
increase_stat_node(st, name, parent_id, with_children, value)
increases by value a stat_node
set_stat_node(st, name, parent_id, with_children, value)
sets the value of a stat_node
zero_stat_node(st, name, parent_id, with_children)
resets to zero a stat_node
Averages work by tracking both the number of items added to node (the ticking
action) and the value of each item added to the node. This is done
automatically for ranged nodes; for other node types you need to call one of
the functions below to associate item values with each tick.
avg_stat_node_add_value_notick(st, name, parent_id, with_children, value)
avg_stat_node_add_value_int(st, name, parent_id, with_children, value)
avg_stat_node_add_value_float(st, name, parent_id, with_children, value)
The difference between the above functions is whether the item count is
increased or not. To properly compute the average you need to either call
avg_stat_node_add_value or avg_stat_node_add_value_notick combined
tick_stat_node. The later sequence allows for plug-ins which are compatible
with older Wireshark versions which ignores avg_stat_node_add_value because
it does not understand the command. This would result in 0 counts for all
nodes. It is preferred to use avg_stat_node_add_value if you are not writing
a plug-in.
avg_stat_node_add_value_int is used the same way as tick_stat_node with the
exception that you now specify an additional value associated with the tick.
avg_stat_node_add_value_float is used to compute averages of floats, for nodes
with the STAT_DT_FLOAT datatype.
Do not mix increase_stat_node, set_stat_node or zero_stat_node
with avg_stat_node_add_value_int as this will lead to incorrect results for the
average value.
stats_tree now also support setting flags per node to control the behaviour
of these nodes. This can be done using the stat_node_set_flags and
stat_node_clear_flags functions. Currently these flags are defined:
ST_FLG_DEF_NOEXPAND: By default the top-level nodes in a tree are
automatically expanded in the GUI. Setting this flag on
such a node prevents the node from automatically
expanding. (However, if there are fewer than some fixed
total number of nodes, currently 100, in the tree, then
all the nodes will be expanded anyway.)
ST_FLG_SORT_TOP: Nodes with this flag is sorted separately from nodes
without this flag (in effect partitioning tree into a top
and bottom half. Each half is sorted normally. Top always
appear first :)
The same node manipulations can also be performed via generic functions:
stats_tree_manip_node_int(mode, st, name, parent_id, with_children, value);
stats_tree_manip_node_float(mode, st, name, parent_id, with_children, value);
mode is an enum with the following set of values:
MN_INCREASE
MN_SET
MN_AVERAGE
MN_AVERAGE_NOTICK
MN_SET_FLAGS
MN_CLEAR_FLAGS
You can find more examples of these in $srcdir/plugins/epan/stats_tree/pinfo_stats_tree.c
Luis E. G. Ontanon.