[<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