lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220620152647.2498927-3-dchumak@nvidia.com>
Date:   Mon, 20 Jun 2022 18:26:44 +0300
From:   Dima Chumak <dchumak@...dia.com>
To:     Jakub Kicinski <kuba@...nel.org>
CC:     Jiri Pirko <jiri@...dia.com>,
        "David S. Miller" <davem@...emloft.net>,
        Eric Dumazet <edumazet@...gle.com>,
        Paolo Abeni <pabeni@...hat.com>, <netdev@...r.kernel.org>,
        Dima Chumak <dchumak@...dia.com>
Subject: [PATCH net-next 2/5] devlink: Introduce police rate limit type

Define a new DEVLINK_RATE_LIMIT_TYPE_POLICE along with the related
devlink_rate object attributes and their devlink_ops.

The new attributes are optional and specific to 'limit_type police'
only. Driver implementations are allowed to support any or none of them.

Example of limiting inbound traffic with the new limit type:

$ devlink port function rate set netdevsim/netdevsim10/1 \
          limit_type police rx_max 10mbit rx_burst 1mb

Signed-off-by: Dima Chumak <dchumak@...dia.com>
---
 include/net/devlink.h        |  40 +++++++
 include/uapi/linux/devlink.h |   8 ++
 net/core/devlink.c           | 223 ++++++++++++++++++++++++++++++++++-
 3 files changed, 268 insertions(+), 3 deletions(-)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 4fe8e657da44..3de1cc42b10c 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -103,6 +103,17 @@ struct devlink_rate_shaping_attrs {
 	u64 tx_share;
 };
 
+struct devlink_rate_police_attrs {
+	u64 tx_max;
+	u64 tx_burst;
+	u64 rx_max;
+	u64 rx_burst;
+	u64 tx_pkts;
+	u64 tx_pkts_burst;
+	u64 rx_pkts;
+	u64 rx_pkts_burst;
+};
+
 struct devlink_rate {
 	struct list_head list;
 	enum devlink_rate_limit_type limit_type;
@@ -112,6 +123,7 @@ struct devlink_rate {
 
 	union { /* on limit_type */
 		struct devlink_rate_shaping_attrs shaping_attrs;
+		struct devlink_rate_police_attrs police_attrs;
 	};
 
 	struct devlink_rate *parent;
@@ -1501,10 +1513,38 @@ struct devlink_ops {
 				      u64 tx_share, struct netlink_ext_ack *extack);
 	int (*rate_leaf_tx_max_set)(struct devlink_rate *devlink_rate, void *priv,
 				    u64 tx_max, struct netlink_ext_ack *extack);
+	int (*rate_leaf_tx_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+				      u64 tx_burst, struct netlink_ext_ack *extack);
+	int (*rate_leaf_rx_max_set)(struct devlink_rate *devlink_rate, void *priv,
+				    u64 rx_max, struct netlink_ext_ack *extack);
+	int (*rate_leaf_rx_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+				      u64 rx_burst, struct netlink_ext_ack *extack);
+	int (*rate_leaf_tx_pkts_set)(struct devlink_rate *devlink_rate, void *priv,
+				     u64 tx_pkts, struct netlink_ext_ack *extack);
+	int (*rate_leaf_tx_pkts_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+					   u64 tx_pkts_burst, struct netlink_ext_ack *extack);
+	int (*rate_leaf_rx_pkts_set)(struct devlink_rate *devlink_rate, void *priv,
+				     u64 rx_pkts, struct netlink_ext_ack *extack);
+	int (*rate_leaf_rx_pkts_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+					   u64 rx_pkts_burst, struct netlink_ext_ack *extack);
 	int (*rate_node_tx_share_set)(struct devlink_rate *devlink_rate, void *priv,
 				      u64 tx_share, struct netlink_ext_ack *extack);
 	int (*rate_node_tx_max_set)(struct devlink_rate *devlink_rate, void *priv,
 				    u64 tx_max, struct netlink_ext_ack *extack);
+	int (*rate_node_tx_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+				      u64 tx_burst, struct netlink_ext_ack *extack);
+	int (*rate_node_rx_max_set)(struct devlink_rate *devlink_rate, void *priv,
+				    u64 rx_max, struct netlink_ext_ack *extack);
+	int (*rate_node_rx_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+				      u64 rx_burst, struct netlink_ext_ack *extack);
+	int (*rate_node_tx_pkts_set)(struct devlink_rate *devlink_rate, void *priv,
+				     u64 tx_pkts, struct netlink_ext_ack *extack);
+	int (*rate_node_tx_pkts_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+					   u64 tx_pkts_burst, struct netlink_ext_ack *extack);
+	int (*rate_node_rx_pkts_set)(struct devlink_rate *devlink_rate, void *priv,
+				     u64 rx_pkts, struct netlink_ext_ack *extack);
+	int (*rate_node_rx_pkts_burst_set)(struct devlink_rate *devlink_rate, void *priv,
+					   u64 rx_pkts_burst, struct netlink_ext_ack *extack);
 	int (*rate_node_new)(struct devlink_rate *rate_node, void **priv,
 			     struct netlink_ext_ack *extack);
 	int (*rate_node_del)(struct devlink_rate *rate_node, void *priv,
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 53aad0d09231..4903f7b6dc93 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -224,6 +224,7 @@ enum devlink_rate_type {
 enum devlink_rate_limit_type {
 	DEVLINK_RATE_LIMIT_TYPE_UNSET,
 	DEVLINK_RATE_LIMIT_TYPE_SHAPING,
+	DEVLINK_RATE_LIMIT_TYPE_POLICE,
 };
 
 enum devlink_param_cmode {
@@ -582,6 +583,13 @@ enum devlink_attr {
 	DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES,	/* nested */
 
 	DEVLINK_ATTR_RATE_LIMIT_TYPE,		/* u16 */
+	DEVLINK_ATTR_RATE_TX_BURST,		/* u64 */
+	DEVLINK_ATTR_RATE_RX_MAX,		/* u64 */
+	DEVLINK_ATTR_RATE_RX_BURST,		/* u64 */
+	DEVLINK_ATTR_RATE_TX_PKTS,		/* u64 */
+	DEVLINK_ATTR_RATE_TX_PKTS_BURST,	/* u64 */
+	DEVLINK_ATTR_RATE_RX_PKTS,		/* u64 */
+	DEVLINK_ATTR_RATE_RX_PKTS_BURST,	/* u64 */
 
 	/* add new attributes above here, update the policy in devlink.c */
 
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 756d95c72b4d..c74cdd0bd44d 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -366,6 +366,12 @@ devlink_rate_is_shaping(struct devlink_rate *devlink_rate)
 	return devlink_rate->limit_type == DEVLINK_RATE_LIMIT_TYPE_SHAPING;
 }
 
+static inline bool
+devlink_rate_is_police(struct devlink_rate *devlink_rate)
+{
+	return devlink_rate->limit_type == DEVLINK_RATE_LIMIT_TYPE_POLICE;
+}
+
 static struct devlink_rate *
 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info)
 {
@@ -1125,6 +1131,31 @@ static int devlink_nl_rate_fill(struct sk_buff *msg,
 		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE,
 				      devlink_rate->shaping_attrs.tx_share, DEVLINK_ATTR_PAD))
 			goto nla_put_failure;
+	} else if (devlink_rate_is_police(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_BURST,
+				      devlink_rate->police_attrs.tx_burst, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_RX_MAX,
+				      devlink_rate->police_attrs.rx_max, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_RX_BURST,
+				      devlink_rate->police_attrs.rx_burst, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_PKTS,
+				      devlink_rate->police_attrs.tx_pkts, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_PKTS_BURST,
+				      devlink_rate->police_attrs.tx_pkts_burst, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_RX_PKTS,
+				      devlink_rate->police_attrs.rx_pkts, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
+		if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_RX_PKTS_BURST,
+				      devlink_rate->police_attrs.rx_pkts_burst, DEVLINK_ATTR_PAD))
+			goto nla_put_failure;
 	}
 
 	if (devlink_rate->parent)
@@ -1966,7 +1997,110 @@ static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
 							new_val, info->extack);
 		if (err)
 			return err;
-		devlink_rate->shaping_attrs.tx_max = new_val;
+
+		if (devlink_rate_is_police(devlink_rate))
+			devlink_rate->police_attrs.tx_max = new_val;
+		else
+			devlink_rate->shaping_attrs.tx_max = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_TX_BURST] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_BURST]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_tx_burst_set(devlink_rate, devlink_rate->priv,
+							  new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_tx_burst_set(devlink_rate, devlink_rate->priv,
+							  new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.tx_burst = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_RX_MAX] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_RX_MAX]);
+
+		if (devlink_rate_is_leaf(devlink_rate)) {
+			err = ops->rate_leaf_rx_max_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		} else if (devlink_rate_is_node(devlink_rate)) {
+			err = ops->rate_node_rx_max_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		}
+		if (err)
+			return err;
+		devlink_rate->police_attrs.rx_max = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_RX_BURST] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_RX_BURST]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_rx_burst_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_rx_burst_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.rx_burst = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_TX_PKTS] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_PKTS]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_tx_pkts_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_tx_pkts_set(devlink_rate, devlink_rate->priv,
+							new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.tx_pkts = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_TX_PKTS_BURST] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_PKTS_BURST]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_tx_pkts_burst_set(devlink_rate, devlink_rate->priv,
+							       new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_tx_pkts_burst_set(devlink_rate, devlink_rate->priv,
+							       new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.tx_pkts_burst = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_RX_PKTS] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_RX_PKTS]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_rx_pkts_set(devlink_rate, devlink_rate->priv,
+							 new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_rx_pkts_set(devlink_rate, devlink_rate->priv,
+							 new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.rx_pkts = new_val;
+	}
+
+	if (attrs[DEVLINK_ATTR_RATE_RX_PKTS_BURST] && devlink_rate_is_police(devlink_rate)) {
+		new_val = nla_get_u64(attrs[DEVLINK_ATTR_RATE_RX_PKTS_BURST]);
+
+		if (devlink_rate_is_leaf(devlink_rate))
+			err = ops->rate_leaf_rx_pkts_burst_set(devlink_rate, devlink_rate->priv,
+							       new_val, info->extack);
+		else if (devlink_rate_is_node(devlink_rate))
+			err = ops->rate_node_rx_pkts_burst_set(devlink_rate, devlink_rate->priv,
+							       new_val, info->extack);
+		if (err)
+			return err;
+		devlink_rate->police_attrs.rx_pkts_burst = new_val;
 	}
 
 	if (nla_parent)
@@ -1977,7 +2111,12 @@ static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
 	 */
 	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->shaping_attrs.tx_max && !devlink_rate->shaping_attrs.tx_share) ||
+	     (devlink_rate_is_police(devlink_rate) &&
+	      !devlink_rate->police_attrs.tx_max && !devlink_rate->police_attrs.tx_burst &&
+	      !devlink_rate->police_attrs.rx_max && !devlink_rate->police_attrs.rx_burst &&
+	      !devlink_rate->police_attrs.tx_pkts && !devlink_rate->police_attrs.tx_pkts_burst &&
+	      !devlink_rate->police_attrs.rx_pkts && !devlink_rate->police_attrs.rx_pkts_burst)))
 		devlink_rate->limit_type = DEVLINK_RATE_LIMIT_TYPE_UNSET;
 
 	return err;
@@ -1995,7 +2134,43 @@ static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops,
 			return false;
 		}
 		if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) {
-			NL_SET_ERR_MSG_MOD(info->extack, "TX max set isn't supported for the leafs");
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX max set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_BURST] && !ops->rate_leaf_tx_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX burst set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_MAX] && !ops->rate_leaf_rx_max_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX max set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_BURST] && !ops->rate_leaf_rx_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX burst set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_PKTS] && !ops->rate_leaf_tx_pkts_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX pkts set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_PKTS_BURST] && !ops->rate_leaf_tx_pkts_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX pkts burst set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_PKTS] && !ops->rate_leaf_rx_pkts_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX pkts set isn't supported for the leafs");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_PKTS_BURST] && !ops->rate_leaf_rx_pkts_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX pkts burst set isn't supported for the leafs");
 			return false;
 		}
 		if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
@@ -2012,6 +2187,41 @@ static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops,
 			NL_SET_ERR_MSG_MOD(info->extack, "TX max set isn't supported for the nodes");
 			return false;
 		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_BURST] && !ops->rate_node_tx_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX burst set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_MAX] && !ops->rate_node_rx_max_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX max set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_BURST] && !ops->rate_node_rx_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX burst set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_PKTS] && !ops->rate_node_tx_pkts_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX pkts set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_TX_PKTS_BURST] && !ops->rate_node_tx_pkts_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "TX pkts burst set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_PKTS] && !ops->rate_node_rx_pkts_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX pkts set isn't supported for the nodes");
+			return false;
+		}
+		if (attrs[DEVLINK_ATTR_RATE_RX_PKTS_BURST] && !ops->rate_node_rx_pkts_burst_set) {
+			NL_SET_ERR_MSG_MOD(info->extack,
+					   "RX pkts burst set isn't supported for the nodes");
+			return false;
+		}
 		if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
 		    !ops->rate_node_parent_set) {
 			NL_SET_ERR_MSG_MOD(info->extack, "Parent set isn't supported for the nodes");
@@ -9075,6 +9285,13 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 },
 	[DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING },
 	[DEVLINK_ATTR_RATE_LIMIT_TYPE] = { .type = NLA_U16 },
+	[DEVLINK_ATTR_RATE_TX_BURST] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_RX_MAX] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_RX_BURST] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_TX_PKTS] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_TX_PKTS_BURST] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_RX_PKTS] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_RATE_RX_PKTS_BURST] = { .type = NLA_U64 },
 };
 
 static const struct genl_small_ops devlink_nl_ops[] = {
-- 
2.36.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ