[ovs-dev] [PATCH v2 1/3] datapath: compat: fix udp checksum calculation

Pravin B Shelar pshelar at ovn.org
Tue Jul 26 22:24:07 UTC 2016


In upstream linux kernel networking stack udp_set_csum() is called
with only udp header applied but in case of compat layer it can
be called with IP header. So following patch take the offset into
account.

Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
 acinclude.m4                            | 1 -
 datapath/linux/compat/include/net/udp.h | 2 +-
 datapath/linux/compat/udp.c             | 5 +++--
 datapath/linux/compat/udp_tunnel.c      | 3 ++-
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 5f38539..3f31e5f 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -639,7 +639,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
                   [OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [inet_get_local_port_range(net],
                                    [OVS_DEFINE([HAVE_UDP_FLOW_SRC_PORT])])])
   OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [udp_v4_check])
-  OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [udp_set_csum])
   OVS_GREP_IFELSE([$KSRC/include/net/udp_tunnel.h], [udp_tunnel_gro_complete])
   OVS_FIND_FIELD_IFELSE([$KSRC/include/net/udp_tunnel.h], [udp_tunnel_sock_cfg],
                         [gro_receive])
diff --git a/datapath/linux/compat/include/net/udp.h b/datapath/linux/compat/include/net/udp.h
index fa49fa5..266e70a 100644
--- a/datapath/linux/compat/include/net/udp.h
+++ b/datapath/linux/compat/include/net/udp.h
@@ -54,7 +54,7 @@ static inline __sum16 udp_v4_check(int len, __be32 saddr,
 }
 #endif
 
-#ifndef HAVE_UDP_SET_CSUM
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
 #define udp_set_csum rpl_udp_set_csum
 void rpl_udp_set_csum(bool nocheck, struct sk_buff *skb,
 		      __be32 saddr, __be32 daddr, int len);
diff --git a/datapath/linux/compat/udp.c b/datapath/linux/compat/udp.c
index f0362b6..4cd22fa 100644
--- a/datapath/linux/compat/udp.c
+++ b/datapath/linux/compat/udp.c
@@ -1,6 +1,6 @@
 #include <linux/version.h>
 
-#ifndef HAVE_UDP_SET_CSUM
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
 
 #include <net/udp.h>
 
@@ -26,12 +26,13 @@ void rpl_udp_set_csum(bool nocheck, struct sk_buff *skb,
 		skb->csum_offset = offsetof(struct udphdr, check);
 		uh->check = ~udp_v4_check(len, saddr, daddr, 0);
 	} else {
+		int l4_offset = skb_transport_offset(skb);
 		__wsum csum;
 
 		BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
 
 		uh->check = 0;
-		csum = skb_checksum(skb, 0, len, 0);
+		csum = skb_checksum(skb, l4_offset, len, 0);
 		uh->check = udp_v4_check(len, saddr, daddr, csum);
 		if (uh->check == 0)
 			uh->check = CSUM_MANGLED_0;
diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c
index 9265c8a..9cf7286 100644
--- a/datapath/linux/compat/udp_tunnel.c
+++ b/datapath/linux/compat/udp_tunnel.c
@@ -203,12 +203,13 @@ static void udp6_set_csum(bool nocheck, struct sk_buff *skb,
 		skb->csum_offset = offsetof(struct udphdr, check);
 		uh->check = ~udp_v6_check(len, saddr, daddr, 0);
 	} else {
+		int l4_offset = skb_transport_offset(skb);
 		__wsum csum;
 
 		BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
 
 		uh->check = 0;
-		csum = skb_checksum(skb, 0, len, 0);
+		csum = skb_checksum(skb, l4_offset, len, 0);
 		uh->check = udp_v6_check(len, saddr, daddr, csum);
 		if (uh->check == 0)
 			uh->check = CSUM_MANGLED_0;
-- 
1.9.1




More information about the dev mailing list