fuel-plugin-ovs/ovs_build/ovs_nsh_patches/v2.6.1/0001-Enable-current-VxLAN-g...

615 lines
24 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 9f7148f9dc03053a4a3231a7cf819c447a178a17 Mon Sep 17 00:00:00 2001
From: Yi Yang <yi.y.yang@intel.com>
Date: Fri, 11 Nov 2016 11:13:18 +0800
Subject: [PATCH 1/8] Enable current VxLAN-gpe work and meet NSH requirements
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 | 1 +
datapath/linux/compat/vxlan.c | 4 +-
datapath/vport-netdev.c | 3 +-
datapath/vport-vxlan.c | 15 ++++
include/openvswitch/match.h | 4 +
include/openvswitch/meta-flow.h | 28 +++++++
include/openvswitch/packets.h | 4 +-
lib/flow.c | 8 ++
lib/match.c | 34 +++++++++
lib/meta-flow.c | 36 +++++++++
lib/netdev-vport.c | 2 +
lib/nx-match.c | 4 +
lib/odp-util.c | 89 ++++++++++++++++++++++-
tests/ofproto.at | 4 +-
tests/ovs-ofctl.at | 4 +
17 files changed, 241 insertions(+), 8 deletions(-)
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 0f32664..2dcae07 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] = {
@@ -523,6 +524,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);
@@ -709,7 +713,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 12260d8..44b7ce4 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -291,6 +291,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 5bc8969..5a994b2 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -201,6 +201,7 @@ reserved_flags2:2;
struct vxlan_metadata {
u32 gbp;
+ u32 gpe;
};
/* per UDP socket information */
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index d5dbe8d..a80610b 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -705,7 +705,6 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
if (vs->flags & VXLAN_F_GPE) {
if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
goto drop;
- raw_proto = true;
}
if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto,
@@ -896,10 +895,9 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
if (vxflags & VXLAN_F_GBP)
vxlan_build_gbp_hdr(vxh, vxflags, md);
if (vxflags & VXLAN_F_GPE) {
- err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol);
+ err = vxlan_build_gpe_hdr(vxh, vxflags, inner_protocol);
if (err < 0)
goto out_free;
- inner_protocol = skb->protocol;
}
ovs_skb_set_inner_protocol(skb, inner_protocol);
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 970f7d3..0ee076b 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -102,7 +102,8 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)
}
if (vport->dev->flags & IFF_LOOPBACK ||
- vport->dev->type != ARPHRD_ETHER ||
+ (vport->dev->type != ARPHRD_ETHER &&
+ vport->dev->type != ARPHRD_NONE) ||
ovs_is_internal_dev(vport->dev)) {
err = -EINVAL;
goto error_put;
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index 11965c0..e32c970 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/include/openvswitch/match.h b/include/openvswitch/match.h
index 3b7f32f..93af1b8 100644
--- a/include/openvswitch/match.h
+++ b/include/openvswitch/match.h
@@ -89,6 +89,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/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index b091c1b..9e569ef 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -493,6 +493,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(200) 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(201) since v2.4.
+ * OXM: none.
+ */
+ MFF_TUN_GPE_FLAGS,
+
#if TUN_METADATA_NUM_OPTS == 64
/* "tun_metadata<N>".
*
diff --git a/include/openvswitch/packets.h b/include/openvswitch/packets.h
index 5d97309..1e82df0 100644
--- a/include/openvswitch/packets.h
+++ b/include/openvswitch/packets.h
@@ -34,7 +34,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/lib/flow.c b/lib/flow.c
index ba4f8c7..375979b 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -897,6 +897,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);
@@ -1292,6 +1298,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 d78e6a1..f19648d 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -305,6 +305,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);
@@ -1029,6 +1055,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/meta-flow.c b/lib/meta-flow.c
index d07f927..5d0721f 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);
@@ -434,6 +438,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:
@@ -568,6 +574,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;
@@ -823,6 +835,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;
@@ -1161,6 +1179,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;
@@ -1484,6 +1508,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;
@@ -1793,6 +1823,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/netdev-vport.c b/lib/netdev-vport.c
index ac31da6..cff0f5c 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -526,6 +526,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 b03ccf2..65d7ee3 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1036,6 +1036,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 6d29b67..b9e8aa7 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1755,6 +1755,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] = {
@@ -1916,7 +1917,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)];
@@ -1930,6 +1934,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;
}
@@ -2016,6 +2026,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);
@@ -2410,6 +2427,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);
@@ -3705,6 +3742,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;
@@ -3831,6 +3902,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_;
@@ -4066,6 +4152,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/tests/ofproto.at b/tests/ofproto.at
index 6e55270..7b7f02b 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -2190,7 +2190,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 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 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:
@@ -2205,6 +2205,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 cbb818e..2267be0 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' \
--
2.1.0