2 * scsi_stat 2006 Ronnie Sahlberg
4 * $Id: scsi_stat.c 17252 2006-02-11 13:05:24Z lego $
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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 SRT (Server Response Time) statistics
35 #include <epan/packet_info.h>
36 #include <epan/epan.h>
38 #include <epan/stat_cmd_args.h>
39 #include "stat_menu.h"
40 #include "gui_stat_menu.h"
41 #include "simple_dialog.h"
42 #include "gui_utils.h"
43 #include "dlg_utils.h"
48 #include "filter_dlg.h"
49 #include "compat_macros.h"
50 #include "service_response_time_table.h"
51 #include "gtkglobals.h"
52 #include <epan/conversation.h>
53 #include <epan/dissectors/packet-scsi.h>
54 #include <epan/dissectors/packet-fc.h>
56 static GtkWidget *dlg=NULL;
58 /* used to keep track of the statistics for an entire scsi command set */
59 typedef struct _scsistat_t {
61 srt_stat_table srt_table;
63 const value_string *cdbnames;
67 static guint8 scsi_program=0;
68 static GtkWidget *filter_entry;
71 scsistat_gen_title(scsistat_t *rs)
75 title = g_strdup_printf("SCSI Service Response Time statistics for %s: %s",
76 rs->prog, cf_get_display_name(&cfile));
81 scsistat_set_title(scsistat_t *rs)
85 title = scsistat_gen_title(rs);
86 gtk_window_set_title(GTK_WINDOW(rs->win), title);
91 scsistat_reset(void *arg)
95 reset_srt_table_data(&rs->srt_table);
96 scsistat_set_title(rs);
108 scsistat_program_select(GtkWidget *item _U_, gpointer key)
116 scsistat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
118 scsistat_t *rs = arg;
119 const scsi_task_data_t *ri = arg2;
121 /* we are only interested in response packets */
122 if(ri->type!=SCSI_PDU_TYPE_RSP){
125 /* we are only interested in a specific commandset */
126 if( (!ri->itl) || ((ri->itl->cmdset&SCSI_CMDSET_MASK)!=rs->cmdset) ){
129 /* check that the opcode looks sane */
130 if( (!ri->itlq) || (ri->itlq->scsi_opcode>255) ){
134 add_srt_table_data(&rs->srt_table, ri->itlq->scsi_opcode, &ri->itlq->fc_time, pinfo);
140 scsistat_draw(void *arg)
142 scsistat_t *rs = arg;
144 draw_srt_table_data(&rs->srt_table);
149 /* since the gtk2 implementation of tap is multithreaded we must protect
150 * remove_tap_listener() from modifying the list while draw_tap_listener()
151 * is running. the other protected block is in main.c
153 * there should not be any other critical regions in gtk2
156 win_destroy_cb(GtkWindow *win _U_, gpointer data)
158 scsistat_t *rs=(scsistat_t *)data;
160 protect_thread_critical_region();
161 remove_tap_listener(rs);
162 unprotect_thread_critical_region();
164 free_srt_table_data(&rs->srt_table);
169 /* When called, this function will create a new instance of gtk2-scsistat.
172 gtk_scsistat_init(const char *optarg, void* userdata _U_)
177 char filter_string[256];
179 GtkWidget *stat_label;
180 GtkWidget *filter_label;
184 const char *filter=NULL;
185 GString *error_string;
189 if(sscanf(optarg,"scsi,srt,%d,%n",&program,&pos)==1){
196 fprintf(stderr, "wireshark: invalid \"-z scsi,srt,<cmdset>[,<filter>]\" argument\n");
200 scsi_program=program;
201 rs=g_malloc(sizeof(scsistat_t));
205 rs->prog="SBC (disk)";
206 rs->cdbnames=scsi_sbc2_vals;
207 hf_name="scsi.sbc.opcode";
210 rs->prog="SSC (tape)";
211 rs->cdbnames=scsi_ssc2_vals;
212 hf_name="scsi.ssc.opcode";
215 rs->prog="MMC (cd/dvd)";
216 rs->cdbnames=scsi_mmc_vals;
217 hf_name="scsi.mmc.opcode";
221 rs->win=window_new(GTK_WINDOW_TOPLEVEL, "scsi-stat");
222 gtk_window_set_default_size(GTK_WINDOW(rs->win), 550, 400);
223 scsistat_set_title(rs);
225 vbox=gtk_vbox_new(FALSE, 3);
226 gtk_container_add(GTK_CONTAINER(rs->win), vbox);
227 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
229 title_string = scsistat_gen_title(rs);
230 stat_label=gtk_label_new(title_string);
231 g_free(title_string);
232 gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
234 g_snprintf(filter_string,255,"Filter:%s",filter?filter:"");
235 filter_label=gtk_label_new(filter_string);
236 gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
238 /* We must display TOP LEVEL Widget before calling init_srt_table() */
239 gtk_widget_show_all(rs->win);
241 init_srt_table(&rs->srt_table, 256, vbox, hf_name);
244 init_srt_table_row(&rs->srt_table, i, val_to_str(i, rs->cdbnames, "Unknown-0x%02x"));
248 error_string=register_tap_listener("scsi", rs, filter, scsistat_reset, scsistat_packet, scsistat_draw);
250 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
251 g_string_free(error_string, TRUE);
252 free_srt_table_data(&rs->srt_table);
258 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
259 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
261 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
262 window_set_cancel_button(rs->win, close_bt, window_cancel_button_cb);
264 SIGNAL_CONNECT(rs->win, "delete_event", window_delete_event_cb, NULL);
265 SIGNAL_CONNECT(rs->win, "destroy", win_destroy_cb, rs);
267 gtk_widget_show_all(rs->win);
268 window_present(rs->win);
270 cf_retap_packets(&cfile, FALSE);
276 scsistat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
281 str = g_string_new("scsi,srt");
282 g_string_sprintfa(str, ",%d", scsi_program);
283 filter=gtk_entry_get_text(GTK_ENTRY(filter_entry));
285 g_string_sprintfa(str, ",%s", filter);
288 gtk_scsistat_init(str->str,NULL);
289 g_string_free(str, TRUE);
294 gtk_scsistat_cb(GtkWidget *w _U_, gpointer d _U_)
296 GtkWidget *prog_menu;
298 GtkWidget *prog_box, *prog_label, *prog_opt;
299 GtkWidget *filter_box, *filter_bt;
300 GtkWidget *menu_item;
301 GtkWidget *bbox, *start_button, *cancel_button;
303 static construct_args_t args = {
304 "Service Response Time Statistics Filter",
310 /* if the window is already open, bring it to front */
312 gdk_window_raise(dlg->window);
316 dlg=dlg_window_new("Wireshark: Compute SCSI SRT statistics");
317 gtk_window_set_default_size(GTK_WINDOW(dlg), 300, -1);
319 dlg_box=gtk_vbox_new(FALSE, 10);
320 gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
321 gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
322 gtk_widget_show(dlg_box);
325 prog_box=gtk_hbox_new(FALSE, 10);
328 gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
329 prog_label=gtk_label_new("Commandset:");
330 gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
331 gtk_widget_show(prog_label);
334 prog_opt=gtk_option_menu_new();
335 prog_menu=gtk_menu_new();
338 menu_item=gtk_menu_item_new_with_label("SBC (disk)");
339 SIGNAL_CONNECT(menu_item, "activate", scsistat_program_select, SCSI_DEV_SBC);
340 gtk_widget_show(menu_item);
341 gtk_menu_append(GTK_MENU(prog_menu), menu_item);
345 menu_item=gtk_menu_item_new_with_label("SSC (tape)");
346 SIGNAL_CONNECT(menu_item, "activate", scsistat_program_select, SCSI_DEV_SSC);
347 gtk_widget_show(menu_item);
348 gtk_menu_append(GTK_MENU(prog_menu), menu_item);
351 menu_item=gtk_menu_item_new_with_label("MMC (cd/dvd)");
352 SIGNAL_CONNECT(menu_item, "activate", scsistat_program_select, SCSI_DEV_CDROM);
353 gtk_widget_show(menu_item);
354 gtk_menu_append(GTK_MENU(prog_menu), menu_item);
357 gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
358 gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
359 gtk_widget_show(prog_opt);
361 gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
362 gtk_widget_show(prog_box);
365 filter_box=gtk_hbox_new(FALSE, 3);
368 filter_bt=BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
369 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
370 gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
371 gtk_widget_show(filter_bt);
374 filter_entry=gtk_entry_new();
375 SIGNAL_CONNECT(filter_entry, "changed", filter_te_syntax_check_cb, NULL);
377 /* filter prefs dialog */
378 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_entry);
379 /* filter prefs dialog */
381 gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
382 filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
384 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
386 gtk_widget_show(filter_entry);
388 gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
389 gtk_widget_show(filter_box);
392 bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
393 gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
394 gtk_widget_show(bbox);
396 start_button = OBJECT_GET_DATA(bbox, WIRESHARK_STOCK_CREATE_STAT);
397 SIGNAL_CONNECT_OBJECT(start_button, "clicked",
398 scsistat_start_button_clicked, NULL);
400 cancel_button = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
401 window_set_cancel_button(dlg, cancel_button, window_cancel_button_cb);
403 /* Give the initial focus to the "Filter" entry box. */
404 gtk_widget_grab_focus(filter_entry);
406 gtk_widget_grab_default(start_button );
408 SIGNAL_CONNECT(dlg, "delete_event", window_delete_event_cb, NULL);
409 SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
411 gtk_widget_show_all(dlg);
417 register_tap_listener_gtkscsistat(void)
419 register_stat_cmd_arg("scsi,srt,", gtk_scsistat_init, NULL);
421 register_stat_menu_item("SCSI...", REGISTER_STAT_GROUP_RESPONSE_TIME,
422 gtk_scsistat_cb, NULL, NULL, NULL);