Major speed improvement for filtering and dissection.

It should not dump core as far as all my tests are concerned and Menu_Statistics/ProtocolHierStats work

It needs more testing and there might still be cases where it will crash that will need to be fixed  but I feel it will be worth it since it will decrease the time to filter very large capture files dramatically.

Real significant performance boost for very large captures.


(If we cant fix all the problems we can just revert this patch)



svn path=/trunk/; revision=14051
This commit is contained in:
Ronnie Sahlberg 2005-04-11 08:43:51 +00:00
parent c9be421b16
commit 2bc81b2a48
6 changed files with 221 additions and 36 deletions

View File

@ -160,7 +160,7 @@ capture_eth(const guchar *pd, int offset, int len, packet_counts *ld)
}
static void
dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
int fcs_len)
{
proto_item *ti;
@ -170,6 +170,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
const char *src_addr, *dst_addr;
static eth_hdr ehdrs[4];
static int ehdr_num=0;
proto_tree *tree;
ehdr_num++;
if(ehdr_num>=4){
@ -177,6 +178,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
ehdr=&ehdrs[ehdr_num];
tree=parent_tree;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet");
@ -198,7 +200,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* a first look before we assume that it's actually an
* Ethernet packet.
*/
if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree))
if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, parent_tree))
goto end_of_eth;
if (ehdr->type <= IEEE_802_3_MAX_LEN) {
@ -212,7 +214,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb_get_guint8(tvb, 2) == 0x0C &&
tvb_get_guint8(tvb, 3) == 0x00 &&
tvb_get_guint8(tvb, 4) == 0x00 ) {
dissect_isl(tvb, pinfo, tree, fcs_len);
dissect_isl(tvb, pinfo, parent_tree, fcs_len);
goto end_of_eth;
}
}
@ -263,6 +265,15 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
}
/* if IP is not referenced from any filters we dont need to worry about
generating any tree items. We must do this after we created the actual
protocol above so that proto hier stat still works though.
*/
if(!proto_field_is_referenced(parent_tree, proto_eth)){
tree=NULL;
fh_tree=NULL;
}
proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
@ -270,21 +281,21 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree,
dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree,
hf_eth_len, hf_eth_trailer, fcs_len);
} else {
if (eth_interpret_as_fw1_monitor) {
if ((dst_addr[0] == 'i') || (dst_addr[0] == 'I') ||
(dst_addr[0] == 'o') || (dst_addr[0] == 'O')) {
call_dissector(fw1_handle, tvb, pinfo, tree);
call_dissector(fw1_handle, tvb, pinfo, parent_tree);
goto end_of_eth;
}
}
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II");
if (tree) {
ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
if (parent_tree) {
ti = proto_tree_add_protocol_format(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
"Ethernet II, Src: %s, Dst: %s",
ether_to_str(src_addr), ether_to_str(dst_addr));
@ -297,7 +308,7 @@ dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree, hf_eth_type,
ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_type,
hf_eth_trailer, fcs_len);
}

View File

@ -73,12 +73,15 @@ static const value_string p2p_dirs[] = {
static dissector_table_t wtap_encap_dissector_table;
static void
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_tree *fh_tree;
proto_tree *fh_tree=NULL;
proto_item *volatile ti = NULL;
nstime_t ts;
int cap_len, pkt_len;
proto_tree *tree;
tree=parent_tree;
pinfo->current_proto = "Frame";
@ -123,7 +126,6 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* Put in frame header information. */
if (tree) {
cap_len = tvb_length(tvb);
pkt_len = tvb_reported_length(tvb);
@ -131,7 +133,19 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
"Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, pkt_len, cap_len);
fh_tree = proto_item_add_subtree(ti, ett_frame);
}
/* if IP is not referenced from any filters we dont need to worry about
generating any tree items. We must do this after we created the actual
protocol above so that proto hier stat still works though.
*/
if(!proto_field_is_referenced(tree, proto_frame)){
tree=NULL;
fh_tree = NULL;
}
if (fh_tree) {
proto_tree_add_boolean_hidden(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
if(pinfo->fd->flags.ref_time){
@ -187,18 +201,18 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
TRY {
if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
tvb, pinfo, tree)) {
tvb, pinfo, parent_tree)) {
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
pinfo->fd->lnk_t);
call_dissector(data_handle,tvb, pinfo, tree);
call_dissector(data_handle,tvb, pinfo, parent_tree);
}
}
CATCH_ALL {
show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
}
ENDTRY;
@ -210,7 +224,7 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tap_queue_packet(frame_tap, pinfo, NULL);
if (mate_handle) call_dissector(mate_handle,tvb, pinfo, tree);
if (mate_handle) call_dissector(mate_handle,tvb, pinfo, parent_tree);
}

View File

@ -814,7 +814,7 @@ static guint16 ip_checksum(const guint8 *ptr, int len)
}
static void
dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_tree *ip_tree = NULL, *field_tree;
proto_item *ti = NULL, *tf;
@ -833,6 +833,9 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
e_ip *iph;
const guchar *src_addr, *dst_addr;
guint32 src32, dst32;
proto_tree *tree;
tree=parent_tree;
eip_current++;
if(eip_current==4){
@ -856,6 +859,14 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
hi_nibble(iph->ip_v_hl));
}
/* if IP is not referenced from any filters we dont need to worry about
generating any tree items. We must do this after we created the actual
protocol above so that proto hier stat still works though.
*/
if(!proto_field_is_referenced(parent_tree, proto_ip)){
tree=NULL;
}
if (hlen < IPH_MIN_LEN) {
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
@ -1088,7 +1099,7 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
tree);
parent_tree);
pinfo->fragmented = save_fragmented;
goto end_of_ip;
}
@ -1100,13 +1111,13 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
even be labelled as an IP frame; ideally, if a frame being dissected
throws an exception, it'll be labelled as a mangled frame of the
type in question. */
if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
/* Unknown protocol */
if (update_col_info) {
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
}
call_dissector(data_handle,next_tvb, pinfo, tree);
call_dissector(data_handle,next_tvb, pinfo, parent_tree);
}
pinfo->fragmented = save_fragmented;

View File

@ -3673,7 +3673,7 @@ static ber_sequence_t ERROR_sequence[] = {
dissect_krb5_e_checksum }, /* used by PacketCable */
{ 0, 0, 0, NULL }
};
static int
int
dissect_krb5_ERROR(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
{
offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ERROR_sequence, -1, -1);

View File

@ -48,6 +48,35 @@
#define cVALS(x) (const value_string*)(x)
#if 1
#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
/* If this item is not referenced we dont have to do much work \
at all but we should still return a node so that \
field items below this node ( think proto_item_add_subtree() )\
will still have somewhere to attach to \
or else filtering will not work (they would be ignored since tree\
would be NULL). \
DONT try to fake a node where PITEM_FINFO(pi) is NULL \
since dissectors that want to do proto_item_set_len() ot \
other operations that dereference this would crash. \
We dont fake FT_PROTOCOL either since these are cheap and \
some stuff (proto hier stat) assumes they always exist. \
*/ \
if(!(PTREE_DATA(tree)->visible)){ \
if(PITEM_FINFO(tree)){ \
register header_field_info *hfinfo; \
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
if((hfinfo->ref_count == 0) \
&& (hfinfo->type!=FT_PROTOCOL)){ \
/* just return tree back to the caller */\
return tree; \
} \
} \
}
#else
#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
#endif
static gboolean
proto_tree_free_node(proto_node *node, gpointer data);
@ -187,6 +216,10 @@ static SLAB_FREE_LIST_DEFINE(item_label_t)
SLAB_FREE(il, item_label_t)
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
hfinfo=gpa_hfinfo.hfi[hfindex];
/* List which stores protocols and fields that have been registered */
typedef struct _gpa_hfinfo_t {
@ -426,6 +459,23 @@ static void
free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
{
GPtrArray *ptrs = value;
gint hfid = (gint)key;
header_field_info *hfinfo;
PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
if(hfinfo->ref_count){
/* when a field is referenced by a filter this also
affects the refcount for the parent protocol so we need
to adjust the refcount for the parent as well
*/
if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
header_field_info *parent_hfinfo;
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
parent_hfinfo->ref_count -= hfinfo->ref_count;
}
hfinfo->ref_count = 0;
}
g_ptr_array_free(ptrs, TRUE);
}
@ -483,9 +533,32 @@ proto_tree_set_visible(proto_tree *tree, gboolean visible)
PTREE_DATA(tree)->visible = visible;
}
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
hfinfo=gpa_hfinfo.hfi[hfindex];
/* Assume dissector set only its protocol fields.
This function is called by dissectors and allowes to speed up filtering
in ethereal, if this function returns FALSE it is safe to reset tree to NULL
and thus skip calling most of the expensive proto_tree_add_...()
functions.
If the tree is visible we implicitely assume the field is referenced.
*/
gboolean
proto_field_is_referenced(proto_tree *tree, int proto_id)
{
register header_field_info *hfinfo;
if (!tree)
return FALSE;
if (PTREE_DATA(tree)->visible)
return TRUE;
PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
if (hfinfo->ref_count != 0)
return TRUE;
return FALSE;
}
/* Finds a record in the hf_info_records array by id. */
header_field_info*
@ -667,6 +740,8 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
if (!tree)
return(NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
if (new_fi == NULL)
@ -891,10 +966,12 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
/* If the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
hash = PTREE_DATA(tree)->interesting_hfids;
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
if (ptrs) {
g_ptr_array_add(ptrs, new_fi);
if (new_fi->hfinfo->ref_count) {
hash = PTREE_DATA(tree)->interesting_hfids;
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
if (ptrs) {
g_ptr_array_add(ptrs, new_fi);
}
}
return pi;
@ -992,6 +1069,8 @@ proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
@ -1065,6 +1144,8 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
hfinfo->type == FT_RELATIVE_TIME);
@ -1127,6 +1208,8 @@ proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
@ -1188,6 +1271,8 @@ proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
@ -1249,6 +1334,8 @@ proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
@ -1334,6 +1421,8 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
@ -1436,6 +1525,8 @@ proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
@ -1503,6 +1594,8 @@ proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
@ -1564,6 +1657,8 @@ proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
@ -1625,6 +1720,8 @@ proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
@ -1686,6 +1783,8 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_UINT8:
@ -1772,6 +1871,8 @@ proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
@ -1811,6 +1912,8 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gin
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
switch(hfinfo->type) {
case FT_INT8:
@ -1896,6 +1999,8 @@ proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, g
if (!tree)
return (NULL);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
@ -1988,10 +2093,12 @@ proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
/* If the proto_tree wants to keep a record of this finfo
* for quick lookup, then record it. */
hash = PTREE_DATA(tree)->interesting_hfids;
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
if (ptrs) {
g_ptr_array_add(ptrs, fi);
if (fi->hfinfo->ref_count) {
hash = PTREE_DATA(tree)->interesting_hfids;
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
if (ptrs) {
g_ptr_array_add(ptrs, fi);
}
}
/* Does the caller want to know the fi pointer? */
@ -2299,10 +2406,26 @@ proto_tree_create_root(void)
void
proto_tree_prime_hfid(proto_tree *tree, gint hfid)
{
header_field_info *hfinfo;
g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
GINT_TO_POINTER(hfid), g_ptr_array_new());
}
PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
/* this field is referenced by a filter so increase the refcount.
also increase the refcount for the parent, i.e the protocol.
*/
hfinfo->ref_count++;
/* only increase the refcount if there is a parent.
if this is a protocol and not a field then parent will be -1
and there is no parent to add any refcounting for.
*/
if (hfinfo->parent != -1) {
header_field_info *parent_hfinfo;
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
parent_hfinfo->ref_count++;
}
}
proto_tree*
proto_item_add_subtree(proto_item *pi, gint idx) {
@ -2314,6 +2437,7 @@ proto_item_add_subtree(proto_item *pi, gint idx) {
fi = PITEM_FINFO(pi);
DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
fi->tree_type = idx;
return (proto_tree*) pi;
}
@ -2331,14 +2455,16 @@ proto_item_get_subtree(proto_item *pi) {
proto_item*
proto_item_get_parent(proto_item *ti) {
if (!ti)
/* dont bother if tree is not visible */
if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
return (NULL);
return ti->parent;
}
proto_item*
proto_item_get_parent_nth(proto_item *ti, int gen) {
if (!ti)
/* dont bother if tree is not visible */
if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
return (NULL);
while (gen--) {
ti = ti->parent;
@ -2351,7 +2477,8 @@ proto_item_get_parent_nth(proto_item *ti, int gen) {
proto_item*
proto_tree_get_parent(proto_tree *tree) {
if (!tree)
/* dont bother if tree is not visible */
if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
return (NULL);
return (proto_item*) tree;
}
@ -2445,6 +2572,7 @@ proto_register_protocol(char *name, char *short_name, char *filter_name)
hfinfo->strings = protocol;
hfinfo->bitmask = 0;
hfinfo->bitshift = 0;
hfinfo->ref_count = 0;
hfinfo->blurb = "";
hfinfo->parent = -1; /* this field differentiates protos and fields */

View File

@ -154,6 +154,12 @@ struct _header_field_info {
/* ------- set by proto routines (prefilled by HFILL macro, see below) ------ */
int id; /**< Field ID */
int parent; /**< parent protocol tree */
/* This field keeps track of whether a field is
* referenced in any filter or not and if so how
* many times. If a filter is being referenced the
* refcount for the parent protocol is updated as well
*/
int ref_count; /**< is this field referenced by a filter or not */
int bitshift; /**< bits to shift (FT_BOOLEAN only) */
header_field_info *same_name_next; /**< Link to next hfinfo with same abbrev*/
header_field_info *same_name_prev; /**< Link to previous hfinfo with same abbrev*/
@ -164,7 +170,7 @@ struct _header_field_info {
* _header_field_info. If new fields are added or removed, it should
* be changed as necessary.
*/
#define HFILL 0, 0, 0, NULL, NULL
#define HFILL 0, 0, 0, 0, NULL, NULL
/** Used when registering many fields at once, using proto_register_field_array() */
typedef struct hf_register_info {
@ -265,6 +271,21 @@ extern void proto_init(const char *plugin_dir,
/** Frees memory used by proto routines. Called at program shutdown */
extern void proto_cleanup(void);
/** This function takes a tree and a protocol id as parameter and
will return TRUE/FALSE for whether the protocol or any of the filterable
fields in the protocol is referenced by any fitlers.
If this function returns FALSE then it is safe to skip any
proto_tree_add_...() calls and just treat the call as if the
dissector was called with tree==NULL.
If you reset the tree to NULL by this dissector returning FALSE,
you will still need to call any subdissector with the original value of
tree or filtering will break.
The purpose of this is to optimize ethereal for speed and make it
faster for when filters are being used.
*/
extern gboolean proto_field_is_referenced(proto_tree *tree, int proto_id);
/** Create a subtree under an existing item.