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