From: William Tu <u9012063@gmail.com>
To: netdev@vger.kernel.org
Cc: Pravin B Shelar <pshelar@ovn.org>
Subject: [PATCHv2 net-next 2/2] openvswitch: add erspan version II support
Date: Tue, 9 Jan 2018 17:51:22 -0800 [thread overview]
Message-ID: <1515549082-4141-3-git-send-email-u9012063@gmail.com> (raw)
In-Reply-To: <1515549082-4141-1-git-send-email-u9012063@gmail.com>
The patch adds support for configuring the erspan V2 fields for
openvswitch. For compatibility reason, the previously added
attribute 'OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS' is renamed to
'OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTSV1' and deprecated, and the newly added
attribute 'OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS' will handle both V1 and V2.
Signed-off-by: William Tu <u9012063@gmail.com>
Cc: Pravin B Shelar <pshelar@ovn.org>
---
include/uapi/linux/openvswitch.h | 13 +++-
net/openvswitch/flow_netlink.c | 129 ++++++++++++++++++++++++++++++++++++---
2 files changed, 132 insertions(+), 10 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 4265d7f9e1f2..77c3424cc4ef 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -273,6 +273,16 @@ enum {
#define OVS_VXLAN_EXT_MAX (__OVS_VXLAN_EXT_MAX - 1)
+enum {
+ OVS_ERSPAN_OPT_UNSPEC,
+ OVS_ERSPAN_OPT_IDX, /* be32 index */
+ OVS_ERSPAN_OPT_VER, /* u8 version number */
+ OVS_ERSPAN_OPT_DIR, /* u8 direction */
+ OVS_ERSPAN_OPT_HWID, /* u8 hardware ID */
+ __OVS_ERSPAN_OPT_MAX,
+};
+
+#define OVS_ERSPAN_OPT_MAX (__OVS_ERSPAN_OPT_MAX - 1)
/* OVS_VPORT_ATTR_OPTIONS attributes for tunnels.
*/
@@ -363,7 +373,8 @@ enum ovs_tunnel_key_attr {
OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */
OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */
OVS_TUNNEL_KEY_ATTR_PAD,
- OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* be32 ERSPAN index. */
+ OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTSV1, /* be32 ERSPAN v1 index (deprecated). */
+ OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* Nested OVS_ERSPAN_OPT_* */
__OVS_TUNNEL_KEY_ATTR_MAX
};
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index bce1f78b0de5..9c6b210e7893 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -335,7 +335,10 @@ size_t ovs_tun_key_attr_size(void)
*/
+ nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
+ nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_DST */
- + nla_total_size(4); /* OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS */
+ + nla_total_size(4); /* OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTSV1 */
+ /* OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with
+ * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
+ */
}
static size_t ovs_nsh_key_attr_size(void)
@@ -386,6 +389,13 @@ static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] =
[OVS_VXLAN_EXT_GBP] = { .len = sizeof(u32) },
};
+static const struct ovs_len_tbl ovs_erspan_opt_lens[OVS_ERSPAN_OPT_MAX + 1] = {
+ [OVS_ERSPAN_OPT_IDX] = { .len = sizeof(u32) },
+ [OVS_ERSPAN_OPT_VER] = { .len = sizeof(u8) },
+ [OVS_ERSPAN_OPT_DIR] = { .len = sizeof(u8) },
+ [OVS_ERSPAN_OPT_HWID] = { .len = sizeof(u8) },
+};
+
static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
[OVS_TUNNEL_KEY_ATTR_ID] = { .len = sizeof(u64) },
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = { .len = sizeof(u32) },
@@ -402,7 +412,9 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
.next = ovs_vxlan_ext_key_lens },
[OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) },
- [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = sizeof(u32) },
+ [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTSV1] = { .len = sizeof(u32) },
+ [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_NESTED,
+ .next = ovs_erspan_opt_lens },
};
static const struct ovs_len_tbl
@@ -640,16 +652,78 @@ static int erspan_tun_opt_from_nlattr(const struct nlattr *attr,
{
unsigned long opt_key_offset;
struct erspan_metadata opts;
+ struct nlattr *a;
+ u16 hwid, dir;
+ int rem;
BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
memset(&opts, 0, sizeof(opts));
- opts.u.index = nla_get_be32(attr);
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+
+ if (type > OVS_ERSPAN_OPT_MAX) {
+ OVS_NLERR(log, "ERSPAN option %d out of range max %d",
+ type, OVS_ERSPAN_OPT_MAX);
+ return -EINVAL;
+ }
+
+ if (!check_attr_len(nla_len(a),
+ ovs_erspan_opt_lens[type].len)) {
+ OVS_NLERR(log, "ERSPAN option %d has unexpected len %d expected %d",
+ type, nla_len(a),
+ ovs_erspan_opt_lens[type].len);
+ return -EINVAL;
+ }
- /* Index has only 20-bit */
- if (ntohl(opts.u.index) & ~INDEX_MASK) {
- OVS_NLERR(log, "ERSPAN index number %x too large.",
- ntohl(opts.u.index));
+ switch (type) {
+ case OVS_ERSPAN_OPT_IDX:
+ opts.u.index = nla_get_be32(a);
+ if (ntohl(opts.u.index) & ~INDEX_MASK) {
+ OVS_NLERR(log,
+ "ERSPAN index number %x too large.",
+ ntohl(opts.u.index));
+ return -EINVAL;
+ }
+ break;
+ case OVS_ERSPAN_OPT_VER:
+ opts.version = nla_get_u8(a);
+ if (opts.version != 1 && opts.version != 2) {
+ OVS_NLERR(log,
+ "ERSPAN version %d not supported.",
+ opts.version);
+ return -EINVAL;
+ }
+ break;
+ case OVS_ERSPAN_OPT_DIR:
+ dir = nla_get_u8(a);
+ if (dir != 0 && dir != 1) {
+ OVS_NLERR(log,
+ "ERSPAN direction %d invalid.",
+ dir);
+ return -EINVAL;
+ }
+ opts.u.md2.dir = dir;
+ break;
+ case OVS_ERSPAN_OPT_HWID:
+ hwid = nla_get_u8(a);
+ if (hwid & ~(HWID_MASK >> HWID_OFFSET)) {
+ OVS_NLERR(log,
+ "ERSPAN hardware ID %x invalid.",
+ hwid);
+ return -EINVAL;
+ }
+ set_hwid(&opts.u.md2, hwid);
+ break;
+ default:
+ OVS_NLERR(log, "Unknown ERSPAN opt attribute %d",
+ type);
+ return -EINVAL;
+ }
+ }
+ if (rem) {
+ OVS_NLERR(log, "ERSPAN opt message has %d unknown bytes.",
+ rem);
return -EINVAL;
}
@@ -768,6 +842,10 @@ static int ip_tun_from_nlattr(const struct nlattr *attr,
break;
case OVS_TUNNEL_KEY_ATTR_PAD:
break;
+ case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTSV1:
+ OVS_NLERR(log, "ERSPAN attribute %d is deprecated.",
+ type);
+ return -EINVAL;
case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
if (opts_type) {
OVS_NLERR(log, "Multiple metadata blocks provided");
@@ -846,6 +924,39 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb,
return 0;
}
+static int erspan_opt_to_nlattr(struct sk_buff *skb,
+ const void *tun_opts, int swkey_tun_opts_len)
+{
+ const struct erspan_metadata *opts = tun_opts;
+ struct nlattr *nla;
+
+ nla = nla_nest_start(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS);
+ if (!nla)
+ return -EMSGSIZE;
+
+ if (nla_put_u8(skb, OVS_ERSPAN_OPT_VER, opts->version) < 0)
+ return -EMSGSIZE;
+
+ if (opts->version == 1) {
+ if (nla_put_be32(skb, OVS_ERSPAN_OPT_IDX, opts->u.index) < 0)
+ return -EMSGSIZE;
+
+ } else if (opts->version == 2) {
+ if (nla_put_u8(skb, OVS_ERSPAN_OPT_DIR,
+ opts->u.md2.dir) < 0)
+ return -EMSGSIZE;
+
+ if (nla_put_u8(skb, OVS_ERSPAN_OPT_HWID,
+ get_hwid(&opts->u.md2)) < 0)
+ return -EMSGSIZE;
+ } else {
+ return -EINVAL;
+ }
+
+ nla_nest_end(skb, nla);
+ return 0;
+}
+
static int __ip_tun_to_nlattr(struct sk_buff *skb,
const struct ip_tunnel_key *output,
const void *tun_opts, int swkey_tun_opts_len,
@@ -906,8 +1017,8 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb,
vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
return -EMSGSIZE;
else if (output->tun_flags & TUNNEL_ERSPAN_OPT &&
- nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
- ((struct erspan_metadata *)tun_opts)->u.index))
+ erspan_opt_to_nlattr(skb, tun_opts,
+ swkey_tun_opts_len))
return -EMSGSIZE;
}
--
2.7.4
next prev parent reply other threads:[~2018-01-10 1:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-10 1:51 [PATCHv2 net-next 0/2] net: erspan: add support for openvswitch William Tu
2018-01-10 1:51 ` [PATCHv2 net-next 1/2] net: erspan: use bitfield instead of mask and offset William Tu
2018-01-10 1:51 ` William Tu [this message]
2018-01-10 21:29 ` [PATCHv2 net-next 2/2] openvswitch: add erspan version II support Jiri Benc
2018-01-10 21:35 ` Jiri Benc
2018-01-10 22:02 ` Jiri Benc
2018-01-11 16:34 ` William Tu
2018-01-12 8:27 ` Jiri Benc
2018-01-12 18:39 ` Pravin Shelar
2018-01-12 19:22 ` William Tu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1515549082-4141-3-git-send-email-u9012063@gmail.com \
--to=u9012063@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pshelar@ovn.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.