[ovs-dev] [PATCH 02/11] datapath: Account for now exposed VXLAN definitions

Thomas Graf tgraf at noironetworks.com
Tue Jan 27 15:35:05 UTC 2015


This brings the compat version of vxlan_udp_encap_recv() and
vxlan_xmit_skb() in line with upstream commit:

	commit 3bf3947526c1053ddf2523f261395d682718f56c
	Author: Tom Herbert <therbert at google.com>
	Date:   Thu Jan 8 12:31:18 2015 -0800

    vxlan: Improve support for header flags

    This patch cleans up the header flags of VXLAN in anticipation of
    defining some new ones:

    - Move header related definitions from vxlan.c to vxlan.h
    - Change VXLAN_FLAGS to be VXLAN_HF_VNI (only currently defined flag)
    - Move check for unknown flags to after we find vxlan_sock, this
      assumes that some flags may be processed based on tunnel
      configuration
    - Add a comment about why the stack treating unknown set flags as an
      error instead of ignoring them

    Signed-off-by: Tom Herbert <therbert at google.com>
    Signed-off-by: David S. Miller <davem at davemloft.net>

Upstream: 3bf394 ("vxlan: Improve support for header flags")
Signed-off-by: Thomas Graf <tgraf at noironetworks.com>
---
 acinclude.m4                              |  2 ++
 datapath/linux/compat/include/net/vxlan.h | 14 +++++++++++-
 datapath/linux/compat/vxlan.c             | 37 ++++++++++++++++++++++---------
 3 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 39ceb50..7db7737 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -387,6 +387,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
 
   OVS_GREP_IFELSE([$KSRC/include/linux/openvswitch.h], [openvswitch_handle_frame_hook],
                   [OVS_DEFINE([HAVE_RHEL_OVS_HOOK])])
+  OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [__NET_VXLAN_H],
+                  [OVS_DEFINE([HAVE_NET_VXLAN_H])])
   OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [vxlan_xmit_skb])
   OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [bool xnet],
                   [OVS_DEFINE([HAVE_VXLAN_XMIT_SKB_XNET_ARG])])
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index 83e9210..f3d93c0 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -7,9 +7,21 @@
 #include <net/gre.h>
 
 #include <linux/version.h>
-#ifdef USE_KERNEL_TUNNEL_API
+
+#ifdef HAVE_NET_VXLAN_H
 #include_next <net/vxlan.h>
+#endif
+
+#ifndef VXLAN_HLEN
+/* VXLAN header flags. */
+#define VXLAN_HF_VNI 0x08000000
 
+#define VXLAN_N_VID     (1u << 24)
+#define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
+#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
+#endif
+
+#ifdef USE_KERNEL_TUNNEL_API
 static inline int rpl_vxlan_xmit_skb(struct vxlan_sock *vs,
                    struct rtable *rt, struct sk_buff *skb,
                    __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 7deaa11..1946cac 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -60,10 +60,6 @@
 #include "vlan.h"
 #ifndef USE_KERNEL_TUNNEL_API
 
-#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
-
-#define VXLAN_FLAGS 0x08000000	/* struct vxlanhdr.vx_flags required value. */
-
 /* VXLAN protocol header */
 struct vxlanhdr {
 	__be32 vx_flags;
@@ -75,18 +71,21 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
 	struct vxlan_sock *vs;
 	struct vxlanhdr *vxh;
+	u32 flags, vni;
 
 	/* Need Vxlan and inner Ethernet header to be present */
 	if (!pskb_may_pull(skb, VXLAN_HLEN))
 		goto error;
 
-	/* Return packets with reserved bits set */
 	vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1);
-	if (vxh->vx_flags != htonl(VXLAN_FLAGS) ||
-	    (vxh->vx_vni & htonl(0xff))) {
-		pr_warn("invalid vxlan flags=%#x vni=%#x\n",
-			ntohl(vxh->vx_flags), ntohl(vxh->vx_vni));
-		goto error;
+	flags = ntohl(vxh->vx_flags);
+	vni = ntohl(vxh->vx_vni);
+
+	if (flags & VXLAN_HF_VNI) {
+		flags &= ~VXLAN_HF_VNI;
+	} else {
+		/* VNI flag always required to be set */
+		goto bad_flags;
 	}
 
 	if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB)))
@@ -96,6 +95,19 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	if (!vs)
 		goto drop;
 
+	if (flags || (vni & 0xff)) {
+		/* If there are any unprocessed flags remaining treat
+		* this as a malformed packet. This behavior diverges from
+		* VXLAN RFC (RFC7348) which stipulates that bits in reserved
+		* in reserved fields are to be ignored. The approach here
+		* maintains compatbility with previous stack code, and also
+		* is more robust and provides a little more security in
+		* adding extensions to VXLAN.
+		*/
+
+		goto bad_flags;
+	}
+
 	vs->rcv(vs, skb, vxh->vx_vni);
 	return 0;
 
@@ -103,6 +115,9 @@ drop:
 	/* Consume bad packet */
 	kfree_skb(skb);
 	return 0;
+bad_flags:
+	pr_debug("invalid vxlan flags=%#x vni=%#x\n",
+		 ntohl(vxh->vx_flags), ntohl(vxh->vx_vni));
 
 error:
 	/* Return non vxlan pkt */
@@ -204,7 +219,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 	skb_reset_inner_headers(skb);
 
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
-	vxh->vx_flags = htonl(VXLAN_FLAGS);
+	vxh->vx_flags = htonl(VXLAN_HF_VNI);
 	vxh->vx_vni = vni;
 
 	__skb_push(skb, sizeof(*uh));
-- 
1.9.3




More information about the dev mailing list