615 lines
24 KiB
Diff
615 lines
24 KiB
Diff
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
|
||
|