All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key
@ 2018-06-26 18:53 Jakub Kicinski
  2018-06-26 18:53 ` [PATCH net-next 1/4] net/sched: act_tunnel_key: disambiguate metadata dst error cases Jakub Kicinski
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-26 18:53 UTC (permalink / raw)
  To: davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Jakub Kicinski

Hi,

Simon & Pieter say:

This set adds Geneve Options support to the TC tunnel key action.
It provides the plumbing required to configure Geneve variable length
options.  The options can be configured in the form CLASS:TYPE:DATA,
where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit
hexadecimal value and DATA as a variable length hexadecimal value.
Additionally multiple options may be listed using a comma delimiter.


Pieter Jansen van Vuuren (1):
  net: check tunnel option type in tunnel flags

Simon Horman (3):
  net/sched: act_tunnel_key: disambiguate metadata dst error cases
  net/sched: act_tunnel_key: add extended ack support
  net/sched: add tunnel option support to act_tunnel_key

 drivers/net/geneve.c                      |   6 +-
 drivers/net/vxlan.c                       |   3 +-
 include/net/ip_tunnels.h                  |   8 +-
 include/uapi/linux/tc_act/tc_tunnel_key.h |  26 +++
 net/core/filter.c                         |   2 +-
 net/ipv4/ip_gre.c                         |   2 +
 net/ipv6/ip6_gre.c                        |   2 +
 net/openvswitch/flow_netlink.c            |   8 +-
 net/sched/act_tunnel_key.c                | 242 +++++++++++++++++++++-
 9 files changed, 280 insertions(+), 19 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net-next 1/4] net/sched: act_tunnel_key: disambiguate metadata dst error cases
  2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
@ 2018-06-26 18:53 ` Jakub Kicinski
  2018-06-26 18:53 ` [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support Jakub Kicinski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-26 18:53 UTC (permalink / raw)
  To: davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Simon Horman, David Ahern, Alexander Aring

From: Simon Horman <simon.horman@netronome.com>

Metadata may be NULL for one of two reasons:
* Missing user input
* Failure to allocate the metadata dst

Disambiguate these case by returning -EINVAL for the former and -ENOMEM
for the latter rather than -EINVAL for both cases.

This is in preparation for using extended ack to provide more information
to users when parsing their input.

Cc: David Ahern <dsa@cumulusnetworks.com>
Cc: Alexander Aring <aring@mojatatu.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 net/sched/act_tunnel_key.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 626dac81a48a..2edd389e7c92 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -143,10 +143,13 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 			metadata = __ipv6_tun_set_dst(&saddr, &daddr, 0, 0, dst_port,
 						      0, flags,
 						      key_id, 0);
+		} else {
+			ret = -EINVAL;
+			goto err_out;
 		}
 
 		if (!metadata) {
-			ret = -EINVAL;
+			ret = -ENOMEM;
 			goto err_out;
 		}
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support
  2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
  2018-06-26 18:53 ` [PATCH net-next 1/4] net/sched: act_tunnel_key: disambiguate metadata dst error cases Jakub Kicinski
@ 2018-06-26 18:53 ` Jakub Kicinski
  2018-06-26 19:50   ` David Ahern
  2018-06-26 18:53 ` [PATCH net-next 3/4] net: check tunnel option type in tunnel flags Jakub Kicinski
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-26 18:53 UTC (permalink / raw)
  To: davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Simon Horman, David Ahern, Alexander Aring,
	Pieter Jansen van Vuuren

From: Simon Horman <simon.horman@netronome.com>

Add extended ack support for the tunnel key action by using NL_SET_ERR_MSG
during validation of user input.

Cc: David Ahern <dsahern@gmail.com>
Cc: Alexander Aring <aring@mojatatu.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 net/sched/act_tunnel_key.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 2edd389e7c92..20e98ed8d498 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -86,16 +86,22 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 	int ret = 0;
 	int err;
 
-	if (!nla)
+	if (!nla) {
+		NL_SET_ERR_MSG(extack, "Tunnel requires attributes to be passed");
 		return -EINVAL;
+	}
 
 	err = nla_parse_nested(tb, TCA_TUNNEL_KEY_MAX, nla, tunnel_key_policy,
-			       NULL);
-	if (err < 0)
+			       extack);
+	if (err < 0) {
+		NL_SET_ERR_MSG(extack, "Failed to parse nested tunnel key attributes");
 		return err;
+	}
 
-	if (!tb[TCA_TUNNEL_KEY_PARMS])
+	if (!tb[TCA_TUNNEL_KEY_PARMS]) {
+		NL_SET_ERR_MSG(extack, "Missing tunnel key parameters");
 		return -EINVAL;
+	}
 
 	parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
 	exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -107,6 +113,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 		break;
 	case TCA_TUNNEL_KEY_ACT_SET:
 		if (!tb[TCA_TUNNEL_KEY_ENC_KEY_ID]) {
+			NL_SET_ERR_MSG(extack, "Missing tunnel key id");
 			ret = -EINVAL;
 			goto err_out;
 		}
@@ -144,11 +151,13 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 						      0, flags,
 						      key_id, 0);
 		} else {
+			NL_SET_ERR_MSG(extack, "Missing either ipv4 or ipv6 src and dst");
 			ret = -EINVAL;
 			goto err_out;
 		}
 
 		if (!metadata) {
+			NL_SET_ERR_MSG(extack, "Cannot allocate tunnel metadata dst");
 			ret = -ENOMEM;
 			goto err_out;
 		}
@@ -156,6 +165,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 		metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX;
 		break;
 	default:
+		NL_SET_ERR_MSG(extack, "Unknown tunnel key action");
 		ret = -EINVAL;
 		goto err_out;
 	}
@@ -163,14 +173,18 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 	if (!exists) {
 		ret = tcf_idr_create(tn, parm->index, est, a,
 				     &act_tunnel_key_ops, bind, true);
-		if (ret)
+		if (ret) {
+			NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
 			return ret;
+		}
 
 		ret = ACT_P_CREATED;
 	} else {
 		tcf_idr_release(*a, bind);
-		if (!ovr)
+		if (!ovr) {
+			NL_SET_ERR_MSG(extack, "TC IDR already exists");
 			return -EEXIST;
+		}
 	}
 
 	t = to_tunnel_key(*a);
@@ -180,6 +194,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 	if (unlikely(!params_new)) {
 		if (ret == ACT_P_CREATED)
 			tcf_idr_release(*a, bind);
+		NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters");
 		return -ENOMEM;
 	}
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 3/4] net: check tunnel option type in tunnel flags
  2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
  2018-06-26 18:53 ` [PATCH net-next 1/4] net/sched: act_tunnel_key: disambiguate metadata dst error cases Jakub Kicinski
  2018-06-26 18:53 ` [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support Jakub Kicinski
@ 2018-06-26 18:53 ` Jakub Kicinski
  2018-06-27  3:08   ` kbuild test robot
  2018-06-26 18:53 ` [PATCH net-next 4/4] net/sched: add tunnel option support to act_tunnel_key Jakub Kicinski
  2018-06-28  7:17 ` [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key David Miller
  4 siblings, 1 reply; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-26 18:53 UTC (permalink / raw)
  To: davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Pieter Jansen van Vuuren, Jakub Kicinski

From: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>

Check the tunnel option type stored in tunnel flags when creating options
for tunnels. Thereby ensuring we do not set geneve, vxlan or erspan tunnel
options on interfaces that are not associated with them.

Make sure all users of the infrastructure set correct flags, for the BPF
helper we have to set all bits to keep backward compatibility.

Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 drivers/net/geneve.c           | 6 ++++--
 drivers/net/vxlan.c            | 3 ++-
 include/net/ip_tunnels.h       | 8 ++++++--
 net/core/filter.c              | 2 +-
 net/ipv4/ip_gre.c              | 2 ++
 net/ipv6/ip6_gre.c             | 2 ++
 net/openvswitch/flow_netlink.c | 8 ++++++--
 7 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 3e94375b9b01..471edd76ff55 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -236,7 +236,8 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
 		}
 		/* Update tunnel dst according to Geneve options. */
 		ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
-					gnvh->options, gnvh->opt_len * 4);
+					gnvh->options, gnvh->opt_len * 4,
+					TUNNEL_GENEVE_OPT);
 	} else {
 		/* Drop packets w/ critical options,
 		 * since we don't support any...
@@ -675,7 +676,8 @@ static void geneve_build_header(struct genevehdr *geneveh,
 	geneveh->proto_type = htons(ETH_P_TEB);
 	geneveh->rsvd2 = 0;
 
-	ip_tunnel_info_opts_get(geneveh->options, info);
+	if (info->key.tun_flags & TUNNEL_GENEVE_OPT)
+		ip_tunnel_info_opts_get(geneveh->options, info);
 }
 
 static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index cc14e0cd5647..7eb30d7c8bd7 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2122,7 +2122,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 		vni = tunnel_id_to_key32(info->key.tun_id);
 		ifindex = 0;
 		dst_cache = &info->dst_cache;
-		if (info->options_len)
+		if (info->options_len &&
+		    info->key.tun_flags & TUNNEL_VXLAN_OPT)
 			md = ip_tunnel_info_opts(info);
 		ttl = info->key.ttl;
 		tos = info->key.tos;
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 90ff430f5e9d..b0d022ff6ea1 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -466,10 +466,12 @@ static inline void ip_tunnel_info_opts_get(void *to,
 }
 
 static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info,
-					   const void *from, int len)
+					   const void *from, int len,
+					   __be16 flags)
 {
 	memcpy(ip_tunnel_info_opts(info), from, len);
 	info->options_len = len;
+	info->key.tun_flags |= flags;
 }
 
 static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate)
@@ -511,9 +513,11 @@ static inline void ip_tunnel_info_opts_get(void *to,
 }
 
 static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info,
-					   const void *from, int len)
+					   const void *from, int len,
+					   __be16 flags)
 {
 	info->options_len = 0;
+	info->key.tun_flags |= flags;
 }
 
 #endif /* CONFIG_INET */
diff --git a/net/core/filter.c b/net/core/filter.c
index e7f12e9f598c..dade922678f6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3582,7 +3582,7 @@ BPF_CALL_3(bpf_skb_set_tunnel_opt, struct sk_buff *, skb,
 	if (unlikely(size > IP_TUNNEL_OPTS_MAX))
 		return -ENOMEM;
 
-	ip_tunnel_info_opts_set(info, from, size);
+	ip_tunnel_info_opts_set(info, from, size, TUNNEL_OPTIONS_PRESENT);
 
 	return 0;
 }
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 2d8efeecf619..c8ca5d8f0f75 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -587,6 +587,8 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 		goto err_free_skb;
 
 	key = &tun_info->key;
+	if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
+		goto err_free_rt;
 	md = ip_tunnel_info_opts(tun_info);
 	if (!md)
 		goto err_free_rt;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c8cf2fdbb13b..367177786e34 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -990,6 +990,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 		fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 
 		dsfield = key->tos;
+		if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
+			goto tx_err;
 		md = ip_tunnel_info_opts(tun_info);
 		if (!md)
 			goto tx_err;
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 492ab0c36f7c..26ab964923fd 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -2515,8 +2515,9 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
 	struct ip_tunnel_info *tun_info;
 	struct ovs_tunnel_info *ovs_tun;
 	struct nlattr *a;
-	int err = 0, start, opts_type;
+	int err = 0, start, opts_type, dst_opt_type;
 
+	dst_opt_type = 0;
 	ovs_match_init(&match, &key, true, NULL);
 	opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
 	if (opts_type < 0)
@@ -2528,10 +2529,13 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
 			err = validate_geneve_opts(&key);
 			if (err < 0)
 				return err;
+			dst_opt_type = TUNNEL_GENEVE_OPT;
 			break;
 		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
+			dst_opt_type = TUNNEL_VXLAN_OPT;
 			break;
 		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
+			dst_opt_type = TUNNEL_ERSPAN_OPT;
 			break;
 		}
 	}
@@ -2574,7 +2578,7 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
 	 */
 	ip_tunnel_info_opts_set(tun_info,
 				TUN_METADATA_OPTS(&key, key.tun_opts_len),
-				key.tun_opts_len);
+				key.tun_opts_len, dst_opt_type);
 	add_nested_action_end(*sfa, start);
 
 	return err;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next 4/4] net/sched: add tunnel option support to act_tunnel_key
  2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
                   ` (2 preceding siblings ...)
  2018-06-26 18:53 ` [PATCH net-next 3/4] net: check tunnel option type in tunnel flags Jakub Kicinski
@ 2018-06-26 18:53 ` Jakub Kicinski
  2018-06-28  7:17 ` [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key David Miller
  4 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-26 18:53 UTC (permalink / raw)
  To: davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Simon Horman, Pieter Jansen van Vuuren

From: Simon Horman <simon.horman@netronome.com>

Allow setting tunnel options using the act_tunnel_key action.

Options are expressed as class:type:data and multiple options
may be listed using a comma delimiter.

 # ip link add name geneve0 type geneve dstport 0 external
 # tc qdisc add dev eth0 ingress
 # tc filter add dev eth0 protocol ip parent ffff: \
     flower indev eth0 \
        ip_proto udp \
        action tunnel_key \
            set src_ip 10.0.99.192 \
            dst_ip 10.0.99.193 \
            dst_port 6081 \
            id 11 \
            geneve_opts 0102:80:00800022,0102:80:00800022 \
    action mirred egress redirect dev geneve0

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 include/uapi/linux/tc_act/tc_tunnel_key.h |  26 +++
 net/sched/act_tunnel_key.c                | 214 +++++++++++++++++++++-
 2 files changed, 236 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/tc_act/tc_tunnel_key.h b/include/uapi/linux/tc_act/tc_tunnel_key.h
index 72bbefe5d1d1..1b7bdd841b98 100644
--- a/include/uapi/linux/tc_act/tc_tunnel_key.h
+++ b/include/uapi/linux/tc_act/tc_tunnel_key.h
@@ -36,9 +36,35 @@ enum {
 	TCA_TUNNEL_KEY_PAD,
 	TCA_TUNNEL_KEY_ENC_DST_PORT,	/* be16 */
 	TCA_TUNNEL_KEY_NO_CSUM,		/* u8 */
+	TCA_TUNNEL_KEY_ENC_OPTS,	/* Nested TCA_TUNNEL_KEY_ENC_OPTS_
+					 * attributes
+					 */
 	__TCA_TUNNEL_KEY_MAX,
 };
 
 #define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)
 
+enum {
+	TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC,
+	TCA_TUNNEL_KEY_ENC_OPTS_GENEVE,		/* Nested
+						 * TCA_TUNNEL_KEY_ENC_OPTS_
+						 * attributes
+						 */
+	__TCA_TUNNEL_KEY_ENC_OPTS_MAX,
+};
+
+#define TCA_TUNNEL_KEY_ENC_OPTS_MAX (__TCA_TUNNEL_KEY_ENC_OPTS_MAX - 1)
+
+enum {
+	TCA_TUNNEL_KEY_ENC_OPT_GENEVE_UNSPEC,
+	TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,		/* u16 */
+	TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE,		/* u8 */
+	TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA,		/* 4 to 128 bytes */
+
+	__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX,
+};
+
+#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \
+	(__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1)
+
 #endif
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 20e98ed8d498..5eace86ea687 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
+#include <net/geneve.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 #include <net/dst.h>
@@ -57,6 +58,135 @@ static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a,
 	return action;
 }
 
+static const struct nla_policy
+enc_opts_policy[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1] = {
+	[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]	= { .type = NLA_NESTED },
+};
+
+static const struct nla_policy
+geneve_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1] = {
+	[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]	   = { .type = NLA_U16 },
+	[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]	   = { .type = NLA_U8 },
+	[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]	   = { .type = NLA_BINARY,
+						       .len = 128 },
+};
+
+static int
+tunnel_key_copy_geneve_opt(const struct nlattr *nla, void *dst, int dst_len,
+			   struct netlink_ext_ack *extack)
+{
+	struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
+	int err, data_len, opt_len;
+	u8 *data;
+
+	err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX,
+			       nla, geneve_opt_policy, extack);
+	if (err < 0)
+		return err;
+
+	if (!tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] ||
+	    !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] ||
+	    !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]) {
+		NL_SET_ERR_MSG(extack, "Missing tunnel key geneve option class, type or data");
+		return -EINVAL;
+	}
+
+	data = nla_data(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
+	data_len = nla_len(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
+	if (data_len < 4) {
+		NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is less than 4 bytes long");
+		return -ERANGE;
+	}
+	if (data_len % 4) {
+		NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is not a multiple of 4 bytes long");
+		return -ERANGE;
+	}
+
+	opt_len = sizeof(struct geneve_opt) + data_len;
+	if (dst) {
+		struct geneve_opt *opt = dst;
+
+		WARN_ON(dst_len < opt_len);
+
+		opt->opt_class =
+			nla_get_u16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]);
+		opt->type = nla_get_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]);
+		opt->length = data_len / 4; /* length is in units of 4 bytes */
+		opt->r1 = 0;
+		opt->r2 = 0;
+		opt->r3 = 0;
+
+		memcpy(opt + 1, data, data_len);
+	}
+
+	return opt_len;
+}
+
+static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
+				int dst_len, struct netlink_ext_ack *extack)
+{
+	int err, rem, opt_len, len = nla_len(nla), opts_len = 0;
+	const struct nlattr *attr, *head = nla_data(nla);
+
+	err = nla_validate(head, len, TCA_TUNNEL_KEY_ENC_OPTS_MAX,
+			   enc_opts_policy, extack);
+	if (err)
+		return err;
+
+	nla_for_each_attr(attr, head, len, rem) {
+		switch (nla_type(attr)) {
+		case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE:
+			opt_len = tunnel_key_copy_geneve_opt(attr, dst,
+							     dst_len, extack);
+			if (opt_len < 0)
+				return opt_len;
+			opts_len += opt_len;
+			if (dst) {
+				dst_len -= opt_len;
+				dst += opt_len;
+			}
+			break;
+		}
+	}
+
+	if (!opts_len) {
+		NL_SET_ERR_MSG(extack, "Empty list of tunnel options");
+		return -EINVAL;
+	}
+
+	if (rem > 0) {
+		NL_SET_ERR_MSG(extack, "Trailing data after parsing tunnel key options attributes");
+		return -EINVAL;
+	}
+
+	return opts_len;
+}
+
+static int tunnel_key_get_opts_len(struct nlattr *nla,
+				   struct netlink_ext_ack *extack)
+{
+	return tunnel_key_copy_opts(nla, NULL, 0, extack);
+}
+
+static int tunnel_key_opts_set(struct nlattr *nla, struct ip_tunnel_info *info,
+			       int opts_len, struct netlink_ext_ack *extack)
+{
+	info->options_len = opts_len;
+	switch (nla_type(nla_data(nla))) {
+	case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE:
+#if IS_ENABLED(CONFIG_INET)
+		info->key.tun_flags |= TUNNEL_GENEVE_OPT;
+		return tunnel_key_copy_opts(nla, ip_tunnel_info_opts(info),
+					    opts_len, extack);
+#else
+		return -EAFNOSUPPORT;
+#endif
+	default:
+		NL_SET_ERR_MSG(extack, "Cannot set tunnel options for unknown tunnel type");
+		return -EINVAL;
+	}
+}
+
 static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
 	[TCA_TUNNEL_KEY_PARMS]	    = { .len = sizeof(struct tc_tunnel_key) },
 	[TCA_TUNNEL_KEY_ENC_IPV4_SRC] = { .type = NLA_U32 },
@@ -66,6 +196,7 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
 	[TCA_TUNNEL_KEY_ENC_KEY_ID]   = { .type = NLA_U32 },
 	[TCA_TUNNEL_KEY_ENC_DST_PORT] = {.type = NLA_U16},
 	[TCA_TUNNEL_KEY_NO_CSUM]      = { .type = NLA_U8 },
+	[TCA_TUNNEL_KEY_ENC_OPTS]     = { .type = NLA_NESTED },
 };
 
 static int tunnel_key_init(struct net *net, struct nlattr *nla,
@@ -81,6 +212,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 	struct tcf_tunnel_key *t;
 	bool exists = false;
 	__be16 dst_port = 0;
+	int opts_len = 0;
 	__be64 key_id;
 	__be16 flags;
 	int ret = 0;
@@ -128,6 +260,15 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 		if (tb[TCA_TUNNEL_KEY_ENC_DST_PORT])
 			dst_port = nla_get_be16(tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
 
+		if (tb[TCA_TUNNEL_KEY_ENC_OPTS]) {
+			opts_len = tunnel_key_get_opts_len(tb[TCA_TUNNEL_KEY_ENC_OPTS],
+							   extack);
+			if (opts_len < 0) {
+				ret = opts_len;
+				goto err_out;
+			}
+		}
+
 		if (tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC] &&
 		    tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]) {
 			__be32 saddr;
@@ -138,7 +279,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 
 			metadata = __ip_tun_set_dst(saddr, daddr, 0, 0,
 						    dst_port, flags,
-						    key_id, 0);
+						    key_id, opts_len);
 		} else if (tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC] &&
 			   tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]) {
 			struct in6_addr saddr;
@@ -162,6 +303,14 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
 			goto err_out;
 		}
 
+		if (opts_len) {
+			ret = tunnel_key_opts_set(tb[TCA_TUNNEL_KEY_ENC_OPTS],
+						  &metadata->u.tun_info,
+						  opts_len, extack);
+			if (ret < 0)
+				goto err_out;
+		}
+
 		metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX;
 		break;
 	default:
@@ -234,6 +383,61 @@ static void tunnel_key_release(struct tc_action *a)
 	}
 }
 
+static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
+				       const struct ip_tunnel_info *info)
+{
+	int len = info->options_len;
+	u8 *src = (u8 *)(info + 1);
+	struct nlattr *start;
+
+	start = nla_nest_start(skb, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
+	if (!start)
+		return -EMSGSIZE;
+
+	while (len > 0) {
+		struct geneve_opt *opt = (struct geneve_opt *)src;
+
+		if (nla_put_u16(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,
+				opt->opt_class) ||
+		    nla_put_u8(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE,
+			       opt->type) ||
+		    nla_put(skb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA,
+			    opt->length * 4, opt + 1))
+			return -EMSGSIZE;
+
+		len -= sizeof(struct geneve_opt) + opt->length * 4;
+		src += sizeof(struct geneve_opt) + opt->length * 4;
+	}
+
+	nla_nest_end(skb, start);
+	return 0;
+}
+
+static int tunnel_key_opts_dump(struct sk_buff *skb,
+				const struct ip_tunnel_info *info)
+{
+	struct nlattr *start;
+	int err;
+
+	if (!info->options_len)
+		return 0;
+
+	start = nla_nest_start(skb, TCA_TUNNEL_KEY_ENC_OPTS);
+	if (!start)
+		return -EMSGSIZE;
+
+	if (info->key.tun_flags & TUNNEL_GENEVE_OPT) {
+		err = tunnel_key_geneve_opts_dump(skb, info);
+		if (err)
+			return err;
+	} else {
+		return -EINVAL;
+	}
+
+	nla_nest_end(skb, start);
+	return 0;
+}
+
 static int tunnel_key_dump_addresses(struct sk_buff *skb,
 				     const struct ip_tunnel_info *info)
 {
@@ -284,8 +488,9 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
 		goto nla_put_failure;
 
 	if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET) {
-		struct ip_tunnel_key *key =
-			&params->tcft_enc_metadata->u.tun_info.key;
+		struct ip_tunnel_info *info =
+			&params->tcft_enc_metadata->u.tun_info;
+		struct ip_tunnel_key *key = &info->key;
 		__be32 key_id = tunnel_id_to_key32(key->tun_id);
 
 		if (nla_put_be32(skb, TCA_TUNNEL_KEY_ENC_KEY_ID, key_id) ||
@@ -293,7 +498,8 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
 					      &params->tcft_enc_metadata->u.tun_info) ||
 		    nla_put_be16(skb, TCA_TUNNEL_KEY_ENC_DST_PORT, key->tp_dst) ||
 		    nla_put_u8(skb, TCA_TUNNEL_KEY_NO_CSUM,
-			       !(key->tun_flags & TUNNEL_CSUM)))
+			       !(key->tun_flags & TUNNEL_CSUM)) ||
+		    tunnel_key_opts_dump(skb, info))
 			goto nla_put_failure;
 	}
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support
  2018-06-26 18:53 ` [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support Jakub Kicinski
@ 2018-06-26 19:50   ` David Ahern
  0 siblings, 0 replies; 9+ messages in thread
From: David Ahern @ 2018-06-26 19:50 UTC (permalink / raw)
  To: Jakub Kicinski, davem, jbenc
  Cc: Roopa Prabhu, jiri, jhs, xiyou.wangcong, daniel, oss-drivers,
	netdev, Simon Horman, Alexander Aring, Pieter Jansen van Vuuren

On 6/26/18 12:53 PM, Jakub Kicinski wrote:
> From: Simon Horman <simon.horman@netronome.com>
> 
> Add extended ack support for the tunnel key action by using NL_SET_ERR_MSG
> during validation of user input.
> 
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Alexander Aring <aring@mojatatu.com>
> Signed-off-by: Simon Horman <simon.horman@netronome.com>
> Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> ---
>  net/sched/act_tunnel_key.c | 27 +++++++++++++++++++++------
>  1 file changed, 21 insertions(+), 6 deletions(-)
> 

Reviewed-by: David Ahern <dsahern@gmail.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 3/4] net: check tunnel option type in tunnel flags
  2018-06-26 18:53 ` [PATCH net-next 3/4] net: check tunnel option type in tunnel flags Jakub Kicinski
@ 2018-06-27  3:08   ` kbuild test robot
  0 siblings, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2018-06-27  3:08 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: kbuild-all, davem, jbenc, Roopa Prabhu, jiri, jhs,
	xiyou.wangcong, daniel, oss-drivers, netdev,
	Pieter Jansen van Vuuren, Jakub Kicinski

Hi Pieter,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Jakub-Kicinski/net-Geneve-options-support-for-TC-act_tunnel_key/20180627-030036
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> net/openvswitch/flow_netlink.c:2532:38: sparse: incorrect type in assignment (different base types) @@    expected int [signed] [assigned] dst_opt_type @@    got restrint [signed] [assigned] dst_opt_type @@
   net/openvswitch/flow_netlink.c:2532:38:    expected int [signed] [assigned] dst_opt_type
   net/openvswitch/flow_netlink.c:2532:38:    got restricted __be16 [usertype] <noident>
   net/openvswitch/flow_netlink.c:2535:38: sparse: incorrect type in assignment (different base types) @@    expected int [signed] [assigned] dst_opt_type @@    got restrint [signed] [assigned] dst_opt_type @@
   net/openvswitch/flow_netlink.c:2535:38:    expected int [signed] [assigned] dst_opt_type
   net/openvswitch/flow_netlink.c:2535:38:    got restricted __be16 [usertype] <noident>
   net/openvswitch/flow_netlink.c:2538:38: sparse: incorrect type in assignment (different base types) @@    expected int [signed] [assigned] dst_opt_type @@    got restrint [signed] [assigned] dst_opt_type @@
   net/openvswitch/flow_netlink.c:2538:38:    expected int [signed] [assigned] dst_opt_type
   net/openvswitch/flow_netlink.c:2538:38:    got restricted __be16 [usertype] <noident>
>> net/openvswitch/flow_netlink.c:2581:51: sparse: incorrect type in argument 4 (different base types) @@    expected restricted __be16 [usertype] flags @@    got icted __be16 [usertype] flags @@
   net/openvswitch/flow_netlink.c:2581:51:    expected restricted __be16 [usertype] flags
   net/openvswitch/flow_netlink.c:2581:51:    got int [signed] [assigned] dst_opt_type
   net/openvswitch/flow_netlink.c:3064:39: sparse: expression using sizeof(void)

vim +2532 net/openvswitch/flow_netlink.c

  2508	
  2509	static int validate_and_copy_set_tun(const struct nlattr *attr,
  2510					     struct sw_flow_actions **sfa, bool log)
  2511	{
  2512		struct sw_flow_match match;
  2513		struct sw_flow_key key;
  2514		struct metadata_dst *tun_dst;
  2515		struct ip_tunnel_info *tun_info;
  2516		struct ovs_tunnel_info *ovs_tun;
  2517		struct nlattr *a;
  2518		int err = 0, start, opts_type, dst_opt_type;
  2519	
  2520		dst_opt_type = 0;
  2521		ovs_match_init(&match, &key, true, NULL);
  2522		opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
  2523		if (opts_type < 0)
  2524			return opts_type;
  2525	
  2526		if (key.tun_opts_len) {
  2527			switch (opts_type) {
  2528			case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
  2529				err = validate_geneve_opts(&key);
  2530				if (err < 0)
  2531					return err;
> 2532				dst_opt_type = TUNNEL_GENEVE_OPT;
  2533				break;
  2534			case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
  2535				dst_opt_type = TUNNEL_VXLAN_OPT;
  2536				break;
  2537			case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
  2538				dst_opt_type = TUNNEL_ERSPAN_OPT;
  2539				break;
  2540			}
  2541		}
  2542	
  2543		start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET, log);
  2544		if (start < 0)
  2545			return start;
  2546	
  2547		tun_dst = metadata_dst_alloc(key.tun_opts_len, METADATA_IP_TUNNEL,
  2548					     GFP_KERNEL);
  2549	
  2550		if (!tun_dst)
  2551			return -ENOMEM;
  2552	
  2553		err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
  2554		if (err) {
  2555			dst_release((struct dst_entry *)tun_dst);
  2556			return err;
  2557		}
  2558	
  2559		a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
  2560				 sizeof(*ovs_tun), log);
  2561		if (IS_ERR(a)) {
  2562			dst_release((struct dst_entry *)tun_dst);
  2563			return PTR_ERR(a);
  2564		}
  2565	
  2566		ovs_tun = nla_data(a);
  2567		ovs_tun->tun_dst = tun_dst;
  2568	
  2569		tun_info = &tun_dst->u.tun_info;
  2570		tun_info->mode = IP_TUNNEL_INFO_TX;
  2571		if (key.tun_proto == AF_INET6)
  2572			tun_info->mode |= IP_TUNNEL_INFO_IPV6;
  2573		tun_info->key = key.tun_key;
  2574	
  2575		/* We need to store the options in the action itself since
  2576		 * everything else will go away after flow setup. We can append
  2577		 * it to tun_info and then point there.
  2578		 */
  2579		ip_tunnel_info_opts_set(tun_info,
  2580					TUN_METADATA_OPTS(&key, key.tun_opts_len),
> 2581					key.tun_opts_len, dst_opt_type);
  2582		add_nested_action_end(*sfa, start);
  2583	
  2584		return err;
  2585	}
  2586	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key
  2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
                   ` (3 preceding siblings ...)
  2018-06-26 18:53 ` [PATCH net-next 4/4] net/sched: add tunnel option support to act_tunnel_key Jakub Kicinski
@ 2018-06-28  7:17 ` David Miller
  2018-06-28 16:39   ` Jakub Kicinski
  4 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2018-06-28  7:17 UTC (permalink / raw)
  To: jakub.kicinski
  Cc: jbenc, roopa, jiri, jhs, xiyou.wangcong, daniel, oss-drivers, netdev

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Tue, 26 Jun 2018 11:53:04 -0700

> Hi,
> 
> Simon & Pieter say:
> 
> This set adds Geneve Options support to the TC tunnel key action.
> It provides the plumbing required to configure Geneve variable length
> options.  The options can be configured in the form CLASS:TYPE:DATA,
> where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit
> hexadecimal value and DATA as a variable length hexadecimal value.
> Additionally multiple options may be listed using a comma delimiter.

Looks like there are some sparse endianness warnings to fix up as
per kbuild robot.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key
  2018-06-28  7:17 ` [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key David Miller
@ 2018-06-28 16:39   ` Jakub Kicinski
  0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2018-06-28 16:39 UTC (permalink / raw)
  To: David Miller
  Cc: jbenc, roopa, jiri, jhs, xiyou.wangcong, daniel, oss-drivers, netdev

On Thu, 28 Jun 2018 16:17:31 +0900 (KST), David Miller wrote:
> From: Jakub Kicinski <jakub.kicinski@netronome.com>
> Date: Tue, 26 Jun 2018 11:53:04 -0700
> 
> > Hi,
> > 
> > Simon & Pieter say:
> > 
> > This set adds Geneve Options support to the TC tunnel key action.
> > It provides the plumbing required to configure Geneve variable length
> > options.  The options can be configured in the form CLASS:TYPE:DATA,
> > where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit
> > hexadecimal value and DATA as a variable length hexadecimal value.
> > Additionally multiple options may be listed using a comma delimiter.  
> 
> Looks like there are some sparse endianness warnings to fix up as
> per kbuild robot.

Sorry about that!

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-06-28 16:39 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-26 18:53 [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key Jakub Kicinski
2018-06-26 18:53 ` [PATCH net-next 1/4] net/sched: act_tunnel_key: disambiguate metadata dst error cases Jakub Kicinski
2018-06-26 18:53 ` [PATCH net-next 2/4] net/sched: act_tunnel_key: add extended ack support Jakub Kicinski
2018-06-26 19:50   ` David Ahern
2018-06-26 18:53 ` [PATCH net-next 3/4] net: check tunnel option type in tunnel flags Jakub Kicinski
2018-06-27  3:08   ` kbuild test robot
2018-06-26 18:53 ` [PATCH net-next 4/4] net/sched: add tunnel option support to act_tunnel_key Jakub Kicinski
2018-06-28  7:17 ` [PATCH net-next 0/4] net: Geneve options support for TC act_tunnel_key David Miller
2018-06-28 16:39   ` Jakub Kicinski

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.