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 <therb...@google.com>
    Signed-off-by: David S. Miller <da...@davemloft.net>

Upstream: af5fcba7 ("udp: Generic functions to set checksum")
Signed-off-by: Jesse Gross <je...@nicira.com>
---
 datapath/linux/.gitignore               |  1 +
 datapath/linux/Modules.mk               |  1 +
 datapath/linux/compat/include/net/udp.h | 12 +++++++++
 datapath/linux/compat/udp.c             | 43 +++++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+)
 create mode 100644 datapath/linux/compat/udp.c

diff --git a/datapath/linux/.gitignore b/datapath/linux/.gitignore
index fb19d78..2fb1198 100644
--- a/datapath/linux/.gitignore
+++ b/datapath/linux/.gitignore
@@ -38,6 +38,7 @@
 /time.c
 /tmp
 /tunnel.c
+/udp.c
 /udp_tunnel.c
 /utils.c
 /vlan.c
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 945f859..53865da 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
@@ -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
diff --git a/datapath/linux/compat/include/net/udp.h 
b/datapath/linux/compat/include/net/udp.h
index 88174ae..f1841d4 100644
--- a/datapath/linux/compat/include/net/udp.h
+++ b/datapath/linux/compat/include/net/udp.h
@@ -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
index 0000000..a27928f
--- /dev/null
+++ b/datapath/linux/compat/udp.c
@@ -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 */
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to