<< | Thread Index | >> ]    [ << | Date Index | >> ]

Subject: [PATCH] Fix for fragmented SKBs under Linux 2.4 + DF/MTU options
From: lf,AT,elemental,DOT,net
Date: Thu, 13 Dec 2001 22:12:13 +0100

Hi all!

        The appended patch contains one bug fix and two new features:

        1. SKBs may be fragmented under Linux 2.4 and CIPE doesn't handle
        this. Normally this bug doesn't surface as it seems that only
        fragmented IP packets result in fragmented SKBs. But with one of the
        force (P)MTU patches installed this leads to CRC errors as CIPE
        doesn't see the whole packet. So this patch to sock.c adds a call to
        skb_linearize which copies the SKB fragments together into one chunk
        of data. This will affect performance a little bit, but I think that
        it might be hard to teach all parts of the CIPE kernel module to
        handle SKB fragments properly.

        2. New option for ciped: "ignoredf". This option disables the copying
        of the DF bit from tunneled IP packets to the IP header of the UDP
        packets.

        3. New option for ciped: "forcemtu". This option forces the (P)MTU
        of routes pointing to the tunnel to the MTU of the tunnel interface.

        Both options (together with setting the MTU of the tunnel interface
        to 1500) should help with bridging and to cope with broken PMTU
        discovery (through wrong ICMP filtering, etc.) on the Internet. But
        note that the increased overhead will affect performance and
        latency.

        This patch is tested under both Linux 2.2 und Linux 2.4 but not
        extensively yet.

Cheers,
Lars.

diff -ur cipe-1.5.2/cipe/cipe.h cipe-1.5.2-mtu/cipe/cipe.h
--- cipe-1.5.2/cipe/cipe.h      Thu Dec 21 11:23:34 2000
+++ cipe-1.5.2-mtu/cipe/cipe.h  Thu Dec 13 22:37:55 2001
@@ -92,11 +92,16 @@
     char                name[IFNAMSIZ];
 };
 
-/* Flag values. */
+/* 
+ * Flag values. Use only the upper 8 bit for external flags. 
+ * See CIPF_MASK_EXT below.
+ */
 #define CIPF_MAY_CLEAR          0x0100
 #define CIPF_MAY_STKEY          0x0200
 #define CIPF_MAY_DYNIP          0x0400
 #define CIPF_DO_CSUM           0x0800
+#define CIPF_IGNORE_DF         0x1000
+#define CIPF_FORCE_MTU         0x2000
 
 /*** Key exchange related definitions ***/
 
@@ -153,6 +158,9 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 #define LINUX_23
 #endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#define LINUX_24
+#endif
 #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)) && 
defined(__i386__)
 #define REGPARM /* __attribute__((regparm,3)) XX needs testing */
 #else
diff -ur cipe-1.5.2/cipe/ciped.c cipe-1.5.2-mtu/cipe/ciped.c
--- cipe-1.5.2/cipe/ciped.c     Sun Feb 11 22:42:39 2001
+++ cipe-1.5.2-mtu/cipe/ciped.c Wed Dec 12 02:09:01 2001
@@ -364,6 +364,10 @@
         p.flags|=CIPF_MAY_DYNIP;
     if (OI(checksum))
        p.flags|=CIPF_DO_CSUM;
+    if (OI(ignoredf))
+       p.flags|=CIPF_IGNORE_DF;
+    if (OI(forcemtu))
+       p.flags|=CIPF_FORCE_MTU;
     p.cttl=OI(cttl);
     if (ioctl_setpar(f, device, &p)<0)
        err("opendev: setpar");
diff -ur cipe-1.5.2/cipe/options.in cipe-1.5.2-mtu/cipe/options.in
--- cipe-1.5.2/cipe/options.in  Mon Nov 20 00:08:35 2000
+++ cipe-1.5.2-mtu/cipe/options.in      Thu Dec 13 23:39:43 2001
@@ -77,3 +77,8 @@
 checksum bool
  Use checksummed UDP carrier packets. Only necessary if the network
  does not like unchecksummed packets.
+ignoredf bool
+ Ignore the DF bit on tunneled IP packets and allow the encapsulated packet 
+ to be fragmented.
+forcemtu bool
+ Force PMTU of routes through the tunnel to the MTU of the tunnel interface.
diff -ur cipe-1.5.2/cipe/output.c cipe-1.5.2-mtu/cipe/output.c
--- cipe-1.5.2/cipe/output.c    Tue May  1 23:23:42 2001
+++ cipe-1.5.2-mtu/cipe/output.c        Wed Dec 12 02:09:01 2001
@@ -133,7 +133,8 @@
                goto tx_error_out;
            }
            tos = old_iph->tos;
-           df = old_iph->frag_off&__constant_htons(IP_DF);
+           if (!tunnel->flags&CIPF_IGNORE_DF)
+               df = old_iph->frag_off&__constant_htons(IP_DF);
            ttl = tunnel->cttl ? tunnel->cttl : old_iph->ttl;
        } else {
            ttl = tunnel->cttl ? tunnel->cttl : 64; /* XX */
@@ -177,12 +178,21 @@
                goto tx_error;
        }
 
-        mtu = rt->u.dst.pmtu - (cipehdrlen+cipefootlen);
-        if (tunnel->sockshost)
-            mtu -= sizeof(struct sockshdr);
+       if (tunnel->flags&CIPF_FORCE_MTU)
+       {
+               mtu = dev->mtu;
+       }
+       else
+       {
+               mtu = rt->u.dst.pmtu - (cipehdrlen+cipefootlen);
+               if (tunnel->sockshost)
+                       mtu -= sizeof(struct sockshdr);
+        }
 
-        dprintk(DEB_OUT, (KERN_DEBUG "pmtu=%d dmtu=%d size=%d\n",
-                          mtu, tdev->mtu, skb->len));
+        dprintk(DEB_OUT, (KERN_DEBUG "pmtu=%d dmtu=%d size=%d df=%d 
+forcemtu=%d ignoredf=%d\n",
+                          mtu, tdev->mtu, skb->len, df, 
+                          (tunnel->flags&CIPF_FORCE_MTU)?1:0,
+                          (tunnel->flags&CIPF_IGNORE_DF)?1:0));
 
        if (mtu < 68) {
                printk(KERN_ERR "%s: MTU too small\n", dev->name);
@@ -192,14 +202,9 @@
        if (skb->dst && mtu < skb->dst->pmtu) {
                skb->dst->pmtu = mtu;
                dprintk(DEB_OUT, (KERN_NOTICE "%s: adjusting PMTU\n", 
dev->name));
-#if 0
-                /* TEST: is this OK? */
-               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, 
htonl(mtu));
-                goto tx_error;
-#endif
         }
 
-       if (old_iph && (old_iph->frag_off&__constant_htons(IP_DF)) && mtu < 
ntohs(old_iph->tot_len)) {
+       if (old_iph && df && mtu < ntohs(old_iph->tot_len)) {
                dprintk(DEB_OUT, (KERN_NOTICE "%s: fragmentation needed\n", 
dev->name));
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, 
htonl(mtu));
                goto tx_error;
diff -ur cipe-1.5.2/cipe/sock.c cipe-1.5.2-mtu/cipe/sock.c
--- cipe-1.5.2/cipe/sock.c      Sun Feb 11 22:42:40 2001
+++ cipe-1.5.2-mtu/cipe/sock.c  Thu Dec 13 23:30:11 2001
@@ -245,6 +245,20 @@
 #endif
     rsport=skb->h.uh->source;
     skb_put(n,skb->len);
+#ifdef LINUX_24
+    if (skb_is_nonlinear(skb)) {
+#ifdef DEBUG
+       dprintk(DEB_INP, (KERN_INFO DEVNAME
+                         ": skb is non linear, will linearize\n"));
+#endif
+       if (skb_linearize(skb, GFP_KERNEL) != 0)
+       {
+               printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n",
+                      c->dev->name);
+               goto error;
+       }
+    }
+#endif 
     memcpy(n->data, skb->h.raw, skb->len);
     n->h.uh=(struct udphdr *)n->data;
 
-- 
Lars Fenneberg, lf,AT,elemental,DOT,net (private), lf,AT,mcs-cityline,DOT,net 
(work)





<< | Thread Index | >> ]    [ << | Date Index | >> ]