Thread (9 messages) flat view 9 messages, 5 authors, 2014-07-15
STALE4405d

[PATCH 2/2 net-next] vxlan: Minimal support for Generic Protocol Extension (VXLAN-gpe)

From: Thomas Graf <tgraf@suug.ch>
Date: 2014-07-11 16:59:59
Subsystem: networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Check for the presence of the GPE bit and interpret the inner protocol
field accordingly. For now, only ethernet in VXLAN is supported. Other
protocol types will result in the packet being dropped.

Based on original work by Pritesh Kothari.

Cc: Madhu Challa <redacted>
Co-authored-by: Pritesh Kothari (pritkoth) [off-list ref]
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 drivers/net/vxlan.c | 55 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 12 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 2e9fbcc..c9af24b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -65,28 +65,39 @@
 
 /* Base VXLAN header:
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |R|R|R|R|I|R|R|R|               Reserved                        |
+ * |R|R|R|R|I|P|R|R|               Reserved                        |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |                VXLAN Network Identifier (VNI) |   Reserved    |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  * I = 1	VXLAN Network Identifier (VNI) present
+ * P = 1	Generic Protocol Extension (VXLAN-gpe)
+ *
+ * VXLAN-gpe:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|R|R|R|I|1|R|R|   Reserved    |     Inner Protocol Type       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                VXLAN Network Identifier (VNI) |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
+
 /* VXLAN protocol header */
 struct vxlanhdr {
 #ifdef __LITTLE_ENDIAN_BITFIELD
-	__u8	reserved_flags1:3,
+	__u8	reserved_flags1:2,
+		gpe:1,
 		vni_present:1,
 		reserved_flags2:4;
 #elif defined(__BIG_ENDIAN_BITFIELD)
 	__u8	reserved_flags2:4,
 		vni_present:1,
-		reserved_flags1:3;
+		gpe:1,
+		reserved_flags1:2;
 #else
 #error	"Please fix <asm/byteorder.h>"
 #endif
 	__u8	vx_reserved1;
-	__be16	vx_reserved2;
+	__be16	vx_inner_proto; /* Only valid if gpe flag is set */
 	__be32	vx_vni;
 };
 
@@ -98,8 +109,9 @@ union vxlan_oct_hdr {
 #define vxlan_flags(vxh) (((union vxlan_oct_hdr *)(vxh))->octets[0])
 
 enum {
+	VXLAN_FLAG_GPE		= 0x04,
 	VXLAN_FLAG_VNI		= 0x08,
-	VXLAN_FLAG_RESERVED	= 0xF7,
+	VXLAN_FLAG_RESERVED	= 0xF3,
 };
 
 /* UDP port for VXLAN traffic.
@@ -1162,6 +1174,26 @@ static void vxlan_igmp_leave(struct work_struct *work)
 	dev_put(vxlan->dev);
 }
 
+static int vxlan_handle_extensions(struct sk_buff *skb, struct vxlanhdr *vxh)
+{
+	if (!vxh->vni_present) {
+		netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
+			   vxlan_flags(vxh), ntohl(vxh->vx_vni));
+		return -EINVAL;
+	}
+
+	if (vxh->gpe) {
+		/* Only Ethernet in VXLAN supported for now */
+		if (vxh->vx_inner_proto != htons(ETH_P_TEB)) {
+			netdev_dbg(skb->dev, "unsupported inner vxlan proto %#x vni %#x\n",
+				   ntohs(vxh->vx_inner_proto), ntohl(vxh->vx_vni));
+			return -EPFNOSUPPORT;
+		}
+	}
+
+	return 0;
+}
+
 /* Callback from net/ipv4/udp.c to receive packets */
 static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
@@ -1173,11 +1205,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 		goto error;
 
 	vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1);
-	if (!vxh->vni_present) {
-		netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
-			   vxlan_flags(vxh), ntohl(vxh->vx_vni));
-		goto error;
-	}
+
+	if (unlikely(vxlan_flags(vxh) != VXLAN_FLAG_VNI))
+		if (vxlan_handle_extensions(skb, vxh) < 0)
+			goto error;
 
 	if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB)))
 		goto drop;
@@ -1648,7 +1679,7 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
 	vxlan_flags(vxh) = VXLAN_FLAG_VNI;
 	vxh->vx_reserved1 = 0;
-	vxh->vx_reserved2 = 0;
+	vxh->vx_inner_proto = 0;
 	vxh->vx_vni = vni;
 
 	__skb_push(skb, sizeof(*uh));
@@ -1722,7 +1753,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
 	vxlan_flags(vxh) = VXLAN_FLAG_VNI;
 	vxh->vx_reserved1 = 0;
-	vxh->vx_reserved2 = 0;
+	vxh->vx_inner_proto = 0;
 	vxh->vx_vni = vni;
 
 	__skb_push(skb, sizeof(*uh));
-- 
1.9.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help