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