forked from osmocom/wireshark
From Florent.Drouin@alcatel.fr:
Please find two new TAP for Camel Statistics. The first one updates counters related to camel operations. It is located in the GSM submenu. The second one , named Camel Service Response Time, gives the time ellapsed between a couple of camel specifics operations. (For example InitialDP/Continue or InitialDP GPRS/Continue GPRS). With Wireshark, you can have the Min/Max/Mean delay time for your traces files, and with Tshark, you have the additional information for percentile (1%,95% 99% etc ) To enable the use of the Camel statistics, you have 2 new parameters in the preferences, - SRT, enable the service Response Time calculation. - persistentSRT, keep the data in a context, even after the camel session has been closed. This is mandatory with Wireshark, to have a clean display of the stats. Only the new files checked in for now because of include problems. svn path=/trunk/; revision=19420
This commit is contained in:
parent
8a60a1006b
commit
ad50bdf507
|
@ -0,0 +1,798 @@
|
|||
/*
|
||||
* camel-persistentdata.c
|
||||
* Source for lists and hash tables used in wireshark's camel dissector
|
||||
* for calculation of delays in camel calls
|
||||
* Copyright 2006 Florent Drouin
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <epan/emem.h>
|
||||
#include "epan/packet.h"
|
||||
#include "epan/conversation.h"
|
||||
#include "epan/camel-persistentdata.h"
|
||||
#include "epan/dissectors/packet-tcap.h"
|
||||
#include "epan/dissectors/packet-mtp3.h"
|
||||
|
||||
static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
|
||||
static guint camelsrt_call_hash(gconstpointer k);
|
||||
static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
|
||||
packet_info *pinfo);
|
||||
static struct camelsrt_call_t * new_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
|
||||
packet_info *pinfo);
|
||||
|
||||
static void update_camelsrt_call(struct camelsrt_call_t * p_camelsrt_call,
|
||||
packet_info *pinfo,
|
||||
guint msg_category _U_);
|
||||
|
||||
static struct camelsrt_call_t * append_camelsrt_call(struct camelsrt_call_t * prev_call,
|
||||
packet_info *pinfo);
|
||||
|
||||
static void camelsrt_begin_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info);
|
||||
|
||||
static void camelsrt_request_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info,
|
||||
guint srt_type);
|
||||
|
||||
static void camelsrt_report_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info,
|
||||
guint srt_type);
|
||||
|
||||
static void camelsrt_close_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info);
|
||||
|
||||
static void camelsrt_display_DeltaTime(proto_tree *tree,
|
||||
tvbuff_t *tvb,
|
||||
nstime_t* value_ptr,
|
||||
guint category);
|
||||
|
||||
static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call);
|
||||
|
||||
void camelsrt_tcap_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct tcaphash_context_t * tcap_context);
|
||||
|
||||
/* When several Camel components are received in a single TCAP message,
|
||||
we have to use several buffers for the stored parameters
|
||||
because else this data are erased during TAP dissector call */
|
||||
#define MAX_CAMEL_INSTANCE 10
|
||||
int camelsrt_global_current=0;
|
||||
struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
|
||||
|
||||
/* Configuration parameters to enable or disable the Service Response Time */
|
||||
extern gboolean gcamel_HandleSRT;
|
||||
gboolean gcamel_PersistentSRT=FALSE;
|
||||
gboolean gcamel_DisplaySRT=FALSE;
|
||||
gboolean gcamel_StatSRT=FALSE;
|
||||
|
||||
extern int camel_tap;
|
||||
|
||||
extern int hf_camelsrt_SessionId;
|
||||
extern int hf_camelsrt_RequestNumber;
|
||||
extern int hf_camelsrt_Duplicate;
|
||||
extern int hf_camelsrt_RequestFrame;
|
||||
extern int hf_camelsrt_ResponseFrame;
|
||||
extern int hf_camelsrt_DeltaTime;
|
||||
extern int hf_camelsrt_SessionTime;
|
||||
extern int hf_camelsrt_DeltaTime31;
|
||||
extern int hf_camelsrt_DeltaTime75;
|
||||
extern int hf_camelsrt_DeltaTime65;
|
||||
extern int hf_camelsrt_DeltaTime22;
|
||||
extern int hf_camelsrt_DeltaTime35;
|
||||
extern int hf_camelsrt_DeltaTime80;
|
||||
|
||||
/* Global hash tables*/
|
||||
static GHashTable *srt_calls = NULL;
|
||||
guint32 camelsrt_global_SessionId=1;
|
||||
|
||||
/*
|
||||
* DEBUG fonctions
|
||||
*/
|
||||
|
||||
#undef DEBUG_CAMELSRT
|
||||
/* #define DEBUG_CAMELSRT */
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
static unsigned debug_level = 99;
|
||||
|
||||
static void dbg(unsigned level, char* fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
if (level > debug_level) return;
|
||||
va_start(ap,fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions needed for Hash-Table
|
||||
*/
|
||||
|
||||
/* compare 2 keys */
|
||||
static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
|
||||
{
|
||||
const struct camelsrt_call_info_key_t * key1 = (const struct camelsrt_call_info_key_t *) k1;
|
||||
const struct camelsrt_call_info_key_t * key2 = (const struct camelsrt_call_info_key_t *) k2;
|
||||
|
||||
return (key1->SessionIdKey == key2->SessionIdKey) ;
|
||||
}
|
||||
|
||||
/* calculate a hash key */
|
||||
static guint camelsrt_call_hash(gconstpointer k)
|
||||
{
|
||||
const struct camelsrt_call_info_key_t * key = (const struct camelsrt_call_info_key_t *) k;
|
||||
return key->SessionIdKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the dialog by Key and Time
|
||||
*/
|
||||
static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
|
||||
packet_info *pinfo)
|
||||
{
|
||||
struct camelsrt_call_t * p_camelsrt_call = NULL;
|
||||
p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
|
||||
|
||||
if(p_camelsrt_call) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"D%d ", p_camelsrt_call->session_id);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(23,"Not in hash ");
|
||||
#endif
|
||||
}
|
||||
|
||||
return p_camelsrt_call;
|
||||
}
|
||||
|
||||
/*
|
||||
* New record to create, to identify a new transaction
|
||||
*/
|
||||
static struct camelsrt_call_t * new_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
|
||||
packet_info *pinfo)
|
||||
|
||||
{
|
||||
struct camelsrt_call_info_key_t * p_new_camelsrt_call_key;
|
||||
struct camelsrt_call_t * p_new_camelsrt_call = NULL;
|
||||
|
||||
/* Register the transaction in the hash table
|
||||
with the tcap transaction Id as main Key
|
||||
Once created, this entry will be updated later */
|
||||
|
||||
p_new_camelsrt_call_key = se_alloc(sizeof(struct camelsrt_call_info_key_t));
|
||||
p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
|
||||
p_new_camelsrt_call = se_alloc(sizeof(struct camelsrt_call_t));
|
||||
raz_camelsrt_call(p_new_camelsrt_call);
|
||||
p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"D%d ", p_new_camelsrt_call->session_id);
|
||||
#endif
|
||||
/* store it */
|
||||
g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
|
||||
return p_new_camelsrt_call;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update a record with the data of the Request
|
||||
*/
|
||||
static void update_camelsrt_call(struct camelsrt_call_t * p_camelsrt_call,
|
||||
packet_info *pinfo,
|
||||
guint msg_category _U_)
|
||||
{
|
||||
p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
|
||||
p_camelsrt_call->category[msg_category].rsp_num = 0;
|
||||
p_camelsrt_call->category[msg_category].responded = FALSE;
|
||||
p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Routine called when the TAP is initialized.
|
||||
* so hash table are (re)created
|
||||
*/
|
||||
void camelsrt_init_routine(void)
|
||||
{
|
||||
|
||||
/* free hash-tables and mem_chunks for SRT */
|
||||
if (srt_calls != NULL) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(16,"Destroy hash ");
|
||||
#endif
|
||||
g_hash_table_destroy(srt_calls);
|
||||
}
|
||||
|
||||
/* create new hash-tables and mem_chunks for SRT */
|
||||
srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(16,"Create hash ");
|
||||
#endif
|
||||
/* Reset the session counter */
|
||||
camelsrt_global_SessionId=1;
|
||||
|
||||
/* The Display of SRT is enable
|
||||
* 1) For wireshark only if Persistent Stat is enable
|
||||
* 2) For Tshark, if the SRT handling is enable
|
||||
*/
|
||||
gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Service Response Time analyze, called just after the camel dissector
|
||||
* According to the camel operation, we
|
||||
* - open/close a context for the camel session
|
||||
* - look for a request, or look for the corresponding response
|
||||
*/
|
||||
void camelsrt_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
|
||||
#endif
|
||||
|
||||
switch (p_camelsrt_info->opcode) {
|
||||
|
||||
case 0: /*InitialDP*/
|
||||
camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_INITIALDP);
|
||||
break;
|
||||
case 60: /*InitialDPSMS*/
|
||||
camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_SMS_INITIALDP);
|
||||
break;
|
||||
case 78: /*InitialDPGPRS*/
|
||||
camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_GPRS_INITIALDP);
|
||||
break;
|
||||
|
||||
case 23: /*RequestReportBCSMEvent*/
|
||||
break;
|
||||
|
||||
case 63: /*RequestReportSMSEvent*/
|
||||
break;
|
||||
|
||||
case 81: /*RequestReportGPRSEvent*/
|
||||
break;
|
||||
|
||||
case 24: /*EventReportBCSMEvent*/
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_DISC );
|
||||
break;
|
||||
|
||||
case 64: /*EventReportSMS*/
|
||||
/* Session has been explicity closed without TC_END */
|
||||
camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
tcapsrt_close(p_camelsrt_info->tcap_context, pinfo);
|
||||
break;
|
||||
|
||||
case 80: /*EventReportGPRS*/
|
||||
camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_GPRS_REPORT);
|
||||
break;
|
||||
|
||||
case 35: /*ApplyCharging*/
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_ACR1 );
|
||||
break;
|
||||
|
||||
case 71: /*ApplyChargingGPRS*/
|
||||
break;
|
||||
|
||||
case 36: /*ApplyChargingReport*/
|
||||
camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_ACR1 );
|
||||
break;
|
||||
|
||||
case 72: /*ApplyChargingReportGPRS*/
|
||||
break;
|
||||
|
||||
case 31: /*Continue*/
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_INITIALDP);
|
||||
break;
|
||||
case 65: /*ContinueSMS*/
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_SMS_INITIALDP);
|
||||
break;
|
||||
case 75: /*ContinueGPRS*/
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_GPRS_INITIALDP);
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_GPRS_REPORT);
|
||||
break;
|
||||
|
||||
case 22: /*ReleaseCall*/
|
||||
camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
|
||||
CAMELSRT_VOICE_DISC);
|
||||
/* Session has been closed by Network */
|
||||
camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
break;
|
||||
|
||||
case 66: /*ReleaseSMS*/
|
||||
/* Session has been closed by Network */
|
||||
camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
tcapsrt_close(p_camelsrt_info->tcap_context,pinfo);
|
||||
break;
|
||||
|
||||
case 79: /*ReleaseGPRS*/
|
||||
/* Session has been closed by Network */
|
||||
camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
break;
|
||||
} /* switch opcode */
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback function for the TCAP dissector
|
||||
* This callback function is used to inform the camel layer, that the session
|
||||
* has been Closed or Aborted by a TCAP message without Camel component
|
||||
* So, we can close the context for camel session, and update the stats.
|
||||
*/
|
||||
void camelsrt_tcap_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct tcaphash_context_t * p_tcap_context)
|
||||
{
|
||||
struct camelsrt_info_t * p_camelsrt_info;
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Camel_CallBack ");
|
||||
#endif
|
||||
p_camelsrt_info=camelsrt_razinfo();
|
||||
|
||||
p_camelsrt_info->tcap_context=p_tcap_context;
|
||||
if (p_tcap_context) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Close TCAP ");
|
||||
#endif
|
||||
p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
|
||||
camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
|
||||
tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create the record identifiying the Camel session
|
||||
* As the Tcap session id given by the TCAP dissector is uniq, it will be
|
||||
* used as main key.
|
||||
*/
|
||||
static void camelsrt_begin_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info)
|
||||
{
|
||||
struct camelsrt_call_t * p_camelsrt_call;
|
||||
struct camelsrt_call_info_key_t camelsrt_call_key;
|
||||
|
||||
p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
|
||||
|
||||
/* prepare the key data */
|
||||
camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
|
||||
|
||||
/* look up the request */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"\n Session begin #%d\n", pinfo->fd->num);
|
||||
dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
|
||||
#endif
|
||||
p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
|
||||
if (p_camelsrt_call) {
|
||||
/* We have seen this request before -> do nothing */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(22,"Already seen ");
|
||||
#endif
|
||||
} else { /* p_camelsrt_call has not been found */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
|
||||
#endif
|
||||
p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key, pinfo);
|
||||
p_camelsrt_call->tcap_context=p_camelsrt_info->tcap_context;
|
||||
update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Update Callback ");
|
||||
#endif
|
||||
p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the request, and try to find the response
|
||||
*
|
||||
*/
|
||||
static void camelsrt_request_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info,
|
||||
guint srt_type )
|
||||
{
|
||||
struct camelsrt_call_t * p_camelsrt_call;
|
||||
struct camelsrt_call_info_key_t camelsrt_call_key;
|
||||
proto_item *ti;
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
|
||||
#endif
|
||||
|
||||
/* look only for matching request, if matching conversation is available. */
|
||||
camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
|
||||
#endif
|
||||
p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
|
||||
if(p_camelsrt_call) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(12,"Found ");
|
||||
#endif
|
||||
if (gcamel_DisplaySRT)
|
||||
proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
|
||||
|
||||
|
||||
/* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
|
||||
* we will prepare the measurement for 3 slices with 3 categories */
|
||||
if (srt_type==CAMELSRT_VOICE_ACR1) {
|
||||
if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
|
||||
srt_type=CAMELSRT_VOICE_ACR1;
|
||||
} else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
|
||||
&& (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
|
||||
&& (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
|
||||
srt_type=CAMELSRT_VOICE_ACR2;
|
||||
} else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
|
||||
&& (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
|
||||
&& (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
|
||||
srt_type=CAMELSRT_VOICE_ACR3;
|
||||
} else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR1;
|
||||
} else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR2;
|
||||
} else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR3;
|
||||
}
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(70,"Request ACR %u ",srt_type);
|
||||
dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
|
||||
dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
|
||||
dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
|
||||
#endif
|
||||
} /* not ACR */
|
||||
p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
|
||||
|
||||
|
||||
if (p_camelsrt_call->category[srt_type].req_num == 0) {
|
||||
/* We have not yet seen a request to that call, so this must be the first request
|
||||
remember its frame number. */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(5,"Set reqlink #%d ", pinfo->fd->num);
|
||||
#endif
|
||||
update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
|
||||
} else {
|
||||
/* We have seen a request to this call - but was it *this* request? */
|
||||
if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
|
||||
|
||||
if (srt_type!=CAMELSRT_VOICE_DISC) {
|
||||
/* No, so it's a duplicate resquest. Mark it as such. */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
|
||||
#endif
|
||||
p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
|
||||
if (gcamel_DisplaySRT)
|
||||
proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
|
||||
|
||||
} else {
|
||||
/* Ignore duplicate frame */
|
||||
if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
|
||||
p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(5,"DISC Set reqlink #%d ", pinfo->fd->num);
|
||||
#endif
|
||||
update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
|
||||
} /* greater frame */
|
||||
} /* DISC */
|
||||
} /* req_num already seen */
|
||||
} /* req_num != 0 */
|
||||
|
||||
/* add link to response frame, if available */
|
||||
if ( gcamel_DisplaySRT &&
|
||||
(p_camelsrt_call->category[srt_type].rsp_num != 0) &&
|
||||
(p_camelsrt_call->category[srt_type].req_num != 0) &&
|
||||
(p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
|
||||
#endif
|
||||
ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
|
||||
p_camelsrt_call->category[srt_type].rsp_num,
|
||||
"Linked response %s in frame %u",
|
||||
val_to_str(srt_type, camelSRTtype_naming, "Unk"),
|
||||
p_camelsrt_call->category[srt_type].rsp_num);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
} /* frame valid */
|
||||
}/* call reference */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if the received message is a response to a previous request
|
||||
* registered is the camel session context.
|
||||
*/
|
||||
static void camelsrt_report_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info,
|
||||
guint srt_type )
|
||||
{
|
||||
struct camelsrt_call_t * p_camelsrt_call;
|
||||
struct camelsrt_call_info_key_t camelsrt_call_key;
|
||||
nstime_t delta;
|
||||
proto_item *ti;
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
|
||||
#endif
|
||||
camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
|
||||
/* look only for matching request, if matching conversation is available. */
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
|
||||
#endif
|
||||
p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
|
||||
if(p_camelsrt_call) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
|
||||
#endif
|
||||
if ( gcamel_DisplaySRT )
|
||||
proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
|
||||
|
||||
if (srt_type==CAMELSRT_VOICE_ACR1) {
|
||||
if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR1;
|
||||
} else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR2;
|
||||
} else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
|
||||
&& p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
|
||||
srt_type=CAMELSRT_VOICE_ACR1;
|
||||
}
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(70,"Report ACR %u ",srt_type);
|
||||
#endif
|
||||
} /* not ACR */
|
||||
p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
|
||||
|
||||
if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
|
||||
if ( (p_camelsrt_call->category[srt_type].req_num != 0)
|
||||
&& (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
|
||||
/* We have not yet seen a response to that call, so this must be the first response;
|
||||
remember its frame number only if response comes after request */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(14,"Set reslink #%d req %d ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
|
||||
#endif
|
||||
p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
|
||||
|
||||
} else {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(2,"badreslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
|
||||
#endif
|
||||
} /* req_num != 0 */
|
||||
} else { /* rsp_num != 0 */
|
||||
/* We have seen a response to this call - but was it *this* response? */
|
||||
if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
|
||||
/* No, so it's a duplicate response. Mark it as such. */
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
|
||||
#endif
|
||||
p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
|
||||
if ( gcamel_DisplaySRT )
|
||||
proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
|
||||
}
|
||||
} /* rsp_num != 0 */
|
||||
|
||||
if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
|
||||
(p_camelsrt_call->category[srt_type].rsp_num != 0) &&
|
||||
(p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
|
||||
|
||||
p_camelsrt_call->category[srt_type].responded = TRUE;
|
||||
p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
|
||||
#endif
|
||||
/* Indicate the frame to which this is a reply. */
|
||||
if ( gcamel_DisplaySRT ) {
|
||||
ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
|
||||
p_camelsrt_call->category[srt_type].req_num,
|
||||
"Linked request %s in frame %u",
|
||||
val_to_str(srt_type, camelSRTtype_naming, "Unk"),
|
||||
p_camelsrt_call->category[srt_type].req_num);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
}
|
||||
/* Calculate Service Response Time */
|
||||
nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
|
||||
|
||||
p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
|
||||
p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
|
||||
p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
|
||||
|
||||
/* display Service Response Time and make it filterable */
|
||||
camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
|
||||
|
||||
} /*req_num != 0 && not duplicate */
|
||||
} /* call reference found */
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the Camel session info, and close the session.
|
||||
* Then remove the associated context, if we do not have persistentSRT enable
|
||||
*/
|
||||
static void camelsrt_close_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camelsrt_info)
|
||||
{
|
||||
struct camelsrt_call_t * p_camelsrt_call;
|
||||
struct camelsrt_call_info_key_t camelsrt_call_key;
|
||||
nstime_t delta;
|
||||
|
||||
p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(10,"\n Session end #%d\n", pinfo->fd->num);
|
||||
#endif
|
||||
/* look only for matching request, if matching conversation is available. */
|
||||
camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
|
||||
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
|
||||
#endif
|
||||
p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
|
||||
if(p_camelsrt_call) {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(12,"Found ");
|
||||
#endif
|
||||
/* Calculate Service Response Time */
|
||||
nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
|
||||
p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
|
||||
p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
|
||||
p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
|
||||
p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
|
||||
p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
|
||||
|
||||
if ( !gcamel_PersistentSRT ) {
|
||||
g_hash_table_remove(srt_calls, &camelsrt_call_key);
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(20,"remove hash ");
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG_CAMELSRT
|
||||
dbg(20,"keep hash ");
|
||||
#endif
|
||||
}
|
||||
} /* call reference found */
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the delta time between two messages in a field corresponding
|
||||
* to the category (hf_camelsrt_DeltaTimexx).
|
||||
*/
|
||||
static void camelsrt_display_DeltaTime(proto_tree *tree,
|
||||
tvbuff_t *tvb,
|
||||
nstime_t* value_ptr,
|
||||
guint category)
|
||||
{
|
||||
proto_item *ti;
|
||||
|
||||
if ( gcamel_DisplaySRT ) {
|
||||
switch(category) {
|
||||
case CAMELSRT_VOICE_INITIALDP:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
case CAMELSRT_VOICE_ACR1:
|
||||
case CAMELSRT_VOICE_ACR2:
|
||||
case CAMELSRT_VOICE_ACR3:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
case CAMELSRT_VOICE_DISC:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
case CAMELSRT_GPRS_INITIALDP:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
case CAMELSRT_GPRS_REPORT:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
case CAMELSRT_SMS_INITIALDP:
|
||||
ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Message Info used by the main dissector
|
||||
* Data are linked to a TCAP transaction
|
||||
*/
|
||||
struct camelsrt_info_t * camelsrt_razinfo(void)
|
||||
{
|
||||
struct camelsrt_info_t * p_camelsrt_info ;
|
||||
|
||||
/* Global buffer for packet extraction */
|
||||
camelsrt_global_current++;
|
||||
if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
|
||||
camelsrt_global_current=0;
|
||||
}
|
||||
|
||||
p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
|
||||
memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
|
||||
|
||||
p_camelsrt_info->opcode=255;
|
||||
|
||||
return p_camelsrt_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the data per call for the Service Response Time Statistics
|
||||
* Data are linked to a Camel operation in a TCAP transaction
|
||||
*/
|
||||
static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call)
|
||||
{
|
||||
memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* camel-persistentdata.h
|
||||
* Definitions for lists and hash tables used in wireshark's camel dissector
|
||||
* for calculation of delays in camel-transactions
|
||||
* Copyright 2006 Florent Drouin
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __camelsrt_HASH__
|
||||
#define __camelsrt_HASH__
|
||||
|
||||
#include "epan/packet.h"
|
||||
#include "epan/conversation.h"
|
||||
#include "epan/dissectors/packet-camel.h"
|
||||
#include "epan/tcap-persistentdata.h"
|
||||
|
||||
#define NB_CAMELSRT_CATEGORY 9+1 /* Number of type of message */
|
||||
/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
|
||||
is a category, we want to measure the delay between the two messages */
|
||||
|
||||
#define CAMELSRT_SESSION 1
|
||||
|
||||
#define CAMELSRT_VOICE_INITIALDP 2
|
||||
#define CAMELSRT_VOICE_ACR1 3
|
||||
#define CAMELSRT_VOICE_ACR2 4
|
||||
#define CAMELSRT_VOICE_ACR3 5
|
||||
#define CAMELSRT_VOICE_DISC 6
|
||||
|
||||
#define CAMELSRT_GPRS_INITIALDP 7
|
||||
#define CAMELSRT_GPRS_REPORT 8
|
||||
|
||||
#define CAMELSRT_SMS_INITIALDP 9
|
||||
|
||||
static const value_string camelSRTtype_naming[]= {
|
||||
{ CAMELSRT_SESSION, "TCAP_Session" },
|
||||
{ CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
|
||||
{ CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
|
||||
{ CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
|
||||
{ CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
|
||||
{ CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
|
||||
{ CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
|
||||
{ CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
|
||||
{ CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
|
||||
{ 0,NULL}
|
||||
};
|
||||
|
||||
/* If we have a request message and its response,
|
||||
(eg: ApplyCharging, ApplyChargingReport)
|
||||
the frames numbers are stored in this structure */
|
||||
|
||||
struct camelsrt_category_t {
|
||||
guint32 req_num; /* frame number request seen */
|
||||
guint32 rsp_num; /* frame number response seen */
|
||||
nstime_t req_time; /* arrival time of request */
|
||||
gboolean responded; /* true, if request has been responded */
|
||||
};
|
||||
|
||||
/* List of stored parameters for a Camel dialogue
|
||||
All this parameters are linked to the hash table key below (use of Tid)
|
||||
In case of same Tid reused, the Camel parameters are chained.
|
||||
The right dialogue will be identified with the arrival time of the InitialDP */
|
||||
|
||||
struct camelsrt_call_t {
|
||||
guint32 session_id; /* Identify the session, with an internal number */
|
||||
struct tcaphash_context_t * tcap_context;
|
||||
struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
|
||||
};
|
||||
|
||||
|
||||
/* The Key for the hash table is the TCAP origine transaction identifier
|
||||
of the TC_BEGIN containing the InitialDP */
|
||||
|
||||
struct camelsrt_call_info_key_t {
|
||||
guint32 SessionIdKey;
|
||||
};
|
||||
|
||||
/* Info for a couple of messages (or category)
|
||||
The request must be available, not duplicated,
|
||||
and once the corresponding response received,
|
||||
we can deduce the Delta Time between Request/response */
|
||||
|
||||
struct camelsrt_msginfo_t {
|
||||
gboolean request_available;
|
||||
gboolean is_duplicate;
|
||||
gboolean is_delta_time;
|
||||
nstime_t req_time;
|
||||
nstime_t delta_time;
|
||||
};
|
||||
|
||||
/* List of infos to store for the analyse */
|
||||
|
||||
struct camelsrt_info_t {
|
||||
guint32 tcap_session_id;
|
||||
void * tcap_context;
|
||||
guint8 opcode; /* operation code of message received */
|
||||
guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /* category for the received message */
|
||||
struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
|
||||
};
|
||||
|
||||
void camelsrt_init_routine(void);
|
||||
|
||||
struct camelsrt_info_t * camelsrt_razinfo(void);
|
||||
|
||||
void camelsrt_call_matching(tvbuff_t *tvb,
|
||||
packet_info * pinfo _U_,
|
||||
proto_tree *tree,
|
||||
struct camelsrt_info_t * p_camel_info);
|
||||
|
||||
#endif /* __camelsrt_HASH__*/
|
|
@ -0,0 +1,233 @@
|
|||
/* camel_counter.c
|
||||
* camel message counter for Wireshark
|
||||
* Copyright 2006 Florent Drouin (based on h225_counter.c from Lars Roland)
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "epan/packet_info.h"
|
||||
#include "epan/epan.h"
|
||||
#include "epan/value_string.h"
|
||||
#include "epan/tap.h"
|
||||
|
||||
#include "register.h"
|
||||
#include "timestats.h"
|
||||
#include "simple_dialog.h"
|
||||
#include "file.h"
|
||||
#include "globals.h"
|
||||
#include "stat_menu.h"
|
||||
#include "tap_dfilter_dlg.h"
|
||||
|
||||
#include "gtk/main.h"
|
||||
#include "gtk/dlg_utils.h"
|
||||
#include "gtk/gui_utils.h"
|
||||
#include "gtk/gui_stat_util.h"
|
||||
#include "gtk/compat_macros.h"
|
||||
#include "epan/camel-persistentdata.h"
|
||||
|
||||
static void gtk_camelcounter_reset(void *phs);
|
||||
static int gtk_camelcounter_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi);
|
||||
static void gtk_camelcounter_draw(void *phs);
|
||||
static void win_destroy_cb(GtkWindow *win _U_, gpointer data);
|
||||
static void gtk_camelcounter_init(const char *optarg, void *userdata _U_);
|
||||
void register_tap_listener_gtk_camelcounter(void);
|
||||
|
||||
/* following values represent the size of their valuestring arrays */
|
||||
|
||||
struct camelcounter_t {
|
||||
GtkWidget *win;
|
||||
GtkWidget *vbox;
|
||||
char *filter;
|
||||
GtkWidget *scrolled_window;
|
||||
GtkCList *table;
|
||||
guint32 camel_msg[camel_MAX_NUM_OPR_CODES];
|
||||
};
|
||||
|
||||
static void gtk_camelcounter_reset(void *phs)
|
||||
{
|
||||
struct camelcounter_t * p_counter= ( struct camelcounter_t *) phs;
|
||||
int i;
|
||||
|
||||
/* Erase Message Type count */
|
||||
for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
|
||||
p_counter->camel_msg[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If there is a valid camel operation, increase the value in the array of counter
|
||||
*/
|
||||
static int gtk_camelcounter_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi)
|
||||
{
|
||||
struct camelcounter_t * p_counter =(struct camelcounter_t *)phs;
|
||||
const struct camelsrt_info_t * pi=phi;
|
||||
if (pi->opcode != 255)
|
||||
p_counter->camel_msg[pi->opcode]++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void gtk_camelcounter_draw(void *phs)
|
||||
{
|
||||
struct camelcounter_t *p_counter=(struct camelcounter_t *)phs;
|
||||
int i;
|
||||
char *str[2];
|
||||
|
||||
for(i=0;i<2;i++) {
|
||||
str[i]=g_malloc(sizeof(char[256]));
|
||||
}
|
||||
/* Now print Message and Reason Counter Table */
|
||||
/* clear list before printing */
|
||||
gtk_clist_clear(p_counter->table);
|
||||
|
||||
for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
|
||||
/* Message counter */
|
||||
if(p_counter->camel_msg[i]!=0) {
|
||||
g_snprintf(str[0], sizeof(char[256]),
|
||||
"Request %s", val_to_str(i,camel_opr_code_strings,"Unknown message "));
|
||||
g_snprintf(str[1], sizeof(char[256]),
|
||||
"%d", p_counter->camel_msg[i]);
|
||||
gtk_clist_append(p_counter->table, str);
|
||||
}
|
||||
} /* Message Type */
|
||||
gtk_widget_show(GTK_WIDGET(p_counter->table));
|
||||
}
|
||||
|
||||
void protect_thread_critical_region(void);
|
||||
void unprotect_thread_critical_region(void);
|
||||
|
||||
static void win_destroy_cb(GtkWindow *win _U_, gpointer data)
|
||||
{
|
||||
struct camelcounter_t *hs=(struct camelcounter_t *)data;
|
||||
|
||||
protect_thread_critical_region();
|
||||
remove_tap_listener(hs);
|
||||
unprotect_thread_critical_region();
|
||||
|
||||
if(hs->filter){
|
||||
g_free(hs->filter);
|
||||
hs->filter=NULL;
|
||||
}
|
||||
g_free(hs);
|
||||
}
|
||||
|
||||
static const gchar *titles[]={
|
||||
"Message Type or Reason",
|
||||
"Count" };
|
||||
|
||||
static void gtk_camelcounter_init(const char *optarg, void *userdata _U_)
|
||||
{
|
||||
struct camelcounter_t *p_camelcounter;
|
||||
const char *filter=NULL;
|
||||
const char *emptyfilter="";
|
||||
GString *error_string;
|
||||
GtkWidget *bbox;
|
||||
GtkWidget *close_bt;
|
||||
|
||||
if(strncmp(optarg,"camel,counter,",14) == 0){
|
||||
filter=optarg+14;
|
||||
} else {
|
||||
filter=NULL;
|
||||
}
|
||||
|
||||
p_camelcounter=g_malloc(sizeof(struct camelcounter_t));
|
||||
p_camelcounter->filter=g_strdup(filter);
|
||||
|
||||
gtk_camelcounter_reset(p_camelcounter);
|
||||
|
||||
p_camelcounter->win=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: CAMEL counters");
|
||||
gtk_window_set_default_size(GTK_WINDOW(p_camelcounter->win), 500, 300);
|
||||
|
||||
p_camelcounter->vbox=gtk_vbox_new(FALSE, 3);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(p_camelcounter->vbox), 12);
|
||||
|
||||
init_main_stat_window(p_camelcounter->win, p_camelcounter->vbox, "CAMEL Messages Counters", filter);
|
||||
|
||||
/* init a scrolled window*/
|
||||
p_camelcounter->scrolled_window = scrolled_window_new(NULL, NULL);
|
||||
|
||||
p_camelcounter->table = create_stat_table(p_camelcounter->scrolled_window, p_camelcounter->vbox, 2, titles);
|
||||
|
||||
if (filter) {
|
||||
error_string=register_tap_listener("CAMEL", p_camelcounter, filter,
|
||||
gtk_camelcounter_reset,
|
||||
gtk_camelcounter_packet,
|
||||
gtk_camelcounter_draw);
|
||||
} else {
|
||||
error_string=register_tap_listener("CAMEL", p_camelcounter, emptyfilter,
|
||||
gtk_camelcounter_reset,
|
||||
gtk_camelcounter_packet,
|
||||
gtk_camelcounter_draw);
|
||||
}
|
||||
|
||||
if(error_string){
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
|
||||
g_string_free(error_string, TRUE);
|
||||
g_free(p_camelcounter);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Button row. */
|
||||
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
|
||||
gtk_box_pack_end(GTK_BOX(p_camelcounter->vbox), bbox, FALSE, FALSE, 0);
|
||||
|
||||
close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
|
||||
window_set_cancel_button(p_camelcounter->win, close_bt, window_cancel_button_cb);
|
||||
|
||||
SIGNAL_CONNECT(p_camelcounter->win, "delete_event", window_delete_event_cb, NULL);
|
||||
SIGNAL_CONNECT(p_camelcounter->win, "destroy", win_destroy_cb, p_camelcounter);
|
||||
|
||||
gtk_widget_show_all(p_camelcounter->win);
|
||||
window_present(p_camelcounter->win);
|
||||
|
||||
cf_retap_packets(&cfile, FALSE);
|
||||
}
|
||||
|
||||
static tap_dfilter_dlg camel_counter_dlg = {
|
||||
"CAMEL Messages and Response Status",
|
||||
"camel,counter",
|
||||
gtk_camelcounter_init,
|
||||
-1
|
||||
};
|
||||
|
||||
void /* Next line mandatory */
|
||||
register_tap_listener_gtk_camelcounter(void)
|
||||
{
|
||||
register_dfilter_stat(&camel_counter_dlg, "GSM/CAMEL",
|
||||
REGISTER_STAT_GROUP_TELEPHONY);
|
||||
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/* camel_srt.c
|
||||
* camel Service Response Time statistics for Wireshark
|
||||
* Copyright 2006 Florent Drouin (based on h225_ras_srt.c from Lars Roland)
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "epan/packet_info.h"
|
||||
#include "epan/epan.h"
|
||||
#include "epan/value_string.h"
|
||||
#include "epan/tap.h"
|
||||
|
||||
#include "register.h"
|
||||
#include "timestats.h"
|
||||
#include "simple_dialog.h"
|
||||
#include "file.h"
|
||||
#include "globals.h"
|
||||
#include "stat_menu.h"
|
||||
#include "tap_dfilter_dlg.h"
|
||||
|
||||
#include "gtk/main.h"
|
||||
#include "gtk/dlg_utils.h"
|
||||
#include "gtk/gui_utils.h"
|
||||
#include "gtk/gui_stat_util.h"
|
||||
#include "gtk/compat_macros.h"
|
||||
#include "gtk/service_response_time_table.h"
|
||||
|
||||
#include "epan/camel-persistentdata.h"
|
||||
|
||||
/* used to keep track of the statistics for an entire program interface */
|
||||
struct camelsrt_t {
|
||||
GtkWidget *win;
|
||||
srt_stat_table camel_srt_table;
|
||||
};
|
||||
|
||||
static void camelsrt_set_title(struct camelsrt_t * p_camelsrt);
|
||||
static void camelsrt_reset(void *phs);
|
||||
static int camelsrt_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi);
|
||||
|
||||
static void camelsrt_draw(void *phs);
|
||||
static void win_destroy_cb(GtkWindow *win _U_, gpointer data);
|
||||
static void gtk_camelsrt_init(const char *optarg, void *userdata _U_);
|
||||
void register_tap_listener_gtk_camelsrt(void);
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void camelsrt_set_title(struct camelsrt_t * p_camelsrt)
|
||||
{
|
||||
char * title;
|
||||
title = g_strdup_printf("CAMEL Service Response Time statistics: %s",
|
||||
cf_get_display_name(&cfile));
|
||||
gtk_window_set_title(GTK_WINDOW(p_camelsrt->win), title);
|
||||
g_free(title);
|
||||
}
|
||||
|
||||
static void camelsrt_reset(void *phs)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
reset_srt_table_data(&hs->camel_srt_table);
|
||||
camelsrt_set_title(hs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the delta time between Request and Response
|
||||
* As we can make several measurement per message, we use a boolean array for the category
|
||||
* Then, if the measurement is provided, check if it is valid, and update the table
|
||||
*/
|
||||
static int camelsrt_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
const struct camelsrt_info_t * pi=phi;
|
||||
int i;
|
||||
|
||||
for (i=1; i<NB_CAMELSRT_CATEGORY; i++) {
|
||||
if ( pi->bool_msginfo[i] &&
|
||||
pi->msginfo[i].is_delta_time
|
||||
&& pi->msginfo[i].request_available
|
||||
&& !pi->msginfo[i].is_duplicate ) {
|
||||
|
||||
add_srt_table_data(&hs->camel_srt_table, i, &pi->msginfo[i].req_time, pinfo);
|
||||
|
||||
}
|
||||
} /* category */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void camelsrt_draw(void *phs)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
draw_srt_table_data(&hs->camel_srt_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine for Display
|
||||
*/
|
||||
static void win_destroy_cb(GtkWindow *win _U_, gpointer data)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)data;
|
||||
|
||||
protect_thread_critical_region();
|
||||
remove_tap_listener(hs);
|
||||
unprotect_thread_critical_region();
|
||||
|
||||
free_srt_table_data(&hs->camel_srt_table);
|
||||
g_free(hs);
|
||||
}
|
||||
|
||||
static void gtk_camelsrt_init(const char *optarg, void *userdata _U_)
|
||||
{
|
||||
struct camelsrt_t * p_camelsrt;
|
||||
const char *filter=NULL;
|
||||
const char *emptyfilter="";
|
||||
|
||||
GtkWidget *cmd_label;
|
||||
GtkWidget *main_label;
|
||||
GtkWidget *filter_label;
|
||||
char filter_string[256];
|
||||
GString *error_string;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *bbox;
|
||||
GtkWidget *close_bt;
|
||||
int i;
|
||||
|
||||
if(strncmp(optarg,"camel,srt,",10) == 0){
|
||||
filter=optarg+10;
|
||||
} else {
|
||||
filter=NULL;
|
||||
}
|
||||
|
||||
p_camelsrt=g_malloc(sizeof(struct camelsrt_t));
|
||||
|
||||
p_camelsrt->win=window_new(GTK_WINDOW_TOPLEVEL, "camel-srt");
|
||||
gtk_window_set_default_size(GTK_WINDOW(p_camelsrt->win), 550, 400);
|
||||
camelsrt_set_title(p_camelsrt);
|
||||
|
||||
vbox=gtk_vbox_new(FALSE, 3);
|
||||
gtk_container_add(GTK_CONTAINER(p_camelsrt->win), vbox);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
|
||||
|
||||
main_label=gtk_label_new("CAMEL Service Response Time statistics");
|
||||
gtk_box_pack_start(GTK_BOX(vbox), main_label, FALSE, FALSE, 0);
|
||||
gtk_widget_show(main_label);
|
||||
|
||||
g_snprintf(filter_string,255,"Filter:%s",filter?filter:"");
|
||||
filter_label=gtk_label_new(filter_string);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
|
||||
gtk_widget_show(filter_label);
|
||||
|
||||
cmd_label=gtk_label_new("CAMEL Commands");
|
||||
gtk_box_pack_start(GTK_BOX(vbox), cmd_label, FALSE, FALSE, 0);
|
||||
gtk_widget_show(cmd_label);
|
||||
|
||||
/* We must display TOP LEVEL Widget before calling init_srt_table() */
|
||||
gtk_widget_show_all(p_camelsrt->win);
|
||||
|
||||
init_srt_table(&p_camelsrt->camel_srt_table, NB_CAMELSRT_CATEGORY, vbox, NULL);
|
||||
for(i=0 ;i<NB_CAMELSRT_CATEGORY; i++) {
|
||||
init_srt_table_row(&p_camelsrt->camel_srt_table, i,
|
||||
val_to_str(i,camelSRTtype_naming,"Unknown"));
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelsrt,
|
||||
filter,
|
||||
camelsrt_reset,
|
||||
camelsrt_packet,
|
||||
camelsrt_draw);
|
||||
} else {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelsrt,
|
||||
emptyfilter,
|
||||
camelsrt_reset,
|
||||
camelsrt_packet,
|
||||
camelsrt_draw);
|
||||
}
|
||||
|
||||
if(error_string){
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
|
||||
g_string_free(error_string, TRUE);
|
||||
g_free(p_camelsrt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Button row. */
|
||||
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
|
||||
gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
|
||||
|
||||
close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
|
||||
window_set_cancel_button(p_camelsrt->win, close_bt, window_cancel_button_cb);
|
||||
|
||||
SIGNAL_CONNECT(p_camelsrt->win, "delete_event", window_delete_event_cb, NULL);
|
||||
SIGNAL_CONNECT(p_camelsrt->win, "destroy", win_destroy_cb, p_camelsrt);
|
||||
|
||||
gtk_widget_show_all(p_camelsrt->win);
|
||||
window_present(p_camelsrt->win);
|
||||
cf_retap_packets(&cfile, FALSE);
|
||||
|
||||
}
|
||||
|
||||
static tap_dfilter_dlg camel_srt_dlg = {
|
||||
"CAMEL Service Response Time",
|
||||
"camel,srt",
|
||||
gtk_camelsrt_init,
|
||||
-1
|
||||
};
|
||||
|
||||
void /* Next line mandatory */
|
||||
register_tap_listener_gtk_camelsrt(void)
|
||||
{
|
||||
register_dfilter_stat(&camel_srt_dlg, "CAMEL",
|
||||
REGISTER_STAT_GROUP_RESPONSE_TIME);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* tap_camelcounter.c
|
||||
* camel message counter for tshark
|
||||
* Copyright 2006 Florent DROUIN
|
||||
* This part of code is extracted from tap-h225counter.c from Lars Roland
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "epan/packet_info.h"
|
||||
#include "epan/tap.h"
|
||||
#include "epan/value_string.h"
|
||||
#include "register.h"
|
||||
#include "epan/stat_cmd_args.h"
|
||||
#include "epan/camel-persistentdata.h"
|
||||
|
||||
void register_tap_listener_camelcounter(void);
|
||||
|
||||
/* used to keep track of the statistics for an entire program interface */
|
||||
struct camelcounter_t {
|
||||
char *filter;
|
||||
guint32 camel_msg[camel_MAX_NUM_OPR_CODES];
|
||||
};
|
||||
|
||||
|
||||
static void camelcounter_reset(void *phs)
|
||||
{
|
||||
struct camelcounter_t * p_counter= ( struct camelcounter_t *) phs;
|
||||
memset(p_counter,0,sizeof(struct camelcounter_t));
|
||||
}
|
||||
|
||||
static int camelcounter_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi)
|
||||
{
|
||||
struct camelcounter_t * p_counter =(struct camelcounter_t *)phs;
|
||||
const struct camelsrt_info_t * pi=phi;
|
||||
if (pi->opcode != 255)
|
||||
p_counter->camel_msg[pi->opcode]++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void camelcounter_draw(void *phs)
|
||||
{
|
||||
struct camelcounter_t * p_counter= (struct camelcounter_t *)phs;
|
||||
int i;
|
||||
printf("\n");
|
||||
printf("CAMEL Message and Response Status Counter:\n");
|
||||
printf("------------------------------------------\n");
|
||||
|
||||
for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
|
||||
/* Message counter */
|
||||
if(p_counter->camel_msg[i]!=0) {
|
||||
printf("%30s ", val_to_str(i,camel_opr_code_strings,"Unknown message "));
|
||||
printf("%6d\n", p_counter->camel_msg[i]);
|
||||
}
|
||||
} /* Message Type */
|
||||
printf("------------------------------------------\n");
|
||||
}
|
||||
|
||||
static void camelcounter_init(const char *optarg, void* userdata _U_)
|
||||
{
|
||||
struct camelcounter_t *p_camelcounter;
|
||||
const char *filter=NULL;
|
||||
const char *emptyfilter="";
|
||||
GString *error_string;
|
||||
|
||||
if(!strncmp(optarg,"camel,counter,",13)){
|
||||
filter=optarg+13;
|
||||
} else {
|
||||
filter=NULL;
|
||||
}
|
||||
|
||||
p_camelcounter = g_malloc(sizeof(struct camelcounter_t));
|
||||
if(filter){
|
||||
p_camelcounter->filter=g_malloc(strlen(filter)+1);
|
||||
strcpy(p_camelcounter->filter,filter);
|
||||
} else {
|
||||
p_camelcounter->filter=NULL;
|
||||
}
|
||||
|
||||
camelcounter_reset(p_camelcounter);
|
||||
|
||||
if (filter) {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelcounter,
|
||||
filter,
|
||||
NULL,
|
||||
camelcounter_packet,
|
||||
camelcounter_draw);
|
||||
} else {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelcounter,
|
||||
emptyfilter,
|
||||
NULL,
|
||||
camelcounter_packet,
|
||||
camelcounter_draw);
|
||||
}
|
||||
|
||||
if(error_string){
|
||||
/* error, we failed to attach to the tap. clean up */
|
||||
g_free(p_camelcounter->filter);
|
||||
g_free(p_camelcounter);
|
||||
|
||||
fprintf(stderr, "tshark: Couldn't register camel,counter tap: %s\n",
|
||||
error_string->str);
|
||||
g_string_free(error_string, TRUE);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void /* Next line mandatory */
|
||||
register_tap_listener_camelcounter(void)
|
||||
{
|
||||
register_stat_cmd_arg("camel,counter", camelcounter_init, NULL);
|
||||
}
|
|
@ -0,0 +1,276 @@
|
|||
/* tap_camelsrt.c
|
||||
* CAMEL Service Response Time statistics for tshark
|
||||
* Copyright 2006 Florent Drouin (based on tap_h225rassrt.c from Lars Roland)
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "epan/packet_info.h"
|
||||
#include <epan/tap.h>
|
||||
#include "epan/value_string.h"
|
||||
#include "register.h"
|
||||
#include "epan/dissectors/packet-camel.h"
|
||||
#include "epan/camel-persistentdata.h"
|
||||
#include "timestats.h"
|
||||
#include "epan/stat_cmd_args.h"
|
||||
|
||||
#undef MIN
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
void register_tap_listener_camelsrt(void);
|
||||
|
||||
/* Save the the first NUM_RAS_STATS stats in the array to calculate percentile */
|
||||
#define NUM_RAS_STATS 500000
|
||||
|
||||
/* Number of couple message Request/Response to analyze*/
|
||||
#define NB_CRITERIA 7
|
||||
|
||||
/* used to keep track of the statistics for an entire program interface */
|
||||
struct camelsrt_t {
|
||||
char *filter;
|
||||
guint32 count[NB_CAMELSRT_CATEGORY];
|
||||
timestat_t stats[NB_CAMELSRT_CATEGORY];
|
||||
nstime_t delta_time[NB_CAMELSRT_CATEGORY][NUM_RAS_STATS];
|
||||
};
|
||||
|
||||
/* Check if we have to inhibit the display or not */
|
||||
extern gboolean gcamel_StatSRT;
|
||||
extern gboolean gtcap_StatSRT;
|
||||
|
||||
/* Reset the counter */
|
||||
static void camelsrt_reset(void *phs)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
memset(hs,0,sizeof(struct camelsrt_t));
|
||||
}
|
||||
|
||||
|
||||
static int camelsrt_packet(void *phs,
|
||||
packet_info *pinfo _U_,
|
||||
epan_dissect_t *edt _U_,
|
||||
const void *phi)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
const struct camelsrt_info_t * pi=phi;
|
||||
int i;
|
||||
|
||||
for (i=0; i<NB_CAMELSRT_CATEGORY; i++) {
|
||||
if (pi->bool_msginfo[i] &&
|
||||
pi->msginfo[i].is_delta_time
|
||||
&& pi->msginfo[i].request_available
|
||||
&& !pi->msginfo[i].is_duplicate ) {
|
||||
|
||||
time_stat_update(&(hs->stats[i]),
|
||||
&(pi->msginfo[i].delta_time),
|
||||
pinfo);
|
||||
|
||||
if (hs->count[i] < NUM_RAS_STATS) {
|
||||
hs->delta_time[i][hs->count[i]++]
|
||||
= pi->msginfo[i].delta_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void camelsrt_draw(void *phs)
|
||||
{
|
||||
struct camelsrt_t *hs=(struct camelsrt_t *)phs;
|
||||
guint j,z;
|
||||
guint32 li;
|
||||
int somme,iteration=0;
|
||||
timestat_t *rtd_temp;
|
||||
double x,delay,delay_max,delay_min,delta;
|
||||
double criteria[NB_CRITERIA]={ 5.0, 10.0, 75.0, 90.0, 95.0,99.0,99.90 };
|
||||
double delay_criteria[NB_CRITERIA];
|
||||
|
||||
printf("\n");
|
||||
printf("Camel Service Response Time (SRT) Statistics:\n");
|
||||
printf("=================================================================================================\n");
|
||||
printf("| Category | Measure | Min SRT | Max SRT | Avg SRT | Min frame | Max frame |\n");
|
||||
printf("|-------------------------|---------|-----------|-----------|-----------|-----------|-----------|\n");
|
||||
|
||||
j=1;
|
||||
printf("|%24s |%8u |%8.2f s |%8.2f s |%8.2f s |%10u |%10u |\n",
|
||||
val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
|
||||
hs->stats[j].num,
|
||||
nstime_to_sec(&(hs->stats[j].min)),
|
||||
nstime_to_sec(&(hs->stats[j].max)),
|
||||
get_average(&(hs->stats[j].tot),hs->stats[j].num)/1000.0,
|
||||
hs->stats[j].min_num,
|
||||
hs->stats[j].max_num
|
||||
);
|
||||
for(j=2; j<NB_CAMELSRT_CATEGORY; j++) {
|
||||
if(hs->stats[j].num==0){
|
||||
printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
|
||||
val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
|
||||
0, 0.0, 0.0, 0.0, 0, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
|
||||
val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
|
||||
hs->stats[j].num,
|
||||
MIN(9999,nstime_to_msec(&(hs->stats[j].min))),
|
||||
MIN(9999,nstime_to_msec(&(hs->stats[j].max))),
|
||||
MIN(9999,get_average(&(hs->stats[j].tot),hs->stats[j].num)),
|
||||
hs->stats[j].min_num,
|
||||
hs->stats[j].max_num
|
||||
);
|
||||
} /* j category */
|
||||
|
||||
printf("=================================================================================================\n");
|
||||
/*
|
||||
* Display 95%
|
||||
*/
|
||||
|
||||
printf("| Category/Criteria |");
|
||||
for(z=0; z<NB_CRITERIA; z++) printf("%7.2f%% |", criteria[z]);
|
||||
printf("\n");
|
||||
|
||||
printf("|-------------------------|");
|
||||
for(z=0; z<NB_CRITERIA; z++) printf("---------|");
|
||||
printf("\n");
|
||||
/* calculate the delay max to have a given number of messages (in percentage) */
|
||||
for(j=2;j<NB_CAMELSRT_CATEGORY;j++) {
|
||||
|
||||
rtd_temp = &(hs->stats[j]);
|
||||
|
||||
if (hs->count[j]>0) {
|
||||
/* Calculate the delay to answer to p% of the MS */
|
||||
for(z=0; z<NB_CRITERIA; z++) {
|
||||
iteration=0;
|
||||
delay_max=(double)rtd_temp->max.secs*1000 +(double)rtd_temp->max.nsecs/1000000;
|
||||
delay_min=(double)rtd_temp->min.secs*1000 +(double)rtd_temp->min.nsecs/1000000;
|
||||
delay=delay_min;
|
||||
delta=delay_max-delay_min;
|
||||
while( (delta > 0.001) && (iteration < 10000) ) {
|
||||
somme=0;
|
||||
iteration++;
|
||||
|
||||
for(li=0;li<hs->count[j];li++) {
|
||||
x=hs->delta_time[j][li].secs*1000
|
||||
+ (double)hs->delta_time[j][li].nsecs/1000000;
|
||||
if (x <= delay) somme++;
|
||||
}
|
||||
if ( somme*100 > hs->count[j]*criteria[z] ) { /* trop grand */
|
||||
delay_max=delay;
|
||||
delay=(delay_max+delay_min)/2;
|
||||
delta=delay_max-delay_min;
|
||||
} else { /* trop petit */
|
||||
delay_min=delay;
|
||||
delay=(delay_max+delay_min)/2;
|
||||
delta=delay_max-delay_min;
|
||||
}
|
||||
} /* while */
|
||||
delay_criteria[z]=delay;
|
||||
} /* z criteria */
|
||||
/* Append the result to the table */
|
||||
printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
|
||||
for(z=0; z<NB_CRITERIA; z++) printf("%8.2f |", MIN(9999,delay_criteria[z]));
|
||||
printf("\n");
|
||||
} else { /* count */
|
||||
printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
|
||||
for(z=0; z<NB_CRITERIA; z++) printf("%8.2f |", 0.0);
|
||||
printf("\n");
|
||||
} /* count */
|
||||
}/* j category */
|
||||
printf("===========================");
|
||||
for(z=0; z<NB_CRITERIA; z++) printf("==========");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void camelsrt_init(const char *optarg, void* userdata _U_)
|
||||
{
|
||||
struct camelsrt_t *p_camelsrt;
|
||||
const char *filter=NULL;
|
||||
const char *emptyfilter="";
|
||||
|
||||
GString *error_string;
|
||||
|
||||
if(!strncmp(optarg,"camel,srt,",9)){
|
||||
filter=optarg+9;
|
||||
} else {
|
||||
filter=NULL;
|
||||
}
|
||||
|
||||
p_camelsrt = g_malloc(sizeof(struct camelsrt_t));
|
||||
if(filter){
|
||||
p_camelsrt->filter=g_malloc(strlen(filter)+1);
|
||||
strcpy(p_camelsrt->filter,filter);
|
||||
} else {
|
||||
p_camelsrt->filter=NULL;
|
||||
}
|
||||
camelsrt_reset(p_camelsrt);
|
||||
|
||||
if (filter) {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelsrt,
|
||||
filter,
|
||||
NULL,
|
||||
camelsrt_packet,
|
||||
camelsrt_draw);
|
||||
} else {
|
||||
error_string=register_tap_listener("CAMEL",
|
||||
p_camelsrt,
|
||||
emptyfilter,
|
||||
NULL,
|
||||
camelsrt_packet,
|
||||
camelsrt_draw);
|
||||
}
|
||||
|
||||
if(error_string){
|
||||
/* error, we failed to attach to the tap. clean up */
|
||||
g_free(p_camelsrt->filter);
|
||||
g_free(p_camelsrt);
|
||||
|
||||
fprintf(stderr, "tshark: Couldn't register camel,srt tap: %s\n",
|
||||
error_string->str);
|
||||
g_string_free(error_string, TRUE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are using tshark, we have to display the stats, even if the stats are not persistent
|
||||
* As the frame are proceeded in the chronological order, we do not need persistent stats
|
||||
* Whereas, with wireshark, it is not possible to have the correct display, if the stats are
|
||||
* not saved along the analyze
|
||||
*/
|
||||
gtcap_StatSRT=TRUE;
|
||||
gcamel_StatSRT=TRUE;
|
||||
}
|
||||
|
||||
|
||||
void /* Next line mandatory */
|
||||
register_tap_listener_camelsrt(void)
|
||||
{
|
||||
register_stat_cmd_arg("camel,srt", camelsrt_init, NULL);
|
||||
}
|
Loading…
Reference in New Issue