]> git.proxmox.com Git - ovs.git/commitdiff
datapath: Account for "udp: Generic functions to set checksum"
authorJesse Gross <jesse@nicira.com>
Sat, 7 Feb 2015 03:24:32 +0000 (19:24 -0800)
committerJesse Gross <jesse@nicira.com>
Fri, 20 Feb 2015 19:00:31 +0000 (11:00 -0800)
Upstream commit:
    udp: Generic functions to set checksum

    Added udp_set_csum and udp6_set_csum functions to set UDP checksums
    in packets. These are for simple UDP packets such as those that might
    be created in UDP tunnels.

Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Upstream: af5fcba7 ("udp: Generic functions to set checksum")
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Thomas Graf <tgraf@noironetworks.com>
datapath/linux/.gitignore
datapath/linux/Modules.mk
datapath/linux/compat/include/net/udp.h
datapath/linux/compat/udp.c [new file with mode: 0644]

index fb19d78bed1f0270de479ffe4ebfcd1770a9dac8..2fb11988846228eb55da63bc061f8164eb8b3087 100644 (file)
@@ -38,6 +38,7 @@
 /time.c
 /tmp
 /tunnel.c
+/udp.c
 /udp_tunnel.c
 /utils.c
 /vlan.c
index 945f8591108d416b6e4865b3ab0b059b0b03aaab..53865dab9ea0127099997f69e1ebd794723f5de9 100644 (file)
@@ -11,6 +11,7 @@ openvswitch_sources += \
        linux/compat/net_namespace.c \
        linux/compat/reciprocal_div.c \
        linux/compat/skbuff-openvswitch.c \
+       linux/compat/udp.c \
        linux/compat/udp_tunnel.c \
        linux/compat/vxlan.c    \
        linux/compat/utils.c
index 88174aebe2f41916faeb876a66c8414d8c337ae8..f1841d4a24d030978e6ea471b901c04aa263a6ed 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __NET_UDP_WRAPPER_H
 #define __NET_UDP_WRAPPER_H  1
 
+#include <linux/version.h>
 #include_next <net/udp.h>
 
 #ifndef HAVE_UDP_FLOW_SRC_PORT
@@ -34,4 +35,15 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
 }
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+static inline __sum16 udp_v4_check(int len, __be32 saddr,
+                                  __be32 daddr, __wsum base)
+{
+       return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
+}
+
+void udp_set_csum(bool nocheck, struct sk_buff *skb,
+                 __be32 saddr, __be32 daddr, int len);
+#endif
+
 #endif
diff --git a/datapath/linux/compat/udp.c b/datapath/linux/compat/udp.c
new file mode 100644 (file)
index 0000000..a27928f
--- /dev/null
@@ -0,0 +1,43 @@
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+
+#include <net/udp.h>
+
+/* Function to set UDP checksum for an IPv4 UDP packet. This is intended
+ * for the simple case like when setting the checksum for a UDP tunnel.
+ */
+void udp_set_csum(bool nocheck, struct sk_buff *skb,
+                 __be32 saddr, __be32 daddr, int len)
+{
+       struct udphdr *uh = udp_hdr(skb);
+
+       if (nocheck)
+               uh->check = 0;
+       else if (skb_is_gso(skb))
+               uh->check = ~udp_v4_check(len, saddr, daddr, 0);
+       else if (skb_dst(skb) && skb_dst(skb)->dev &&
+                (skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
+
+               BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
+
+               skb->ip_summed = CHECKSUM_PARTIAL;
+               skb->csum_start = skb_transport_header(skb) - skb->head;
+               skb->csum_offset = offsetof(struct udphdr, check);
+               uh->check = ~udp_v4_check(len, saddr, daddr, 0);
+       } else {
+               __wsum csum;
+
+               BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
+
+               uh->check = 0;
+               csum = skb_checksum(skb, 0, len, 0);
+               uh->check = udp_v4_check(len, saddr, daddr, csum);
+               if (uh->check == 0)
+                       uh->check = CSUM_MANGLED_0;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+       }
+}
+
+#endif /* Linux version < 3.16 */