[ovs-dev] [PATCH v3 16/16] userspace: add vxlan-gpe support for dpdk netdev

Yi Yang yi.y.yang at intel.com
Mon Feb 6 13:04:50 UTC 2017


Signed-off-by: Yi Yang <yi.y.yang at intel.com>
---
 include/openvswitch/automake.mk |  3 +-
 include/openvswitch/vxlangpe.h  | 80 +++++++++++++++++++++++++++++++++++++++++
 lib/netdev-native-tnl.c         | 59 +++++++++++++++++++++++++++---
 lib/packets.c                   |  2 ++
 4 files changed, 139 insertions(+), 5 deletions(-)
 create mode 100644 include/openvswitch/vxlangpe.h

diff --git a/include/openvswitch/automake.mk b/include/openvswitch/automake.mk
index c0e276f..5f92197 100644
--- a/include/openvswitch/automake.mk
+++ b/include/openvswitch/automake.mk
@@ -29,5 +29,6 @@ openvswitchinclude_HEADERS = \
 	include/openvswitch/uuid.h \
 	include/openvswitch/version.h \
 	include/openvswitch/vconn.h \
-	include/openvswitch/vlog.h
+	include/openvswitch/vlog.h \
+	include/openvswitch/vxlangpe.h
 
diff --git a/include/openvswitch/vxlangpe.h b/include/openvswitch/vxlangpe.h
new file mode 100644
index 0000000..68e2a4f
--- /dev/null
+++ b/include/openvswitch/vxlangpe.h
@@ -0,0 +1,80 @@
+#ifndef __OPENVSWITCH_VXLANGPE_H
+#define __OPENVSWITCH_VXLANGPE_H 1
+
+#include "openvswitch/types.h"
+
+#define u8 uint8_t
+#define u32 uint8_t
+#define __be32 ovs_be32
+
+/*
+ * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|R|Ver|I|P|R|O|       Reserved                |Next Protocol  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                VXLAN Network Identifier (VNI) |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Ver = Version. Indicates VXLAN GPE protocol version.
+ *
+ * P = Next Protocol Bit. The P bit is set to indicate that the
+ *     Next Protocol field is present.
+ *
+ * O = OAM Flag Bit. The O bit is set to indicate that the packet
+ *     is an OAM packet.
+ *
+ * Next Protocol = This 8 bit field indicates the protocol header
+ * immediately following the VXLAN GPE header.
+ *
+ * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
+ */
+
+struct vxlanhdr_gpe {
+#ifdef WORDS_BIGENDIAN
+	u8	reserved_flags2:2,
+		version:2,
+		instance_applied:1,
+		np_applied:1,
+		reserved_flags1:1,
+		oam_flag:1;
+#else
+	u8	oam_flag:1,
+		reserved_flags1:1,
+		np_applied:1,
+		instance_applied:1,
+		version:2,
+		reserved_flags2:2;
+#endif
+	u8	reserved_flags3;
+	u8	reserved_flags4;
+	u8	next_protocol;
+	__be32	vx_vni;
+};
+
+/* VXLAN-GPE header flags. */
+#define VXLAN_HF_VER	((1U <<29) | (1U <<28))
+#define VXLAN_HF_NP	(1U <<26)
+#define VXLAN_HF_OAM	(1U <<24)
+
+#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
+			     0xff)
+
+/* VXLAN-GPE header Next Protocol. */
+#define VXLAN_GPE_NP_IPV4      0x01
+#define VXLAN_GPE_NP_IPV6      0x02
+#define VXLAN_GPE_NP_ETHERNET  0x03
+#define VXLAN_GPE_NP_NSH       0x04
+
+struct vxlan_metadata {
+	u32		gbp;
+	u32		gpe;
+};
+
+#define VXLAN_F_GPE			0x4000
+#define VXLAN_HF_GPE 0x04000000
+
+#define ETH_P_IP        0x0800          /* Internet Protocol packet     */
+#define ETH_P_IPV6      0x86DD          /* IPv6 over bluebook           */
+#define ETH_P_TEB       0x6558          /* Trans Ether Bridging         */
+
+#endif /* __OPENVSWITCH_VXLANGPE_H */
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 52c1c9f..17f591b 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -44,6 +44,7 @@
 #include "unaligned.h"
 #include "unixctl.h"
 #include "openvswitch/vlog.h"
+#include "openvswitch/vxlangpe.h"
 
 VLOG_DEFINE_THIS_MODULE(native_tnl);
 static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
@@ -499,6 +500,7 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
     struct flow_tnl *tnl = &md->tunnel;
     struct vxlanhdr *vxh;
     unsigned int hlen;
+    ovs_be32 vx_flags;
 
     pkt_metadata_init_tnl(md);
     if (VXLAN_HLEN > dp_packet_l4_size(packet)) {
@@ -510,10 +512,34 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
         goto err;
     }
 
-    if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
+    vx_flags = get_16aligned_be32(&vxh->vx_flags);
+    if (vx_flags & htonl(VXLAN_HF_GPE)) {
+	vx_flags &= htonl(~VXLAN_GPE_USED_BITS);
+	struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh;
+	/* Drop the OAM packets */
+	if (gpe->oam_flag)
+	    goto err;
+	switch(gpe->next_protocol) {
+	case VXLAN_GPE_NP_IPV4:
+	    md->packet_ethertype = htons(ETH_P_IP);
+	    break;
+	case VXLAN_GPE_NP_IPV6:
+	    md->packet_ethertype = htons(ETH_P_IPV6);
+	    break;
+	case VXLAN_GPE_NP_ETHERNET:
+	    //packet->md.packet_ethertype = htons(ETH_P_TEB);
+	    md->packet_ethertype = htons(0);
+	    break;
+	default:
+	    /* Unknow next protocol, drop it */
+	    goto err;
+	}
+    }
+
+    if (vx_flags != htonl(VXLAN_FLAGS) ||
        (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
         VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
-                     ntohl(get_16aligned_be32(&vxh->vx_flags)),
+                     ntohl(vx_flags),
                      ntohl(get_16aligned_be32(&vxh->vx_vni)));
         goto err;
     }
@@ -521,6 +547,9 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
     tnl->flags |= FLOW_TNL_F_KEY;
 
     dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
+    if (md->packet_ethertype) {
+        packet->l3_ofs = 0;
+    }
 
     return packet;
 err:
@@ -543,8 +572,30 @@ netdev_vxlan_build_header(const struct netdev *netdev,
 
     vxh = udp_build_header(tnl_cfg, data, params);
 
-    put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
-    put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
+    if(tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GPE)) {
+	struct vxlanhdr_gpe *gpe;
+	gpe = (struct vxlanhdr_gpe *)vxh;
+        put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS | VXLAN_HF_GPE));
+        put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
+	if (tnl_cfg->is_layer3) {
+	    switch(ntohs(params->flow->dl_type)) {
+	    case ETH_P_IP:
+		gpe->next_protocol = VXLAN_GPE_NP_IPV4;
+		break;
+	    case ETH_P_IPV6:
+		gpe->next_protocol = VXLAN_GPE_NP_IPV6;
+		break;
+	    case ETH_P_TEB:
+		gpe->next_protocol = VXLAN_GPE_NP_ETHERNET;
+		break;
+	    }
+	} else {
+	    gpe->next_protocol = VXLAN_GPE_NP_ETHERNET;
+	}
+    } else {
+	put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
+	put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
+    }
 
     ovs_mutex_unlock(&dev->mutex);
     data->header_len += sizeof *vxh;
diff --git a/lib/packets.c b/lib/packets.c
index f9ad79c..299f309 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -231,10 +231,12 @@ push_eth(struct dp_packet *packet, const struct eth_addr *dst,
          const struct eth_addr *src)
 {
     struct eth_header *eh;
+    struct pkt_metadata *md = &packet->md;
 
     eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
     eh->eth_dst = *dst;
     eh->eth_src = *src;
+    eh->eth_type = md->packet_ethertype;
 }
 
 /* Removes Ethernet header, including VLAN header, from 'packet'.
-- 
2.1.0



More information about the dev mailing list