* pppoe and receive checksum offload
@ 2005-02-24 23:59 Stephen Hemminger
2005-02-28 4:20 ` David S. Miller
2005-02-28 11:31 ` Herbert Xu
0 siblings, 2 replies; 11+ messages in thread
From: Stephen Hemminger @ 2005-02-24 23:59 UTC (permalink / raw)
To: David S. Miller, mostrows, Alexey Kuznetsov; +Cc: netdev
Someone reported a problem with skge hardware receive checksumming and PPPOE
but it looks like a generic problem. Since PPPOE adds additional header
bytes the hardware computed checksum will be wrong.
Not sure if this is correct, but shouldn't pppoe be doing the following:
-----
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c 2005-02-24 15:40:10 -08:00
+++ b/drivers/net/pppoe.c 2005-02-24 15:40:10 -08:00
@@ -339,6 +339,7 @@
int len = ntohs(ph->length);
skb_pull(skb, sizeof(struct pppoe_hdr));
skb_trim(skb, len);
+ skb->ip_summed = CHECKSUM_NONE;
ppp_input(&po->chan, skb);
} else if (sk->sk_state & PPPOX_RELAY) {
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: pppoe and receive checksum offload 2005-02-24 23:59 pppoe and receive checksum offload Stephen Hemminger @ 2005-02-28 4:20 ` David S. Miller 2005-02-28 9:21 ` Alexey Kuznetsov 2005-02-28 17:12 ` Stephen Hemminger 2005-02-28 11:31 ` Herbert Xu 1 sibling, 2 replies; 11+ messages in thread From: David S. Miller @ 2005-02-28 4:20 UTC (permalink / raw) To: Stephen Hemminger; +Cc: mostrows, kuznet, netdev On Thu, 24 Feb 2005 15:59:06 -0800 Stephen Hemminger <shemminger@osdl.org> wrote: > Someone reported a problem with skge hardware receive checksumming and PPPOE > but it looks like a generic problem. Since PPPOE adds additional header > bytes the hardware computed checksum will be wrong. > > Not sure if this is correct, but shouldn't pppoe be doing the following: Changing or expanding the link level headers should only mess up the hw checksum if you are using CHECKSUM_HW, is that what your skge driver is using? ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 4:20 ` David S. Miller @ 2005-02-28 9:21 ` Alexey Kuznetsov 2005-02-28 17:12 ` Stephen Hemminger 1 sibling, 0 replies; 11+ messages in thread From: Alexey Kuznetsov @ 2005-02-28 9:21 UTC (permalink / raw) To: David S. Miller; +Cc: Stephen Hemminger, mostrows, kuznet, netdev Hello! > Changing or expanding the link level headers should only mess > up the hw checksum if you are using CHECKSUM_HW, is that what > your skge driver is using? Well, even if this driver uses CHECKSUM_UNNECESSARY, the bug is still apparently present for another devices which use CHECKSUM_HW. Actually, the bug is in ppp_input(). It is responsible for setting correct ip_summed before doing netif_rx(). It could even optimize subtracting checksum of stripped ppp header from ip_summed (f.e. ipgre_rcv() do this) But suggested fix is still correct. Unless there are another users of ppp_input() with the same problem. Alexey ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 4:20 ` David S. Miller 2005-02-28 9:21 ` Alexey Kuznetsov @ 2005-02-28 17:12 ` Stephen Hemminger 2005-02-28 23:32 ` David S. Miller 1 sibling, 1 reply; 11+ messages in thread From: Stephen Hemminger @ 2005-02-28 17:12 UTC (permalink / raw) To: David S. Miller; +Cc: mostrows, kuznet, netdev >>Someone reported a problem with skge hardware receive checksumming and PPPOE >>> but it looks like a generic problem. Since PPPOE adds additional header >>> bytes the hardware computed checksum will be wrong. >>> >>> Not sure if this is correct, but shouldn't pppoe be doing the following: > > > Changing or expanding the link level headers should only mess > up the hw checksum if you are using CHECKSUM_HW, is that what > your skge driver is using? The hardware doesn't appear to actually decode the packet, it just has the ability to compute data sum of packet starting at an arbitrary byte offset. This matched the description of CHECKSUM_HW so that is what I used. The original sk98lin attempted to receive hardware checksumming but never actually turned it on. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 17:12 ` Stephen Hemminger @ 2005-02-28 23:32 ` David S. Miller 2005-03-01 0:01 ` shemminger 0 siblings, 1 reply; 11+ messages in thread From: David S. Miller @ 2005-02-28 23:32 UTC (permalink / raw) To: Stephen Hemminger; +Cc: mostrows, kuznet, netdev On Mon, 28 Feb 2005 09:12:52 -0800 Stephen Hemminger <shemminger@osdl.org> wrote: > The original sk98lin attempted to receive hardware checksumming > but never actually turned it on. Because there is a bug in the chip wherein checksums can be miscalculated. I forget the details, but I do remember that you can't enable checksumming safely because of this. In drivers/net/sk98lin/skcsum.c it mentions this: * Note: * There is a bug in the GENESIS ASIC which may lead to wrong checksums. I know this comment is above the send checksum routine, but I am pretty sure the bug applies to both directions. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 23:32 ` David S. Miller @ 2005-03-01 0:01 ` shemminger 0 siblings, 0 replies; 11+ messages in thread From: shemminger @ 2005-03-01 0:01 UTC (permalink / raw) To: David S. Miller; +Cc: Stephen Hemminger, mostrows, kuznet, netdev > On Mon, 28 Feb 2005 09:12:52 -0800 > Stephen Hemminger <shemminger@osdl.org> wrote: > >> The original sk98lin attempted to receive hardware checksumming >> but never actually turned it on. > > Because there is a bug in the chip wherein checksums can be > miscalculated. I forget the details, but I do remember that > you can't enable checksumming safely because of this. > > In drivers/net/sk98lin/skcsum.c it mentions this: > > * Note: > * There is a bug in the GENESIS ASIC which may lead to wrong > checksums. > > I know this comment is above the send checksum routine, but I > am pretty sure the bug applies to both directions. The driver covers two types of chips (Genesis and Yukon). The new driver only allows receive checksum on Yukon chipset. Almost all current hardware uses Yukon and it has been pretty well tested. The issues the sk98lin had were sloppy coding and handling of unsigned arithmetic. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-24 23:59 pppoe and receive checksum offload Stephen Hemminger 2005-02-28 4:20 ` David S. Miller @ 2005-02-28 11:31 ` Herbert Xu 2005-02-28 11:39 ` Herbert Xu 1 sibling, 1 reply; 11+ messages in thread From: Herbert Xu @ 2005-02-28 11:31 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David S. Miller, mostrows, Alexey Kuznetsov, netdev On Thu, Feb 24, 2005 at 11:59:06PM +0000, Stephen Hemminger wrote: > > Not sure if this is correct, but shouldn't pppoe be doing the following: > ----- > diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c > --- a/drivers/net/pppoe.c 2005-02-24 15:40:10 -08:00 > +++ b/drivers/net/pppoe.c 2005-02-24 15:40:10 -08:00 > @@ -339,6 +339,7 @@ > int len = ntohs(ph->length); > skb_pull(skb, sizeof(struct pppoe_hdr)); > skb_trim(skb, len); > + skb->ip_summed = CHECKSUM_NONE; This penalises CHECKSUM_HW. We should have a generic helper function that does the checksum folding for CHECKSUM_HW and if otherwise set ip_summed to CHECKSUM_NONE. In fact it looks like the current code in ip_gre is broken in this respect as well. Let me whip up a patch tomorrow. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 11:31 ` Herbert Xu @ 2005-02-28 11:39 ` Herbert Xu 2005-02-28 14:04 ` Alexey Kuznetsov 0 siblings, 1 reply; 11+ messages in thread From: Herbert Xu @ 2005-02-28 11:39 UTC (permalink / raw) To: Stephen Hemminger; +Cc: David S. Miller, mostrows, Alexey Kuznetsov, netdev On Mon, Feb 28, 2005 at 10:31:06PM +1100, herbert wrote: > > In fact it looks like the current code in ip_gre is broken > in this respect as well. Actually ip_gre is probably right. It seems that CHECKSUM_UNNECESSARY should not be set for PPPOE/GRE packets at all. So it would be a bug in the sk* driver. Alexey/Dave, is this interpretation of ip_summed correct? Of course we still need to fix up CHECKSUM_HW in pppoe. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 11:39 ` Herbert Xu @ 2005-02-28 14:04 ` Alexey Kuznetsov 2005-03-01 1:04 ` Herbert Xu 0 siblings, 1 reply; 11+ messages in thread From: Alexey Kuznetsov @ 2005-02-28 14:04 UTC (permalink / raw) To: Herbert Xu Cc: Stephen Hemminger, David S. Miller, mostrows, Alexey Kuznetsov, netdev Hello! > Actually ip_gre is probably right. It seems that CHECKSUM_UNNECESSARY > should not be set for PPPOE/GRE packets at all. So it would be a bug in > the sk* driver. > > Alexey/Dave, is this interpretation of ip_summed correct? What's about CHECKSUM_UNNECESSARY, yes, it is set only for TCP/UDP packets, when device verifies the checksum itself. It is not the case for PPOE frames. CHECKSUM_HW is more flxible, ipip/gre tunnels use this adjusting skb->csum by checksum of stripped headers. ppp_input() could do the same thing. It does not, hence suggested patch is corrrect minimal solution. Alexey ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-02-28 14:04 ` Alexey Kuznetsov @ 2005-03-01 1:04 ` Herbert Xu 2005-03-10 5:13 ` David S. Miller 0 siblings, 1 reply; 11+ messages in thread From: Herbert Xu @ 2005-03-01 1:04 UTC (permalink / raw) To: Alexey Kuznetsov; +Cc: Stephen Hemminger, David S. Miller, mostrows, netdev [-- Attachment #1: Type: text/plain, Size: 559 bytes --] On Mon, Feb 28, 2005 at 05:04:01PM +0300, Alexey Kuznetsov wrote: > > ppp_input() could do the same thing. It does not, hence suggested patch > is corrrect minimal solution. Agreed. We should use Stephen's patch for 2.6.11. For 2.6.12, does this patch look sane? As usual, I'd love to get some better names for the new helper functions. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt [-- Attachment #2: p --] [-- Type: text/plain, Size: 4452 bytes --] ===== drivers/net/pppoe.c 1.48 vs edited ===== --- 1.48/drivers/net/pppoe.c 2005-01-21 16:02:12 +11:00 +++ edited/drivers/net/pppoe.c 2005-03-01 11:20:44 +11:00 @@ -338,7 +338,9 @@ struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; int len = ntohs(ph->length); skb_pull(skb, sizeof(struct pppoe_hdr)); - skb_trim(skb, len); + skb_postpull_rcsum(skb, ph, sizeof(*ph)); + if (pskb_trim_rcsum(skb, len)) + goto abort_kfree; ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { ===== include/linux/skbuff.h 1.60 vs edited ===== --- 1.60/include/linux/skbuff.h 2005-02-06 14:23:06 +11:00 +++ edited/include/linux/skbuff.h 2005-03-01 11:15:43 +11:00 @@ -1054,6 +1054,42 @@ return __skb_linearize(skb, gfp); } +/** + * skb_postpull_rcsum - update checksum for received skb after pull + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * After doing a pull on a received packet, you need to call this to + * update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE + * so that it can be recomputed from scratch. + */ + +static inline void skb_postpull_rcsum(struct sk_buff *skb, + const void *start, int len) +{ + if (skb->ip_summed == CHECKSUM_HW) + skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); +} + +/** + * pskb_trim_rcsum - trim received skb and update checksum + * @skb: buffer to trim + * @len: new length + * + * This is exactly the same as pskb_trim except that it ensures the + * checksum of received packets are still valid after the operation. + */ + +static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) +{ + if (len >= skb->len) + return 0; + if (skb->ip_summed == CHECKSUM_HW) + skb->ip_summed = CHECKSUM_NONE; + return __pskb_trim(skb, len); +} + static inline void *kmap_skb_frag(const skb_frag_t *frag) { #ifdef CONFIG_HIGHMEM ===== net/ipv4/ip_gre.c 1.46 vs edited ===== --- 1.46/net/ipv4/ip_gre.c 2005-01-14 15:41:05 +11:00 +++ edited/net/ipv4/ip_gre.c 2005-03-01 11:17:35 +11:00 @@ -618,10 +618,8 @@ skb->mac.raw = skb->nh.raw; skb->nh.raw = __pskb_pull(skb, offset); + skb_postpull_rcsum(skb, skb->mac.raw, offset); memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); - if (skb->ip_summed == CHECKSUM_HW) - skb->csum = csum_sub(skb->csum, - csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0)); skb->pkt_type = PACKET_HOST; #ifdef CONFIG_NET_IPGRE_BROADCAST if (MULTICAST(iph->daddr)) { ===== net/ipv4/ip_input.c 1.27 vs edited ===== --- 1.27/net/ipv4/ip_input.c 2005-01-27 17:03:17 +11:00 +++ edited/net/ipv4/ip_input.c 2005-03-01 11:21:19 +11:00 @@ -410,10 +410,9 @@ * is IP we can trim to the true length of the frame. * Note this now means skb->len holds ntohs(iph->tot_len). */ - if (skb->len > len) { - __pskb_trim(skb, len); - if (skb->ip_summed == CHECKSUM_HW) - skb->ip_summed = CHECKSUM_NONE; + if (pskb_trim_rcsum(skb, len)) { + IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); + goto drop; } } ===== net/ipv6/ip6_input.c 1.22 vs edited ===== --- 1.22/net/ipv6/ip6_input.c 2004-08-23 18:15:14 +10:00 +++ edited/net/ipv6/ip6_input.c 2005-03-01 11:24:32 +11:00 @@ -95,15 +95,11 @@ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; - if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { - if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){ - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); - goto drop; - } - hdr = skb->nh.ipv6h; - if (skb->ip_summed == CHECKSUM_HW) - skb->ip_summed = CHECKSUM_NONE; + if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { + IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + goto drop; } + hdr = skb->nh.ipv6h; } if (hdr->nexthdr == NEXTHDR_HOP) { @@ -138,7 +134,6 @@ unsigned int nhoff; int nexthdr; u8 hash; - int cksum_sub = 0; skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); @@ -173,11 +168,8 @@ if (ipprot->flags & INET6_PROTO_FINAL) { struct ipv6hdr *hdr; - if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) { - skb->csum = csum_sub(skb->csum, - csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0)); - cksum_sub++; - } + skb_postpull_rcsum(skb, skb->nh.raw, + skb->h.raw - skb->nh.raw); hdr = skb->nh.ipv6h; if (ipv6_addr_is_multicast(&hdr->daddr) && !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: pppoe and receive checksum offload 2005-03-01 1:04 ` Herbert Xu @ 2005-03-10 5:13 ` David S. Miller 0 siblings, 0 replies; 11+ messages in thread From: David S. Miller @ 2005-03-10 5:13 UTC (permalink / raw) To: Herbert Xu; +Cc: kuznet, shemminger, mostrows, netdev On Tue, 1 Mar 2005 12:04:24 +1100 Herbert Xu <herbert@gondor.apana.org.au> wrote: > On Mon, Feb 28, 2005 at 05:04:01PM +0300, Alexey Kuznetsov wrote: > > > > ppp_input() could do the same thing. It does not, hence suggested patch > > is corrrect minimal solution. > > Agreed. We should use Stephen's patch for 2.6.11. > > For 2.6.12, does this patch look sane? As usual, I'd love to get > some better names for the new helper functions. I'm not so picky about the names. Patch applied, thanks Herbert :-) If Stephen cares, he can try to submit his patch for 2.6.11.x via stable@kernel.org, I have no problem with that. ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2005-03-10 5:13 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-02-24 23:59 pppoe and receive checksum offload Stephen Hemminger 2005-02-28 4:20 ` David S. Miller 2005-02-28 9:21 ` Alexey Kuznetsov 2005-02-28 17:12 ` Stephen Hemminger 2005-02-28 23:32 ` David S. Miller 2005-03-01 0:01 ` shemminger 2005-02-28 11:31 ` Herbert Xu 2005-02-28 11:39 ` Herbert Xu 2005-02-28 14:04 ` Alexey Kuznetsov 2005-03-01 1:04 ` Herbert Xu 2005-03-10 5:13 ` David S. 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).