2 * rpc_progs 2002 Ronnie Sahlberg
4 * $Id: rpc_progs.c,v 1.1 2002/09/07 09:28:05 sahlberg Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* This module provides rpc call/reply RTT statistics to tethereal.
26 * It is only used by tethereal and not ethereal
28 * It serves as an example on how to use the tap api.
36 #include "epan/packet_info.h"
38 #include "rpc_progs.h"
39 #include "packet-rpc.h"
41 static GtkWidget *win=NULL;
42 static GtkWidget *table=NULL;
43 static int num_progs=0;
45 /* used to keep track of statistics for a specific program/version */
46 typedef struct _rpc_program_t {
47 struct _rpc_program_t *next;
73 static rpc_program_t *prog_list=NULL;
77 rpcprogs_reset(void *dummy _U_)
81 for(rp=prog_list;rp;rp=rp->next){
93 add_new_program(rpc_program_t *rp)
96 gtk_table_resize(GTK_TABLE(table), num_progs+1, 6);
97 rp->wprogram=gtk_label_new("0");
98 gtk_table_attach_defaults(GTK_TABLE(table), rp->wprogram, 0,1,num_progs,num_progs+1);
99 gtk_widget_show(rp->wprogram);
100 rp->wversion=gtk_label_new("0");
101 gtk_table_attach_defaults(GTK_TABLE(table), rp->wversion, 1,2,num_progs,num_progs+1);
102 gtk_widget_show(rp->wversion);
103 rp->wnum=gtk_label_new("0");
104 gtk_table_attach_defaults(GTK_TABLE(table), rp->wnum, 2,3,num_progs,num_progs+1);
105 gtk_widget_show(rp->wnum);
106 rp->wmin=gtk_label_new("0");
107 gtk_table_attach_defaults(GTK_TABLE(table), rp->wmin, 3,4,num_progs,num_progs+1);
108 gtk_widget_show(rp->wmin);
109 rp->wmax=gtk_label_new("0");
110 gtk_table_attach_defaults(GTK_TABLE(table), rp->wmax, 4,5,num_progs,num_progs+1);
111 gtk_widget_show(rp->wmax);
112 rp->wavg=gtk_label_new("0");
113 gtk_table_attach_defaults(GTK_TABLE(table), rp->wavg, 5,6,num_progs,num_progs+1);
114 gtk_widget_show(rp->wavg);
128 rpcprogs_packet(void *dummy _U_, packet_info *pinfo, rpc_call_info_value *ri)
134 /* the list was empty */
135 rp=g_malloc(sizeof(rpc_program_t));
138 rp->program=ri->prog;
139 rp->version=ri->vers;
141 } else if((ri->prog==prog_list->program)
142 &&(ri->vers==prog_list->version)){
144 } else if( (ri->prog<prog_list->program)
145 ||((ri->prog==prog_list->program)&&(ri->vers<prog_list->version))){
146 /* we should be first entry in list */
147 rp=g_malloc(sizeof(rpc_program_t));
150 rp->program=ri->prog;
151 rp->version=ri->vers;
154 /* we go somewhere else in the list */
155 for(rp=prog_list;rp;rp=rp->next){
157 && (rp->next->program==ri->prog)
158 && (rp->next->version==ri->vers)){
163 || (rp->next->program>ri->prog)
164 || ( (rp->next->program==ri->prog)
165 &&(rp->next->version>ri->vers))){
167 trp=g_malloc(sizeof(rpc_program_t));
168 add_new_program(trp);
170 trp->program=ri->prog;
171 trp->version=ri->vers;
180 /* we are only interested in reply packets */
185 /* calculate time delta between request and reply */
186 delta.secs=pinfo->fd->abs_secs-ri->req_time.secs;
187 delta.nsecs=pinfo->fd->abs_usecs*1000-ri->req_time.nsecs;
189 delta.nsecs+=1000000000;
194 && (rp->max.nsecs==0) ){
195 rp->max.secs=delta.secs;
196 rp->max.nsecs=delta.nsecs;
200 && (rp->min.nsecs==0) ){
201 rp->min.secs=delta.secs;
202 rp->min.nsecs=delta.nsecs;
205 if( (delta.secs<rp->min.secs)
206 ||( (delta.secs==rp->min.secs)
207 &&(delta.nsecs<rp->min.nsecs) ) ){
208 rp->min.secs=delta.secs;
209 rp->min.nsecs=delta.nsecs;
212 if( (delta.secs>rp->max.secs)
213 ||( (delta.secs==rp->max.secs)
214 &&(delta.nsecs>rp->max.nsecs) ) ){
215 rp->max.secs=delta.secs;
216 rp->max.nsecs=delta.nsecs;
219 rp->tot.secs += delta.secs;
220 rp->tot.nsecs += delta.nsecs;
221 if(rp->tot.nsecs>1000000000){
222 rp->tot.nsecs-=1000000000;
232 rpcprogs_draw(void *dummy _U_)
242 for(rp=prog_list,i=1;rp;rp=rp->next,i++){
243 /* scale it to units of 10us.*/
244 /* for long captures with a large tot time, this can overflow on 32bit */
245 td=(int)rp->tot.secs;
246 td=td*100000+(int)rp->tot.nsecs/10000;
253 sprintf(rp->sprogram,"%s",rpc_prog_name(rp->program));
254 gtk_label_set_text(GTK_LABEL(rp->wprogram), rp->sprogram);
256 sprintf(rp->sversion,"%d",rp->version);
257 gtk_label_set_text(GTK_LABEL(rp->wversion), rp->sversion);
259 sprintf(rp->snum,"%d",rp->num);
260 gtk_label_set_text(GTK_LABEL(rp->wnum), rp->snum);
262 sprintf(rp->smin,"%3d.%05d",(int)rp->min.secs,(int)rp->min.nsecs/10000);
263 gtk_label_set_text(GTK_LABEL(rp->wmin), rp->smin);
265 sprintf(rp->smax,"%3d.%05d",(int)rp->max.secs,(int)rp->max.nsecs/10000);
266 gtk_label_set_text(GTK_LABEL(rp->wmax), rp->smax);
268 sprintf(rp->savg,"%3d.%05d",(int)td/100000,(int)td%100000);
269 gtk_label_set_text(GTK_LABEL(rp->wavg), rp->savg);
274 /* since the gtk2 implementation of tap is multithreaded we must protect
275 * remove_tap_listener() from modifying the list while draw_tap_listener()
276 * is running. the other protected block is in main.c
278 * there should not be any other critical regions in gtk2
280 void protect_thread_critical_region(void);
281 void unprotect_thread_critical_region(void);
283 win_destroy_cb(void *dummy _U_, gpointer data _U_)
285 rpc_program_t *rp, *rp2;
287 protect_thread_critical_region();
288 remove_tap_listener(win);
289 unprotect_thread_critical_region();
292 for(rp=prog_list;rp;){
301 /* When called, this function will start rpcprogs
304 gtk_rpcprogs_init(void)
306 char title_string[60];
308 GtkWidget *stat_label;
312 gdk_window_raise(win->window);
316 win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
317 sprintf(title_string,"ONC-RPC Program Statistics");
318 gtk_window_set_title(GTK_WINDOW(win), title_string);
319 gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(win_destroy_cb), win);
321 vbox=gtk_vbox_new(FALSE, 0);
322 gtk_container_add(GTK_CONTAINER(win), vbox);
323 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
324 gtk_widget_show(vbox);
326 stat_label=gtk_label_new(title_string);
327 gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
328 gtk_widget_show(stat_label);
331 table=gtk_table_new(1, 5, TRUE);
332 gtk_container_add(GTK_CONTAINER(vbox), table);
334 tmp=gtk_label_new("Program");
335 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 0,1,0,1);
336 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
337 gtk_widget_show(tmp);
339 tmp=gtk_label_new("Version");
340 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 1,2,0,1);
341 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
342 gtk_widget_show(tmp);
344 tmp=gtk_label_new("Calls");
345 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 2,3,0,1);
346 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
347 gtk_widget_show(tmp);
349 tmp=gtk_label_new("Min RTT");
350 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 3,4,0,1);
351 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
352 gtk_widget_show(tmp);
354 tmp=gtk_label_new("Max RTT");
355 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 4,5,0,1);
356 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
357 gtk_widget_show(tmp);
359 tmp=gtk_label_new("Avg RTT");
360 gtk_table_attach_defaults(GTK_TABLE(table), tmp, 5,6,0,1);
361 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_RIGHT);
362 gtk_widget_show(tmp);
365 gtk_widget_show(table);
367 if(register_tap_listener("rpc", win, NULL, (void*)rpcprogs_reset, (void*)rpcprogs_packet, (void*)rpcprogs_draw)){
368 fprintf(stderr, "ethereal: gtk_rpcprogs_init() failed to register tap\n");
373 gtk_widget_show_all(win);