vxlan: fix wrong usage of VXLAN_VID_MASK

commit dfd8645ea1 wrongly assumes that VXLAN_VDI_MASK includes
eight lower order reserved bits of VNI field that are using for remote
checksum offload.

Right now, when VNI number greater then 0xffff, vxlan_udp_encap_recv()
will always return with 'bad_flag' error, reducing the usable vni range
from 0..16777215 to 0..65535. Also, it doesn't really check whether RCO
bits processed or not.

Fix it by adding new VNI mask which has all 32 bits of VNI field:
24 bits for id and 8 bits for other usage.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexey Kodanev 2015-03-13 19:13:53 +03:00 committed by David S. Miller
parent b57578b3d5
commit 40fb70f3aa
2 changed files with 3 additions and 2 deletions

View File

@ -1218,7 +1218,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
goto drop; goto drop;
flags &= ~VXLAN_HF_RCO; flags &= ~VXLAN_HF_RCO;
vni &= VXLAN_VID_MASK; vni &= VXLAN_VNI_MASK;
} }
/* For backwards compatibility, only allow reserved fields to be /* For backwards compatibility, only allow reserved fields to be
@ -1239,7 +1239,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
flags &= ~VXLAN_GBP_USED_BITS; flags &= ~VXLAN_GBP_USED_BITS;
} }
if (flags || (vni & ~VXLAN_VID_MASK)) { if (flags || vni & ~VXLAN_VNI_MASK) {
/* If there are any unprocessed flags remaining treat /* If there are any unprocessed flags remaining treat
* this as a malformed packet. This behavior diverges from * this as a malformed packet. This behavior diverges from
* VXLAN RFC (RFC7348) which stipulates that bits in reserved * VXLAN RFC (RFC7348) which stipulates that bits in reserved

View File

@ -91,6 +91,7 @@ struct vxlanhdr {
#define VXLAN_N_VID (1u << 24) #define VXLAN_N_VID (1u << 24)
#define VXLAN_VID_MASK (VXLAN_N_VID - 1) #define VXLAN_VID_MASK (VXLAN_N_VID - 1)
#define VXLAN_VNI_MASK (VXLAN_VID_MASK << 8)
#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
struct vxlan_metadata { struct vxlan_metadata {