netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dima Chumak <dchumak@nvidia.com>
To: Jakub Kicinski <kuba@kernel.org>
Cc: Jiri Pirko <jiri@nvidia.com>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Paolo Abeni <pabeni@redhat.com>, <netdev@vger.kernel.org>,
	Dima Chumak <dchumak@nvidia.com>
Subject: [PATCH net-next 1/5] devlink: Introduce limit_type attr for rate objects
Date: Mon, 20 Jun 2022 18:26:43 +0300	[thread overview]
Message-ID: <20220620152647.2498927-2-dchumak@nvidia.com> (raw)
In-Reply-To: <20220620152647.2498927-1-dchumak@nvidia.com>

Lay foundation to support different kinds of rate limiting that may be
performed by rate objects.

Existing rate limiting type is dubbed as 'shaping' and it is assumed by
default when limit_type attribute isn't set explicitly. Following patch
in the series will introduce new limit type 'police'.

Leaf rate objects inherit their limit_type from a parent node object if
it hasn't been explicitly set for the leaf object.

Signed-off-by: Dima Chumak <dchumak@nvidia.com>
---
 .../net/ethernet/mellanox/mlx5/core/esw/qos.c |  28 +++-
 include/net/devlink.h                         |  12 +-
 include/uapi/linux/devlink.h                  |   7 +
 net/core/devlink.c                            | 123 ++++++++++++++----
 4 files changed, 140 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
index 694c54066955..50bd4536fab1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
@@ -874,8 +874,8 @@ int mlx5_esw_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *
 int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
 				   struct netlink_ext_ack *extack)
 {
-	struct mlx5_esw_rate_group *group;
 	struct mlx5_eswitch *esw;
+	void *group;
 	int err = 0;
 
 	esw = mlx5_devlink_eswitch_get(rate_node->devlink);
@@ -890,7 +890,17 @@ int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
 		goto unlock;
 	}
 
-	group = esw_qos_create_rate_group(esw, extack);
+	switch (rate_node->limit_type) {
+	case DEVLINK_RATE_LIMIT_TYPE_UNSET:
+		group = ERR_PTR(-EINVAL);
+		break;
+	case DEVLINK_RATE_LIMIT_TYPE_SHAPING:
+		group = esw_qos_create_rate_group(esw, extack);
+		break;
+	default:
+		group = ERR_PTR(-EOPNOTSUPP);
+	}
+
 	if (IS_ERR(group)) {
 		err = PTR_ERR(group);
 		goto unlock;
@@ -905,7 +915,6 @@ int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
 int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
 				   struct netlink_ext_ack *extack)
 {
-	struct mlx5_esw_rate_group *group = priv;
 	struct mlx5_eswitch *esw;
 	int err;
 
@@ -914,7 +923,18 @@ int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
 		return PTR_ERR(esw);
 
 	mutex_lock(&esw->state_lock);
-	err = esw_qos_destroy_rate_group(esw, group, extack);
+
+	switch (rate_node->limit_type) {
+	case DEVLINK_RATE_LIMIT_TYPE_UNSET:
+		err = -EINVAL;
+		break;
+	case DEVLINK_RATE_LIMIT_TYPE_SHAPING:
+		err = esw_qos_destroy_rate_group(esw, priv, extack);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+	}
+
 	mutex_unlock(&esw->state_lock);
 	return err;
 }
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 2a2a2a0c93f7..4fe8e657da44 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -98,13 +98,21 @@ struct devlink_port_attrs {
 	};
 };
 
+struct devlink_rate_shaping_attrs {
+	u64 tx_max;
+	u64 tx_share;
+};
+
 struct devlink_rate {
 	struct list_head list;
+	enum devlink_rate_limit_type limit_type;
 	enum devlink_rate_type type;
 	struct devlink *devlink;
 	void *priv;
-	u64 tx_share;
-	u64 tx_max;
+
+	union { /* on limit_type */
+		struct devlink_rate_shaping_attrs shaping_attrs;
+	};
 
 	struct devlink_rate *parent;
 	union {
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index b3d40a5d72ff..53aad0d09231 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -221,6 +221,11 @@ enum devlink_rate_type {
 	DEVLINK_RATE_TYPE_NODE,
 };
 
+enum devlink_rate_limit_type {
+	DEVLINK_RATE_LIMIT_TYPE_UNSET,
+	DEVLINK_RATE_LIMIT_TYPE_SHAPING,
+};
+
 enum devlink_param_cmode {
 	DEVLINK_PARAM_CMODE_RUNTIME,
 	DEVLINK_PARAM_CMODE_DRIVERINIT,
@@ -576,6 +581,8 @@ enum devlink_attr {
 	DEVLINK_ATTR_LINECARD_TYPE,		/* string */
 	DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES,	/* nested */
 
+	DEVLINK_ATTR_RATE_LIMIT_TYPE,		/* u16 */
+
 	/* add new attributes above here, update the policy in devlink.c */
 
 	__DEVLINK_ATTR_MAX,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index db61f3a341cb..756d95c72b4d 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -354,6 +354,18 @@ devlink_rate_is_node(struct devlink_rate *devlink_rate)
 	return devlink_rate->type == DEVLINK_RATE_TYPE_NODE;
 }
 
+static inline bool
+devlink_rate_is_unset(struct devlink_rate *devlink_rate)
+{
+	return devlink_rate->limit_type == DEVLINK_RATE_LIMIT_TYPE_UNSET;
+}
+
+static inline bool
+devlink_rate_is_shaping(struct devlink_rate *devlink_rate)
+{
+	return devlink_rate->limit_type == DEVLINK_RATE_LIMIT_TYPE_SHAPING;
+}
+
 static struct devlink_rate *
 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info)
 {
@@ -1093,13 +1105,27 @@ static int devlink_nl_rate_fill(struct sk_buff *msg,
 			goto nla_put_failure;
 	}
 
-	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE,
-			      devlink_rate->tx_share, DEVLINK_ATTR_PAD))
+	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_LIMIT_TYPE,
+			      devlink_rate->limit_type, DEVLINK_ATTR_PAD))
 		goto nla_put_failure;
 
-	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX,
-			      devlink_rate->tx_max, DEVLINK_ATTR_PAD))
-		goto nla_put_failure;
+	if (devlink_rate_is_unset(devlink_rate)) {
+		/* For backward compatibility with older user-space clients that
+		 * don't understatnd DEVLINK_ATTR_RATE_LIMIT_TYPE, report tx_max
+		 * and tx_share as being "unlimited".
+		 */
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX, 0, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE, 0, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+	} else if (devlink_rate_is_shaping(devlink_rate)) {
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX,
+				      devlink_rate->shaping_attrs.tx_max, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE,
+				      devlink_rate->shaping_attrs.tx_share, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+	}
 
 	if (devlink_rate->parent)
 		if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME,
@@ -1850,6 +1876,12 @@ devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
 			return -EEXIST;
 		}
 
+		if (parent->limit_type != devlink_rate->limit_type) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "Parent and object should be of the same limit_type");
+			return -EINVAL;
+		}
+
 		if (devlink_rate_is_leaf(devlink_rate))
 			err = ops->rate_leaf_parent_set(devlink_rate, parent,
 							devlink_rate->priv, parent->priv,
@@ -1873,44 +1905,82 @@ static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
 			       struct genl_info *info)
 {
 	struct nlattr *nla_parent, **attrs = info->attrs;
-	int err = -EOPNOTSUPP;
-	u64 rate;
+	struct devlink_rate *parent;
+	int err = 0;
+	u16 new_limit_type;
+	u64 new_val;
+
+	nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
+
+	if (attrs[DEVLINK_ATTR_RATE_LIMIT_TYPE]) {
+		new_limit_type = nla_get_u16(attrs[DEVLINK_ATTR_RATE_LIMIT_TYPE]);
+		if (devlink_rate_is_unset(devlink_rate))
+			devlink_rate->limit_type = new_limit_type;
+		if (devlink_rate->limit_type != new_limit_type) {
+			if (devlink_rate_is_node(devlink_rate)) {
+				NL_SET_ERR_MSG_MOD(info->extack,
+						   "Cannot change limit_type of the rate node object, delete and add a new one instead.");
+				return -EINVAL;
+			}
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "Cannot change limit_type of the rate leaf object, reset current rate attributes first.");
+			return -EBUSY;
+		}
+	}
+
+	if (devlink_rate_is_unset(devlink_rate)) {
+		if (nla_parent) {
+			parent = devlink_rate_node_get_by_name(devlink_rate->devlink,
+							       nla_data(nla_parent));
+			if (!IS_ERR(parent))
+				devlink_rate->limit_type = parent->limit_type;
+			else
+				devlink_rate->limit_type = DEVLINK_RATE_LIMIT_TYPE_SHAPING;
+		} else {
+			devlink_rate->limit_type = DEVLINK_RATE_LIMIT_TYPE_SHAPING;
+		}
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && devlink_rate_is_shaping(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]);
 
-	if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) {
-		rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]);
 		if (devlink_rate_is_leaf(devlink_rate))
 			err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv,
-							  rate, info->extack);
+							  new_val, info->extack);
 		else if (devlink_rate_is_node(devlink_rate))
 			err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv,
-							  rate, info->extack);
+							  new_val, info->extack);
 		if (err)
 			return err;
-		devlink_rate->tx_share = rate;
+		devlink_rate->shaping_attrs.tx_share = new_val;
 	}
 
 	if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) {
-		rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]);
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]);
+
 		if (devlink_rate_is_leaf(devlink_rate))
 			err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv,
-							rate, info->extack);
+							new_val, info->extack);
 		else if (devlink_rate_is_node(devlink_rate))
 			err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv,
-							rate, info->extack);
+							new_val, info->extack);
 		if (err)
 			return err;
-		devlink_rate->tx_max = rate;
+		devlink_rate->shaping_attrs.tx_max = new_val;
 	}
 
-	nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
-	if (nla_parent) {
-		err = devlink_nl_rate_parent_node_set(devlink_rate, info,
-						      nla_parent);
-		if (err)
-			return err;
-	}
+	if (nla_parent)
+		err = devlink_nl_rate_parent_node_set(devlink_rate, info, nla_parent);
 
-	return 0;
+	/* reset limit_type when all attrs have been cleared, relevant only for
+	 * leaf objects as node objects get deleted altogether
+	 */
+	if (devlink_rate_is_leaf(devlink_rate) && !devlink_rate->parent &&
+	    ((devlink_rate_is_shaping(devlink_rate) &&
+	      !devlink_rate->shaping_attrs.tx_max && !devlink_rate->shaping_attrs.tx_share)))
+		devlink_rate->limit_type = DEVLINK_RATE_LIMIT_TYPE_UNSET;
+
+	return err;
 }
 
 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops,
@@ -2002,6 +2072,10 @@ static int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb,
 
 	rate_node->devlink = devlink;
 	rate_node->type = DEVLINK_RATE_TYPE_NODE;
+	if (info->attrs[DEVLINK_ATTR_RATE_LIMIT_TYPE])
+		rate_node->limit_type = nla_get_u16(info->attrs[DEVLINK_ATTR_RATE_LIMIT_TYPE]);
+	if (rate_node->limit_type == DEVLINK_RATE_LIMIT_TYPE_UNSET)
+		rate_node->limit_type = DEVLINK_RATE_LIMIT_TYPE_SHAPING;
 	rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL);
 	if (!rate_node->name) {
 		err = -ENOMEM;
@@ -9000,6 +9074,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING },
 	[DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 },
 	[DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING },
+	[DEVLINK_ATTR_RATE_LIMIT_TYPE] = { .type = NLA_U16 },
 };
 
 static const struct genl_small_ops devlink_nl_ops[] = {
-- 
2.36.1


  reply	other threads:[~2022-06-20 15:27 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-20 15:26 [PATCH net-next 0/5] devlink rate police limiter Dima Chumak
2022-06-20 15:26 ` Dima Chumak [this message]
2022-06-20 15:26 ` [PATCH net-next 2/5] devlink: Introduce police rate limit type Dima Chumak
2022-06-20 15:26 ` [PATCH net-next 3/5] netdevsim: Support devlink rate limit_type police Dima Chumak
2022-06-20 15:26 ` [PATCH net-next 4/5] selftest: netdevsim: Add devlink rate police sub-test Dima Chumak
2022-06-20 15:26 ` [PATCH net-next 5/5] Documentation: devlink rate objects limit_type Dima Chumak
2022-06-20 15:35 ` [PATCH iproute2-next 1/5] uapi: devlink.h DEVLINK_ATTR_RATE_LIMIT_TYPE Dima Chumak
2022-06-20 15:35 ` [PATCH iproute2-next 2/5] devlink: Add port rate limit_type support Dima Chumak
2022-06-20 15:35 ` [PATCH iproute2-next 3/5] utils: Add get_size64() Dima Chumak
2022-06-20 15:35 ` [PATCH iproute2-next 4/5] uapi: devlink.h DEVLINK_RATE_LIMIT_TYPE_POLICE Dima Chumak
2022-06-20 15:35 ` [PATCH iproute2-next 5/5] devlink: Introduce port rate limit_type police Dima Chumak
2022-06-20 20:04 ` [PATCH net-next 0/5] devlink rate police limiter Jakub Kicinski
2022-06-30 15:27   ` Dima Chumak
2022-06-30 18:13     ` Jakub Kicinski
2022-07-07 11:20       ` Jiri Pirko
2022-07-07 20:16         ` Jakub Kicinski
2022-07-08  7:27           ` Jiri Pirko
2022-07-08 18:05             ` Jakub Kicinski
2022-07-09  5:14               ` Jiri Pirko
2022-07-11 17:29                 ` Jakub Kicinski
2022-07-12  6:03                   ` Jiri Pirko
2022-07-13  0:13                     ` Jakub Kicinski
2022-07-13  5:04                       ` Jiri Pirko
2022-07-13 17:52                         ` Jakub Kicinski
2022-07-14  4:55                           ` Jiri Pirko
2022-07-14 16:07                             ` Jakub Kicinski

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=20220620152647.2498927-2-dchumak@nvidia.com \
    --to=dchumak@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=jiri@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).