aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2005-04-11 08:43:51 +0000
committerRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2005-04-11 08:43:51 +0000
commit2bc81b2a48e33a3106da06712e0c3fe8393d83a7 (patch)
treefd1aa3854c60bf357117093a84d9b1ede7b2735b
parentc9be421b16d2b981b6f2ad010c81387b1a72bac0 (diff)
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
-rw-r--r--epan/dissectors/packet-eth.c27
-rw-r--r--epan/dissectors/packet-frame.c28
-rw-r--r--epan/dissectors/packet-ip.c19
-rw-r--r--epan/dissectors/packet-kerberos.c2
-rw-r--r--epan/proto.c158
-rw-r--r--epan/proto.h23
6 files changed, 221 insertions, 36 deletions
diff --git a/epan/dissectors/packet-eth.c b/epan/dissectors/packet-eth.c
index 6f903cc1e1..2e11e6a124 100644
--- a/epan/dissectors/packet-eth.c
+++ b/epan/dissectors/packet-eth.c
@@ -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);
}
diff --git a/epan/dissectors/packet-frame.c b/epan/dissectors/packet-frame.c
index 2dbe49c286..3630d8aa43 100644
--- a/epan/dissectors/packet-frame.c
+++ b/epan/dissectors/packet-frame.c
@@ -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);
}
diff --git a/epan/dissectors/packet-ip.c b/epan/dissectors/packet-ip.c
index 2292eeeb15..f762edb76f 100644
--- a/epan/dissectors/packet-ip.c
+++ b/epan/dissectors/packet-ip.c
@@ -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;
diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c
index 3145c066e2..aeaaa9b955 100644
--- a/epan/dissectors/packet-kerberos.c
+++ b/epan/dissectors/packet-kerberos.c
@@ -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);
diff --git a/epan/proto.c b/epan/proto.c
index e45a77e963..eba7cb41ac 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -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 */
diff --git a/epan/proto.h b/epan/proto.h
index db01f62935..30564b23da 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -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.