Hi: This patch is totally untested but shows how we can use xfrm_mode to remove unnecessary code sharing between modes that in fact end up slowing things down. In particular, notice how we've eliminated a double IP header copying for tunnel mode which is in fact the common case.
I need to finish it for IPv6 and actually test this one :) Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e2e4771..30524b9 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -172,11 +172,8 @@ } } ((struct iphdr*)work_buf)->protocol = ah->nexthdr; - skb->nh.raw = skb_pull(skb, ah_hlen); - memcpy(skb->nh.raw, work_buf, iph->ihl*4); - skb->nh.iph->tot_len = htons(skb->len); - skb_pull(skb, skb->nh.iph->ihl*4); - skb->h.raw = skb->data; + skb->h.raw = memcpy(skb->nh.raw, work_buf, iph->ihl * 4) + ah_hlen; + __skb_pull(skb, ah_hlen + iph->ihl * 4); return 0; diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 9d1881c..451803e 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -143,10 +143,8 @@ int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int nfrags; - int encap_len = 0; u8 nexthdr[2]; struct scatterlist *sg; - u8 workbuf[60]; int padlen; if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) @@ -209,7 +207,6 @@ struct udphdr *uh; uh = (struct udphdr *)(iph + 1); - encap_len = (void*)esph - (void*)uh; /* * 1) if the NAT-T peer's IP or port changed then @@ -246,11 +243,9 @@ iph->protocol = nexthdr[1]; pskb_trim(skb, skb->len - alen - padlen - 2); - memcpy(workbuf, skb->nh.raw, iph->ihl*4); - skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); - skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; - memcpy(skb->nh.raw, workbuf, iph->ihl*4); - skb->nh.iph->tot_len = htons(skb->len); + skb->h.raw = __skb_pull(skb, + sizeof(struct ip_esp_hdr) + esp->conf.ivlen) - + iph->ihl * 4; return 0; diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index cd810f4..704937b 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -45,7 +45,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) { int err, plen, dlen; - struct iphdr *iph; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch; struct crypto_tfm *tfm; @@ -74,8 +73,6 @@ skb_put(skb, dlen - plen); memcpy(skb->data, scratch, dlen); - iph = skb->nh.iph; - iph->tot_len = htons(dlen + iph->ihl * 4); out: put_cpu(); return err; @@ -108,9 +105,8 @@ skb->nh.raw += sizeof(struct ip_comp_hdr); memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4); iph = skb->nh.iph; - iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr)); iph->protocol = nexthdr; - skb->h.raw = skb->data; + skb->h.raw = skb->nh.raw; err = ipcomp_decompress(x, skb); out: diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c index e46d9a4..c2e507e 100644 --- a/net/ipv4/xfrm4_mode_transport.c +++ b/net/ipv4/xfrm4_mode_transport.c @@ -40,6 +40,11 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb) { + if (skb->h.raw != skb->nh.raw) + skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, + skb->nh.iph->ihl * 4); + skb->nh.iph->tot_len = htons(skb->len); + skb->h.raw = skb->data; return 0; } diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index f8d880b..a304d1d 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -73,9 +73,11 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) { - struct iphdr *iph = skb->nh.iph; + struct iphdr *iph; int err = -EINVAL; + skb->nh.raw = skb->data; + iph = skb->nh.iph; if (iph->protocol != IPPROTO_IPIP) goto out; if (!pskb_may_pull(skb, sizeof(struct iphdr))) diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c