[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