nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 tapping with stats_tree
2  
3 Let's suppose that you want to write a tap only to keep counters, and you
4 don't want to get involved with GUI programming or maybe you'd like to make
5 it a plugin. A stats_tree might be the way to go. The stats_tree module takes
6 care of the representation (GUI for wireshark and text for tshark) of the
7 tap data. So there's very little code to write to make a tap listener usable
8 from both wireshark and tshark.
9  
10 First, you should add the TAP to the dissector in question as described in
11 README.tapping .
12  
13 Once the dissector in question is "tapped" you have to write the stats tree
14 code which is made of three parts:
15  
16 The init callback routine:
17 which will be executed before any packet is passed to the tap. Here you
18 should create the "static" nodes of your tree. As well as initialize your
19 data.
20  
21 The (per)packet callback routine:
22 As the tap_packet callback is going to be called for every packet, it
23 should be used to increment the counters.
24  
25 The cleanup callback:
26 It is called at the destruction of the stats_tree and might be used to
27 free ....
28  
29 Other than that the stats_tree should be registered.
30  
31 If you want to make it a plugin, stats_tree_register() should be called by
32 plugin_register_tap_listener() read README.plugin for other information
33 regarding wireshark plugins.
34  
35 If you want it as part of the dissector stats_tree_register() can be called
36 either by proto_register_xxx() or if you prefer by proto_reg_handoff_xxx().
37  
38  
39 A small example of a very basic stats_tree plugin follows.
40  
41 ----- example stats_tree plugin ------
42 /* udpterm_stats_tree.c
43 * A small example of stats_tree plugin that counts udp packets by termination
44 * 2005, Luis E. G. Ontanon
45 *
46 * Wireshark - Network traffic analyzer
47 * By Gerald Combs <gerald@wireshark.org>
48 * Copyright 1998 Gerald Combs
49 *
50 * This program is free software; you can redistribute it and/or
51 * modify it under the terms of the GNU General Public License
52 * as published by the Free Software Foundation; either version 2
53 * of the License, or (at your option) any later version.
54 *
55 * This program is distributed in the hope that it will be useful,
56 * but WITHOUT ANY WARRANTY; without even the implied warranty of
57 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58 * GNU General Public License for more details.
59 *
60 * You should have received a copy of the GNU General Public License
61 * along with this program; if not, write to the Free Software
62 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
63 */
64  
65 #include "config.h"
66  
67 #ifndef ENABLE_STATIC
68 #include <gmodule.h>
69 #else
70 #include <glib.h>
71 #endif
72  
73 #include <epan/stats_tree.h>
74 #include <epan/dissectors/udp.h>
75  
76 static int st_udp_term;
77 static gchar* st_str_udp_term = "UDP terminations";
78  
79 /* this one initializes the tree, creating the root nodes */
80 extern void udp_term_stats_tree_init(stats_tree* st) {
81 /* we create a node under which we'll add every termination */
82 st_udp_term = stats_tree_create_node(st, st_str_udp_term, 0, TRUE);
83 }
84  
85 /* this one will be called with every udp packet */
86 extern int udp_term_stats_tree_packet(stats_tree *st, /* st as it was passed to us */
87 packet_info *pinfo, /* we'll fetch the addresses from here */
88 epan_dissect_t *edt _U_, /* unused */
89 const void *p) /* we'll use this to fetch the ports */
90 {
91 static guint8 str[128];
92 e_udphdr* udphdr = (e_udphdr*) p;
93  
94 /* we increment by one (tick) the root node */
95 tick_stat_node(st, st_str_udp_term, 0, FALSE);
96  
97 /* we then tick a node for this src_addr:src_port
98 if the node doesn't exists it will be created */
99 g_snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_src),udphdr->sport);
100 tick_stat_node(st, str, st_udp_term, FALSE);
101  
102 /* same thing for dst */
103 g_snprintf(str, sizeof(str),"%s:%u",address_to_str(&pinfo->net_dst),udphdr->dport);
104 tick_stat_node(st, str, st_udp_term, FALSE);
105  
106 return 1;
107 }
108  
109 #ifndef ENABLE_STATIC
110 WS_DLL_PUBLIC_DEF const gchar version[] = "0.0";
111  
112 WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void) {
113  
114 stats_tree_register_plugin("udp", /* the proto we are going to "tap" */
115 "udp_terms", /* the abbreviation for this tree (to be used as -z udp_terms,tree) */
116 st_str_udp_term, /* the name of the menu and window (use "/" for sub menus)*/
117 0, /* tap listener flags for per-packet callback */
118 udp_term_stats_tree_packet, /* the per packet callback */
119 udp_term_stats_tree_init, /* the init callback */
120 NULL ); /* the cleanup callback (in this case there isn't) */
121  
122 }
123 #endif
124  
125 ----- END ------
126  
127 the stats_tree API
128 ==================
129 every stats_tree callback has a stats_tree* parameter (st), stats_tree is an obscure
130 data structure which should be passed to the api functions.
131  
132 stats_tree_register( tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
133 registers a new stats tree
134  
135 stats_tree_register_plugin(tapname, abbr, name, flags, packet_cb, init_cb, cleanup_cb);
136 registers a new stats tree from a plugin
137  
138 stats_tree_parent_id_by_name( st, parent_name)
139 returns the id of a candidate parent node given its name
140  
141  
142 Node functions
143 ==============
144  
145 All the functions that operate on nodes return a parent_id
146  
147 stats_tree_create_node(st, name, parent_id, with_children)
148 Creates a node in the tree (to be used in the in init_cb)
149 name: the name of the new node
150 parent_id: the id of the parent_node (NULL for root)
151 with_children: TRUE if this node will have "dynamically created" children
152 (i.e. it will be a candidate parent)
153  
154  
155 stats_tree_create_node_by_pname(st, name, parent_name, with_children);
156 As before but creates a node using its parent's name
157  
158  
159 stats_tree_create_range_node(st, name, parent_id, ...)
160 stats_tree_create_range_node_string(st, name, parent_id, num_str_ranges, str_ranges)
161 stats_tree_range_node_with_pname(st, name, parent_name, ...)
162 Creates a node in the tree, that will contain a ranges list.
163 example:
164 stats_tree_create_range_node(st,name,parent_id,
165 "-99","100-199","200-299","300-399","400-", NULL);
166  
167 stats_tree_tick_range( st, name, parent_id, value_in_range);
168 stats_tree_tick_range_by_pname(st,name,parent_name,value_in_range)
169 Increases by one the ranged node and the sub node to whose range the value belongs
170  
171  
172 stats_tree_create_pivot(st, name, parent_id);
173 stats_tree_create_pivot_by_pname(st, name, parent_name);
174 Creates a "pivot node"
175  
176 stats_tree_tick_pivot(st, pivot_id, pivoted_string);
177 Each time a pivot node will be ticked it will get increased, and, it will
178 increase (or create) the children named as pivoted_string
179  
180  
181 the following will either increase or create a node (with value 1) when called
182  
183 tick_stat_node(st,name,parent_id,with_children)
184 increases by one a stat_node
185  
186 increase_stat_node(st,name,parent_id,with_children,value)
187 increases by value a stat_node
188  
189 set_stat_node(st,name,parent_id,with_children,value)
190 sets the value of a stat_node
191  
192 zero_stat_node(st,name,parent_id,with_children)
193 resets to zero a stat_node
194  
195 Averages work by tracking both the number of items added to node (the ticking
196 action) and the value of each item added to the node. This is done
197 automatically for ranged nodes; for other node types you need to call one of
198 the functions below to associate item values with each tick.
199  
200 avg_stat_node_add_value_notick(st,name,parent_id,with_children,value)
201 avg_stat_node_add_value(st,name,parent_id,with_children,value)
202  
203 The difference between the above functions is whether the item count is
204 increased or not. To properly compute the average you need to either call
205 avg_stat_node_add_value or avg_stat_node_add_value_notick combined
206 tick_stat_node. The later sequence allows for plug-ins which are compatible
207 with older wireshark versions which ignores avg_stat_node_add_value because
208 it does not understand the command. This would result in 0 counts for all
209 nodes. It is preferred to use avg_stat_node_add_value if you are not writing
210 a plug-in.
211  
212 avg_stat_node_add_value is used the same way as tick_stat_node with the
213 exception that you now specify an additional value associated with the tick.
214  
215 Do not mix increase_stat_node, set_stat_node or zero_stat_node
216 with avg_stat_node_add_value as this will lead to incorrect results for the
217 average value.
218  
219 stats_tree now also support setting flags per node to control the behaviour
220 of these nodes. This can be done using the stat_node_set_flags and
221 stat_node_clear_flags functions. Currently these flags are defined:
222  
223 ST_FLG_DEF_NOEXPAND: By default the top-level nodes in a tree are
224 automatically expanded in the GUI. Setting this flag on
225 such a node prevents the node from automatically expanding.
226 ST_FLG_SORT_TOP: Nodes with this flag is sorted separately from nodes
227 without this flag (in effect partitioning tree into a top and
228 bottom half. Each half is sorted normally. Top always appear
229 first :)
230  
231 You can find more examples of these in $srcdir/plugins/stats_tree/pinfo_stats_tree.c
232  
233 Luis E. G. Ontanon.