Ethereal-dev: Re: [Ethereal-dev] Optimization: remove the unconditional ip_checksum() in packe
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Kaul <mykaul@xxxxxxxxx>
Date: Sat, 24 Sep 2005 20:00:47 +0300
Attached patch.
Comments are welcome + extensive testing, please.
Regards,
Y.
Comments are welcome + extensive testing, please.
Regards,
Y.
On 9/23/05, Ulf Lamping <ulf.lamping@xxxxxx> wrote:
Kaul wrote:
> >From packet-ip.c:
> if (tvb_bytes_exist(tvb, offset, hlen)) {
> ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
> if (tree) {
> if (ipsum == 0) {
> ...
> I suggest here calculating the checksum only if the tree exists:
> if (tree & tvb_bytes_exist(tvb, offset, hlen) {
> ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
> if(ipsum == 0) {
> ...
>
> I'm aware that later on ipsum is needed:
> if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
> tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
> ipsum == 0) {
>
> but here I suggest changing this to:
>
> if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
> tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
> (ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen)) == 0) {
>
> So, if there's no tree and there's no need for defragmentation, the
> checksum is not calculated at all!
> I'd be happy to supply a small patch that does just that, along with
> other minor optimizations to packet-ip.c, if this seems reasonable to
> the list.
>
> Y.
Sounds reasonable. BTW: What's the intentions for this, a slight
performance improvement?
In addition, you might consider adding a Preference setting (it's not
too difficult) to switch off checksum checking completely, just as we
already have it for TCP.
Regards, ULFL
Index: packet-ip.c
===================================================================
--- packet-ip.c (revision 15985)
+++ packet-ip.c (working copy)
@@ -72,6 +72,9 @@
if the packet in the payload has more than 128 bytes */
static gboolean favor_icmp_mpls_ext = FALSE;
+/* Perform IP checksum */
+static gboolean ip_check_checksum = TRUE;
+
static int proto_ip = -1;
static int hf_ip_version = -1;
static int hf_ip_hdr_len = -1;
@@ -375,9 +378,6 @@
return;
}
switch (pd[offset + 9]) {
- case IP_PROTO_SCTP:
- ld->sctp++;
- break;
case IP_PROTO_TCP:
ld->tcp++;
break;
@@ -388,6 +388,9 @@
case IP_PROTO_ICMPV6: /* XXX - separate counters? */
ld->icmp++;
break;
+ case IP_PROTO_SCTP:
+ ld->sctp++;
+ break;
case IP_PROTO_OSPF:
ld->ospf++;
break;
@@ -911,13 +914,16 @@
goto end_of_ip;
}
- if (tree) {
- proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
- "Header length: %u bytes", hlen);
- }
-
iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
+ iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
+ iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
+ iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
+ iph->ip_p = tvb_get_guint8(tvb, offset + 9);
+ iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
+
if (tree) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
+ "Header length: %u bytes", hlen);
if (g_ip_dscp_actif) {
tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
"Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
@@ -948,7 +954,6 @@
inside an ICMP datagram; we need to somehow let the
dissector we call know that, as it might want to avoid
doing its checksumming. */
- iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
/* Adjust the length of this tvbuff to include only the IP datagram. */
set_actual_length(tvb, iph->ip_len);
@@ -964,15 +969,9 @@
}
goto end_of_ip;
}
- if (tree)
- proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
-
- iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
- if (tree)
- proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
-
- iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
if (tree) {
+ proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
+ proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
field_tree = proto_item_add_subtree(tf, ett_ip_off);
@@ -984,60 +983,55 @@
proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
(iph->ip_off & IP_OFFSET)*8);
- }
-
- if (tree)
proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
-
- iph->ip_p = tvb_get_guint8(tvb, offset + 9);
- if (tree) {
proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
"Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
}
- iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
/*
* If we have the entire IP header available, check the checksum.
*/
- if (tvb_bytes_exist(tvb, offset, hlen)) {
- ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
- if (tree) {
- if (ipsum == 0) {
- item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
- "Header checksum: 0x%04x [correct]", iph->ip_sum);
- checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, TRUE);
+
+ if (tree) {
+ if(ip_check_checksum && tvb_bytes_exist(tvb, offset, hlen)) {
+ ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
+ if (ipsum == 0) {
+ item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
+ "Header checksum: 0x%04x [correct]", iph->ip_sum);
+ checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, TRUE);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
+ } else {
+ item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
+ "Header checksum: 0x%04x [incorrect, should be 0x%04x]", iph->ip_sum,
+ in_cksum_shouldbe(iph->ip_sum, ipsum));
+ checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
+ }
+ } else {
+ item = proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
+ checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
+ }
PROTO_ITEM_SET_GENERATED(item);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
- PROTO_ITEM_SET_GENERATED(item);
- } else {
- item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
- "Header checksum: 0x%04x [incorrect, should be 0x%04x]", iph->ip_sum,
- in_cksum_shouldbe(iph->ip_sum, ipsum));
- checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
- PROTO_ITEM_SET_GENERATED(item);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
- PROTO_ITEM_SET_GENERATED(item);
- }
- }
- } else {
- ipsum = 0;
- if (tree) {
- item = proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
- checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
- PROTO_ITEM_SET_GENERATED(item);
- item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
- PROTO_ITEM_SET_GENERATED(item);
- }
}
+
src_addr = tvb_get_ptr(tvb, offset + IPH_SRC, 4);
- src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, src_addr);
SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src_addr);
SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, src_addr);
+
+ dst_addr = tvb_get_ptr(tvb, offset + IPH_DST, 4);
+ SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
+ SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
+ SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
+
if (tree) {
memcpy(&addr, iph->ip_src.data, 4);
if (ip_summary_in_tree) {
@@ -1053,14 +1047,7 @@
item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 12, 4, get_hostname(addr));
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
- }
- dst_addr = tvb_get_ptr(tvb, offset + IPH_DST, 4);
- dst32 = tvb_get_ntohl(tvb, offset + IPH_DST);
- SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
- SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
- SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
- if (tree) {
memcpy(&addr, iph->ip_dst.data, 4);
if (ip_summary_in_tree) {
proto_item_append_text(ti, ", Dst: %s (%s)",
@@ -1075,9 +1062,7 @@
item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 16, 4, get_hostname(addr));
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_HIDDEN(item);
- }
- if (tree) {
/* Decode IP options, if any. */
if (hlen > IPH_MIN_LEN) {
/* There's more than just the fixed-length header. Decode the
@@ -1108,8 +1093,12 @@
save_fragmented = pinfo->fragmented;
if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
- ipsum == 0) {
- ipfd_head = fragment_add_check(tvb, offset, pinfo,
+ ((ip_check_checksum == 0) ||
+ (tvb_bytes_exist(tvb, offset -hlen, hlen) && ip_checksum(tvb_get_ptr(tvb, offset -hlen, hlen), hlen) == 0))) {
+
+ src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
+ dst32 = tvb_get_ntohl(tvb, offset + IPH_DST);
+ ipfd_head = fragment_add_check(tvb, offset, pinfo,
iph->ip_id ^ src32 ^ dst32,
ip_fragment_table,
ip_reassembled_table,
@@ -2137,6 +2126,10 @@
"Show IP summary in protocol tree",
"Whether the IP summary line should be shown in the protocol tree",
&ip_summary_in_tree);
+ prefs_register_bool_preference(ip_module, "check_checksum" ,
+ "Validate the IP checksum if possible",
+ "Whether to validate the IP checksum",
+ &ip_check_checksum);
register_dissector("ip", dissect_ip, proto_ip);
register_init_routine(ip_defragment_init);
- Follow-Ups:
- References:
- Prev by Date: Re: [Ethereal-dev] packet-xml.c
- Next by Date: [Ethereal-dev] Re: [Ethereal-cvs] rev 15993: /trunk/epan/dissectors/: packet-ospf.c
- Previous by thread: Re: [Ethereal-dev] Optimization: remove the unconditional ip_checksum() in packet-ip?
- Next by thread: Re: [Ethereal-dev] Optimization: remove the unconditional ip_checksum() in packet-ip?
- Index(es):