2 * rpcstat 2002 Ronnie Sahlberg
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
11 /* This module provides rpc call/reply SRT statistics to tshark.
12 * It is only used by tshark and not wireshark
23 #include <epan/packet_info.h>
25 #include <epan/stat_tap_ui.h>
26 #include <epan/dissectors/packet-rpc.h>
28 #include <wsutil/cmdarg_err.h>
30 #define MICROSECS_PER_SEC 1000000
31 #define NANOSECS_PER_SEC 1000000000
33 void register_tap_listener_rpcprogs(void);
35 /* used to keep track of statistics for a specific program/version */
36 typedef struct _rpc_program_t
{
37 struct _rpc_program_t
*next
;
46 static rpc_program_t
*prog_list
;
47 static int already_enabled
;
49 static tap_packet_status
50 rpcprogs_packet(void *dummy1 _U_
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *pri
, tap_flags_t flags _U_
)
52 const rpc_call_info_value
*ri
= (const rpc_call_info_value
*)pri
;
54 rpc_program_t
*rp
= NULL
;
57 /* the list was empty */
58 rp
= g_new(rpc_program_t
, 1);
60 rp
->program
= ri
->prog
;
61 rp
->version
= ri
->vers
;
70 } else if ((ri
->prog
== prog_list
->program
)
71 && (ri
->vers
== prog_list
->version
)) {
73 } else if ( (ri
->prog
< prog_list
->program
)
74 || ((ri
->prog
== prog_list
->program
) && (ri
->vers
< prog_list
->version
))) {
75 /* we should be first entry in list */
76 rp
= g_new(rpc_program_t
, 1);
78 rp
->program
= ri
->prog
;
79 rp
->version
= ri
->vers
;
89 /* we go somewhere else in the list */
90 for (rp
=prog_list
; rp
; rp
=rp
->next
) {
92 && (rp
->next
->program
== ri
->prog
)
93 && (rp
->next
->version
== ri
->vers
)) {
98 || (rp
->next
->program
> ri
->prog
)
99 || ( (rp
->next
->program
== ri
->prog
)
100 && (rp
->next
->version
> ri
->vers
))) {
102 trp
= g_new(rpc_program_t
, 1);
103 trp
->next
= rp
->next
;
104 trp
->program
= ri
->prog
;
105 trp
->version
= ri
->vers
;
121 /* we are only interested in reply packets */
122 if (ri
->request
|| !rp
) {
123 return TAP_PACKET_DONT_REDRAW
;
126 /* calculate time delta between request and reply */
127 nstime_delta(&delta
, &pinfo
->abs_ts
, &ri
->req_time
);
129 if ((rp
->max
.secs
== 0)
130 && (rp
->max
.nsecs
== 0) ) {
131 rp
->max
.secs
= delta
.secs
;
132 rp
->max
.nsecs
= delta
.nsecs
;
135 if ((rp
->min
.secs
== 0)
136 && (rp
->min
.nsecs
== 0) ) {
137 rp
->min
.secs
= delta
.secs
;
138 rp
->min
.nsecs
= delta
.nsecs
;
141 if ( (delta
.secs
< rp
->min
.secs
)
142 || ( (delta
.secs
== rp
->min
.secs
)
143 && (delta
.nsecs
< rp
->min
.nsecs
) ) ) {
144 rp
->min
.secs
= delta
.secs
;
145 rp
->min
.nsecs
= delta
.nsecs
;
148 if ( (delta
.secs
> rp
->max
.secs
)
149 || ( (delta
.secs
== rp
->max
.secs
)
150 && (delta
.nsecs
> rp
->max
.nsecs
) ) ) {
151 rp
->max
.secs
= delta
.secs
;
152 rp
->max
.nsecs
= delta
.nsecs
;
155 rp
->tot
.secs
+= delta
.secs
;
156 rp
->tot
.nsecs
+= delta
.nsecs
;
157 if (rp
->tot
.nsecs
> NANOSECS_PER_SEC
) {
158 rp
->tot
.nsecs
-= NANOSECS_PER_SEC
;
163 return TAP_PACKET_REDRAW
;
168 rpcprogs_draw(void *dummy _U_
)
175 printf("==========================================================\n");
176 printf("ONC-RPC Program Statistics:\n");
177 printf("Program Version Calls Min SRT Max SRT Avg SRT\n");
178 for (rp
= prog_list
;rp
;rp
= rp
->next
) {
179 /* Only display procs with non-zero calls */
183 /* Scale the average SRT in units of 1us and round to the nearest us. */
184 td
= ((uint64_t)(rp
->tot
.secs
)) * NANOSECS_PER_SEC
+ rp
->tot
.nsecs
;
185 td
= ((td
/ rp
->num
) + 500) / 1000;
187 snprintf(str
, sizeof(str
), "%s(%d)", rpc_prog_name(rp
->program
), rp
->program
);
188 printf("%-15s %2u %6d %3d.%06d %3d.%06d %3" PRIu64
".%06" PRIu64
"\n",
192 (int)(rp
->min
.secs
), (rp
->min
.nsecs
+500)/1000,
193 (int)(rp
->max
.secs
), (rp
->max
.nsecs
+500)/1000,
194 td
/MICROSECS_PER_SEC
, td
%MICROSECS_PER_SEC
197 printf("===================================================================\n");
202 rpcprogs_init(const char *opt_arg _U_
, void *userdata _U_
)
204 GString
*error_string
;
206 if (already_enabled
) {
211 error_string
= register_tap_listener("rpc", NULL
, NULL
, 0, NULL
, rpcprogs_packet
, rpcprogs_draw
, NULL
);
213 cmdarg_err("Couldn't register rpc,programs tap: %s",
215 g_string_free(error_string
, TRUE
);
220 static stat_tap_ui rpcprogs_ui
= {
221 REGISTER_STAT_GROUP_GENERIC
,
230 register_tap_listener_rpcprogs(void)
232 register_stat_tap_ui(&rpcprogs_ui
, NULL
);
236 * Editor modelines - https://www.wireshark.org/tools/modelines.html
241 * indent-tabs-mode: t
244 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
245 * :indentSize=8:tabSize=8:noTabs=false: