fuel-plugin-ovs/ovs_build/patches/0001-ovs-vxlan-gpe-vxlan-ex...

733 lines
27 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 5d79831435ec4e5bea20cc36c3f83eacf6fd065c Mon Sep 17 00:00:00 2001
From: Yi Yang <yi.y.yang@intel.com>
Date: Mon, 11 Apr 2016 15:58:14 +0800
Subject: [PATCH 1/6] ovs-vxlan-gpe: vxlan extension to support vxlan-gpe
tunnel port
Signed-off-by: Mengke Liu <mengke.liu@intel.com>
Signed-off-by: Ricky Li <ricky.li@intel.com>
Signed-off-by: Johnson Li <johnson.li@intel.com>
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
---
datapath/flow_netlink.c | 8 +-
datapath/linux/compat/include/linux/openvswitch.h | 1 +
datapath/linux/compat/include/net/vxlan.h | 73 +++++++++++++++++++
datapath/linux/compat/vxlan.c | 30 ++++++++
datapath/vport-vxlan.c | 15 ++++
lib/flow.c | 8 ++
lib/match.c | 34 +++++++++
lib/match.h | 4 +
lib/meta-flow.c | 36 +++++++++
lib/meta-flow.h | 28 +++++++
lib/netdev-vport.c | 2 +
lib/nx-match.c | 4 +
lib/odp-util.c | 89 ++++++++++++++++++++++-
lib/packets.h | 4 +-
tests/ofproto.at | 4 +-
tests/ovs-ofctl.at | 4 +
16 files changed, 340 insertions(+), 4 deletions(-)
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 6ffcc53..351a504 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -309,6 +309,7 @@ size_t ovs_key_attr_size(void)
static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
[OVS_VXLAN_EXT_GBP] = { .len = sizeof(u32) },
+ [OVS_VXLAN_EXT_GPE] = { .len = sizeof(u32) },
};
static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
@@ -521,6 +522,9 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
case OVS_VXLAN_EXT_GBP:
opts.gbp = nla_get_u32(a);
break;
+ case OVS_VXLAN_EXT_GPE:
+ opts.gpe = nla_get_u32(a);
+ break;
default:
OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
type);
@@ -677,7 +681,9 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb,
if (!nla)
return -EMSGSIZE;
- if (nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
+ if (opts->gbp && nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
+ return -EMSGSIZE;
+ else if (opts->gpe && nla_put_u32(skb, OVS_VXLAN_EXT_GPE, opts->gpe) < 0)
return -EMSGSIZE;
nla_nest_end(skb, nla);
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
index 3b39ebb..44adb81 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -287,6 +287,7 @@ enum ovs_vport_attr {
enum {
OVS_VXLAN_EXT_UNSPEC,
OVS_VXLAN_EXT_GBP, /* Flag or __u32 */
+ OVS_VXLAN_EXT_GPE,
__OVS_VXLAN_EXT_MAX,
};
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index 75a5a7a..2bfc3f8 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -84,6 +84,75 @@ struct vxlanhdr_gbp {
#define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16)
#define VXLAN_GBP_ID_MASK (0xFFFF)
+/*
+ * VXLAN Generic Protocol Extension Extension:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|R|Ver|I|P|R|O|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R| Next Proto |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | VXLAN Network Identifier (VNI) | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * Ver = Version. Indicates VXLAN GPE protocol version. The initial
+ * version is 0. If a receiver does not support the version
+ * indicated it MUST drop the packet.
+ *
+ * I = Instance Bit. The I bit MUST be set to indicate a valid VNI.
+ *
+ * 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.
+ *
+ * [1] https://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-01.txt
+ */
+
+struct vxlanhdr_gpe {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ uint8_t oam_flag:1;
+ uint8_t reserved_flags1:1;
+ uint8_t np_applied:1;
+ uint8_t instance_applied:1;
+ uint8_t gpe_version:2;
+ uint8_t reserved_flags2:2;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ uint8_t reserved_flags2:2;
+ uint8_t gpe_version:2;
+ uint8_t instance_applied:1;
+ uint8_t np_applied:1;
+ uint8_t reserved_flags1:1;
+ uint8_t oam_flag:1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ uint8_t reserved_flags3;
+ uint8_t reserved_flags4;
+ uint8_t next_proto;
+ __be32 vx_vni;
+};
+
+/* 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
+
+/* skb->mark mapping
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|R|Ver|I|P|R|O|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R| Next Proto |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define VXLAN_GPE_OAM_FLAG (BIT(0) << 24)
+#define VXLAN_GPE_NP_APPLIED (BIT(0) << 26)
+#define VXLAN_GPE_INSTANCE_APPLIED (BIT(0) << 27)
+#define VXLAN_GPE_VERSION ((BIT(0) << 28) | (BIT(0) << 29))
+
+#define VXLAN_GPE_NP_MASK (0xFF)
+
+#define VXLAN_GPE_USED_BITS (VXLAN_GPE_OAM_FLAG | VXLAN_GPE_NP_APPLIED \
+ | VXLAN_GPE_INSTANCE_APPLIED | VXLAN_GPE_VERSION | 0xFF)
+
/* VXLAN protocol header:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |G|R|R|R|I|R|R|C| Reserved |
@@ -104,6 +173,7 @@ struct vxlanhdr {
#define VXLAN_HF_RCO BIT(21)
#define VXLAN_HF_VNI BIT(27)
#define VXLAN_HF_GBP BIT(31)
+#define VXLAN_HF_GPE BIT(26)
/* Remote checksum offload header option */
#define VXLAN_RCO_MASK 0x7f /* Last byte of vni field */
@@ -120,6 +190,7 @@ struct vxlanhdr {
struct vxlan_metadata {
__be32 vni;
u32 gbp;
+ u32 gpe;
};
#define VNI_HASH_BITS 10
@@ -205,11 +276,13 @@ struct vxlan_dev {
#define VXLAN_F_GBP 0x800
#define VXLAN_F_REMCSUM_NOPARTIAL 0x1000
#define VXLAN_F_COLLECT_METADATA 0x2000
+#define VXLAN_F_GPE 0x4000
/* Flags that are used in the receive path. These flags must match in
* order for a socket to be shareable
*/
#define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \
+ VXLAN_F_GPE | \
VXLAN_F_UDP_ZERO_CSUM6_RX | \
VXLAN_F_REMCSUM_RX | \
VXLAN_F_REMCSUM_NOPARTIAL | \
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 4faa18f..7ef051c 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -971,6 +971,18 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
md->gbp |= VXLAN_GBP_POLICY_APPLIED;
flags &= ~VXLAN_GBP_USED_BITS;
+ } else if ((flags & VXLAN_HF_GPE) && (vs->flags & VXLAN_F_GPE)) {
+ struct vxlanhdr_gpe *gpe;
+
+ gpe = (struct vxlanhdr_gpe *)vxh;
+ md->gpe = ntohs(gpe->next_proto);
+
+ buf.dst.u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
+
+ if (gpe->oam_flag)
+ md->gpe |= VXLAN_GPE_OAM_FLAG;
+
+ flags &= ~VXLAN_GPE_USED_BITS;
}
if (flags || vni & ~VXLAN_VNI_MASK) {
@@ -1023,6 +1035,22 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
}
+static void vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags,
+ struct vxlan_metadata *md)
+{
+ struct vxlanhdr_gpe *gpe;
+
+ if (!md->gpe)
+ return;
+
+ gpe = (struct vxlanhdr_gpe*)vxh;
+ vxh->vx_flags |= htonl(VXLAN_HF_GPE);
+
+ if (md->gpe & VXLAN_GPE_OAM_FLAG)
+ gpe->oam_flag = 1;
+ gpe->next_proto = md->gpe & VXLAN_GPE_NP_MASK;
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb,
@@ -1106,6 +1134,8 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
if (vxflags & VXLAN_F_GBP)
vxlan_build_gbp_hdr(vxh, vxflags, md);
+ else if (vxflags & VXLAN_F_GPE)
+ vxlan_build_gpe_hdr(vxh, vxflags, md);
ovs_skb_set_inner_protocol(skb, htons(ETH_P_TEB));
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index c05f5d4..5d775cc 100644
--- a/datapath/vport-vxlan.c
+++ b/datapath/vport-vxlan.c
@@ -52,6 +52,18 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
return -EMSGSIZE;
nla_nest_end(skb, exts);
+ } else if (vxlan->flags & VXLAN_F_GPE) {
+ struct nlattr *exts;
+
+ exts = nla_nest_start(skb, OVS_TUNNEL_ATTR_EXTENSION);
+ if (!exts)
+ return -EMSGSIZE;
+
+ if (vxlan->flags & VXLAN_F_GPE &&
+ nla_put_flag(skb, OVS_VXLAN_EXT_GPE))
+ return -EMSGSIZE;
+
+ nla_nest_end(skb, exts);
}
return 0;
@@ -59,6 +71,7 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
static const struct nla_policy exts_policy[OVS_VXLAN_EXT_MAX + 1] = {
[OVS_VXLAN_EXT_GBP] = { .type = NLA_FLAG, },
+ [OVS_VXLAN_EXT_GPE] = { .type = NLA_FLAG, },
};
static int vxlan_configure_exts(struct vport *vport, struct nlattr *attr,
@@ -76,6 +89,8 @@ static int vxlan_configure_exts(struct vport *vport, struct nlattr *attr,
if (exts[OVS_VXLAN_EXT_GBP])
conf->flags |= VXLAN_F_GBP;
+ else if (exts[OVS_VXLAN_EXT_GPE])
+ conf->flags |= VXLAN_F_GPE;
return 0;
}
diff --git a/lib/flow.c b/lib/flow.c
index b9ce331..d24bdc9 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -870,6 +870,12 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
if (flow->tunnel.gbp_flags) {
match_set_tun_gbp_flags(flow_metadata, flow->tunnel.gbp_flags);
}
+ if (flow->tunnel.gpe_np != htons(0)) {
+ match_set_tun_gpe_np(flow_metadata, flow->tunnel.gpe_np);
+ }
+ if (flow->tunnel.gpe_flags) {
+ match_set_tun_gpe_flags(flow_metadata, flow->tunnel.gpe_flags);
+ }
tun_metadata_get_fmd(&flow->tunnel, flow_metadata);
if (flow->metadata != htonll(0)) {
match_set_metadata(flow_metadata, flow->metadata);
@@ -1265,6 +1271,8 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
WC_MASK_FIELD(wc, tunnel.tp_dst);
WC_MASK_FIELD(wc, tunnel.gbp_id);
WC_MASK_FIELD(wc, tunnel.gbp_flags);
+ WC_MASK_FIELD(wc, tunnel.gpe_np);
+ WC_MASK_FIELD(wc, tunnel.gpe_flags);
if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) {
if (flow->tunnel.metadata.present.map) {
diff --git a/lib/match.c b/lib/match.c
index fd571d9..52437c9 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -289,6 +289,32 @@ match_set_tun_gbp_flags(struct match *match, uint8_t flags)
}
void
+match_set_tun_gpe_np_masked(struct match *match, uint8_t np, uint8_t mask)
+{
+ match->wc.masks.tunnel.gpe_np = mask;
+ match->flow.tunnel.gpe_np = np & mask;
+}
+
+void
+match_set_tun_gpe_np(struct match *match, uint8_t np)
+{
+ match_set_tun_gpe_np_masked(match, np, UINT8_MAX);
+}
+
+void
+match_set_tun_gpe_flags_masked(struct match *match, uint8_t flags, uint8_t mask)
+{
+ match->wc.masks.tunnel.gpe_flags = mask;
+ match->flow.tunnel.gpe_flags = flags & mask;
+}
+
+void
+match_set_tun_gpe_flags(struct match *match, uint8_t flags)
+{
+ match_set_tun_gpe_flags_masked(match, flags, UINT8_MAX);
+}
+
+void
match_set_in_port(struct match *match, ofp_port_t ofp_port)
{
match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
@@ -1013,6 +1039,14 @@ format_flow_tunnel(struct ds *s, const struct match *match)
ds_put_format(s, "tun_gbp_flags=%#"PRIx8",", tnl->gbp_flags);
}
+ if (wc->masks.tunnel.gpe_np) {
+ ds_put_format(s, "tun_gpe_np=%#"PRIx8",", tnl->gpe_np);
+ }
+
+ if (wc->masks.tunnel.gpe_flags) {
+ ds_put_format(s, "tun_gpe_flags=%#"PRIx8",", tnl->gpe_flags);
+ }
+
if (wc->masks.tunnel.ip_tos) {
ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
}
diff --git a/lib/match.h b/lib/match.h
index 0a6ac29..48aa0b1 100644
--- a/lib/match.h
+++ b/lib/match.h
@@ -86,6 +86,10 @@ void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16
void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id);
void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask);
void match_set_tun_gbp_flags(struct match *match, uint8_t flags);
+void match_set_tun_gpe_np_masked(struct match *match, uint8_t gpe_np, uint8_t mask);
+void match_set_tun_gpe_np(struct match *match, uint8_t gpe_np);
+void match_set_tun_gpe_flags_masked(struct match *match, uint8_t flags, uint8_t mask);
+void match_set_tun_gpe_flags(struct match *match, uint8_t flags);
void match_set_in_port(struct match *, ofp_port_t ofp_port);
void match_set_pkt_mark(struct match *, uint32_t pkt_mark);
void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 721152c..ab77fca 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -213,6 +213,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
return !wc->masks.tunnel.gbp_id;
case MFF_TUN_GBP_FLAGS:
return !wc->masks.tunnel.gbp_flags;
+ case MFF_TUN_GPE_NP:
+ return !wc->masks.tunnel.gpe_np;
+ case MFF_TUN_GPE_FLAGS:
+ return !wc->masks.tunnel.gpe_flags;
CASE_MFF_TUN_METADATA:
return !ULLONG_GET(wc->masks.tunnel.metadata.present.map,
mf->id - MFF_TUN_METADATA0);
@@ -515,6 +519,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
case MFF_TUN_TTL:
case MFF_TUN_GBP_ID:
case MFF_TUN_GBP_FLAGS:
+ case MFF_TUN_GPE_NP:
+ case MFF_TUN_GPE_FLAGS:
CASE_MFF_TUN_METADATA:
case MFF_METADATA:
case MFF_IN_PORT:
@@ -648,6 +654,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
case MFF_TUN_GBP_FLAGS:
value->u8 = flow->tunnel.gbp_flags;
break;
+ case MFF_TUN_GPE_NP:
+ value->u8 = flow->tunnel.gpe_np;
+ break;
+ case MFF_TUN_GPE_FLAGS:
+ value->u8 = flow->tunnel.gpe_flags;
+ break;
case MFF_TUN_TTL:
value->u8 = flow->tunnel.ip_ttl;
break;
@@ -899,6 +911,12 @@ mf_set_value(const struct mf_field *mf,
case MFF_TUN_GBP_FLAGS:
match_set_tun_gbp_flags(match, value->u8);
break;
+ case MFF_TUN_GPE_NP:
+ match_set_tun_gpe_np(match, value->u8);
+ break;
+ case MFF_TUN_GPE_FLAGS:
+ match_set_tun_gpe_flags(match, value->u8);
+ break;
case MFF_TUN_TOS:
match_set_tun_tos(match, value->u8);
break;
@@ -1216,6 +1234,12 @@ mf_set_flow_value(const struct mf_field *mf,
case MFF_TUN_GBP_FLAGS:
flow->tunnel.gbp_flags = value->u8;
break;
+ case MFF_TUN_GPE_NP:
+ flow->tunnel.gpe_np= value->u8;
+ break;
+ case MFF_TUN_GPE_FLAGS:
+ flow->tunnel.gpe_flags= value->u8;
+ break;
case MFF_TUN_TOS:
flow->tunnel.ip_tos = value->u8;
break;
@@ -1535,6 +1559,12 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
case MFF_TUN_GBP_FLAGS:
match_set_tun_gbp_flags_masked(match, 0, 0);
break;
+ case MFF_TUN_GPE_NP:
+ match_set_tun_gpe_np_masked(match, 0, 0);
+ break;
+ case MFF_TUN_GPE_FLAGS:
+ match_set_tun_gpe_flags_masked(match, 0, 0);
+ break;
case MFF_TUN_TOS:
match_set_tun_tos_masked(match, 0, 0);
break;
@@ -1838,6 +1868,12 @@ mf_set(const struct mf_field *mf,
case MFF_TUN_GBP_FLAGS:
match_set_tun_gbp_flags_masked(match, value->u8, mask->u8);
break;
+ case MFF_TUN_GPE_NP:
+ match_set_tun_gpe_np_masked(match, value->u8, mask->u8);
+ break;
+ case MFF_TUN_GPE_FLAGS:
+ match_set_tun_gpe_flags_masked(match, value->u8, mask->u8);
+ break;
case MFF_TUN_TTL:
match_set_tun_ttl_masked(match, value->u8, mask->u8);
break;
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index c73a1af..4bd9ff6 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -491,6 +491,34 @@ enum OVS_PACKED_ENUM mf_field_id {
*/
MFF_TUN_GBP_FLAGS,
+ /* "tun_gpe_np".
+ *
+ * VXLAN Generic Protocol Extension next_proto
+ *
+ * Type: u8.
+ * Maskable: bitwise.
+ * Formatting: hexadecimal.
+ * Prerequisites: none.
+ * Access: read/write.
+ * NXM: NXM_NX_TUN_GPE_NP(111) since v2.4.
+ * OXM: none.
+ */
+ MFF_TUN_GPE_NP,
+
+ /* "tun_gpe_flags".
+ *
+ * VXLAN Generic Protocol Extension flag
+ *
+ * Type: u8.
+ * Maskable: bitwise.
+ * Formatting: hexadecimal.
+ * Prerequisites: none.
+ * Access: read/write.
+ * NXM: NXM_NX_TUN_GPE_FLAGS(112) since v2.4.
+ * OXM: none.
+ */
+ MFF_TUN_GPE_FLAGS,
+
#if TUN_METADATA_NUM_OPTS == 64
/* "tun_metadata<N>".
*
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index e398562..92ceec1 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -583,6 +583,8 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
while (ext) {
if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
+ } else if (!strcmp(type, "vxlan") && !strcmp(ext, "gpe")) {
+ tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
} else {
VLOG_WARN("%s: unknown extension '%s'", name, ext);
}
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 9f0f452..0eecac7 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1037,6 +1037,10 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id);
nxm_put_8m(b, MFF_TUN_GBP_FLAGS, oxm,
flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags);
+ nxm_put_8m(b, MFF_TUN_GPE_NP, oxm,
+ flow->tunnel.gpe_np, match->wc.masks.tunnel.gpe_np);
+ nxm_put_8m(b, MFF_TUN_GPE_FLAGS, oxm,
+ flow->tunnel.gpe_flags, match->wc.masks.tunnel.gpe_flags);
tun_metadata_to_nx_match(b, oxm, match);
/* Registers. */
diff --git a/lib/odp-util.c b/lib/odp-util.c
index b4689cc..7983720 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1727,6 +1727,7 @@ odp_actions_from_string(const char *s, const struct simap *port_names,
static const struct attr_len_tbl ovs_vxlan_ext_attr_lens[OVS_VXLAN_EXT_MAX + 1] = {
[OVS_VXLAN_EXT_GBP] = { .len = 4 },
+ [OVS_VXLAN_EXT_GPE] = { .len = 4 },
};
static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
@@ -1888,7 +1889,10 @@ odp_tun_key_from_attr__(const struct nlattr *attr,
break;
case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: {
static const struct nl_policy vxlan_opts_policy[] = {
- [OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 },
+ [OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 ,
+ .optional = true },
+ [OVS_VXLAN_EXT_GPE] = { .type = NL_A_U32 ,
+ .optional = true },
};
struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
@@ -1902,6 +1906,12 @@ odp_tun_key_from_attr__(const struct nlattr *attr,
tun->gbp_id = htons(gbp & 0xFFFF);
tun->gbp_flags = (gbp >> 16) & 0xFF;
}
+ if (ext[OVS_VXLAN_EXT_GPE]) {
+ uint32_t gpe = nl_attr_get_u32(ext[OVS_VXLAN_EXT_GPE]);
+
+ tun->gpe_np = gpe & 0xFF;
+ tun->gpe_flags = gpe >> 24;
+ }
break;
}
@@ -1988,6 +1998,13 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
nl_msg_put_u32(a, OVS_VXLAN_EXT_GBP,
(tun_key->gbp_flags << 16) | ntohs(tun_key->gbp_id));
nl_msg_end_nested(a, vxlan_opts_ofs);
+ } else if (tun_key->gpe_flags || tun_key->gpe_np) {
+ size_t vxlan_opts_ofs;
+
+ vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
+ nl_msg_put_u32(a, OVS_VXLAN_EXT_GPE,
+ (tun_key->gpe_flags << 24) | (tun_key->gpe_np));
+ nl_msg_end_nested(a, vxlan_opts_ofs);
}
tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a);
@@ -2383,6 +2400,26 @@ format_odp_tun_vxlan_opt(const struct nlattr *attr,
ds_put_cstr(ds, "),");
break;
}
+ case OVS_VXLAN_EXT_GPE: {
+ uint32_t key = nl_attr_get_u32(a);
+ uint8_t np, np_mask;
+ uint8_t flags, flags_mask;
+
+ np = key & 0xFF;
+ flags = (key >> 24) & 0xFF;
+ if (ma) {
+ uint32_t mask = nl_attr_get_u32(ma);
+ np_mask = mask & 0xFF;
+ flags_mask = (mask >> 24) & 0xFF;
+ }
+
+ ds_put_cstr(ds, "gpe(");
+ format_u8x(ds, "np", np, ma ? &np_mask : NULL, verbose);
+ format_u8x(ds, "flags", flags, ma ? &flags_mask : NULL, verbose);
+ ds_chomp(ds, ',');
+ ds_put_cstr(ds, "),");
+ break;
+ }
default:
format_unknown_key(ds, a, ma);
@@ -3670,6 +3707,40 @@ scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask)
}
static int
+scan_vxlan_gpe(const char *s, uint32_t *key, uint32_t *mask)
+{
+ const char *s_base = s;
+ uint8_t np = 0, np_mask = 0;
+ uint8_t flags = 0, flags_mask = 0;
+
+ if (!strncmp(s, "np=", 3)) {
+ s += 3;
+ s += scan_u8(s, &np, mask ? &np_mask : NULL);
+ }
+
+ if (s[0] == ',') {
+ s++;
+ }
+ if (!strncmp(s, "flags=", 6)) {
+ s += 6;
+ s += scan_u8(s, &flags, mask ? &flags_mask : NULL);
+ }
+
+ if (!strncmp(s, "))", 2)) {
+ s += 2;
+
+ *key = (flags << 24) | np;
+ if (mask) {
+ *mask = (flags_mask << 24) | np_mask;
+ }
+
+ return s - s_base;
+ }
+
+ return 0;
+}
+
+static int
scan_geneve(const char *s, struct geneve_scan *key, struct geneve_scan *mask)
{
const char *s_base = s;
@@ -3796,6 +3867,21 @@ vxlan_gbp_to_attr(struct ofpbuf *a, const void *data_)
}
static void
+vxlan_gpe_to_attr(struct ofpbuf *a, const void *data_)
+{
+ const uint32_t *gpe = data_;
+
+ if (*gpe) {
+ size_t vxlan_opts_ofs;
+
+ vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
+ nl_msg_put_u32(a, OVS_VXLAN_EXT_GPE, *gpe);
+ nl_msg_end_nested(a, vxlan_opts_ofs);
+ }
+}
+
+
+static void
geneve_to_attr(struct ofpbuf *a, const void *data_)
{
const struct geneve_scan *geneve = data_;
@@ -4031,6 +4117,7 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
SCAN_FIELD_NESTED("tp_src=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_SRC);
SCAN_FIELD_NESTED("tp_dst=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_DST);
SCAN_FIELD_NESTED_FUNC("vxlan(gbp(", uint32_t, vxlan_gbp, vxlan_gbp_to_attr);
+ SCAN_FIELD_NESTED_FUNC("vxlan(gpe(", uint32_t, vxlan_gpe, vxlan_gpe_to_attr);
SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve,
geneve_to_attr);
SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
diff --git a/lib/packets.h b/lib/packets.h
index a8ea24b..dc97333 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -49,7 +49,9 @@ struct flow_tnl {
ovs_be16 tp_dst;
ovs_be16 gbp_id;
uint8_t gbp_flags;
- uint8_t pad1[5]; /* Pad to 64 bits. */
+ uint8_t gpe_np;
+ uint8_t gpe_flags;
+ uint8_t pad1[3]; /* Pad to 64 bits. */
struct tun_metadata metadata;
};
diff --git a/tests/ofproto.at b/tests/ofproto.at
index fbb6d71..6c7217d 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -1775,7 +1775,7 @@ head_table () {
instructions: meter,apply_actions,clear_actions,write_actions,write_metadata,goto_table
Write-Actions and Apply-Actions features:
actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue
- supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 dnl
+ supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_gpe_np tun_gpe_flags tun_metadata0 dnl
tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl
metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll
matching:
@@ -1790,6 +1790,8 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4
tun_flags: arbitrary mask
tun_gbp_id: arbitrary mask
tun_gbp_flags: arbitrary mask
+ tun_gpe_np: arbitrary mask
+ tun_gpe_flags: arbitrary mask
tun_metadata0: arbitrary mask
tun_metadata1: arbitrary mask
tun_metadata2: arbitrary mask
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index f26f622..dde603d 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -17,6 +17,10 @@ for test_case in \
'tun_gbp_id=0/0x1 NXM,OXM' \
'tun_gbp_flags=0 NXM,OXM' \
'tun_gbp_flags=0/0x1 NXM,OXM' \
+ 'tun_gpe_np=0 NXM,OXM' \
+ 'tun_gpe_np=0/0x1 NXM,OXM' \
+ 'tun_gpe_flags=0 NXM,OXM' \
+ 'tun_gpe_flags=0/0x1 NXM,OXM' \
'tun_metadata0=0 NXM,OXM' \
'tun_metadata0=0/0x1 NXM,OXM' \
'tun_metadata0 NXM,OXM' \
--
1.9.3