Ethereal-dev: [Ethereal-dev] Improving filter speed
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: didier <dgautheron@xxxxxxxx>
Date: Wed, 16 Mar 2005 21:52:40 +0000
HiFilters are slow because dissectors are called with a non null tree parameter.
If you assume that:1) in a frame with A- B -C -D protocols and a filter C.x you can only fully decode C
2) if a filter field is only a protocol type ie tcp, afp you don't need to you can speed it a lot Attached patch: proto.c proto.h the logic. packet-xxx.c dissectors using it. Comments? regards Didier
Index: epan/proto.c
===================================================================
--- epan/proto.c (revision 13776)
+++ epan/proto.c (working copy)
@@ -196,6 +196,10 @@
} gpa_hfinfo_t;
gpa_hfinfo_t gpa_hfinfo;
+#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
+ g_assert((guint)hfindex < gpa_hfinfo.len); \
+ hfinfo=gpa_hfinfo.hfi[hfindex];
+
/* Balanced tree of abbreviations and IDs */
static GTree *gpa_name_tree = NULL;
@@ -423,10 +427,21 @@
}
static void
-free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
+free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
{
GPtrArray *ptrs = value;
+ gint hfid = (gint)key;
+ header_field_info *hfinfo;
+ /* assume interesting_hfids are destroyed in blocks otherwise need to ref count */
+ PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
+ hfinfo->infilter = 0;
+ if (hfinfo->parent != -1) {
+ hfinfo->infilter = 0;
+ PROTO_REGISTRAR_GET_NTH(hfinfo->parent, hfinfo );
+ hfinfo->infilter = 0;
+ }
+
g_ptr_array_free(ptrs, TRUE);
}
@@ -483,10 +498,27 @@
PTREE_DATA(tree)->visible = visible;
}
-#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
- g_assert((guint)hfindex < gpa_hfinfo.len); \
- hfinfo=gpa_hfinfo.hfi[hfindex];
+/* assume dissector set only its protocol fields
+*/
+gboolean
+proto_tree_is_null(proto_tree *tree, int proto_id)
+{
+ register header_field_info *hfinfo;
+
+ if (!tree)
+ return TRUE;
+
+ if (PTREE_DATA(tree)->visible)
+ return FALSE;
+
+ PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
+ if (hfinfo->infilter > 0)
+ return FALSE;
+
+ return TRUE;
+}
+
/* Finds a record in the hf_info_records array by id. */
header_field_info*
proto_registrar_get_nth(guint hfindex)
@@ -891,10 +923,12 @@
/* 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->infilter) {
+ 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;
@@ -1988,10 +2022,12 @@
/* 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->infilter) {
+ 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? */
@@ -2269,8 +2305,23 @@
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);
+ if (hfinfo->parent != -1) {
+ hfinfo->infilter = 1;
+ PROTO_REGISTRAR_GET_NTH(hfinfo->parent, hfinfo);
+ hfinfo->infilter = 1;
+ }
+ else if (!hfinfo->infilter) {
+ /* use -1 for parent, aka protocol field
+ * if -1 trees aren't built
+ */
+ hfinfo->infilter = -1;
+ }
}
@@ -2400,6 +2451,7 @@
hfinfo->strings = NULL;
hfinfo->bitmask = 0;
hfinfo->bitshift = 0;
+ hfinfo->infilter = 0;
hfinfo->blurb = "";
hfinfo->parent = -1; /* this field differentiates protos and fields */
Index: epan/proto.h
===================================================================
--- epan/proto.h (revision 13776)
+++ epan/proto.h (working copy)
@@ -146,6 +146,7 @@
/* ------- set by proto routines (prefilled by HFILL macro, see below) ------ */
int id; /**< Field ID */
int parent; /**< parent protocol tree */
+ int infilter;
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*/
@@ -156,7 +157,7 @@
* _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 {
@@ -257,8 +258,8 @@
/** Frees memory used by proto routines. Called at program shutdown */
extern void proto_cleanup(void);
+extern gboolean proto_tree_is_null(proto_tree *tree, int proto_id);
-
/** Create a subtree under an existing item.
@param ti the parent item of the new subtree
@param idx one of the ett_ array elements registered with proto_register_subtree_array()
Index: epan/dissectors/packet-ip.c
===================================================================
--- epan/dissectors/packet-ip.c (revision 13776)
+++ epan/dissectors/packet-ip.c (working copy)
@@ -832,6 +832,10 @@
static int eip_current=0;
e_ip *iph;
const guchar *src_addr, *dst_addr;
+ proto_tree *save_tree = tree;
+
+ if (proto_tree_is_null(tree, proto_ip))
+ tree = NULL;
eip_current++;
if(eip_current==4){
@@ -847,8 +851,11 @@
iph->ip_v_hl = tvb_get_guint8(tvb, offset);
hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
- if (tree) {
- ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
+ if (save_tree) {
+ ti = proto_tree_add_item(save_tree, proto_ip, tvb, offset, hlen, FALSE);
+ }
+
+ if (tree) {
ip_tree = proto_item_add_subtree(ti, ett_ip);
proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
@@ -1084,7 +1091,7 @@
}
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
- tree);
+ save_tree);
pinfo->fragmented = save_fragmented;
goto end_of_ip;
}
@@ -1096,13 +1103,13 @@
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, save_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, save_tree);
}
pinfo->fragmented = save_fragmented;
Index: epan/dissectors/packet-afp.c
===================================================================
--- epan/dissectors/packet-afp.c (revision 13776)
+++ epan/dissectors/packet-afp.c (working copy)
@@ -3304,9 +3304,12 @@
afp_request_key request_key, *new_request_key;
afp_request_val *request_val;
guint8 afp_command;
-
int len = tvb_reported_length_remaining(tvb,0);
gint col_info = check_col(pinfo->cinfo, COL_INFO);
+ proto_tree *save_tree = tree;
+
+ if (proto_tree_is_null(tree, proto_afp))
+ tree = NULL;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFP");
@@ -3359,10 +3362,11 @@
}
}
- if (tree)
+ if (save_tree)
{
- ti = proto_tree_add_item(tree, proto_afp, tvb, offset, -1,FALSE);
- afp_tree = proto_item_add_subtree(ti, ett_afp);
+ ti = proto_tree_add_item(save_tree, proto_afp, tvb, offset, -1,FALSE);
+ if (tree)
+ afp_tree = proto_item_add_subtree(ti, ett_afp);
}
if (!aspinfo->reply) {
Index: epan/dissectors/packet-dsi.c
===================================================================
--- epan/dissectors/packet-dsi.c (revision 13776)
+++ epan/dissectors/packet-dsi.c (working copy)
@@ -474,8 +474,11 @@
guint32 dsi_reserved;
struct aspinfo aspinfo;
gint col_info;
-
+ proto_tree *save_tree = tree;
+ if (proto_tree_is_null(tree, proto_dsi))
+ tree = NULL;
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
col_info = check_col(pinfo->cinfo, COL_INFO);
@@ -498,9 +501,11 @@
dsi_requestid);
}
-
+ if (save_tree) {
+ ti = proto_tree_add_item(save_tree, proto_dsi, tvb, 0, -1, FALSE);
+ }
+
if (tree) {
- ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, FALSE);
dsi_tree = proto_item_add_subtree(ti, ett_dsi);
proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb,
@@ -559,7 +564,7 @@
proto_item_set_len(dsi_tree, DSI_BLOCKSIZ);
new_tvb = tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,len);
- call_dissector(afp_handle, new_tvb, pinfo, tree);
+ call_dissector(afp_handle, new_tvb, pinfo, save_tree);
}
break;
default:
Index: epan/dissectors/packet-eth.c
===================================================================
--- epan/dissectors/packet-eth.c (revision 13776)
+++ epan/dissectors/packet-eth.c (working copy)
@@ -170,6 +170,8 @@
const char *src_addr, *dst_addr;
static eth_hdr ehdrs[4];
static int ehdr_num=0;
+ proto_tree *save_tree = tree;
+
ehdr_num++;
if(ehdr_num>=4){
@@ -177,6 +179,8 @@
}
ehdr=&ehdrs[ehdr_num];
+ if (proto_tree_is_null(tree, proto_eth))
+ tree = NULL;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet");
@@ -198,7 +202,7 @@
* 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, save_tree))
goto end_of_eth;
if (ehdr->type <= IEEE_802_3_MAX_LEN) {
@@ -212,7 +216,7 @@
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, save_tree, fcs_len);
goto end_of_eth;
}
}
@@ -256,11 +260,12 @@
col_add_fstr(pinfo->cinfo, COL_INFO, "IEEE 802.3 Ethernet %s",
(is_802_2 ? "" : "Raw "));
}
- if (tree) {
- ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
+ if (save_tree) {
+ ti = proto_tree_add_protocol_format(save_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
"IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw "));
- fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
+ if (tree)
+ fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
}
proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
@@ -270,25 +275,25 @@
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, save_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, save_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 (save_tree) {
+ ti = proto_tree_add_protocol_format(save_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
"Ethernet II, Src: %s, Dst: %s",
ether_to_str(src_addr), ether_to_str(dst_addr));
-
- fh_tree = proto_item_add_subtree(ti, ett_ether2);
+ if (tree)
+ fh_tree = proto_item_add_subtree(ti, ett_ether2);
}
proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
@@ -297,7 +302,7 @@
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, save_tree, fh_tree, hf_eth_type,
hf_eth_trailer, fcs_len);
}
Index: epan/dissectors/packet-frame.c
===================================================================
--- epan/dissectors/packet-frame.c (revision 13776)
+++ epan/dissectors/packet-frame.c (working copy)
@@ -76,10 +76,14 @@
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *fh_tree;
- proto_item *volatile ti = NULL;
+ proto_item *ti = NULL;
nstime_t ts;
int cap_len, pkt_len;
+ proto_tree *save_tree = tree;
+ if (proto_tree_is_null(tree, proto_frame))
+ tree = NULL;
+
pinfo->current_proto = "Frame";
if (pinfo->pseudo_header != NULL) {
@@ -122,14 +126,15 @@
}
/* Put in frame header information. */
- if (tree) {
+ if (save_tree) {
cap_len = tvb_length(tvb);
pkt_len = tvb_reported_length(tvb);
- ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
+ ti = proto_tree_add_protocol_format(save_tree, proto_frame, tvb, 0, -1,
"Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, pkt_len, cap_len);
-
+ }
+ if (tree) {
fh_tree = proto_item_add_subtree(ti, ett_frame);
proto_tree_add_boolean_hidden(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
@@ -187,18 +192,18 @@
TRY {
if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
- tvb, pinfo, tree)) {
+ tvb, pinfo, save_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, save_tree);
}
}
CATCH_ALL {
- show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
+ show_exception(tvb, pinfo, save_tree, EXCEPT_CODE, GET_MESSAGE);
}
ENDTRY;
@@ -210,7 +215,7 @@
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, save_tree);
}
- Follow-Ups:
- Re: [Ethereal-dev] Improving filter speed
- From: Gilbert Ramirez
- [Ethereal-dev] Re: Improving filter speed
- From: ronnie sahlberg
- Re: [Ethereal-dev] Improving filter speed
- Prev by Date: Re: [Ethereal-dev] [Coverity] Possible Format String Vulnerabilites
- Next by Date: RE: [Ethereal-dev] Incorrect decode of OUI 00:00:39
- Previous by thread: Re: [Ethereal-dev] Ethereal-win32 : Memory not de-allocated when closing an old sniffer trace or changing display filter
- Next by thread: Re: [Ethereal-dev] Improving filter speed
- Index(es):