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

Subject: [PATCH] enable UDP checksums
From: Olaf Titz <olaf,AT,bigred,DOT,inka,DOT,de>
Date: Mon, 20 Nov 2000 13:24:03 +0100

Here is a patch to enable UDP checksums with a new "checksum" config
option (applies to 1.4 with some fuzz).
This is also in the current snapshot.

Short explanation: the sk->no_check flag found in cipe_attach() only
has its effects on control packets. Data packets are not sent via the
normal UDP sending mechanism, so cipe_xmit() has to compute their
checksum by itself.

Olaf

--- cipe.h      2000/11/16 16:45:00     1.35
+++ cipe.h      2000/11/19 23:08:34     1.36
@@ -94,6 +94,7 @@
 #define CIPF_MAY_CLEAR          0x0100
 #define CIPF_MAY_STKEY          0x0200
 #define CIPF_MAY_DYNIP          0x0400
+#define CIPF_DO_CSUM           0x0800

 /*** Key exchange related definitions ***/

--- ciped.c     2000/11/16 16:45:01     1.42
+++ ciped.c     2000/11/19 23:08:34     1.43
@@ -508,6 +509,8 @@
         p.flags|=CIPF_MAY_CLEAR;
     if (OI(dynip))
         p.flags|=CIPF_MAY_DYNIP;
+    if (OI(checksum))
+       p.flags|=CIPF_DO_CSUM;
     p.cttl=OI(cttl);
     if (ioctl_setpar(f, device, &p)<0)
        err("opendev: setpar");
--- options.in  2000/09/15 13:12:35     1.3
+++ options.in  2000/11/19 23:08:35     1.4
@@ -67,3 +67,6 @@
  Default is no check for answers.
 dynip   bool
  Assume the carrier is on a dynamic IP address. @xref{Dynamic carrier}.
+checksum bool
+ Use checksummed UDP carrier packets. Only necessary if the network
+ does not like unchecksummed packets.
--- output.c    2000/11/08 23:59:08     1.36
+++ output.c    2000/11/19 23:55:16
@@ -14,6 +14,7 @@

 #include "cipe.h"

+#include <net/checksum.h>
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <linux/if_arp.h>
@@ -311,8 +312,16 @@
         udph->dest   = tunnel->peerport;
         udph->len    = htons(length+sizeof(struct udphdr));
         /* Encrypted packets are checksummed already, so we can safely
-          ignore the UDP checksum */
-        udph->check  = 0;
+          ignore the UDP checksum. Provide a means to do it nonetheless */
+       udph->check  = 0;
+       if (tunnel->flags&CIPF_DO_CSUM) {
+           udph->check=csum_tcpudp_magic(
+               iph->saddr, iph->daddr,
+               length+sizeof(struct udphdr), IPPROTO_UDP,
+               csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+           if (!udph->check)
+               udph->check=-1;
+       }

        tunnel->stat.tx_bytes += skb->len;
        tunnel->stat.tx_packets++;
@@ -557,8 +566,16 @@
         udph->dest   = c->peerport;
         udph->len    = htons(length+sizeof(struct udphdr));
         /* Encrypted packets are checksummed already, so we can safely
-          ignore the UDP checksum */
-        udph->check  = 0;
+          ignore the UDP checksum. Provide a means to do it nonetheless */
+       udph->check  = 0;
+       if (tunnel->flags&CIPF_DO_CSUM) {
+           udph->check=csum_tcpudp_magic(
+               iph->saddr, iph->daddr,
+               length+sizeof(struct udphdr), IPPROTO_UDP,
+               csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+           if (!udph->check)
+               udph->check=-1;
+       }

        skb->ip_hdr             = skb->h.iph;
        skb->protocol           =       htons(ETH_P_IP);
--- sock.c      2000/09/28 22:05:06     1.30
+++ sock.c      2000/11/19 23:57:32     1.31
@@ -552,7 +552,7 @@
     /* Fill an otherwise unused field in the sock struct with this info.
        This field is conveniently named and the kernel uses it only for RPC. 
*/
     sk->user_data=c;
-    sk->no_check=1; /* our packets are checksummed internally */
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;

     /* Set up new socket operations */
     c->udp_prot=sk->prot;
@@ -645,7 +645,7 @@
        Actually, this is very similar to a packet socket!
        The ugly cast saves us one deref in the actual ops */
     sk->protinfo.af_packet.bound_dev=(struct NET_DEVICE *)c;
-    sk->no_check=1; /* our packets are checksummed internally */
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;

     sti();
     return 0;

=== end of patch ===





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