datapath: Account for now exposed VXLAN definitions
authorThomas Graf <tgraf@noironetworks.com>
Tue, 3 Feb 2015 20:53:35 +0000 (21:53 +0100)
committerThomas Graf <tgraf@noironetworks.com>
Tue, 3 Feb 2015 20:56:21 +0000 (21:56 +0100)
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@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@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Upstream: 3bf394 ("vxlan: Improve support for header flags")
Signed-off-by: Thomas Graf <tgraf@noironetworks.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
datapath/linux/compat/include/net/vxlan.h
datapath/linux/compat/vxlan.c

index 83e9210..33dbc28 100644 (file)
@@ -7,9 +7,21 @@
 #include <net/gre.h>
 
 #include <linux/version.h>
+
 #ifdef USE_KERNEL_TUNNEL_API
 #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,
index 7deaa11..1946cac 100644 (file)
 #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));