New type of onc-rpc statistics.
authorRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>
Thu, 5 Sep 2002 09:27:56 +0000 (09:27 -0000)
committerRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>
Thu, 5 Sep 2002 09:27:56 +0000 (09:27 -0000)
try: -z rpc,programs

svn path=/trunk/; revision=6190

Makefile.am
Makefile.nmake
doc/tethereal.pod.template
tap-rpcprogs.c [new file with mode: 0644]
tap-rpcprogs.h [new file with mode: 0644]
tethereal.c

index 83a8b18add3d98954bdf9abfe78c19291d30d666..10d6881cf85e787047839c0d7848105c95b1a829 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.468 2002/09/04 20:38:00 jmayer Exp $
+# $Id: Makefile.am,v 1.469 2002/09/05 09:27:50 sahlberg Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -597,6 +597,8 @@ ETHEREAL_COMMON_SRC = \
        tap.h           \
        tap-rpcstat.c   \
        tap-rpcstat.h   \
+       tap-rpcprogs.c  \
+       tap-rpcprogs.h  \
        util.c         \
        util.h         \
        x11-declarations.h \
index 1cbff6a612263d23bb66771687854b5ef1051cd7..78f41e289eff60eca89999a51e58076c174640cb 100644 (file)
@@ -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.206 2002/09/04 20:23:53 guy Exp $
+# $Id: Makefile.nmake,v 1.207 2002/09/05 09:27:50 sahlberg Exp $
 
 include config.nmake
 include <win32.mak>
@@ -307,6 +307,7 @@ ETHEREAL_COMMON_OBJECTS = \
        ringbuffer.obj   \
        tap.obj         \
        tap-rpcstat.obj \
+       tap-rpcprogs.obj        \
        util.obj         \
        xdlc.obj         \
        xmlstub.obj      \
index daeb7af04874b74b611bca6996c238446d3d6432..229b629145859d9e77140a98b6d8aef8ec796b03 100644 (file)
@@ -316,6 +316,13 @@ is number of calls for each procedure, MinRTT, MaxRTT and AvgRTT.
 Example: use B<-z rpc,rtt,100003,3> to collect data for NFS v3.  This
 option can be used multiple times on the command line. 
 
+B<-z> rpc,programs
+
+Collect call/reply RTT data for all known ONC-RPC programs/versions.  
+Data collected is number of calls for each protocol/version, MinRTT, 
+MaxRTT and AvgRTT. 
+This option can only be used once on the command line.
+
 =back
 
 =head1 CAPTURE FILTER SYNTAX
diff --git a/tap-rpcprogs.c b/tap-rpcprogs.c
new file mode 100644 (file)
index 0000000..a2d4ad9
--- /dev/null
@@ -0,0 +1,238 @@
+/* tap-rpcprogs.c
+ * rpcstat   2002 Ronnie Sahlberg
+ *
+ * $Id: tap-rpcprogs.c,v 1.1 2002/09/05 09:27:50 sahlberg Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * 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.
+ */
+
+/* This module provides rpc call/reply RTT statistics to tethereal.
+ * It is only used by tethereal and not ethereal
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include "tap.h"
+#include "tap-rpcprogs.h"
+#include "packet-rpc.h"
+
+
+/* used to keep track of statistics for a specific program/version */
+typedef struct _rpc_program_t {
+       struct _rpc_program_t *next;
+       guint32 program;
+       guint32 version;
+       int num;
+       nstime_t min;
+       nstime_t max;
+       nstime_t tot;
+} rpc_program_t;
+
+static rpc_program_t *prog_list=NULL;
+static int already_enabled=0;
+
+static int
+rpcprogs_packet(void *dummy1 _U_, packet_info *pinfo, rpc_call_info_value *ri)
+{
+       nstime_t delta;
+       rpc_program_t *rp=NULL;
+
+       if(!prog_list){
+               /* the list was empty */
+               rp=g_malloc(sizeof(rpc_program_t));
+               rp->next=NULL;
+               rp->program=ri->prog;
+               rp->version=ri->vers;
+               rp->num=0;
+               rp->min.secs=0;
+               rp->min.nsecs=0;
+               rp->max.secs=0;
+               rp->max.nsecs=0;
+               rp->tot.secs=0;
+               rp->tot.nsecs=0;
+               prog_list=rp;
+       } else if((ri->prog==prog_list->program)
+               &&(ri->vers==prog_list->version)){
+               rp=prog_list;
+       } else if( (ri->prog<prog_list->program)
+               ||((ri->prog==prog_list->program)&&(ri->vers<prog_list->version))){
+               /* we should be first entry in list */
+               rp=g_malloc(sizeof(rpc_program_t));
+               rp->next=prog_list;
+               rp->program=ri->prog;
+               rp->version=ri->vers;
+               rp->num=0;
+               rp->min.secs=0;
+               rp->min.nsecs=0;
+               rp->max.secs=0;
+               rp->max.nsecs=0;
+               rp->tot.secs=0;
+               rp->tot.nsecs=0;
+               prog_list=rp;
+       } else {
+               /* we go somewhere else in the list */
+               for(rp=prog_list;rp;rp=rp->next){
+                       if((rp->next)
+                       && (rp->next->program==ri->prog)
+                       && (rp->next->version==ri->vers)){
+                               rp=rp->next;
+                               break;
+                       }
+                       if((!rp->next)
+                       || (rp->next->program>ri->prog)
+                       || (  (rp->next->program==ri->prog)
+                           &&(rp->next->version>ri->vers))){
+                               rpc_program_t *trp;
+                               trp=g_malloc(sizeof(rpc_program_t));
+                               trp->next=rp->next;
+                               trp->program=ri->prog;
+                               trp->version=ri->vers;
+                               trp->num=0;
+                               trp->min.secs=0;
+                               trp->min.nsecs=0;
+                               trp->max.secs=0;
+                               trp->max.nsecs=0;
+                               trp->tot.secs=0;
+                               trp->tot.nsecs=0;
+                               rp->next=trp;
+                               rp=trp;
+                               break;
+                       }
+               }
+       }
+
+       
+       /* we are only interested in reply packets */
+       if(ri->request){
+               return 0;
+       }
+
+       /* calculate time delta between request and reply */
+       delta.secs=pinfo->fd->abs_secs-ri->req_time.secs;
+       delta.nsecs=pinfo->fd->abs_usecs*1000-ri->req_time.nsecs;
+       if(delta.nsecs<0){
+               delta.nsecs+=1000000000;
+               delta.secs--;
+       }
+
+       if((rp->max.secs==0)
+       && (rp->max.nsecs==0) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+
+       if((rp->min.secs==0)
+       && (rp->min.nsecs==0) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs<rp->min.secs)
+       ||( (delta.secs==rp->min.secs)
+         &&(delta.nsecs<rp->min.nsecs) ) ){
+               rp->min.secs=delta.secs;
+               rp->min.nsecs=delta.nsecs;
+       }
+
+       if( (delta.secs>rp->max.secs)
+       ||( (delta.secs==rp->max.secs)
+         &&(delta.nsecs>rp->max.nsecs) ) ){
+               rp->max.secs=delta.secs;
+               rp->max.nsecs=delta.nsecs;
+       }
+       
+       rp->tot.secs += delta.secs;
+       rp->tot.nsecs += delta.nsecs;
+       if(rp->tot.nsecs>1000000000){
+               rp->tot.nsecs-=1000000000;
+               rp->tot.secs++;
+       }
+       rp->num++;
+
+       return 1;
+}
+
+
+static void
+rpcprogs_draw(void *dummy _U_)
+{
+#ifdef G_HAVE_UINT64
+       guint64 td;
+#else
+       guint32 td;
+#endif
+       rpc_program_t *rp;
+       char str[64];
+
+       printf("\n");
+       printf("===================================================================\n");
+       printf("ONC-RPC Program Statistics:\n");
+       printf("Program    Version  Calls   Min RTT   Max RTT   Avg RTT\n");
+       for(rp=prog_list;rp;rp=rp->next){
+               /* scale it to units of 10us.*/
+               /* for long captures with a large tot time, this can overflow on 32bit */
+               td=(int)rp->tot.secs;
+               td=td*100000+(int)rp->tot.nsecs/10000;
+               if(rp->num){
+                       td/=rp->num;
+               } else {
+                       td=0;
+               }
+
+               sprintf(str,"%s(%d)",rpc_prog_name(rp->program),rp->program);
+               printf("%-15s %2d %6d %3d.%05d %3d.%05d %3d.%05d\n",
+                       str,
+                       rp->version,
+                       rp->num,
+                       (int)rp->min.secs,rp->min.nsecs/10000,
+                       (int)rp->max.secs,rp->max.nsecs/10000,
+                       td/100000, td%100000
+               );
+       }
+       printf("===================================================================\n");
+}
+
+
+void
+rpcprogs_init(void)
+{
+       if(already_enabled){
+               return;
+       }
+       already_enabled=1;
+
+       if(register_tap_listener("rpc", NULL, NULL, NULL, (void*)rpcprogs_packet, (void*)rpcprogs_draw)){
+               fprintf(stderr,"tethereal: rpcprogs_init() failed to attach to tap.\n");
+               exit(1);
+       }
+}
+
+
+
+
diff --git a/tap-rpcprogs.h b/tap-rpcprogs.h
new file mode 100644 (file)
index 0000000..81171cf
--- /dev/null
@@ -0,0 +1,28 @@
+/* tap-rpcprogs.h
+ * rpcprogs   2002 Ronnie Sahlberg
+ *
+ * $Id: tap-rpcprogs.h,v 1.1 2002/09/05 09:27:50 sahlberg Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * 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 rpcprogs_init(void);
+
+
+
index 3ee2e07c758b06ee7cddf8357cf7a7273acb1226..1ea111101f07515ed757685be2ce6c8437694c26 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.155 2002/09/05 06:46:34 sahlberg Exp $
+ * $Id: tethereal.c,v 1.156 2002/09/05 09:27:50 sahlberg Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -97,6 +97,7 @@
 #include <epan/epan_dissect.h>
 #include "tap.h"
 #include "tap-rpcstat.h"
+#include "tap-rpcprogs.h"
 
 #ifdef HAVE_LIBPCAP
 #include <wiretap/wtap-capture.h>
@@ -657,12 +658,17 @@ main(int argc, char *argv[])
               fprintf(stderr, "tethereal: invalid \"-z rpc,rtt,<program>,<version>\" argument\n");
               exit(1);
             }
+          } else if(!strncmp(optarg,"rpc,programs",12)){
+            rpcprogs_init();
           } else {
-            fprintf(stderr, "tethereal: invalid -z argument. Argument must be \"-z rpc,rtt,...\"\n");
+            fprintf(stderr, "tethereal: invalid -z argument. Argument must be one of:\n");
+            fprintf(stderr, "   \"-z rpc,rtt,<program>,<version>\"\n");
+            fprintf(stderr, "   \"-z rpc,programs\"\n");
             exit(1);
           }
         } else {
-          fprintf(stderr, "tethereal: invalid -z argument. Argument must be \"-z rpc,...\"\n");
+          fprintf(stderr, "tethereal: invalid -z argument. Argument must be:\n");
+          fprintf(stderr, "   \"-z rpc,...\"\n");
           exit(1);
         }
         break;