GSList *rt_list;
guint num_rqsts;
guint num_resps;
+ guint min_frame;
+ guint max_frame;
double min_msecs;
double max_msecs;
double tot_msecs;
} icmpstat_t;
-/* This callback is never used by tshark but it is here for completeness. When
+/* This callback is never used by tshark but it is here for completeness. When
* registering below, we could just have left this function as NULL.
*
* When used by wireshark, this function will be called whenever we would need
icmpstat_t *icmpstat = tapdata;
g_slist_free(icmpstat->rt_list);
- icmpstat->rt_list = NULL;
- icmpstat->num_rqsts = 0;
- icmpstat->num_resps = 0;
+ memset(icmpstat, 0, sizeof(icmpstat_t));
icmpstat->min_msecs = 1.0 * G_MAXUINT;
- icmpstat->max_msecs = 0.0;
- icmpstat->tot_msecs = 0.0;
+}
+
+
+static gint compare_doubles(gconstpointer a, gconstpointer b)
+{
+ double ad, bd;
+
+ ad = *(double *)a;
+ bd = *(double *)b;
+
+ if (ad < bd)
+ return -1;
+ if (ad > bd)
+ return 1;
+ return 0;
}
* !0: state has changed, call (*draw) sometime later
*/
static int
-icmpstat_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
+icmpstat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *data)
{
icmpstat_t *icmpstat = tapdata;
const icmp_transaction_t *trans = data;
if (rt == NULL)
return 0;
*rt = trans->resp_time;
- icmpstat->rt_list = g_slist_prepend(icmpstat->rt_list, rt);
+ icmpstat->rt_list = g_slist_insert_sorted(icmpstat->rt_list, rt, compare_doubles);
icmpstat->num_resps++;
- if (icmpstat->min_msecs > trans->resp_time)
+ if (icmpstat->min_msecs > trans->resp_time) {
+ icmpstat->min_frame = trans->resp_frame;
icmpstat->min_msecs = trans->resp_time;
- if (icmpstat->max_msecs < trans->resp_time)
+ }
+ if (icmpstat->max_msecs < trans->resp_time) {
+ icmpstat->max_frame = trans->resp_frame;
icmpstat->max_msecs = trans->resp_time;
+ }
icmpstat->tot_msecs += trans->resp_time;
} else if (trans->rqst_frame)
icmpstat->num_rqsts++;
}
-static double compute_sdev(double average, guint num, GSList *slist)
+/*
+ * Compute the mean, median and standard deviation.
+ */
+static void compute_stats(icmpstat_t *icmpstat, double *mean, double *med, double *sdev)
{
+ GSList *slist = icmpstat->rt_list;
double diff;
- double sq_diff_sum;
+ double sq_diff_sum = 0.0;
- if (num == 0)
- return 0.0;
+ if (icmpstat->num_resps == 0 || slist == NULL) {
+ *mean = 0.0;
+ *med = 0.0;
+ *sdev = 0.0;
+ return;
+ }
- for ( sq_diff_sum = 0.0; slist; slist = g_slist_next(slist)) {
- diff = *(double *)slist->data - average;
- sq_diff_sum += diff * diff;
+ /* (arithmetic) mean */
+ *mean = icmpstat->tot_msecs / icmpstat->num_resps;
+
+ /* median: If we have an odd number of elements in our list, then the
+ * median is simply the middle element, otherwise the median is computed by
+ * averaging the 2 elements on either side of the mid-point. */
+ if (icmpstat->num_resps & 1)
+ *med = *(double *)g_slist_nth_data(slist, icmpstat->num_resps / 2);
+ else {
+ *med =
+ (*(double *)g_slist_nth_data(slist, (icmpstat->num_resps - 1) / 2) +
+ *(double *)g_slist_nth_data(slist, icmpstat->num_resps / 2)) / 2;
}
- return sqrt(sq_diff_sum / num);
+ /* (sample) standard deviation */
+ for ( ; slist; slist = g_slist_next(slist)) {
+ diff = *(double *)slist->data - *mean;
+ sq_diff_sum += diff * diff;
+ }
+ if (icmpstat->num_resps > 1)
+ *sdev = sqrt(sq_diff_sum / (icmpstat->num_resps - 1));
+ else
+ *sdev = 0.0;
}
{
icmpstat_t *icmpstat = tapdata;
unsigned int lost;
- double average, sdev;
+ double mean, sdev, med;
printf("\n");
printf("==========================================================================\n");
- printf("ICMP SRT Statistics (all times in ms):\n");
- printf("Filter: %s\n", icmpstat->filter ? icmpstat->filter : "");
- printf("Requests Replies Lost %% Loss Min SRT Max SRT Avg SRT SDEV\n");
+ printf("ICMP Service Response Time (SRT) Statistics (all times in ms):\n");
+ printf("Filter: %s\n", icmpstat->filter ? icmpstat->filter : "<none>");
+ printf("\nRequests Replies Lost %% Loss\n");
if (icmpstat->num_rqsts) {
lost = icmpstat->num_rqsts - icmpstat->num_resps;
- average = icmpstat->tot_msecs / icmpstat->num_resps;
- sdev = compute_sdev(average, icmpstat->num_resps, icmpstat->rt_list);
- printf("%-10u%-10u%-10u%5.1f%% %-10.3f%-10.3f%-10.3f%-10.3f\n",
+ compute_stats(icmpstat, &mean, &med, &sdev);
+
+ printf("%-10u%-10u%-10u%5.1f%%\n\n",
icmpstat->num_rqsts, icmpstat->num_resps, lost,
- 100.0 * lost / icmpstat->num_rqsts,
+ 100.0 * lost / icmpstat->num_rqsts);
+ printf("Minimum Maximum Mean Median SDeviation Min Frame Max Frame\n");
+ printf("%-10.3f%-10.3f%-10.3f%-10.3f%-10.3f %-10u%-10u\n",
icmpstat->min_msecs >= G_MAXUINT ? 0.0 : icmpstat->min_msecs,
- icmpstat->max_msecs, average, sdev);
- } else
- printf("0 0 0 0.0%% 0.000 0.000 0.000 0.000\n");
+ icmpstat->max_msecs, mean, med, sdev,
+ icmpstat->min_frame, icmpstat->max_frame);
+ } else {
+ printf("0 0 0 0.0%%\n\n");
+ printf("Minimum Maximum Mean Median SDeviation Min Frame Max Frame\n");
+ printf("0.000 0.000 0.000 0.000 0.000 0 0\n");
+ }
printf("==========================================================================\n");
}
if (strstr(optarg, "icmp,srt,"))
filter = optarg + strlen("icmp,srt,");
- icmpstat = g_malloc0(sizeof(icmpstat_t));
- icmpstat->min_msecs = 1.0 * G_MAXUINT;
+ icmpstat = g_try_malloc(sizeof(icmpstat_t));
if (icmpstat == NULL) {
- fprintf(stderr, "tshark: g_malloc() fatal error.\n");
+ fprintf(stderr, "tshark: g_try_malloc() fatal error.\n");
exit(1);
}
+ memset(icmpstat, 0, sizeof(icmpstat_t));
+ icmpstat->min_msecs = 1.0 * G_MAXUINT;
+
if (filter)
icmpstat->filter = g_strdup(filter);