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

Reply via email to