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:
Anders Broman 2006-10-03 22:12:47 +00:00
parent 8a60a1006b
commit ad50bdf507
6 changed files with 1827 additions and 0 deletions

798
epan/camel-persistentdata.c Normal file
View File

@ -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));
}

126
epan/camel-persistentdata.h Normal file
View File

@ -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__*/

233
gtk/camel_counter.c Normal file
View File

@ -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);
}

248
gtk/camel_srt.c Normal file
View File

@ -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);
}

146
tap-camelcounter.c Normal file
View File

@ -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);
}

276
tap-camelsrt.c Normal file
View File

@ -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);
}