Rename stat_cmd_args.[ch] to stat_tap_ui.[ch].
[metze/wireshark/wip.git] / ui / cli / tap-camelsrt.c
1 /* tap_camelsrt.c
2  * CAMEL Service Response Time statistics for tshark
3  * Copyright 2006 Florent Drouin (based on tap_h225rassrt.c from Lars Roland)
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "epan/packet.h"
31 #include "epan/packet_info.h"
32 #include <epan/tap.h>
33 #include "epan/value_string.h"
34 #include "epan/asn1.h"
35 #include "epan/dissectors/packet-camel.h"
36 #include "epan/dissectors/packet-tcap.h"
37 #include "epan/timestats.h"
38 #include "epan/stat_tap_ui.h"
39
40
41 void register_tap_listener_camelsrt(void);
42
43 /* Save the the first NUM_RAS_STATS stats in the array to calculate percentile */
44 #define NUM_RAS_STATS 500000
45
46 /* Number of couple message Request/Response to analyze*/
47 #define NB_CRITERIA 7
48
49 /* used to keep track of the statistics for an entire program interface */
50 struct camelsrt_t {
51   char *filter;
52   guint32 count[NB_CAMELSRT_CATEGORY];
53   timestat_t stats[NB_CAMELSRT_CATEGORY];
54   nstime_t delta_time[NB_CAMELSRT_CATEGORY][NUM_RAS_STATS];
55 };
56
57 /* Reset the counter */
58 static void camelsrt_reset(void *phs)
59 {
60   struct camelsrt_t *hs = (struct camelsrt_t *)phs;
61   memset(hs, 0, sizeof(struct camelsrt_t));
62 }
63
64
65 static int camelsrt_packet(void *phs,
66                            packet_info *pinfo _U_,
67                            epan_dissect_t *edt _U_,
68                            const void *phi)
69 {
70   struct camelsrt_t *hs = (struct camelsrt_t *)phs;
71   const struct camelsrt_info_t * pi = (const struct camelsrt_info_t *)phi;
72   int i;
73
74   for (i=0; i<NB_CAMELSRT_CATEGORY; i++) {
75     if (pi->bool_msginfo[i] &&
76         pi->msginfo[i].is_delta_time
77         && pi->msginfo[i].request_available
78         && !pi->msginfo[i].is_duplicate ) {
79
80       time_stat_update(&(hs->stats[i]),
81                        &(pi->msginfo[i].delta_time),
82                        pinfo);
83
84       if (hs->count[i] < NUM_RAS_STATS) {
85         hs->delta_time[i][hs->count[i]++]
86           = pi->msginfo[i].delta_time;
87       }
88     }
89   }
90   return 1;
91 }
92
93
94 static void camelsrt_draw(void *phs)
95 {
96   struct camelsrt_t *hs = (struct camelsrt_t *)phs;
97   guint j, z;
98   guint32 li;
99   int somme, iteration = 0;
100   timestat_t *rtd_temp;
101   double x, delay, delay_max, delay_min, delta;
102   double criteria[NB_CRITERIA] = { 5.0, 10.0, 75.0, 90.0, 95.0, 99.0, 99.90 };
103   double delay_criteria[NB_CRITERIA];
104
105   printf("\n");
106   printf("Camel Service Response Time (SRT) Statistics:\n");
107   printf("=================================================================================================\n");
108   printf("|        Category         | Measure |  Min SRT  |  Max SRT  |  Avg SRT  | Min frame | Max frame |\n");
109   printf("|-------------------------|---------|-----------|-----------|-----------|-----------|-----------|\n");
110
111   j = 1;
112   printf("|%24s |%8u |%8.2f s |%8.2f s |%8.2f s |%10u |%10u |\n",
113          val_to_str(j, camelSRTtype_naming, "Unknown Message 0x%02x"),
114          hs->stats[j].num,
115          nstime_to_sec(&(hs->stats[j].min)),
116          nstime_to_sec(&(hs->stats[j].max)),
117          get_average(&(hs->stats[j].tot), hs->stats[j].num)/1000.0,
118          hs->stats[j].min_num,
119          hs->stats[j].max_num
120          );
121   for (j=2; j<NB_CAMELSRT_CATEGORY; j++) {
122     if (hs->stats[j].num == 0) {
123       printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
124              val_to_str(j, camelSRTtype_naming, "Unknown Message 0x%02x"),
125              0, 0.0, 0.0, 0.0, 0, 0);
126       continue;
127     }
128
129     printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
130            val_to_str(j, camelSRTtype_naming, "Unknown Message 0x%02x"),
131            hs->stats[j].num,
132            MIN(9999, nstime_to_msec(&(hs->stats[j].min))),
133            MIN(9999, nstime_to_msec(&(hs->stats[j].max))),
134            MIN(9999, get_average(&(hs->stats[j].tot), hs->stats[j].num)),
135            hs->stats[j].min_num,
136            hs->stats[j].max_num
137            );
138   } /* j category */
139
140   printf("=================================================================================================\n");
141   /*
142    * Display 95%
143    */
144
145   printf("|   Category/Criteria     |");
146   for (z=0; z<NB_CRITERIA; z++) printf("%7.2f%% |", criteria[z]);
147   printf("\n");
148
149   printf("|-------------------------|");
150   for (z=0; z<NB_CRITERIA; z++) printf("---------|");
151   printf("\n");
152   /* calculate the delay max to have a given number of messages (in percentage) */
153   for (j=2; j<NB_CAMELSRT_CATEGORY;j++) {
154
155     rtd_temp = &(hs->stats[j]);
156
157     if (hs->count[j] > 0) {
158       /* Calculate the delay to answer to p% of the MS */
159       for (z=0; z<NB_CRITERIA; z++) {
160         iteration = 0;
161         delay_max = (double)rtd_temp->max.secs*1000 +(double)rtd_temp->max.nsecs/1000000;
162         delay_min = (double)rtd_temp->min.secs*1000 +(double)rtd_temp->min.nsecs/1000000;
163         delay = delay_min;
164         delta = delay_max-delay_min;
165         while ( (delta > 0.001) && (iteration < 10000) ) {
166           somme = 0;
167           iteration++;
168
169           for (li=0; li<hs->count[j]; li++) {
170             x = hs->delta_time[j][li].secs*1000
171               + (double)hs->delta_time[j][li].nsecs/1000000;
172             if (x <= delay) somme++;
173           }
174           if ( somme*100 > hs->count[j]*criteria[z] ) { /* trop grand */
175             delay_max = delay;
176             delay = (delay_max+delay_min)/2;
177             delta = delay_max-delay_min;
178           } else { /* trop petit */
179             delay_min = delay;
180             delay = (delay_max+delay_min)/2;
181             delta = delay_max-delay_min;
182           }
183         } /* while */
184         delay_criteria[z] = delay;
185       } /* z criteria */
186       /* Append the result to the table */
187       printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
188       for (z=0; z<NB_CRITERIA; z++) printf("%8.2f |", MIN(9999, delay_criteria[z]));
189       printf("\n");
190     } else { /* count */
191       printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
192       for (z=0; z<NB_CRITERIA; z++) printf("%8.2f |", 0.0);
193       printf("\n");
194     } /* count */
195   }/* j category */
196   printf("===========================");
197   for (z=0; z<NB_CRITERIA; z++) printf("==========");
198   printf("\n");
199 }
200
201 static void camelsrt_init(const char *opt_arg, void *userdata _U_)
202 {
203   struct camelsrt_t *p_camelsrt;
204   GString *error_string;
205
206   p_camelsrt = g_new(struct camelsrt_t, 1);
207   if (!strncmp(opt_arg, "camel,srt,", 9)) {
208     p_camelsrt->filter = g_strdup(opt_arg+9);
209   } else {
210     p_camelsrt->filter = NULL;
211   }
212   camelsrt_reset(p_camelsrt);
213
214   error_string = register_tap_listener("CAMEL",
215                                      p_camelsrt,
216                                      p_camelsrt->filter,
217                                      0,
218                                      NULL,
219                                      camelsrt_packet,
220                                      camelsrt_draw);
221
222   if (error_string) {
223     /* error, we failed to attach to the tap. clean up */
224     g_free(p_camelsrt->filter);
225     g_free(p_camelsrt);
226
227     fprintf(stderr, "tshark: Couldn't register camel,srt tap: %s\n",
228             error_string->str);
229     g_string_free(error_string, TRUE);
230     exit(1);
231   }
232
233   /*
234    * If we are using tshark, we have to display the stats, even if the stats are not persistent
235    * As the frame are proceeded in the chronological order, we do not need persistent stats
236    * Whereas, with wireshark, it is not possible to have the correct display, if the stats are
237    * not saved along the analyze
238    */
239   gtcap_StatSRT = TRUE;
240   gcamel_StatSRT = TRUE;
241 }
242
243 static stat_tap_ui camelsrt_ui = {
244   REGISTER_STAT_GROUP_GENERIC,
245   NULL,
246   "camel,srt",
247   camelsrt_init,
248   -1,
249   0,
250   NULL
251 };
252
253 void /* Next line mandatory */
254 register_tap_listener_camelsrt(void)
255 {
256   register_stat_tap_ui(&camelsrt_ui, NULL);
257 }
258
259 /*
260  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
261  *
262  * Local Variables:
263  * c-basic-offset: 2
264  * tab-width: 8
265  * indent-tabs-mode: nil
266  * End:
267  *
268  * ex: set shiftwidth=2 tabstop=8 expandtab:
269  * :indentSize=2:tabSize=8:noTabs=true:
270  */