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

        commit 3bf3947526c1053ddf2523f261395d682718f56c
        Author: Tom Herbert <therb...@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 <therb...@google.com>
    Signed-off-by: David S. Miller <da...@davemloft.net>

Upstream: 3bf394 ("vxlan: Improve support for header flags")
Signed-off-by: Thomas Graf <tg...@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

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

Reply via email to