* why do we mangle checksums for v6 ICMP?
@ 2006-11-08 22:13 Al Viro
2006-11-08 22:28 ` Al Viro
2006-11-09 17:32 ` Brian Haley
0 siblings, 2 replies; 26+ messages in thread
From: Al Viro @ 2006-11-08 22:13 UTC (permalink / raw)
To: netdev
AFAICS, the rules are:
(1) checksum is 16-bit one's complement of the one's complement sum of
relevant 16bit words.
(2) for v4 UDP all-zeroes has special meaning - no checksum; if you get
it from (1), send all-ones instead.
(3) for v6 UDP we have the same remapping as in (2), but all-zeroes has
different meaning - not "ignore checksum" as in v4, but "reject the
packet".
(4) there is no (4).
IOW, nobody except UDP has any business doing that 0->0xffff
replacement. However, we have
if (icmp6h->icmp6_cksum == 0)
icmp6h->icmp6_cksum = -1;
and similar in net/ipv6/raw.c
AFAICS, both went in with (commit ID by linux-hist repository)
commit 6bac90985c8b65ffc25839c001aa7ef4831d2915
Author: Kazunori Miyazawa <kazunori@miyazawa.org>
Date: Mon May 12 00:21:19 2003 -0700
[IPV4]: Introduce ip6_append_data.
That changeset has very similar changes done in udp.c, icmp.c and raw.c;
remapping of UDP checksum used to be in the area affected by the changeset
and it looks like it got not just preserved in udp.c (as it should), but
copied to icmp.c and raw.c instances.
So... is it really needed there?
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: why do we mangle checksums for v6 ICMP? 2006-11-08 22:13 why do we mangle checksums for v6 ICMP? Al Viro @ 2006-11-08 22:28 ` Al Viro 2006-11-09 17:32 ` Brian Haley 1 sibling, 0 replies; 26+ messages in thread From: Al Viro @ 2006-11-08 22:28 UTC (permalink / raw) To: netdev On Wed, Nov 08, 2006 at 10:13:32PM +0000, Al Viro wrote: > AFAICS, the rules are: > > (1) checksum is 16-bit one's complement of the one's complement sum of > relevant 16bit words. > > (2) for v4 UDP all-zeroes has special meaning - no checksum; if you get > it from (1), send all-ones instead. > > (3) for v6 UDP we have the same remapping as in (2), but all-zeroes has > different meaning - not "ignore checksum" as in v4, but "reject the > packet". > > (4) there is no (4). > > IOW, nobody except UDP has any business doing that 0->0xffff > replacement. However, we have > if (icmp6h->icmp6_cksum == 0) > icmp6h->icmp6_cksum = -1; > and similar in net/ipv6/raw.c > > AFAICS, both went in with (commit ID by linux-hist repository) > commit 6bac90985c8b65ffc25839c001aa7ef4831d2915 > Author: Kazunori Miyazawa <kazunori@miyazawa.org> > Date: Mon May 12 00:21:19 2003 -0700 > > [IPV4]: Introduce ip6_append_data. > > That changeset has very similar changes done in udp.c, icmp.c and raw.c; > remapping of UDP checksum used to be in the area affected by the changeset > and it looks like it got not just preserved in udp.c (as it should), but > copied to icmp.c and raw.c instances. > > So... is it really needed there? While we are at it, shouldn't ip_nat_mangle_udp_packet() do the same remapping in } else udph->check = nf_proto_csum_update(*pskb, htons(oldlen) ^ htons(0xFFFF), htons(datalen), udph->check, 1); branch? Note that udp_manip_pkt() does it in the same situation... ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: why do we mangle checksums for v6 ICMP? 2006-11-08 22:13 why do we mangle checksums for v6 ICMP? Al Viro 2006-11-08 22:28 ` Al Viro @ 2006-11-09 17:32 ` Brian Haley 2006-11-09 23:14 ` David Miller 1 sibling, 1 reply; 26+ messages in thread From: Brian Haley @ 2006-11-09 17:32 UTC (permalink / raw) To: Al Viro; +Cc: netdev Hi Al, Al Viro wrote: > AFAICS, the rules are: > > (1) checksum is 16-bit one's complement of the one's complement sum of > relevant 16bit words. > > (2) for v4 UDP all-zeroes has special meaning - no checksum; if you get > it from (1), send all-ones instead. > > (3) for v6 UDP we have the same remapping as in (2), but all-zeroes has > different meaning - not "ignore checksum" as in v4, but "reject the > packet". > > (4) there is no (4). > > IOW, nobody except UDP has any business doing that 0->0xffff > replacement. However, we have > if (icmp6h->icmp6_cksum == 0) > icmp6h->icmp6_cksum = -1; This doesn't look necessary, RFCs 4443/2463 don't mention it being necessary, and BSD doesn't do it either. I'll cook-up a patch to remove that since I was doing some other mods in that codepath. > and similar in net/ipv6/raw.c Maybe here it only needs to be done if (fl->proto == IPPROTO_UDP)? -Brian ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: why do we mangle checksums for v6 ICMP? 2006-11-09 17:32 ` Brian Haley @ 2006-11-09 23:14 ` David Miller 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley ` (2 more replies) 0 siblings, 3 replies; 26+ messages in thread From: David Miller @ 2006-11-09 23:14 UTC (permalink / raw) To: brian.haley; +Cc: viro, netdev From: Brian Haley <brian.haley@hp.com> Date: Thu, 09 Nov 2006 12:32:18 -0500 > Al Viro wrote: > > AFAICS, the rules are: > > > > (1) checksum is 16-bit one's complement of the one's complement sum of > > relevant 16bit words. > > > > (2) for v4 UDP all-zeroes has special meaning - no checksum; if you get > > it from (1), send all-ones instead. > > > > (3) for v6 UDP we have the same remapping as in (2), but all-zeroes has > > different meaning - not "ignore checksum" as in v4, but "reject the > > packet". > > > > (4) there is no (4). > > > > IOW, nobody except UDP has any business doing that 0->0xffff > > replacement. However, we have > > if (icmp6h->icmp6_cksum == 0) > > icmp6h->icmp6_cksum = -1; > > This doesn't look necessary, RFCs 4443/2463 don't mention it being > necessary, and BSD doesn't do it either. I'll cook-up a patch to remove > that since I was doing some other mods in that codepath. This is how things look to me too. > > and similar in net/ipv6/raw.c > > Maybe here it only needs to be done if (fl->proto == IPPROTO_UDP)? Yes, I believe that is what is needed. ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] IPv6: only modify checksum for UDP 2006-11-09 23:14 ` David Miller @ 2006-11-10 16:24 ` Brian Haley 2006-11-10 17:54 ` David Stevens 2006-11-10 22:55 ` David Miller 2006-11-10 16:25 ` [PATCH] IPv6: optimize echo reply checksum calculation Brian Haley 2006-11-11 18:07 ` why do we mangle checksums for v6 ICMP? Bill Fink 2 siblings, 2 replies; 26+ messages in thread From: Brian Haley @ 2006-11-10 16:24 UTC (permalink / raw) To: David Miller; +Cc: viro, netdev [-- Attachment #1: Type: text/plain, Size: 176 bytes --] Only change upper-layer checksum from 0 to 0xFFFF for UDP (as RFC 768 states), not for others as RFC 4443 doesn't require it. Signed-off-by: Brian Haley <brian.haley@hp.com> [-- Attachment #2: cksum.zero.diff --] [-- Type: text/x-patch, Size: 721 bytes --] diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 81bd45b..dbb9b1f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -246,8 +246,6 @@ static int icmpv6_push_pending_frames(st len, fl->proto, tmp_csum); icmp6h->icmp6_cksum = tmp_csum; } - if (icmp6h->icmp6_cksum == 0) - icmp6h->icmp6_cksum = -1; ip6_push_pending_frames(sk); out: return err; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6bc6655..baf7b82 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -536,7 +536,7 @@ static int rawv6_push_pending_frames(str &fl->fl6_dst, total_len, fl->proto, tmp_csum); - if (tmp_csum == 0) + if (tmp_csum == 0 && fl->proto == IPPROTO_UDP) tmp_csum = -1; csum = tmp_csum; ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley @ 2006-11-10 17:54 ` David Stevens 2006-11-14 0:50 ` David Miller 2006-11-10 22:55 ` David Miller 1 sibling, 1 reply; 26+ messages in thread From: David Stevens @ 2006-11-10 17:54 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev, netdev-owner, viro Sorry, I saw this discussion a little late... The Internet checksum is defined as a 1's-complement sum, so if the alternate 0 does not have a special meaning in a protocol, then by 1's-complement arithmetic, 0 == ~0. So, it looks to me without the remapping that a valid checksum may also fail, if it is simply computed in a different way (or on a different architecture) such that one gets 0 and one gets ~0 as un-modified answers. Since we're checking for equality on 2's-complement machines, I think the easiest thing is to still re-map it. Otherwise, instead of testing for 0, we have to test for both 0 and ~0 in the validity checks, right? Disclaimer: I've just glanced through the discussion, so maybe I've misunderstood the point or effect of the patch... +-DLS ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 17:54 ` David Stevens @ 2006-11-14 0:50 ` David Miller 2006-11-14 1:18 ` Al Viro 2006-11-14 1:44 ` David Stevens 0 siblings, 2 replies; 26+ messages in thread From: David Miller @ 2006-11-14 0:50 UTC (permalink / raw) To: dlstevens; +Cc: brian.haley, netdev, netdev-owner, viro From: David Stevens <dlstevens@us.ibm.com> Date: Fri, 10 Nov 2006 09:54:58 -0800 > The Internet checksum is defined as a 1's-complement sum, so if the > alternate 0 does not have a special meaning in a protocol, then by > 1's-complement arithmetic, 0 == ~0. > So, it looks to me without the remapping that a valid checksum > may also fail, if it is simply computed in a different way (or on a > different > architecture) such that one gets 0 and one gets ~0 as un-modified answers. > Since we're checking for equality on 2's-complement machines, > I think the easiest thing is to still re-map it. Otherwise, instead of > testing > for 0, we have to test for both 0 and ~0 in the validity checks, right? Puzzling :-) Then why is the transformation only performed for UDP in the ipv4 stack? It seems by your logic TCP would need to either do the "if (sum==0) sum=~0;" thing or it would need to accept both "0" and "~0" in the checksum checking path. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-14 0:50 ` David Miller @ 2006-11-14 1:18 ` Al Viro 2006-11-14 1:44 ` David Stevens 1 sibling, 0 replies; 26+ messages in thread From: Al Viro @ 2006-11-14 1:18 UTC (permalink / raw) To: David Miller; +Cc: dlstevens, brian.haley, netdev, netdev-owner On Mon, Nov 13, 2006 at 04:50:58PM -0800, David Miller wrote: > From: David Stevens <dlstevens@us.ibm.com> > Date: Fri, 10 Nov 2006 09:54:58 -0800 > > > The Internet checksum is defined as a 1's-complement sum, so if the > > alternate 0 does not have a special meaning in a protocol, then by > > 1's-complement arithmetic, 0 == ~0. Nope. It isn't. > > So, it looks to me without the remapping that a valid checksum > > may also fail, if it is simply computed in a different way (or on a > > different > > architecture) such that one gets 0 and one gets ~0 as un-modified answers. > > Since we're checking for equality on 2's-complement machines, > > I think the easiest thing is to still re-map it. Otherwise, instead of > > testing > > for 0, we have to test for both 0 and ~0 in the validity checks, right? > > Puzzling :-) Then why is the transformation only performed for > UDP in the ipv4 stack? It seems by your logic TCP would need > to either do the "if (sum==0) sum=~0;" thing or it would need > to accept both "0" and "~0" in the checksum checking path. The check is "1's compelement sum of entire packet (including the checksum) is 0xffff". So unless *everything* *else* in the packet is 0, 0x0000 and 0xffff in checksum are the same. And for very obvious reasons "everything else is 0" won't be recognized as valid packet anyway... The following is true: for any x except 0 we have x # 0xffff equal to x for any x we have x # 0 equal to x x # y is 0 if and only if both x and y are 0. So unless the sum of all words except the checksum is 0 (i.e. all words are except the checksum are 0), 0 and 0xffff in checksum will result in the same total sums. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-14 0:50 ` David Miller 2006-11-14 1:18 ` Al Viro @ 2006-11-14 1:44 ` David Stevens 2006-11-14 1:52 ` Al Viro 1 sibling, 1 reply; 26+ messages in thread From: David Stevens @ 2006-11-14 1:44 UTC (permalink / raw) To: David Miller; +Cc: brian.haley, netdev, netdev-owner, viro David Miller <davem@davemloft.net> wrote on 11/13/2006 04:50:58 PM: > Puzzling :-) Then why is the transformation only performed for > UDP in the ipv4 stack? It seems by your logic TCP would need > to either do the "if (sum==0) sum=~0;" thing or it would need > to accept both "0" and "~0" in the checksum checking path. That's actually what I was suggesting. In 1's-complement, ~0 == -0 which is still 0, so barring any special case (like UDP's "0 means no checksum" rule), it should be equally valid for a packet to have 0 or ~0 as the checksum (with otherwise identical data)-- they are both correct, and equal to each other. That extra 1's-complement 0 is, of course, why UDP can have the special case of remapping 0->~0. Since the patch was for output-side, it doesn't matter whether you remap 0 to ~0 or not (except for the special case), but a receiver technically should allow either. In practice, it won't matter if the machines you're talking to are remapping (or not) in the same way. But 0 and -0 (aka ~0) are still equal. :-) It obviously doesn't come up much. +-DLS ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-14 1:44 ` David Stevens @ 2006-11-14 1:52 ` Al Viro 0 siblings, 0 replies; 26+ messages in thread From: Al Viro @ 2006-11-14 1:52 UTC (permalink / raw) To: David Stevens; +Cc: David Miller, brian.haley, netdev, netdev-owner On Mon, Nov 13, 2006 at 05:44:12PM -0800, David Stevens wrote: > That's actually what I was suggesting. In 1's-complement, > ~0 == -0 which is still 0, so barring any special case (like UDP's > "0 means no checksum" rule), it should be equally valid for a > packet to have 0 or ~0 as the checksum (with otherwise identical > data)-- they are both correct, and equal to each other. That > extra 1's-complement 0 is, of course, why UDP can have the > special case of remapping 0->~0. > Since the patch was for output-side, it doesn't matter > whether you remap 0 to ~0 or not (except for the special case), > but a receiver technically should allow either. Could you please take a break from your Richard B. Johnson imitations and read the fscking RFC? ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley 2006-11-10 17:54 ` David Stevens @ 2006-11-10 22:55 ` David Miller 2006-11-10 23:17 ` Nivedita Singhvi 1 sibling, 1 reply; 26+ messages in thread From: David Miller @ 2006-11-10 22:55 UTC (permalink / raw) To: brian.haley; +Cc: viro, netdev From: Brian Haley <brian.haley@hp.com> Date: Fri, 10 Nov 2006 11:24:45 -0500 > Only change upper-layer checksum from 0 to 0xFFFF for UDP (as RFC 768 > states), not for others as RFC 4443 doesn't require it. > > Signed-off-by: Brian Haley <brian.haley@hp.com> Applied, thanks Brian. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 22:55 ` David Miller @ 2006-11-10 23:17 ` Nivedita Singhvi 2006-11-10 23:26 ` David Miller 0 siblings, 1 reply; 26+ messages in thread From: Nivedita Singhvi @ 2006-11-10 23:17 UTC (permalink / raw) To: David Miller; +Cc: brian.haley, viro, netdev David Miller wrote: > From: Brian Haley <brian.haley@hp.com> > Date: Fri, 10 Nov 2006 11:24:45 -0500 > >> Only change upper-layer checksum from 0 to 0xFFFF for UDP (as RFC 768 >> states), not for others as RFC 4443 doesn't require it. >> >> Signed-off-by: Brian Haley <brian.haley@hp.com> > > Applied, thanks Brian. Brian Haley wrote: > Al Viro wrote: >> Could you fscking read what you've replied to? Your -=1 will turn 0 >> into 0xffff instead of correct 0xfffe. IOW, it's broken in 1:65536 >> cases. > > I looked again at your previous email: > >> Note that even on little-endian you want >> 3 -> 2 >> 2 -> 1 >> 1 -> 0xffff >> 0 -> 0xfffe > > That doesn't look right to me, but I'll take your word that there's one > edge case out there I don't see (even though this worked on Alpha). > Forget about the patch then. Er, given all of the above, Brian, could you share your test cases and/or other/any information on testing this? thanks, Nivedita ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 23:17 ` Nivedita Singhvi @ 2006-11-10 23:26 ` David Miller 2006-11-10 23:36 ` Nivedita Singhvi 2006-11-12 1:30 ` Brian Haley 0 siblings, 2 replies; 26+ messages in thread From: David Miller @ 2006-11-10 23:26 UTC (permalink / raw) To: niv; +Cc: brian.haley, viro, netdev From: Nivedita Singhvi <niv@us.ibm.com> Date: Fri, 10 Nov 2006 15:17:06 -0800 WATCH YOUR QUOTING! > David Miller wrote: > > From: Brian Haley <brian.haley@hp.com> > > Date: Fri, 10 Nov 2006 11:24:45 -0500 > > > >> Only change upper-layer checksum from 0 to 0xFFFF for UDP (as RFC 768 > >> states), not for others as RFC 4443 doesn't require it. > >> > >> Signed-off-by: Brian Haley <brian.haley@hp.com> > > > > Applied, thanks Brian. I applied Brian's FIRST PATCH, which is fine. > Brian Haley wrote: > > Al Viro wrote: > >> Could you fscking read what you've replied to? Your -=1 will turn 0 > >> into 0xffff instead of correct 0xfffe. IOW, it's broken in 1:65536 > >> cases. > > > > I looked again at your previous email: > > > >> Note that even on little-endian you want > >> 3 -> 2 > >> 2 -> 1 > >> 1 -> 0xffff > >> 0 -> 0xfffe > > > > That doesn't look right to me, but I'll take your word that there's one > > edge case out there I don't see (even though this worked on Alpha). > > Forget about the patch then. > > Er, given all of the above, Brian, could you share your test cases > and/or other/any information on testing this? This is a discussion about Brian's SECOND PATCH which needs fixups. Please don't quote things out of context like this! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 23:26 ` David Miller @ 2006-11-10 23:36 ` Nivedita Singhvi 2006-11-12 1:30 ` Brian Haley 1 sibling, 0 replies; 26+ messages in thread From: Nivedita Singhvi @ 2006-11-10 23:36 UTC (permalink / raw) To: David Miller; +Cc: brian.haley, viro, netdev David Miller wrote: > From: Nivedita Singhvi <niv@us.ibm.com> > Date: Fri, 10 Nov 2006 15:17:06 -0800 > > WATCH YOUR QUOTING! That explains it! Arghhhh! Sorry, DaveM, a bit on autopilot trying to put some tests together.. thanks, Nivedita ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: only modify checksum for UDP 2006-11-10 23:26 ` David Miller 2006-11-10 23:36 ` Nivedita Singhvi @ 2006-11-12 1:30 ` Brian Haley 1 sibling, 0 replies; 26+ messages in thread From: Brian Haley @ 2006-11-12 1:30 UTC (permalink / raw) To: David Miller; +Cc: niv, viro, netdev > This is a discussion about Brian's SECOND PATCH which needs > fixups. Please forget about the second patch, optimizing this code path isn't worth it if the -1 trick doesn't work in all cases. -Brian ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-09 23:14 ` David Miller 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley @ 2006-11-10 16:25 ` Brian Haley 2006-11-10 17:34 ` Al Viro 2006-11-11 18:07 ` why do we mangle checksums for v6 ICMP? Bill Fink 2 siblings, 1 reply; 26+ messages in thread From: Brian Haley @ 2006-11-10 16:25 UTC (permalink / raw) To: David Miller; +Cc: viro, netdev [-- Attachment #1: Type: text/plain, Size: 269 bytes --] Since the only difference between echo requests and echo replies is the ICMPv6 type value (which is a difference of 1), just subtracting one from the request checksum will result in the correct checksum for the reply. Signed-off-by: Brian Haley <brian.haley@hp.com> [-- Attachment #2: no.cksum.echo.diff --] [-- Type: text/x-patch, Size: 2414 bytes --] diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index dbb9b1f..ee04610 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -212,7 +212,7 @@ static __inline__ int opt_unrec(struct s return (*op & 0xC0) == 0x80; } -static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len) +static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len, int cksum_needed) { struct sk_buff *skb; struct icmp6hdr *icmp6h; @@ -223,7 +223,9 @@ static int icmpv6_push_pending_frames(st icmp6h = (struct icmp6hdr*) skb->h.raw; memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); - icmp6h->icmp6_cksum = 0; + + if (!cksum_needed) + goto sendit; if (skb_queue_len(&sk->sk_write_queue) == 1) { skb->csum = csum_partial((char *)icmp6h, @@ -246,6 +248,7 @@ static int icmpv6_push_pending_frames(st len, fl->proto, tmp_csum); icmp6h->icmp6_cksum = tmp_csum; } +sendit: ip6_push_pending_frames(sk); out: return err; @@ -451,7 +454,7 @@ void icmpv6_send(struct sk_buff *skb, in ip6_flush_pending_frames(sk); goto out_put; } - err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); + err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr), 1); if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH); @@ -489,6 +492,14 @@ static void icmpv6_echo_reply(struct sk_ memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; + /* + * The only difference between echo requests and echo replies is the + * ICMPv6 type value (which is a difference of 1). So if we subtract + * one from the request checksum, it will result in the correct + * checksum for the reply. + */ + tmp_hdr.icmp6_cksum--; + memset(&fl, 0, sizeof(fl)); fl.proto = IPPROTO_ICMPV6; ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr); @@ -540,7 +551,7 @@ static void icmpv6_echo_reply(struct sk_ ip6_flush_pending_frames(sk); goto out_put; } - err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); + err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr), 0); ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES); ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 16:25 ` [PATCH] IPv6: optimize echo reply checksum calculation Brian Haley @ 2006-11-10 17:34 ` Al Viro 2006-11-10 17:51 ` Brian Haley 0 siblings, 1 reply; 26+ messages in thread From: Al Viro @ 2006-11-10 17:34 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev On Fri, Nov 10, 2006 at 11:25:53AM -0500, Brian Haley wrote: > Since the only difference between echo requests and echo replies is the > ICMPv6 type value (which is a difference of 1), just subtracting one > from the request checksum will result in the correct checksum for the reply. Um, no. That will *not* result in correct checksum. Please, RTFRFC 1071. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 17:34 ` Al Viro @ 2006-11-10 17:51 ` Brian Haley 2006-11-10 18:05 ` Al Viro 0 siblings, 1 reply; 26+ messages in thread From: Brian Haley @ 2006-11-10 17:51 UTC (permalink / raw) To: Al Viro; +Cc: David Miller, netdev Al Viro wrote: > On Fri, Nov 10, 2006 at 11:25:53AM -0500, Brian Haley wrote: >> Since the only difference between echo requests and echo replies is the >> ICMPv6 type value (which is a difference of 1), just subtracting one >> from the request checksum will result in the correct checksum for the reply. > > Um, no. That will *not* result in correct checksum. Please, RTFRFC 1071. I verified this works for echo request/reply on my IA64 box, double-checked with ethereal/wireshark. Is there something specific in RFC 1071 that I should be looking for? -Brian ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 17:51 ` Brian Haley @ 2006-11-10 18:05 ` Al Viro 2006-11-10 18:20 ` Al Viro 0 siblings, 1 reply; 26+ messages in thread From: Al Viro @ 2006-11-10 18:05 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev On Fri, Nov 10, 2006 at 12:51:19PM -0500, Brian Haley wrote: > Al Viro wrote: > >On Fri, Nov 10, 2006 at 11:25:53AM -0500, Brian Haley wrote: > >>Since the only difference between echo requests and echo replies is the > >>ICMPv6 type value (which is a difference of 1), just subtracting one > >>from the request checksum will result in the correct checksum for the > >>reply. > > > >Um, no. That will *not* result in correct checksum. Please, RTFRFC 1071. > > I verified this works for echo request/reply on my IA64 box, > double-checked with ethereal/wireshark. Is there something specific in > RFC 1071 that I should be looking for? Definition of checksum. See also include/net/ip.h::ip_decrease_ttl() for similar situation. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 18:05 ` Al Viro @ 2006-11-10 18:20 ` Al Viro 2006-11-10 19:04 ` Brian Haley 0 siblings, 1 reply; 26+ messages in thread From: Al Viro @ 2006-11-10 18:20 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev On Fri, Nov 10, 2006 at 06:05:34PM +0000, Al Viro wrote: > On Fri, Nov 10, 2006 at 12:51:19PM -0500, Brian Haley wrote: > > Al Viro wrote: > > >On Fri, Nov 10, 2006 at 11:25:53AM -0500, Brian Haley wrote: > > >>Since the only difference between echo requests and echo replies is the > > >>ICMPv6 type value (which is a difference of 1), just subtracting one > > >>from the request checksum will result in the correct checksum for the > > >>reply. > > > > > >Um, no. That will *not* result in correct checksum. Please, RTFRFC 1071. > > > > I verified this works for echo request/reply on my IA64 box, > > double-checked with ethereal/wireshark. Is there something specific in > > RFC 1071 that I should be looking for? > > Definition of checksum. > > See also include/net/ip.h::ip_decrease_ttl() for similar situation. Note that even on little-endian you want 3 -> 2 2 -> 1 1 -> 0xffff 0 -> 0xfffe On big-endian you get 0x102 -> 2 0x101 -> 1 0x100 -> 0xffff 0xff -> 0xfffe ... 0 -> 0xfeff so -= 1 is broken even on ia64 and it's *always* broken on big-endian boxen. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 18:20 ` Al Viro @ 2006-11-10 19:04 ` Brian Haley 2006-11-10 19:17 ` Al Viro 0 siblings, 1 reply; 26+ messages in thread From: Brian Haley @ 2006-11-10 19:04 UTC (permalink / raw) To: Al Viro; +Cc: David Miller, netdev Al Viro wrote: > so -= 1 is broken even on ia64 and it's *always* broken on big-endian > boxen. It's not broken in ia64, I've tested that, just don't have an x86 for testing right now. Can you please apply these changes and prove it's broken? This little trick has been done in other UNIXes for years without any problems. -Brian ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 19:04 ` Brian Haley @ 2006-11-10 19:17 ` Al Viro 2006-11-10 21:06 ` Brian Haley 0 siblings, 1 reply; 26+ messages in thread From: Al Viro @ 2006-11-10 19:17 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev On Fri, Nov 10, 2006 at 02:04:32PM -0500, Brian Haley wrote: > Al Viro wrote: > >so -= 1 is broken even on ia64 and it's *always* broken on big-endian > >boxen. > > It's not broken in ia64, I've tested that, just don't have an x86 for > testing right now. Can you please apply these changes and prove it's > broken? This little trick has been done in other UNIXes for years > without any problems. Could you fscking read what you've replied to? Your -=1 will turn 0 into 0xffff instead of correct 0xfffe. IOW, it's broken in 1:65536 cases. On big-endian boxen (which x86 is not, BTW), it will *always* give the wrong result. -= htons(0x100) is better, but still fscks up in 1:256. You _can_ adjust the checksum; however it's not that trivial. One working variant is if (sum > htons(0x100) sum -= htons(0x100); else sum += 0xffff - htons(0x100); In little-endian case it turns into if (sum > 1) sum--; else sum += 0xfffe; which is why your variant breaks rarely on itanic (or x86 - they are not different in that respect). You still need to handle that corner case, though. As for the various Unices doing the same trick, I suggest you to check what they _really_ do and report bugs for those that have pure -- and nothing else. Again, the checksum is sum modulo 0xffff, *not* 0x10000. And endianness matters, of course, since the packet type is either LSB or MSB, depending on it. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 19:17 ` Al Viro @ 2006-11-10 21:06 ` Brian Haley 2006-11-11 1:45 ` Al Viro 0 siblings, 1 reply; 26+ messages in thread From: Brian Haley @ 2006-11-10 21:06 UTC (permalink / raw) To: Al Viro; +Cc: David Miller, netdev Al Viro wrote: > On Fri, Nov 10, 2006 at 02:04:32PM -0500, Brian Haley wrote: >> Al Viro wrote: >>> so -= 1 is broken even on ia64 and it's *always* broken on big-endian >>> boxen. >> It's not broken in ia64, I've tested that, just don't have an x86 for >> testing right now. Can you please apply these changes and prove it's >> broken? This little trick has been done in other UNIXes for years >> without any problems. > > Could you fscking read what you've replied to? Your -=1 will turn 0 > into 0xffff instead of correct 0xfffe. IOW, it's broken in 1:65536 > cases. I looked again at your previous email: > Note that even on little-endian you want > 3 -> 2 > 2 -> 1 > 1 -> 0xffff > 0 -> 0xfffe That doesn't look right to me, but I'll take your word that there's one edge case out there I don't see (even though this worked on Alpha). Forget about the patch then. -Brian ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] IPv6: optimize echo reply checksum calculation 2006-11-10 21:06 ` Brian Haley @ 2006-11-11 1:45 ` Al Viro 0 siblings, 0 replies; 26+ messages in thread From: Al Viro @ 2006-11-11 1:45 UTC (permalink / raw) To: Brian Haley; +Cc: David Miller, netdev On Fri, Nov 10, 2006 at 04:06:52PM -0500, Brian Haley wrote: > Al Viro wrote: > >On Fri, Nov 10, 2006 at 02:04:32PM -0500, Brian Haley wrote: > >>Al Viro wrote: > >>>so -= 1 is broken even on ia64 and it's *always* broken on big-endian > >>>boxen. > >>It's not broken in ia64, I've tested that, just don't have an x86 for > >>testing right now. Can you please apply these changes and prove it's > >>broken? This little trick has been done in other UNIXes for years > >>without any problems. > > > >Could you fscking read what you've replied to? Your -=1 will turn 0 > >into 0xffff instead of correct 0xfffe. IOW, it's broken in 1:65536 > >cases. > > I looked again at your previous email: > > >Note that even on little-endian you want > > 3 -> 2 > > 2 -> 1 > > 1 -> 0xffff > > 0 -> 0xfffe > > That doesn't look right to me, but I'll take your word that there's one > edge case out there I don't see (even though this worked on Alpha). Sigh... Here's how the checksum is defined: take array of bytes pad it to even length with 0 split it into 16bit words define x # y as (x + y) < 0x10000 ? x + y: x + y - 0xffff calculate sum = w0 # w1 # w2 # ..... # wn take 0xffff - sum (aka ~sum) store the resulting value in pair of bytes (with whatever endianness you used all along). Note that resulting pair of bytes does *not* depend on endianness. See aforementioned RFC for proof and for more fun properties of that sucker. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: why do we mangle checksums for v6 ICMP? 2006-11-09 23:14 ` David Miller 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley 2006-11-10 16:25 ` [PATCH] IPv6: optimize echo reply checksum calculation Brian Haley @ 2006-11-11 18:07 ` Bill Fink 2006-11-13 7:04 ` David Miller 2 siblings, 1 reply; 26+ messages in thread From: Bill Fink @ 2006-11-11 18:07 UTC (permalink / raw) To: David Miller; +Cc: brian.haley, viro, netdev On Thu, 09 Nov 2006, David Miller wrote: > From: Brian Haley <brian.haley@hp.com> > Date: Thu, 09 Nov 2006 12:32:18 -0500 > > > Al Viro wrote: > > > AFAICS, the rules are: > > > > > > (1) checksum is 16-bit one's complement of the one's complement sum of > > > relevant 16bit words. > > > > > > (2) for v4 UDP all-zeroes has special meaning - no checksum; if you get > > > it from (1), send all-ones instead. > > > > > > (3) for v6 UDP we have the same remapping as in (2), but all-zeroes has > > > different meaning - not "ignore checksum" as in v4, but "reject the > > > packet". > > > > > > (4) there is no (4). > > > > > > IOW, nobody except UDP has any business doing that 0->0xffff > > > replacement. However, we have > > > if (icmp6h->icmp6_cksum == 0) > > > icmp6h->icmp6_cksum = -1; > > > > This doesn't look necessary, RFCs 4443/2463 don't mention it being > > necessary, and BSD doesn't do it either. I'll cook-up a patch to remove > > that since I was doing some other mods in that codepath. > > This is how things look to me too. > > > > and similar in net/ipv6/raw.c > > > > Maybe here it only needs to be done if (fl->proto == IPPROTO_UDP)? > > Yes, I believe that is what is needed. On a raw IPv6 socket, shouldn't the IP checksum just be left unchanged, so you can test transmission of IPv6 packets with an invalid zero IP checksum. Or is raw not fully raw? -Bill ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: why do we mangle checksums for v6 ICMP? 2006-11-11 18:07 ` why do we mangle checksums for v6 ICMP? Bill Fink @ 2006-11-13 7:04 ` David Miller 0 siblings, 0 replies; 26+ messages in thread From: David Miller @ 2006-11-13 7:04 UTC (permalink / raw) To: billfink; +Cc: brian.haley, viro, netdev From: Bill Fink <billfink@mindspring.com> Date: Sat, 11 Nov 2006 13:07:24 -0500 > On a raw IPv6 socket, shouldn't the IP checksum just be left > unchanged, so you can test transmission of IPv6 packets with > an invalid zero IP checksum. Or is raw not fully raw? The code path where we do the "0 --> -1" conversion only executes when inet->hdrincl is false. ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2006-11-14 1:52 UTC | newest] Thread overview: 26+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-11-08 22:13 why do we mangle checksums for v6 ICMP? Al Viro 2006-11-08 22:28 ` Al Viro 2006-11-09 17:32 ` Brian Haley 2006-11-09 23:14 ` David Miller 2006-11-10 16:24 ` [PATCH] IPv6: only modify checksum for UDP Brian Haley 2006-11-10 17:54 ` David Stevens 2006-11-14 0:50 ` David Miller 2006-11-14 1:18 ` Al Viro 2006-11-14 1:44 ` David Stevens 2006-11-14 1:52 ` Al Viro 2006-11-10 22:55 ` David Miller 2006-11-10 23:17 ` Nivedita Singhvi 2006-11-10 23:26 ` David Miller 2006-11-10 23:36 ` Nivedita Singhvi 2006-11-12 1:30 ` Brian Haley 2006-11-10 16:25 ` [PATCH] IPv6: optimize echo reply checksum calculation Brian Haley 2006-11-10 17:34 ` Al Viro 2006-11-10 17:51 ` Brian Haley 2006-11-10 18:05 ` Al Viro 2006-11-10 18:20 ` Al Viro 2006-11-10 19:04 ` Brian Haley 2006-11-10 19:17 ` Al Viro 2006-11-10 21:06 ` Brian Haley 2006-11-11 1:45 ` Al Viro 2006-11-11 18:07 ` why do we mangle checksums for v6 ICMP? Bill Fink 2006-11-13 7:04 ` David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).