On Wed, Aug 20, 2003 at 08:16:29AM -0700, David S. Miller wrote: > > And the idea is to replace all of the: > > skb_push(skb, skb->data - skb->mac.raw); > > with: > > skb_push(skb, skb->maclen); > > Right? Eventually yes. > Sounds interesting. There are a few issues. > > 1) packet socket will still need to do the memmove() > 2) getting ->maclen set correctly in all cases might > get tricky > > For #2 it might be simpler to only use skb->maclen when > skb->dev is NULL. > > What do you think? Actually if we require that upon entry into netif_rx that skb->nh.raw and skb->mac.raw are set correctly and are next to each other, then we can avoid having to get mac_len right. This is what the following patch does. Cheers, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.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
Index: include/linux/skbuff.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/linux/skbuff.h,v retrieving revision 1.1.1.8 retrieving revision 1.6 diff -u -r1.1.1.8 -r1.6 --- include/linux/skbuff.h 9 Aug 2003 08:12:03 -0000 1.1.1.8 +++ include/linux/skbuff.h 13 Sep 2003 00:11:55 -0000 1.6 @@ -159,6 +161,7 @@ * @cb: Control buffer. Free for use by every layer. Put private vars here * @len: Length of actual data * @data_len: Data length + * @mac_len: Length of link layer header * @csum: Checksum * @__unused: Dead field, may be reused * @cloned: Head may be cloned (check refcnt to be sure) @@ -199,6 +202,7 @@ struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; + struct ipv6hdr *ipv6h; unsigned char *raw; } h; @@ -227,6 +231,7 @@ unsigned int len, data_len, + mac_len, csum; unsigned char local_df, cloned, Index: net/core/dev.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/core/dev.c,v retrieving revision 1.1.1.17 retrieving revision 1.2 diff -u -r1.1.1.17 -r1.2 --- net/core/dev.c 22 Aug 2003 23:56:14 -0000 1.1.1.17 +++ net/core/dev.c 13 Sep 2003 00:11:55 -0000 1.2 @@ -1547,6 +1547,7 @@ #endif skb->h.raw = skb->nh.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->mac.raw; pt_prev = NULL; rcu_read_lock(); Index: net/ipv4/xfrm4_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_input.c,v retrieving revision 1.1.1.6 retrieving revision 1.9 diff -u -r1.1.1.6 -r1.9 --- net/ipv4/xfrm4_input.c 22 Aug 2003 23:52:18 -0000 1.1.1.6 +++ net/ipv4/xfrm4_input.c 13 Sep 2003 00:11:55 -0000 1.9 @@ -9,6 +9,7 @@ * */ +#include <linux/string.h> #include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> @@ -18,9 +19,10 @@ return xfrm4_rcv_encap(skb, 0); } -static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) +static inline void ipip_ecn_decapsulate(struct sk_buff *skb) { - struct iphdr *inner_iph = skb->nh.iph; + struct iphdr *outer_iph = skb->nh.iph; + struct iphdr *inner_iph = skb->h.ipiph; if (INET_ECN_is_ce(outer_iph->tos) && INET_ECN_is_not_ce(inner_iph->tos)) @@ -95,10 +97,16 @@ if (x->props.mode) { if (iph->protocol != IPPROTO_IPIP) goto drop; - skb->nh.raw = skb->data; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; if (!(x->props.flags & XFRM_STATE_NOECN)) - ipip_ecn_decapsulate(iph, skb); - iph = skb->nh.iph; + ipip_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); decaps = 1; break; Index: net/ipv6/xfrm6_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/xfrm6_input.c,v retrieving revision 1.1.1.7 retrieving revision 1.8 diff -u -r1.1.1.7 -r1.8 --- net/ipv6/xfrm6_input.c 9 Aug 2003 08:12:04 -0000 1.1.1.7 +++ net/ipv6/xfrm6_input.c 13 Sep 2003 00:11:55 -0000 1.8 @@ -9,17 +9,20 @@ * IPv6 support */ +#include <linux/string.h> #include <net/inet_ecn.h> #include <net/ip.h> #include <net/ipv6.h> #include <net/xfrm.h> -static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph, - struct sk_buff *skb) +static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) { - if (INET_ECN_is_ce(ip6_get_dsfield(iph)) && - INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h))) - IP6_ECN_set_ce(skb->nh.ipv6h); + struct ipv6hdr *outer_iph = skb->nh.ipv6h; + struct ipv6hdr *inner_iph = skb->h.ipv6h; + + if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) && + INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph))) + IP6_ECN_set_ce(inner_iph); } int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) @@ -77,10 +80,16 @@ if (x->props.mode) { /* XXX */ if (nexthdr != IPPROTO_IPV6) goto drop; - skb->nh.raw = skb->data; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; if (!(x->props.flags & XFRM_STATE_NOECN)) - ipip6_ecn_decapsulate(iph, skb); - iph = skb->nh.ipv6h; + ipip6_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; decaps = 1; break; }