All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/15] Add packet trap policers support
@ 2020-03-24 19:32 Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
                   ` (14 more replies)
  0 siblings, 15 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Background
==========

Devices capable of offloading the kernel's datapath and perform
functions such as bridging and routing must also be able to send (trap)
specific packets to the kernel (i.e., the CPU) for processing.

For example, a device acting as a multicast-aware bridge must be able to
trap IGMP membership reports to the kernel for processing by the bridge
module.

Motivation
==========

In most cases, the underlying device is capable of handling packet rates
that are several orders of magnitude higher compared to those that can
be handled by the CPU.

Therefore, in order to prevent the underlying device from overwhelming
the CPU, devices usually include packet trap policers that are able to
police the trapped packets to rates that can be handled by the CPU.

Proposed solution
=================

This patch set allows capable device drivers to register their supported
packet trap policers with devlink. User space can then tune the
parameters of these policers (currently, rate and burst size) and read
from the device the number of packets that were dropped by the policer,
if supported.

These packet trap policers can then be bound to existing packet trap
groups, which are used to aggregate logically related packet traps. As a
result, trapped packets are policed to rates that can be handled the
host CPU.

Example usage
=============

Instantiate netdevsim:
# echo "10 1" > /sys/bus/netdevsim/new_device

Dump available packet trap policers:
# devlink trap policer show
netdevsim/netdevsim10:
  policer 1 rate 1000 burst 128
  policer 2 rate 2000 burst 256
  policer 3 rate 3000 burst 512

Change the parameters of a packet trap policer:
# devlink trap policer set netdevsim/netdevsim10 policer 3 rate 100 burst 16

Bind a packet trap policer to a packet trap group:
# devlink trap group set netdevsim/netdevsim10 group acl_drops policer 3

Dump parameters and statistics of a packet trap policer:
# devlink -s trap policer show netdevsim/netdevsim10 policer 3
netdevsim/netdevsim10:
  policer 3 rate 100 burst 16
    stats:
        rx:
          dropped 92

Unbind a packet trap policer from a packet trap group:
# devlink trap group set netdevsim/netdevsim10 group acl_drops nopolicer

Patch set overview
==================

Patch #1 adds the core infrastructure in devlink which allows capable
device drivers to register their supported packet trap policers with
devlink.

Patch #2 extends the existing devlink-trap documentation.

Patch #3 extends netdevsim to register a few dummy packet trap policers
with devlink. Used later on to selftests the core infrastructure.

Patches #4-#5 adds infrastructure in devlink to allow binding of packet
trap policers to packet trap groups.

Patch #6 extends netdevsim to allow such binding.

Patch #7 adds a selftest over netdevsim that verifies the core
devlink-trap policers functionality.

Patches #8-#14 gradually add devlink-trap policers support in mlxsw.

Patch #15 adds a selftest over mlxsw. All registered packet trap
policers are verified to handle the configured rate and burst size.

Future plans
============

* Allow changing default association between packet traps and packet
  trap groups
* Add more packet traps. For example, for control packets (e.g., IGMP)

Ido Schimmel (15):
  devlink: Add packet trap policers support
  Documentation: Add description of packet trap policers
  netdevsim: Add devlink-trap policer support
  devlink: Add packet trap group parameters support
  devlink: Allow setting of packet trap group parameters
  netdevsim: Add support for setting of packet trap group parameters
  selftests: netdevsim: Add test cases for devlink-trap policers
  mlxsw: reg: Extend QPCR register
  mlxsw: spectrum: Track used packet trap policer IDs
  mlxsw: spectrum_trap: Prepare policers for registration with devlink
  mlxsw: spectrum_trap: Add devlink-trap policer support
  mlxsw: spectrum_trap: Do not initialize dedicated discard policer
  mlxsw: spectrum_trap: Switch to use correct packet trap group
  mlxsw: spectrum_trap: Add support for setting of packet trap group
    parameters
  selftests: mlxsw: Add test cases for devlink-trap policers

 .../networking/devlink/devlink-trap.rst       |  26 +
 drivers/net/ethernet/mellanox/mlxsw/core.c    |  71 +++
 drivers/net/ethernet/mellanox/mlxsw/core.h    |  14 +
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  19 +-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  50 +-
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  17 +
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   | 354 +++++++++++--
 .../ethernet/mellanox/mlxsw/spectrum_trap.h   |  24 +
 drivers/net/netdevsim/dev.c                   | 121 ++++-
 drivers/net/netdevsim/netdevsim.h             |   2 +
 include/net/devlink.h                         |  77 ++-
 include/uapi/linux/devlink.h                  |  11 +
 net/core/devlink.c                            | 477 ++++++++++++++++++
 .../drivers/net/mlxsw/devlink_trap_policer.sh | 384 ++++++++++++++
 .../drivers/net/netdevsim/devlink_trap.sh     | 110 ++++
 .../selftests/net/forwarding/devlink_lib.sh   |  43 ++
 16 files changed, 1751 insertions(+), 49 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh

-- 
2.24.1


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

* [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-25  3:31   ` Jakub Kicinski
  2020-03-25  3:37   ` Jakub Kicinski
  2020-03-24 19:32 ` [PATCH net-next 02/15] Documentation: Add description of packet trap policers Ido Schimmel
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Devices capable of offloading the kernel's datapath and perform
functions such as bridging and routing must also be able to send (trap)
specific packets to the kernel (i.e., the CPU) for processing.

For example, a device acting as a multicast-aware bridge must be able to
trap IGMP membership reports to the kernel for processing by the bridge
module.

In most cases, the underlying device is capable of handling packet rates
that are several orders of magnitude higher compared to those that can
be handled by the CPU.

Therefore, in order to prevent the underlying device from overwhelming
the CPU, devices usually include packet trap policers that are able to
police the trapped packets to rates that can be handled by the CPU.

This patch allows capable device drivers to register their supported
packet trap policers with devlink. User space can then tune the
parameters of these policer (currently, rate and burst size) and read
from the device the number of packets that were dropped by the policer,
if supported.

Subsequent patches in the series will allow device drivers to create
default binding between these policers and packet trap groups and allow
user space to change the binding.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/devlink.h        |  63 ++++++
 include/uapi/linux/devlink.h |  11 +
 net/core/devlink.c           | 403 +++++++++++++++++++++++++++++++++++
 3 files changed, 477 insertions(+)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 37230e23b5b0..66c52a2ef2cc 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -35,6 +35,7 @@ struct devlink {
 	struct devlink_dpipe_headers *dpipe_headers;
 	struct list_head trap_list;
 	struct list_head trap_group_list;
+	struct list_head trap_policer_list;
 	const struct devlink_ops *ops;
 	struct device *dev;
 	possible_net_t _net;
@@ -528,6 +529,21 @@ struct devlink_health_reporter_ops {
 			struct netlink_ext_ack *extack);
 };
 
+/**
+ * struct devlink_trap_policer - Immutable packet trap policer attributes.
+ * @id: Policer identifier.
+ * @init_rate: Initial rate in packets / sec.
+ * @init_burst: Initial burst size in packets.
+ *
+ * Describes immutable attributes of packet trap policers that drivers register
+ * with devlink.
+ */
+struct devlink_trap_policer {
+	u32 id;
+	u64 init_rate;
+	u64 init_burst;
+};
+
 /**
  * struct devlink_trap_group - Immutable packet trap group attributes.
  * @name: Trap group name.
@@ -725,6 +741,13 @@ enum devlink_trap_group_generic_id {
 		.generic = true,					      \
 	}
 
+#define DEVLINK_TRAP_POLICER(_id, _rate, _burst)			      \
+	{								      \
+		.id = _id,						      \
+		.init_rate = _rate,					      \
+		.init_burst = _burst,					      \
+	}
+
 struct devlink_ops {
 	int (*reload_down)(struct devlink *devlink, bool netns_change,
 			   struct netlink_ext_ack *extack);
@@ -821,6 +844,38 @@ struct devlink_ops {
 	 */
 	int (*trap_group_init)(struct devlink *devlink,
 			       const struct devlink_trap_group *group);
+	/**
+	 * @trap_policer_init: Trap policer initialization function.
+	 *
+	 * Should be used by device drivers to initialize the trap policer in
+	 * the underlying device.
+	 */
+	int (*trap_policer_init)(struct devlink *devlink,
+				 const struct devlink_trap_policer *policer);
+	/**
+	 * @trap_policer_fini: Trap policer de-initialization function.
+	 *
+	 * Should be used by device drivers to de-initialize the trap policer
+	 * in the underlying device.
+	 */
+	void (*trap_policer_fini)(struct devlink *devlink,
+				  const struct devlink_trap_policer *policer);
+	/**
+	 * @trap_policer_set: Trap policer parameters set function.
+	 */
+	int (*trap_policer_set)(struct devlink *devlink,
+				const struct devlink_trap_policer *policer,
+				u64 rate, u64 burst,
+				struct netlink_ext_ack *extack);
+	/**
+	 * @trap_policer_counter_get: Trap policer counter get function.
+	 *
+	 * Should be used by device drivers to report number of packets dropped
+	 * by the policer.
+	 */
+	int (*trap_policer_counter_get)(struct devlink *devlink,
+					const struct devlink_trap_policer *policer,
+					u64 *p_drops);
 };
 
 static inline void *devlink_priv(struct devlink *devlink)
@@ -1064,6 +1119,14 @@ int devlink_trap_groups_register(struct devlink *devlink,
 void devlink_trap_groups_unregister(struct devlink *devlink,
 				    const struct devlink_trap_group *groups,
 				    size_t groups_count);
+int
+devlink_trap_policers_register(struct devlink *devlink,
+			       const struct devlink_trap_policer *policers,
+			       size_t policers_count);
+void
+devlink_trap_policers_unregister(struct devlink *devlink,
+				 const struct devlink_trap_policer *policers,
+				 size_t policers_count);
 
 #if IS_ENABLED(CONFIG_NET_DEVLINK)
 
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index dfdffc42e87d..856b88ea4aa3 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -117,6 +117,11 @@ enum devlink_command {
 	DEVLINK_CMD_TRAP_GROUP_NEW,
 	DEVLINK_CMD_TRAP_GROUP_DEL,
 
+	DEVLINK_CMD_TRAP_POLICER_GET,	/* can dump */
+	DEVLINK_CMD_TRAP_POLICER_SET,
+	DEVLINK_CMD_TRAP_POLICER_NEW,
+	DEVLINK_CMD_TRAP_POLICER_DEL,
+
 	/* add new commands above here */
 	__DEVLINK_CMD_MAX,
 	DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
@@ -217,6 +222,7 @@ enum devlink_param_reset_dev_on_drv_probe_value {
 enum {
 	DEVLINK_ATTR_STATS_RX_PACKETS,		/* u64 */
 	DEVLINK_ATTR_STATS_RX_BYTES,		/* u64 */
+	DEVLINK_ATTR_STATS_RX_DROPPED,		/* u64 */
 
 	__DEVLINK_ATTR_STATS_MAX,
 	DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1
@@ -429,6 +435,11 @@ enum devlink_attr {
 	DEVLINK_ATTR_NETNS_FD,			/* u32 */
 	DEVLINK_ATTR_NETNS_PID,			/* u32 */
 	DEVLINK_ATTR_NETNS_ID,			/* u32 */
+
+	DEVLINK_ATTR_TRAP_POLICER_ID,			/* u32 */
+	DEVLINK_ATTR_TRAP_POLICER_RATE,			/* u64 */
+	DEVLINK_ATTR_TRAP_POLICER_BURST,		/* u64 */
+
 	/* 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 73bb8fbe3393..63008d3785dc 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5453,6 +5453,23 @@ struct devlink_stats {
 	struct u64_stats_sync syncp;
 };
 
+/**
+ * struct devlink_trap_policer_item - Packet trap policer attributes.
+ * @policer: Immutable packet trap policer attributes.
+ * @rate: Rate in packets / sec.
+ * @burst: Burst size in packets.
+ * @list: trap_policer_list member.
+ *
+ * Describes packet trap policer attributes. Created by devlink during trap
+ * policer registration.
+ */
+struct devlink_trap_policer_item {
+	const struct devlink_trap_policer *policer;
+	u64 rate;
+	u64 burst;
+	struct list_head list;
+};
+
 /**
  * struct devlink_trap_group_item - Packet trap group attributes.
  * @group: Immutable packet trap group attributes.
@@ -5489,6 +5506,19 @@ struct devlink_trap_item {
 	void *priv;
 };
 
+static struct devlink_trap_policer_item *
+devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
+{
+	struct devlink_trap_policer_item *policer_item;
+
+	list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
+		if (policer_item->policer->id == id)
+			return policer_item;
+	}
+
+	return NULL;
+}
+
 static struct devlink_trap_item *
 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
 {
@@ -6026,6 +6056,221 @@ static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
 	return 0;
 }
 
+static struct devlink_trap_policer_item *
+devlink_trap_policer_item_get_from_info(struct devlink *devlink,
+					struct genl_info *info)
+{
+	u32 id;
+
+	if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
+		return NULL;
+	id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
+
+	return devlink_trap_policer_item_lookup(devlink, id);
+}
+
+static int
+devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
+			       const struct devlink_trap_policer *policer)
+{
+	struct nlattr *attr;
+	u64 drops;
+	int err;
+
+	if (!devlink->ops->trap_policer_counter_get)
+		return 0;
+
+	err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
+	if (err)
+		return err;
+
+	attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
+	if (!attr)
+		return -EMSGSIZE;
+
+	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
+			      DEVLINK_ATTR_PAD))
+		goto nla_put_failure;
+
+	nla_nest_end(msg, attr);
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(msg, attr);
+	return -EMSGSIZE;
+}
+
+static int
+devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
+			     const struct devlink_trap_policer_item *policer_item,
+			     enum devlink_command cmd, u32 portid, u32 seq,
+			     int flags)
+{
+	void *hdr;
+	int err;
+
+	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (devlink_nl_put_handle(msg, devlink))
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
+			policer_item->policer->id))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
+			      policer_item->rate, DEVLINK_ATTR_PAD))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
+			      policer_item->burst, DEVLINK_ATTR_PAD))
+		goto nla_put_failure;
+
+	err = devlink_trap_policer_stats_put(msg, devlink,
+					     policer_item->policer);
+	if (err)
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb,
+						struct genl_info *info)
+{
+	struct devlink_trap_policer_item *policer_item;
+	struct netlink_ext_ack *extack = info->extack;
+	struct devlink *devlink = info->user_ptr[0];
+	struct sk_buff *msg;
+	int err;
+
+	if (list_empty(&devlink->trap_policer_list))
+		return -EOPNOTSUPP;
+
+	policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
+	if (!policer_item) {
+		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
+		return -ENOENT;
+	}
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
+					   DEVLINK_CMD_TRAP_POLICER_NEW,
+					   info->snd_portid, info->snd_seq, 0);
+	if (err)
+		goto err_trap_policer_fill;
+
+	return genlmsg_reply(msg, info);
+
+err_trap_policer_fill:
+	nlmsg_free(msg);
+	return err;
+}
+
+static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg,
+						  struct netlink_callback *cb)
+{
+	enum devlink_command cmd = DEVLINK_CMD_TRAP_POLICER_NEW;
+	struct devlink_trap_policer_item *policer_item;
+	u32 portid = NETLINK_CB(cb->skb).portid;
+	struct devlink *devlink;
+	int start = cb->args[0];
+	int idx = 0;
+	int err;
+
+	mutex_lock(&devlink_mutex);
+	list_for_each_entry(devlink, &devlink_list, list) {
+		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+			continue;
+		mutex_lock(&devlink->lock);
+		list_for_each_entry(policer_item, &devlink->trap_policer_list,
+				    list) {
+			if (idx < start) {
+				idx++;
+				continue;
+			}
+			err = devlink_nl_trap_policer_fill(msg, devlink,
+							   policer_item, cmd,
+							   portid,
+							   cb->nlh->nlmsg_seq,
+							   NLM_F_MULTI);
+			if (err) {
+				mutex_unlock(&devlink->lock);
+				goto out;
+			}
+			idx++;
+		}
+		mutex_unlock(&devlink->lock);
+	}
+out:
+	mutex_unlock(&devlink_mutex);
+
+	cb->args[0] = idx;
+	return msg->len;
+}
+
+static int
+devlink_trap_policer_set(struct devlink *devlink,
+			 struct devlink_trap_policer_item *policer_item,
+			 struct genl_info *info)
+{
+	struct nlattr **attrs = info->attrs;
+	u64 rate, burst;
+	int err;
+
+	rate = policer_item->rate;
+	burst = policer_item->burst;
+
+	if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
+		rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
+
+	if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
+		burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
+
+	err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
+					     rate, burst, info->extack);
+	if (err)
+		return err;
+
+	policer_item->rate = rate;
+	policer_item->burst = burst;
+
+	return 0;
+}
+
+static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
+						struct genl_info *info)
+{
+	struct devlink_trap_policer_item *policer_item;
+	struct netlink_ext_ack *extack = info->extack;
+	struct devlink *devlink = info->user_ptr[0];
+
+	if (list_empty(&devlink->trap_policer_list))
+		return -EOPNOTSUPP;
+
+	if (!devlink->ops->trap_policer_set)
+		return -EOPNOTSUPP;
+
+	policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
+	if (!policer_item) {
+		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
+		return -ENOENT;
+	}
+
+	return devlink_trap_policer_set(devlink, policer_item, info);
+}
+
 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
@@ -6064,6 +6309,9 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 	[DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
 	[DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
 	[DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
+	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
+	[DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
+	[DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
 };
 
 static const struct genl_ops devlink_nl_ops[] = {
@@ -6391,6 +6639,19 @@ static const struct genl_ops devlink_nl_ops[] = {
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
 	},
+	{
+		.cmd = DEVLINK_CMD_TRAP_POLICER_GET,
+		.doit = devlink_nl_cmd_trap_policer_get_doit,
+		.dumpit = devlink_nl_cmd_trap_policer_get_dumpit,
+		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
+		/* can be retrieved by unprivileged users */
+	},
+	{
+		.cmd = DEVLINK_CMD_TRAP_POLICER_SET,
+		.doit = devlink_nl_cmd_trap_policer_set_doit,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
+	},
 };
 
 static struct genl_family devlink_nl_family __ro_after_init = {
@@ -6438,6 +6699,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
 	INIT_LIST_HEAD(&devlink->reporter_list);
 	INIT_LIST_HEAD(&devlink->trap_list);
 	INIT_LIST_HEAD(&devlink->trap_group_list);
+	INIT_LIST_HEAD(&devlink->trap_policer_list);
 	mutex_init(&devlink->lock);
 	mutex_init(&devlink->reporters_lock);
 	return devlink;
@@ -6522,6 +6784,7 @@ void devlink_free(struct devlink *devlink)
 {
 	mutex_destroy(&devlink->reporters_lock);
 	mutex_destroy(&devlink->lock);
+	WARN_ON(!list_empty(&devlink->trap_policer_list));
 	WARN_ON(!list_empty(&devlink->trap_group_list));
 	WARN_ON(!list_empty(&devlink->trap_list));
 	WARN_ON(!list_empty(&devlink->reporter_list));
@@ -8317,6 +8580,146 @@ void devlink_trap_groups_unregister(struct devlink *devlink,
 }
 EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
 
+static void
+devlink_trap_policer_notify(struct devlink *devlink,
+			    const struct devlink_trap_policer_item *policer_item,
+			    enum devlink_command cmd)
+{
+	struct sk_buff *msg;
+	int err;
+
+	WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
+		     cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
+					   0, 0);
+	if (err) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
+				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
+}
+
+static int
+devlink_trap_policer_register(struct devlink *devlink,
+			      const struct devlink_trap_policer *policer)
+{
+	struct devlink_trap_policer_item *policer_item;
+	int err;
+
+	if (devlink_trap_policer_item_lookup(devlink, policer->id))
+		return -EEXIST;
+
+	policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
+	if (!policer_item)
+		return -ENOMEM;
+
+	policer_item->policer = policer;
+	policer_item->rate = policer->init_rate;
+	policer_item->burst = policer->init_burst;
+
+	if (devlink->ops->trap_policer_init) {
+		err = devlink->ops->trap_policer_init(devlink, policer);
+		if (err)
+			goto err_policer_init;
+	}
+
+	list_add_tail(&policer_item->list, &devlink->trap_policer_list);
+	devlink_trap_policer_notify(devlink, policer_item,
+				    DEVLINK_CMD_TRAP_POLICER_NEW);
+
+	return 0;
+
+err_policer_init:
+	kfree(policer_item);
+	return err;
+}
+
+static void
+devlink_trap_policer_unregister(struct devlink *devlink,
+				const struct devlink_trap_policer *policer)
+{
+	struct devlink_trap_policer_item *policer_item;
+
+	policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
+	if (WARN_ON_ONCE(!policer_item))
+		return;
+
+	devlink_trap_policer_notify(devlink, policer_item,
+				    DEVLINK_CMD_TRAP_POLICER_DEL);
+	list_del(&policer_item->list);
+	if (devlink->ops->trap_policer_fini)
+		devlink->ops->trap_policer_fini(devlink, policer);
+	kfree(policer_item);
+}
+
+/**
+ * devlink_trap_policers_register - Register packet trap policers with devlink.
+ * @devlink: devlink.
+ * @policers: Packet trap policers.
+ * @policers_count: Count of provided packet trap policers.
+ *
+ * Return: Non-zero value on failure.
+ */
+int
+devlink_trap_policers_register(struct devlink *devlink,
+			       const struct devlink_trap_policer *policers,
+			       size_t policers_count)
+{
+	int i, err;
+
+	mutex_lock(&devlink->lock);
+	for (i = 0; i < policers_count; i++) {
+		const struct devlink_trap_policer *policer = &policers[i];
+
+		if (WARN_ON(policer->id == 0)) {
+			err = -EINVAL;
+			goto err_trap_policer_verify;
+		}
+
+		err = devlink_trap_policer_register(devlink, policer);
+		if (err)
+			goto err_trap_policer_register;
+	}
+	mutex_unlock(&devlink->lock);
+
+	return 0;
+
+err_trap_policer_register:
+err_trap_policer_verify:
+	for (i--; i >= 0; i--)
+		devlink_trap_policer_unregister(devlink, &policers[i]);
+	mutex_unlock(&devlink->lock);
+	return err;
+}
+EXPORT_SYMBOL_GPL(devlink_trap_policers_register);
+
+/**
+ * devlink_trap_policers_unregister - Unregister packet trap policers from devlink.
+ * @devlink: devlink.
+ * @policers: Packet trap policers.
+ * @policers_count: Count of provided packet trap policers.
+ */
+void
+devlink_trap_policers_unregister(struct devlink *devlink,
+				 const struct devlink_trap_policer *policers,
+				 size_t policers_count)
+{
+	int i;
+
+	mutex_lock(&devlink->lock);
+	for (i = policers_count - 1; i >= 0; i--)
+		devlink_trap_policer_unregister(devlink, &policers[i]);
+	mutex_unlock(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devlink_trap_policers_unregister);
+
 static void __devlink_compat_running_version(struct devlink *devlink,
 					     char *buf, size_t len)
 {
-- 
2.24.1


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

* [PATCH net-next 02/15] Documentation: Add description of packet trap policers
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 03/15] netdevsim: Add devlink-trap policer support Ido Schimmel
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Extend devlink-trap documentation with information about packet trap
policers.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 .../networking/devlink/devlink-trap.rst       | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/Documentation/networking/devlink/devlink-trap.rst b/Documentation/networking/devlink/devlink-trap.rst
index 63350e7332ce..a09971c2115c 100644
--- a/Documentation/networking/devlink/devlink-trap.rst
+++ b/Documentation/networking/devlink/devlink-trap.rst
@@ -287,6 +287,32 @@ narrow. The description of these groups must be added to the following table:
      - Contains packet traps for packets that were dropped by the device during
        ACL processing
 
+Packet Trap Policers
+====================
+
+As previously explained, the underlying device can trap certain packets to the
+CPU for processing. In most cases, the underlying device is capable of handling
+packet rates that are several orders of magnitude higher compared to those that
+can be handled by the CPU.
+
+Therefore, in order to prevent the underlying device from overwhelming the CPU,
+devices usually include packet trap policers that are able to police the
+trapped packets to rates that can be handled by the CPU.
+
+The ``devlink-trap`` mechanism allows capable device drivers to register their
+supported packet trap policers with ``devlink``. The device driver can choose
+to associate these policers with supported packet trap groups (see
+:ref:`Generic-Packet-Trap-Groups`) during its initialization, thereby exposing
+its default control plane policy to user space.
+
+Device drivers should allow user space to change the parameters of the policers
+(e.g., rate, burst size) as well as the association between the policers and
+trap groups by implementing the relevant callbacks.
+
+If possible, device drivers should implement a callback that allows user space
+to retrieve the number of packets that were dropped by the policer because its
+configured policy was violated.
+
 Testing
 =======
 
-- 
2.24.1


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

* [PATCH net-next 03/15] netdevsim: Add devlink-trap policer support
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 02/15] Documentation: Add description of packet trap policers Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 04/15] devlink: Add packet trap group parameters support Ido Schimmel
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Register three dummy packet trap policers with devlink and implement
callbacks to change their parameters and read their counters.

This will be used later on in the series to test the devlink-trap
policer infrastructure.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/netdevsim/dev.c       | 96 ++++++++++++++++++++++++++++++-
 drivers/net/netdevsim/netdevsim.h |  1 +
 2 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index 7bfd0622cef1..ce74adbf0e8b 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -192,6 +192,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
 			    &nsim_dev->fail_reload);
 	debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir,
 			    nsim_dev, &nsim_dev_trap_fa_cookie_fops);
+	debugfs_create_bool("fail_trap_policer_counter_get", 0600,
+			    nsim_dev->ddir,
+			    &nsim_dev->fail_trap_policer_counter_get);
 	return 0;
 }
 
@@ -363,6 +366,7 @@ struct nsim_trap_item {
 struct nsim_trap_data {
 	struct delayed_work trap_report_dw;
 	struct nsim_trap_item *trap_items_arr;
+	u64 *trap_policers_cnt_arr;
 	struct nsim_dev *nsim_dev;
 	spinlock_t trap_lock;	/* Protects trap_items_arr */
 };
@@ -397,6 +401,12 @@ enum {
 			    DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
 			    NSIM_TRAP_METADATA)
 
+static const struct devlink_trap_policer nsim_trap_policers_arr[] = {
+	DEVLINK_TRAP_POLICER(1, 1000, 128),
+	DEVLINK_TRAP_POLICER(2, 2000, 256),
+	DEVLINK_TRAP_POLICER(3, 3000, 512),
+};
+
 static const struct devlink_trap_group nsim_trap_groups_arr[] = {
 	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS),
 	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS),
@@ -539,6 +549,7 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
 
 static int nsim_dev_traps_init(struct devlink *devlink)
 {
+	size_t policers_count = ARRAY_SIZE(nsim_trap_policers_arr);
 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
 	struct nsim_trap_data *nsim_trap_data;
 	int err;
@@ -555,6 +566,14 @@ static int nsim_dev_traps_init(struct devlink *devlink)
 		goto err_trap_data_free;
 	}
 
+	nsim_trap_data->trap_policers_cnt_arr = kcalloc(policers_count,
+							sizeof(u64),
+							GFP_KERNEL);
+	if (!nsim_trap_data->trap_policers_cnt_arr) {
+		err = -ENOMEM;
+		goto err_trap_items_free;
+	}
+
 	/* The lock is used to protect the action state of the registered
 	 * traps. The value is written by user and read in delayed work when
 	 * iterating over all the traps.
@@ -563,10 +582,15 @@ static int nsim_dev_traps_init(struct devlink *devlink)
 	nsim_trap_data->nsim_dev = nsim_dev;
 	nsim_dev->trap_data = nsim_trap_data;
 
+	err = devlink_trap_policers_register(devlink, nsim_trap_policers_arr,
+					     policers_count);
+	if (err)
+		goto err_trap_policers_cnt_free;
+
 	err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr,
 					   ARRAY_SIZE(nsim_trap_groups_arr));
 	if (err)
-		goto err_trap_items_free;
+		goto err_trap_policers_unregister;
 
 	err = devlink_traps_register(devlink, nsim_traps_arr,
 				     ARRAY_SIZE(nsim_traps_arr), NULL);
@@ -583,6 +607,11 @@ static int nsim_dev_traps_init(struct devlink *devlink)
 err_trap_groups_unregister:
 	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
 				       ARRAY_SIZE(nsim_trap_groups_arr));
+err_trap_policers_unregister:
+	devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
+					 ARRAY_SIZE(nsim_trap_policers_arr));
+err_trap_policers_cnt_free:
+	kfree(nsim_trap_data->trap_policers_cnt_arr);
 err_trap_items_free:
 	kfree(nsim_trap_data->trap_items_arr);
 err_trap_data_free:
@@ -599,6 +628,9 @@ static void nsim_dev_traps_exit(struct devlink *devlink)
 				 ARRAY_SIZE(nsim_traps_arr));
 	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
 				       ARRAY_SIZE(nsim_trap_groups_arr));
+	devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
+					 ARRAY_SIZE(nsim_trap_policers_arr));
+	kfree(nsim_dev->trap_data->trap_policers_cnt_arr);
 	kfree(nsim_dev->trap_data->trap_items_arr);
 	kfree(nsim_dev->trap_data);
 }
@@ -737,6 +769,66 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink,
 	return 0;
 }
 
+#define NSIM_DEV_TRAP_POLICER_MIN_RATE	1
+#define NSIM_DEV_TRAP_POLICER_MAX_RATE	8000
+#define NSIM_DEV_TRAP_POLICER_MIN_BURST	8
+#define NSIM_DEV_TRAP_POLICER_MAX_BURST	65536
+
+static int
+nsim_dev_devlink_trap_policer_set(struct devlink *devlink,
+				  const struct devlink_trap_policer *policer,
+				  u64 rate, u64 burst,
+				  struct netlink_ext_ack *extack)
+{
+	int bs = fls64(burst);
+
+	if (rate < NSIM_DEV_TRAP_POLICER_MIN_RATE) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
+		return -EINVAL;
+	}
+
+	if (rate > NSIM_DEV_TRAP_POLICER_MAX_RATE) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
+		return -EINVAL;
+	}
+
+	if (burst < NSIM_DEV_TRAP_POLICER_MIN_BURST) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
+		return -EINVAL;
+	}
+
+	if (burst > NSIM_DEV_TRAP_POLICER_MAX_BURST) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
+		return -EINVAL;
+	}
+
+	--bs;
+	if (burst != (1 << bs)) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+nsim_dev_devlink_trap_policer_counter_get(struct devlink *devlink,
+					  const struct devlink_trap_policer *policer,
+					  u64 *p_drops)
+{
+	struct nsim_dev *nsim_dev = devlink_priv(devlink);
+	u64 *cnt;
+
+	if (nsim_dev->fail_trap_policer_counter_get)
+		return -EINVAL;
+
+	cnt = &nsim_dev->trap_data->trap_policers_cnt_arr[policer->id - 1];
+	*p_drops = *cnt;
+	*cnt += jiffies % 64;
+
+	return 0;
+}
+
 static const struct devlink_ops nsim_dev_devlink_ops = {
 	.reload_down = nsim_dev_reload_down,
 	.reload_up = nsim_dev_reload_up,
@@ -744,6 +836,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
 	.flash_update = nsim_dev_flash_update,
 	.trap_init = nsim_dev_devlink_trap_init,
 	.trap_action_set = nsim_dev_devlink_trap_action_set,
+	.trap_policer_set = nsim_dev_devlink_trap_policer_set,
+	.trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get,
 };
 
 #define NSIM_DEV_MAX_MACS_DEFAULT 32
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index e46fc565b981..68788dae5625 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -180,6 +180,7 @@ struct nsim_dev {
 	struct nsim_dev_health health;
 	struct flow_action_cookie *fa_cookie;
 	spinlock_t fa_cookie_lock; /* protects fa_cookie */
+	bool fail_trap_policer_counter_get;
 };
 
 static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev)
-- 
2.24.1


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

* [PATCH net-next 04/15] devlink: Add packet trap group parameters support
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (2 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 03/15] netdevsim: Add devlink-trap policer support Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters Ido Schimmel
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Packet trap groups are used to aggregate logically related packet traps.
Currently, these groups allow user space to batch operations such as
setting the trap action of all member traps.

In order to prevent the CPU from being overwhelmed by too many trapped
packets, it is desirable to bind a packet trap policer to these groups.
For example, to limit all the packets that encountered an exception
during routing to 10Kpps.

Allow device drivers to bind default packet trap policers to packet trap
groups when the latter are registered with devlink.

The next patch will enable user space to change this default binding.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   |  8 ++---
 drivers/net/netdevsim/dev.c                   |  8 ++---
 include/net/devlink.h                         |  5 ++-
 net/core/devlink.c                            | 31 +++++++++++++++++++
 4 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index 727f6ef243df..24f15345ba84 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -166,10 +166,10 @@ static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
 		   _action, false, SP_##_group_id, SET_FW_DEFAULT)
 
 static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = {
-	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS),
+	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
+	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0),
+	DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS, 0),
+	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0),
 };
 
 static const struct devlink_trap mlxsw_sp_traps_arr[] = {
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index ce74adbf0e8b..c344d0f727c7 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -408,10 +408,10 @@ static const struct devlink_trap_policer nsim_trap_policers_arr[] = {
 };
 
 static const struct devlink_trap_group nsim_trap_groups_arr[] = {
-	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS),
-	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS),
+	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
+	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1),
+	DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 2),
+	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 3),
 };
 
 static const struct devlink_trap nsim_traps_arr[] = {
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 66c52a2ef2cc..84c28e0f2d90 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -549,6 +549,7 @@ struct devlink_trap_policer {
  * @name: Trap group name.
  * @id: Trap group identifier.
  * @generic: Whether the trap group is generic or not.
+ * @init_policer_id: Initial policer identifier.
  *
  * Describes immutable attributes of packet trap groups that drivers register
  * with devlink.
@@ -557,6 +558,7 @@ struct devlink_trap_group {
 	const char *name;
 	u16 id;
 	bool generic;
+	u32 init_policer_id;
 };
 
 #define DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT	BIT(0)
@@ -734,11 +736,12 @@ enum devlink_trap_group_generic_id {
 		.metadata_cap = _metadata_cap,				      \
 	}
 
-#define DEVLINK_TRAP_GROUP_GENERIC(_id)					      \
+#define DEVLINK_TRAP_GROUP_GENERIC(_id, _policer_id)			      \
 	{								      \
 		.name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id,		      \
 		.id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id,		      \
 		.generic = true,					      \
+		.init_policer_id = _policer_id,				      \
 	}
 
 #define DEVLINK_TRAP_POLICER(_id, _rate, _burst)			      \
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 63008d3785dc..4ec7c7578709 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5473,6 +5473,7 @@ struct devlink_trap_policer_item {
 /**
  * struct devlink_trap_group_item - Packet trap group attributes.
  * @group: Immutable packet trap group attributes.
+ * @policer_item: Associated policer item. Can be NULL.
  * @list: trap_group_list member.
  * @stats: Trap group statistics.
  *
@@ -5481,6 +5482,7 @@ struct devlink_trap_policer_item {
  */
 struct devlink_trap_group_item {
 	const struct devlink_trap_group *group;
+	struct devlink_trap_policer_item *policer_item;
 	struct list_head list;
 	struct devlink_stats __percpu *stats;
 };
@@ -5895,6 +5897,11 @@ devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
 	    nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
 		goto nla_put_failure;
 
+	if (group_item->policer_item &&
+	    nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
+			group_item->policer_item->policer->id))
+		goto nla_put_failure;
+
 	err = devlink_trap_stats_put(msg, group_item->stats);
 	if (err)
 		goto nla_put_failure;
@@ -8464,6 +8471,25 @@ void *devlink_trap_ctx_priv(void *trap_ctx)
 }
 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
 
+static int
+devlink_trap_group_item_policer_link(struct devlink *devlink,
+				     struct devlink_trap_group_item *group_item)
+{
+	u32 policer_id = group_item->group->init_policer_id;
+	struct devlink_trap_policer_item *policer_item;
+
+	if (policer_id == 0)
+		return 0;
+
+	policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
+	if (WARN_ON_ONCE(!policer_item))
+		return -EINVAL;
+
+	group_item->policer_item = policer_item;
+
+	return 0;
+}
+
 static int
 devlink_trap_group_register(struct devlink *devlink,
 			    const struct devlink_trap_group *group)
@@ -8486,6 +8512,10 @@ devlink_trap_group_register(struct devlink *devlink,
 
 	group_item->group = group;
 
+	err = devlink_trap_group_item_policer_link(devlink, group_item);
+	if (err)
+		goto err_policer_link;
+
 	if (devlink->ops->trap_group_init) {
 		err = devlink->ops->trap_group_init(devlink, group);
 		if (err)
@@ -8499,6 +8529,7 @@ devlink_trap_group_register(struct devlink *devlink,
 	return 0;
 
 err_group_init:
+err_policer_link:
 	free_percpu(group_item->stats);
 err_stats_alloc:
 	kfree(group_item);
-- 
2.24.1


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

* [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (3 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 04/15] devlink: Add packet trap group parameters support Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-25  3:53   ` Jakub Kicinski
  2020-03-24 19:32 ` [PATCH net-next 06/15] netdevsim: Add support for " Ido Schimmel
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The previous patch allowed device drivers to publish their default
binding between packet trap policers and packet trap groups. However,
some users might not be content with this binding and would like to
change it.

In case user space passed a packet trap policer identifier when setting
a packet trap group, invoke the appropriate device driver callback and
pass the new policer identifier.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/devlink.h |  9 +++++++++
 net/core/devlink.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/include/net/devlink.h b/include/net/devlink.h
index 84c28e0f2d90..dea3c3fd9634 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -847,6 +847,15 @@ struct devlink_ops {
 	 */
 	int (*trap_group_init)(struct devlink *devlink,
 			       const struct devlink_trap_group *group);
+	/**
+	 * @trap_group_set: Trap group parameters set function.
+	 *
+	 * Note: @policer can be NULL when a policer is being unbound from
+	 * @group.
+	 */
+	int (*trap_group_set)(struct devlink *devlink,
+			      const struct devlink_trap_group *group,
+			      const struct devlink_trap_policer *policer);
 	/**
 	 * @trap_policer_init: Trap policer initialization function.
 	 *
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 4ec7c7578709..e3042e131c1f 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -6039,6 +6039,45 @@ devlink_trap_group_action_set(struct devlink *devlink,
 	return 0;
 }
 
+static int devlink_trap_group_set(struct devlink *devlink,
+				  struct devlink_trap_group_item *group_item,
+				  struct genl_info *info)
+{
+	struct devlink_trap_policer_item *policer_item;
+	struct netlink_ext_ack *extack = info->extack;
+	const struct devlink_trap_policer *policer;
+	struct nlattr **attrs = info->attrs;
+	int err;
+
+	if (!devlink->ops->trap_group_set) {
+		if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
+			return -EOPNOTSUPP;
+		return 0;
+	}
+
+	policer_item = group_item->policer_item;
+	if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
+		u32 policer_id;
+
+		policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
+		policer_item = devlink_trap_policer_item_lookup(devlink,
+								policer_id);
+		if (policer_id && !policer_item) {
+			NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
+			return -ENOENT;
+		}
+	}
+	policer = policer_item ? policer_item->policer : NULL;
+
+	err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
+	if (err)
+		return err;
+
+	group_item->policer_item = policer_item;
+
+	return 0;
+}
+
 static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
 					      struct genl_info *info)
 {
@@ -6060,6 +6099,10 @@ static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
 	if (err)
 		return err;
 
+	err = devlink_trap_group_set(devlink, group_item, info);
+	if (err)
+		return err;
+
 	return 0;
 }
 
-- 
2.24.1


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

* [PATCH net-next 06/15] netdevsim: Add support for setting of packet trap group parameters
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (4 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 07/15] selftests: netdevsim: Add test cases for devlink-trap policers Ido Schimmel
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Add a dummy callback to set trap group parameters. Return an error when
the 'fail_trap_group_set' debugfs file is set in order to exercise error
paths and verify that error is propagated to user space when should.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/netdevsim/dev.c       | 17 +++++++++++++++++
 drivers/net/netdevsim/netdevsim.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index c344d0f727c7..5349a7216f15 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -192,6 +192,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
 			    &nsim_dev->fail_reload);
 	debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir,
 			    nsim_dev, &nsim_dev_trap_fa_cookie_fops);
+	debugfs_create_bool("fail_trap_group_set", 0600,
+			    nsim_dev->ddir,
+			    &nsim_dev->fail_trap_group_set);
 	debugfs_create_bool("fail_trap_policer_counter_get", 0600,
 			    nsim_dev->ddir,
 			    &nsim_dev->fail_trap_policer_counter_get);
@@ -769,6 +772,19 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink,
 	return 0;
 }
 
+static int
+nsim_dev_devlink_trap_group_set(struct devlink *devlink,
+				const struct devlink_trap_group *group,
+				const struct devlink_trap_policer *policer)
+{
+	struct nsim_dev *nsim_dev = devlink_priv(devlink);
+
+	if (nsim_dev->fail_trap_group_set)
+		return -EINVAL;
+
+	return 0;
+}
+
 #define NSIM_DEV_TRAP_POLICER_MIN_RATE	1
 #define NSIM_DEV_TRAP_POLICER_MAX_RATE	8000
 #define NSIM_DEV_TRAP_POLICER_MIN_BURST	8
@@ -836,6 +852,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
 	.flash_update = nsim_dev_flash_update,
 	.trap_init = nsim_dev_devlink_trap_init,
 	.trap_action_set = nsim_dev_devlink_trap_action_set,
+	.trap_group_set = nsim_dev_devlink_trap_group_set,
 	.trap_policer_set = nsim_dev_devlink_trap_policer_set,
 	.trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get,
 };
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 68788dae5625..f78d8adee014 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -180,6 +180,7 @@ struct nsim_dev {
 	struct nsim_dev_health health;
 	struct flow_action_cookie *fa_cookie;
 	spinlock_t fa_cookie_lock; /* protects fa_cookie */
+	bool fail_trap_group_set;
 	bool fail_trap_policer_counter_get;
 };
 
-- 
2.24.1


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

* [PATCH net-next 07/15] selftests: netdevsim: Add test cases for devlink-trap policers
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (5 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 06/15] netdevsim: Add support for " Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 08/15] mlxsw: reg: Extend QPCR register Ido Schimmel
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Add test cases for packet trap policer set / show commands as well as
for the binding of these policers to packet trap groups.

Both good and bad flows are tested for maximum coverage.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../drivers/net/netdevsim/devlink_trap.sh     | 110 ++++++++++++++++++
 .../selftests/net/forwarding/devlink_lib.sh   |  37 ++++++
 2 files changed, 147 insertions(+)

diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh
index 437d32bd4cfd..35ca856ee493 100755
--- a/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh
+++ b/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh
@@ -16,6 +16,8 @@ ALL_TESTS="
 	trap_group_action_test
 	bad_trap_group_test
 	trap_group_stats_test
+	trap_policer_test
+	trap_policer_bind_test
 	port_del_test
 	dev_del_test
 "
@@ -23,6 +25,7 @@ NETDEVSIM_PATH=/sys/bus/netdevsim/
 DEV_ADDR=1337
 DEV=netdevsim${DEV_ADDR}
 DEVLINK_DEV=netdevsim/${DEV}
+DEBUGFS_DIR=/sys/kernel/debug/netdevsim/$DEV/
 SLEEP_TIME=1
 NETDEV=""
 NUM_NETIFS=0
@@ -256,6 +259,113 @@ trap_group_stats_test()
 	log_test "Trap group statistics"
 }
 
+trap_policer_test()
+{
+	local packets_t0
+	local packets_t1
+
+	if [ $(devlink_trap_policers_num_get) -eq 0 ]; then
+		check_err 1 "Failed to dump policers"
+	fi
+
+	devlink trap policer set $DEVLINK_DEV policer 1337 &> /dev/null
+	check_fail $? "Did not get an error for setting a non-existing policer"
+	devlink trap policer show $DEVLINK_DEV policer 1337 &> /dev/null
+	check_fail $? "Did not get an error for getting a non-existing policer"
+
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 2000 burst 16
+	check_err $? "Failed to set valid parameters for a valid policer"
+	if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then
+		check_err 1 "Policer rate was not changed"
+	fi
+	if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then
+		check_err 1 "Policer burst size was not changed"
+	fi
+
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null
+	check_fail $? "Policer rate was changed to rate lower than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 9000 &> /dev/null
+	check_fail $? "Policer rate was changed to rate higher than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 2 &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size lower than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 65537 &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size higher than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 15 &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size that is not power of 2"
+	if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then
+		check_err 1 "Policer rate was changed to an invalid value"
+	fi
+	if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then
+		check_err 1 "Policer burst size was changed to an invalid value"
+	fi
+
+	packets_t0=$(devlink_trap_policer_rx_dropped_get 1)
+	sleep .1
+	packets_t1=$(devlink_trap_policer_rx_dropped_get 1)
+	if [ ! $packets_t1 -gt $packets_t0 ]; then
+		check_err 1 "Policer drop counter was not incremented"
+	fi
+
+	echo "y"> $DEBUGFS_DIR/fail_trap_policer_counter_get
+	devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null
+	check_fail $? "Managed to read policer drop counter when should not"
+	echo "n"> $DEBUGFS_DIR/fail_trap_policer_counter_get
+	devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null
+	check_err $? "Did not manage to read policer drop counter when should"
+
+	log_test "Trap policer"
+}
+
+trap_group_check_policer()
+{
+	local group_name=$1; shift
+
+	devlink -j -p trap group show $DEVLINK_DEV group $group_name \
+		| jq -e '.[][][]["policer"]' &> /dev/null
+}
+
+trap_policer_bind_test()
+{
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 1
+	check_err $? "Failed to bind a valid policer"
+	if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then
+		check_err 1 "Bound policer was not changed"
+	fi
+
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 1337 \
+		&> /dev/null
+	check_fail $? "Did not get an error for binding a non-existing policer"
+	if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then
+		check_err 1 "Bound policer was changed when should not"
+	fi
+
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 0
+	check_err $? "Failed to unbind a policer when using ID 0"
+	trap_group_check_policer "l2_drops"
+	check_fail $? "Trap group has a policer after unbinding with ID 0"
+
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 1
+	check_err $? "Failed to bind a valid policer"
+
+	devlink trap group set $DEVLINK_DEV group l2_drops nopolicer
+	check_err $? "Failed to unbind a policer when using 'nopolicer' keyword"
+	trap_group_check_policer "l2_drops"
+	check_fail $? "Trap group has a policer after unbinding with 'nopolicer' keyword"
+
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 1
+	check_err $? "Failed to bind a valid policer"
+
+	echo "y"> $DEBUGFS_DIR/fail_trap_group_set
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 2 \
+		&> /dev/null
+	check_fail $? "Managed to bind a policer when should not"
+	echo "n"> $DEBUGFS_DIR/fail_trap_group_set
+	devlink trap group set $DEVLINK_DEV group l2_drops policer 2
+	check_err $? "Did not manage to bind a policer when should"
+
+	log_test "Trap policer binding"
+}
+
 port_del_test()
 {
 	local group_name
diff --git a/tools/testing/selftests/net/forwarding/devlink_lib.sh b/tools/testing/selftests/net/forwarding/devlink_lib.sh
index 0df6d8942721..c48645a344e2 100644
--- a/tools/testing/selftests/net/forwarding/devlink_lib.sh
+++ b/tools/testing/selftests/net/forwarding/devlink_lib.sh
@@ -420,6 +420,43 @@ devlink_trap_drop_cleanup()
 	tc filter del dev $dev egress protocol $proto pref $pref handle $handle flower
 }
 
+devlink_trap_policers_num_get()
+{
+	devlink -j -p trap policer show | jq '.[]["'$DEVLINK_DEV'"] | length'
+}
+
+devlink_trap_policer_rate_get()
+{
+	local policer_id=$1; shift
+
+	devlink -j -p trap policer show $DEVLINK_DEV policer $policer_id \
+		| jq '.[][][]["rate"]'
+}
+
+devlink_trap_policer_burst_get()
+{
+	local policer_id=$1; shift
+
+	devlink -j -p trap policer show $DEVLINK_DEV policer $policer_id \
+		| jq '.[][][]["burst"]'
+}
+
+devlink_trap_policer_rx_dropped_get()
+{
+	local policer_id=$1; shift
+
+	devlink -j -p -s trap policer show $DEVLINK_DEV policer $policer_id \
+		| jq '.[][][]["stats"]["rx"]["dropped"]'
+}
+
+devlink_trap_group_policer_get()
+{
+	local group_name=$1; shift
+
+	devlink -j -p trap group show $DEVLINK_DEV group $group_name \
+		| jq '.[][][]["policer"]'
+}
+
 devlink_port_by_netdev()
 {
 	local if_name=$1
-- 
2.24.1


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

* [PATCH net-next 08/15] mlxsw: reg: Extend QPCR register
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (6 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 07/15] selftests: netdevsim: Add test cases for devlink-trap policers Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 09/15] mlxsw: spectrum: Track used packet trap policer IDs Ido Schimmel
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The QoS Policer Configuration Register (QPCR) is used to configure
hardware policers. Extend this register with following fields and
defines which will be used by subsequent patches:

1. Violate counter: reads number of packets dropped by the policer
2. Clear counter: to ensure we start counting from 0
3. Rate and burst size limits

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 1bc65e597de0..192578632657 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -3296,6 +3296,12 @@ MLXSW_ITEM32(reg, qpcr, g, 0x00, 14, 2);
  */
 MLXSW_ITEM32(reg, qpcr, pid, 0x00, 0, 14);
 
+/* reg_qpcr_clear_counter
+ * Clear counters.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, qpcr, clear_counter, 0x04, 31, 1);
+
 /* reg_qpcr_color_aware
  * Is the policer aware of colors.
  * Must be 0 (unaware) for cpu port.
@@ -3393,6 +3399,17 @@ enum mlxsw_reg_qpcr_action {
  */
 MLXSW_ITEM32(reg, qpcr, violate_action, 0x18, 0, 4);
 
+/* reg_qpcr_violate_count
+ * Counts the number of times violate_action happened on this PID.
+ * Access: RW
+ */
+MLXSW_ITEM64(reg, qpcr, violate_count, 0x20, 0, 64);
+
+#define MLXSW_REG_QPCR_LOWEST_CIR	1
+#define MLXSW_REG_QPCR_HIGHEST_CIR	(2 * 1000 * 1000 * 1000) /* 2Gpps */
+#define MLXSW_REG_QPCR_LOWEST_CBS	4
+#define MLXSW_REG_QPCR_HIGHEST_CBS	24
+
 static inline void mlxsw_reg_qpcr_pack(char *payload, u16 pid,
 				       enum mlxsw_reg_qpcr_ir_units ir_units,
 				       bool bytes, u32 cir, u16 cbs)
-- 
2.24.1


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

* [PATCH net-next 09/15] mlxsw: spectrum: Track used packet trap policer IDs
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (7 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 08/15] mlxsw: reg: Extend QPCR register Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 10/15] mlxsw: spectrum_trap: Prepare policers for registration with devlink Ido Schimmel
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

During initialization the driver configures various packet trap groups
and binds policers to them.

Currently, most of these groups are not exposed to user space and
therefore their policers should not be exposed as well. Otherwise, user
space will be able to alter policer parameters without knowing which
packet traps are policed by the policer.

Use a bitmap to track the used policer IDs so that these policers will
not be registered with devlink in a subsequent patch.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 26 ++++++++++++++++---
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  1 +
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   |  2 ++
 .../ethernet/mellanox/mlxsw/spectrum_trap.h   | 12 +++++++++
 4 files changed, 38 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 35d3a68ef4fd..a109ecbb62b9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -43,6 +43,7 @@
 #include "spectrum_acl_flex_actions.h"
 #include "spectrum_span.h"
 #include "spectrum_ptp.h"
+#include "spectrum_trap.h"
 #include "../mlxfw/mlxfw.h"
 
 #define MLXSW_SP1_FWREV_MAJOR 13
@@ -4556,6 +4557,7 @@ static const struct mlxsw_listener mlxsw_sp1_listener[] = {
 
 static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 {
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
 	enum mlxsw_reg_qpcr_ir_units ir_units;
 	int max_cpu_policers;
@@ -4619,6 +4621,7 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 			continue;
 		}
 
+		__set_bit(i, mlxsw_sp->trap->policers_usage);
 		mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate,
 				    burst_size);
 		err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl);
@@ -4747,20 +4750,32 @@ static void mlxsw_sp_traps_unregister(struct mlxsw_sp *mlxsw_sp,
 
 static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
 {
+	struct mlxsw_sp_trap *trap;
+	u64 max_policers;
 	int err;
 
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_CPU_POLICERS))
+		return -EIO;
+	max_policers = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_CPU_POLICERS);
+	trap = kzalloc(struct_size(trap, policers_usage,
+				   BITS_TO_LONGS(max_policers)), GFP_KERNEL);
+	if (!trap)
+		return -ENOMEM;
+	trap->max_policers = max_policers;
+	mlxsw_sp->trap = trap;
+
 	err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
 	if (err)
-		return err;
+		goto err_cpu_policers_set;
 
 	err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
 	if (err)
-		return err;
+		goto err_trap_groups_set;
 
 	err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp_listener,
 				      ARRAY_SIZE(mlxsw_sp_listener));
 	if (err)
-		return err;
+		goto err_traps_register;
 
 	err = mlxsw_sp_traps_register(mlxsw_sp, mlxsw_sp->listeners,
 				      mlxsw_sp->listeners_count);
@@ -4772,6 +4787,10 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
 err_extra_traps_init:
 	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
 				  ARRAY_SIZE(mlxsw_sp_listener));
+err_traps_register:
+err_trap_groups_set:
+err_cpu_policers_set:
+	kfree(trap);
 	return err;
 }
 
@@ -4781,6 +4800,7 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
 				  mlxsw_sp->listeners_count);
 	mlxsw_sp_traps_unregister(mlxsw_sp, mlxsw_sp_listener,
 				  ARRAY_SIZE(mlxsw_sp_listener));
+	kfree(mlxsw_sp->trap);
 }
 
 #define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index bbd8bec8fee4..fd1acc855b73 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -176,6 +176,7 @@ struct mlxsw_sp {
 	struct mlxsw_sp_ptp_state *ptp_state;
 	struct mlxsw_sp_counter_pool *counter_pool;
 	struct mlxsw_sp_span *span;
+	struct mlxsw_sp_trap *trap;
 	const struct mlxsw_fw_rev *req_rev;
 	const char *fw_filename;
 	const struct mlxsw_sp_kvdl_ops *kvdl_ops;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index 24f15345ba84..6a77bf236c22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -8,6 +8,7 @@
 #include "core.h"
 #include "reg.h"
 #include "spectrum.h"
+#include "spectrum_trap.h"
 
 /* All driver-specific traps must be documented in
  * Documentation/networking/devlink/mlxsw.rst
@@ -309,6 +310,7 @@ static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
 	/* The purpose of "thin" policer is to drop as many packets
 	 * as possible. The dummy group is using it.
 	 */
+	__set_bit(MLXSW_SP_THIN_POLICER_ID, mlxsw_sp->trap->policers_usage);
 	mlxsw_reg_qpcr_pack(qpcr_pl, MLXSW_SP_THIN_POLICER_ID,
 			    MLXSW_REG_QPCR_IR_UNITS_M, false, 1, 4);
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
new file mode 100644
index 000000000000..12c5641b2165
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2020 Mellanox Technologies. All rights reserved */
+
+#ifndef _MLXSW_SPECTRUM_TRAP_H
+#define _MLXSW_SPECTRUM_TRAP_H
+
+struct mlxsw_sp_trap {
+	u64 max_policers;
+	unsigned long policers_usage[]; /* Usage bitmap */
+};
+
+#endif
-- 
2.24.1


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

* [PATCH net-next 10/15] mlxsw: spectrum_trap: Prepare policers for registration with devlink
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (8 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 09/15] mlxsw: spectrum: Track used packet trap policer IDs Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support Ido Schimmel
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Prepare an array of policer IDs to register with devlink and their
associated parameters.

The array is composed from both policers that are currently bound to
exposed trap groups and policers that are not bound to any trap group.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   | 63 ++++++++++++++++++-
 .../ethernet/mellanox/mlxsw/spectrum_trap.h   |  4 ++
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index 6a77bf236c22..5a92a1de6086 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
 /* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <net/devlink.h>
 #include <uapi/linux/devlink.h>
@@ -166,6 +167,11 @@ static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
 	MLXSW_RXL(mlxsw_sp_rx_exception_listener, _id,			      \
 		   _action, false, SP_##_group_id, SET_FW_DEFAULT)
 
+/* Ordered by policer identifier */
+static const struct devlink_trap_policer mlxsw_sp_trap_policers_arr[] = {
+	DEVLINK_TRAP_POLICER(1, 10 * 1024, 128),
+};
+
 static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = {
 	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
 	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0),
@@ -325,6 +331,54 @@ static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
 }
 
+static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
+{
+	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
+	u64 free_policers = 0;
+	u32 last_id = 0;
+	int i;
+
+	for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
+		free_policers++;
+
+	if (ARRAY_SIZE(mlxsw_sp_trap_policers_arr) > free_policers) {
+		dev_err(mlxsw_sp->bus_info->dev, "Exceeded number of supported packet trap policers\n");
+		return -ENOBUFS;
+	}
+
+	trap->policers_arr = kcalloc(free_policers,
+				     sizeof(struct devlink_trap_policer),
+				     GFP_KERNEL);
+	if (!trap->policers_arr)
+		return -ENOMEM;
+
+	trap->policers_count = free_policers;
+
+	for (i = 0; i < free_policers; i++) {
+		const struct devlink_trap_policer *policer;
+
+		if (i < ARRAY_SIZE(mlxsw_sp_trap_policers_arr)) {
+			policer = &mlxsw_sp_trap_policers_arr[i];
+			trap->policers_arr[i] = *policer;
+			last_id = policer->id;
+		} else {
+			/* Use default parameters */
+			trap->policers_arr[i].id = ++last_id;
+			trap->policers_arr[i].init_rate = 1;
+			trap->policers_arr[i].init_burst = 16;
+		}
+	}
+
+	return 0;
+}
+
+static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
+{
+	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
+
+	kfree(trap->policers_arr);
+}
+
 int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
 {
 	size_t groups_count = ARRAY_SIZE(mlxsw_sp_trap_groups_arr);
@@ -343,10 +397,14 @@ int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
 		    ARRAY_SIZE(mlxsw_sp_listeners_arr)))
 		return -EINVAL;
 
+	err = mlxsw_sp_trap_policers_init(mlxsw_sp);
+	if (err)
+		return err;
+
 	err = devlink_trap_groups_register(devlink, mlxsw_sp_trap_groups_arr,
 					   groups_count);
 	if (err)
-		return err;
+		goto err_trap_groups_register;
 
 	err = devlink_traps_register(devlink, mlxsw_sp_traps_arr,
 				     ARRAY_SIZE(mlxsw_sp_traps_arr), mlxsw_sp);
@@ -358,6 +416,8 @@ int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
 err_traps_register:
 	devlink_trap_groups_unregister(devlink, mlxsw_sp_trap_groups_arr,
 				       groups_count);
+err_trap_groups_register:
+	mlxsw_sp_trap_policers_fini(mlxsw_sp);
 	return err;
 }
 
@@ -370,6 +430,7 @@ void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp)
 				 ARRAY_SIZE(mlxsw_sp_traps_arr));
 	devlink_trap_groups_unregister(devlink, mlxsw_sp_trap_groups_arr,
 				       groups_count);
+	mlxsw_sp_trap_policers_fini(mlxsw_sp);
 }
 
 int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
index 12c5641b2165..05bb652b1a76 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
@@ -4,7 +4,11 @@
 #ifndef _MLXSW_SPECTRUM_TRAP_H
 #define _MLXSW_SPECTRUM_TRAP_H
 
+#include <net/devlink.h>
+
 struct mlxsw_sp_trap {
+	struct devlink_trap_policer *policers_arr; /* Registered policers */
+	u64 policers_count; /* Number of registered policers */
 	u64 max_policers;
 	unsigned long policers_usage[]; /* Usage bitmap */
 };
-- 
2.24.1


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

* [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (9 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 10/15] mlxsw: spectrum_trap: Prepare policers for registration with devlink Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-25  3:33   ` Jakub Kicinski
  2020-03-24 19:32 ` [PATCH net-next 12/15] mlxsw: spectrum_trap: Do not initialize dedicated discard policer Ido Schimmel
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Register supported packet trap policers with devlink and implement
callbacks to change their parameters and read their counters.

Prevent user space from passing invalid policer parameters down to the
device by checking their validity and communicating the failure via an
appropriate extack message.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.c    |  57 +++++
 drivers/net/ethernet/mellanox/mlxsw/core.h    |  11 +
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  12 +
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  13 +
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   | 236 +++++++++++++++++-
 .../ethernet/mellanox/mlxsw/spectrum_trap.h   |   8 +
 6 files changed, 326 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 1078f88cff18..6d0590375976 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1198,6 +1198,59 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink,
 	return mlxsw_driver->trap_group_init(mlxsw_core, group);
 }
 
+static int
+mlxsw_devlink_trap_policer_init(struct devlink *devlink,
+				const struct devlink_trap_policer *policer)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->trap_policer_init)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->trap_policer_init(mlxsw_core, policer);
+}
+
+static void
+mlxsw_devlink_trap_policer_fini(struct devlink *devlink,
+				const struct devlink_trap_policer *policer)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->trap_policer_fini)
+		return;
+	mlxsw_driver->trap_policer_fini(mlxsw_core, policer);
+}
+
+static int
+mlxsw_devlink_trap_policer_set(struct devlink *devlink,
+			       const struct devlink_trap_policer *policer,
+			       u64 rate, u64 burst,
+			       struct netlink_ext_ack *extack)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->trap_policer_set)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->trap_policer_set(mlxsw_core, policer, rate, burst,
+					      extack);
+}
+
+static int
+mlxsw_devlink_trap_policer_counter_get(struct devlink *devlink,
+				       const struct devlink_trap_policer *policer,
+				       u64 *p_drops)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->trap_policer_counter_get)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->trap_policer_counter_get(mlxsw_core, policer,
+						      p_drops);
+}
+
 static const struct devlink_ops mlxsw_devlink_ops = {
 	.reload_down		= mlxsw_devlink_core_bus_device_reload_down,
 	.reload_up		= mlxsw_devlink_core_bus_device_reload_up,
@@ -1220,6 +1273,10 @@ static const struct devlink_ops mlxsw_devlink_ops = {
 	.trap_fini			= mlxsw_devlink_trap_fini,
 	.trap_action_set		= mlxsw_devlink_trap_action_set,
 	.trap_group_init		= mlxsw_devlink_trap_group_init,
+	.trap_policer_init		= mlxsw_devlink_trap_policer_init,
+	.trap_policer_fini		= mlxsw_devlink_trap_policer_fini,
+	.trap_policer_set		= mlxsw_devlink_trap_policer_set,
+	.trap_policer_counter_get	= mlxsw_devlink_trap_policer_counter_get,
 };
 
 static int
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 46226823c7a6..035629bc035d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -327,6 +327,17 @@ struct mlxsw_driver {
 			       enum devlink_trap_action action);
 	int (*trap_group_init)(struct mlxsw_core *mlxsw_core,
 			       const struct devlink_trap_group *group);
+	int (*trap_policer_init)(struct mlxsw_core *mlxsw_core,
+				 const struct devlink_trap_policer *policer);
+	void (*trap_policer_fini)(struct mlxsw_core *mlxsw_core,
+				  const struct devlink_trap_policer *policer);
+	int (*trap_policer_set)(struct mlxsw_core *mlxsw_core,
+				const struct devlink_trap_policer *policer,
+				u64 rate, u64 burst,
+				struct netlink_ext_ack *extack);
+	int (*trap_policer_counter_get)(struct mlxsw_core *mlxsw_core,
+					const struct devlink_trap_policer *policer,
+					u64 *p_drops);
 	void (*txhdr_construct)(struct sk_buff *skb,
 				const struct mlxsw_tx_info *tx_info);
 	int (*resources_register)(struct mlxsw_core *mlxsw_core);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index a109ecbb62b9..e8756c921b76 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -5675,6 +5675,10 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_policer_init		= mlxsw_sp_trap_policer_init,
+	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
+	.trap_policer_set		= mlxsw_sp_trap_policer_set,
+	.trap_policer_counter_get	= mlxsw_sp_trap_policer_counter_get,
 	.txhdr_construct		= mlxsw_sp_txhdr_construct,
 	.resources_register		= mlxsw_sp1_resources_register,
 	.kvd_sizes_get			= mlxsw_sp_kvd_sizes_get,
@@ -5709,6 +5713,10 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_policer_init		= mlxsw_sp_trap_policer_init,
+	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
+	.trap_policer_set		= mlxsw_sp_trap_policer_set,
+	.trap_policer_counter_get	= mlxsw_sp_trap_policer_counter_get,
 	.txhdr_construct		= mlxsw_sp_txhdr_construct,
 	.resources_register		= mlxsw_sp2_resources_register,
 	.params_register		= mlxsw_sp2_params_register,
@@ -5742,6 +5750,10 @@ static struct mlxsw_driver mlxsw_sp3_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_policer_init		= mlxsw_sp_trap_policer_init,
+	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
+	.trap_policer_set		= mlxsw_sp_trap_policer_set,
+	.trap_policer_counter_get	= mlxsw_sp_trap_policer_counter_get,
 	.txhdr_construct		= mlxsw_sp_txhdr_construct,
 	.resources_register		= mlxsw_sp2_resources_register,
 	.params_register		= mlxsw_sp2_params_register,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index fd1acc855b73..9858edf7d2e8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -1017,6 +1017,19 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
 			     enum devlink_trap_action action);
 int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 			     const struct devlink_trap_group *group);
+int
+mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
+			   const struct devlink_trap_policer *policer);
+void mlxsw_sp_trap_policer_fini(struct mlxsw_core *mlxsw_core,
+				const struct devlink_trap_policer *policer);
+int
+mlxsw_sp_trap_policer_set(struct mlxsw_core *mlxsw_core,
+			  const struct devlink_trap_policer *policer,
+			  u64 rate, u64 burst, struct netlink_ext_ack *extack);
+int
+mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
+				  const struct devlink_trap_policer *policer,
+				  u64 *p_drops);
 
 static inline struct net *mlxsw_sp_net(struct mlxsw_sp *mlxsw_sp)
 {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index 5a92a1de6086..cc536d06b3ac 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -3,6 +3,7 @@
 
 #include <linux/bitops.h>
 #include <linux/kernel.h>
+#include <linux/netlink.h>
 #include <net/devlink.h>
 #include <uapi/linux/devlink.h>
 
@@ -173,10 +174,10 @@ static const struct devlink_trap_policer mlxsw_sp_trap_policers_arr[] = {
 };
 
 static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = {
-	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
-	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0),
-	DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS, 0),
-	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0),
+	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 1),
+	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1),
+	DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS, 1),
+	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 1),
 };
 
 static const struct devlink_trap mlxsw_sp_traps_arr[] = {
@@ -302,6 +303,20 @@ static const u16 mlxsw_sp_listener_devlink_map[] = {
 #define MLXSW_SP_DISCARD_POLICER_ID	(MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
 #define MLXSW_SP_THIN_POLICER_ID	(MLXSW_SP_DISCARD_POLICER_ID + 1)
 
+static struct mlxsw_sp_trap_policer_item *
+mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
+{
+	struct mlxsw_sp_trap_policer_item *policer_item;
+	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
+
+	list_for_each_entry(policer_item, &trap->policer_item_list, list) {
+		if (policer_item->id == id)
+			return policer_item;
+	}
+
+	return NULL;
+}
+
 static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
 {
 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
@@ -333,10 +348,11 @@ static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
 
 static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
 {
+	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
 	u64 free_policers = 0;
 	u32 last_id = 0;
-	int i;
+	int err, i;
 
 	for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
 		free_policers++;
@@ -369,13 +385,28 @@ static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
 		}
 	}
 
+	INIT_LIST_HEAD(&trap->policer_item_list);
+
+	err = devlink_trap_policers_register(devlink, trap->policers_arr,
+					     trap->policers_count);
+	if (err)
+		goto err_trap_policers_register;
+
 	return 0;
+
+err_trap_policers_register:
+	kfree(trap->policers_arr);
+	return err;
 }
 
 static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
 {
+	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
 
+	devlink_trap_policers_unregister(devlink, trap->policers_arr,
+					 trap->policers_count);
+	WARN_ON(!list_empty(&trap->policer_item_list));
 	kfree(trap->policers_arr);
 }
 
@@ -505,32 +536,29 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
 int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 			     const struct devlink_trap_group *group)
 {
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
 	char htgt_pl[MLXSW_REG_HTGT_LEN];
 	u8 priority, tc, group_id;
-	u16 policer_id;
 
 	switch (group->id) {
 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS:
 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS;
-		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
 		priority = 0;
 		tc = 1;
 		break;
 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS:
 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS;
-		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
 		priority = 0;
 		tc = 1;
 		break;
 	case DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS:
 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS;
-		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
 		priority = 0;
 		tc = 1;
 		break;
 	case DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_DROPS:
 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS;
-		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
 		priority = 0;
 		tc = 1;
 		break;
@@ -538,6 +566,192 @@ int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 		return -EINVAL;
 	}
 
-	mlxsw_reg_htgt_pack(htgt_pl, group_id, policer_id, priority, tc);
+	if (group->init_policer_id) {
+		struct mlxsw_sp_trap_policer_item *policer_item;
+		u32 id = group->init_policer_id;
+
+		policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, id);
+		if (WARN_ON(!policer_item))
+			return -EINVAL;
+		hw_policer_id = policer_item->hw_id;
+	}
+
+	mlxsw_reg_htgt_pack(htgt_pl, group_id, hw_policer_id, priority, tc);
 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
 }
+
+static struct mlxsw_sp_trap_policer_item *
+mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp, u32 id)
+{
+	struct mlxsw_sp_trap_policer_item *policer_item;
+	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
+	u16 hw_id;
+
+	/* We should be able to allocate a policer because the number of
+	 * policers we registered with devlink is in according with the number
+	 * of available policers.
+	 */
+	hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
+	if (WARN_ON(hw_id == trap->max_policers))
+		return ERR_PTR(-ENOBUFS);
+
+	policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
+	if (!policer_item)
+		return ERR_PTR(-ENOMEM);
+
+	__set_bit(hw_id, trap->policers_usage);
+	policer_item->hw_id = hw_id;
+	policer_item->id = id;
+	list_add_tail(&policer_item->list, &trap->policer_item_list);
+
+	return policer_item;
+}
+
+static void
+mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp *mlxsw_sp,
+				struct mlxsw_sp_trap_policer_item *policer_item)
+{
+	list_del(&policer_item->list);
+	__clear_bit(policer_item->hw_id, mlxsw_sp->trap->policers_usage);
+	kfree(policer_item);
+}
+
+static int mlxsw_sp_trap_policer_params_check(u64 rate, u64 burst,
+					      u8 *p_burst_size,
+					      struct netlink_ext_ack *extack)
+{
+	int bs = fls64(burst);
+
+	if (rate < MLXSW_REG_QPCR_LOWEST_CIR) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
+		return -EINVAL;
+	}
+
+	if (rate > MLXSW_REG_QPCR_HIGHEST_CIR) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
+		return -EINVAL;
+	}
+
+	if (!bs) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
+		return -EINVAL;
+	}
+
+	--bs;
+
+	if (burst != (1 << bs)) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
+		return -EINVAL;
+	}
+
+	if (bs < MLXSW_REG_QPCR_LOWEST_CBS) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
+		return -EINVAL;
+	}
+
+	if (bs > MLXSW_REG_QPCR_HIGHEST_CBS) {
+		NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
+		return -EINVAL;
+	}
+
+	*p_burst_size = bs;
+
+	return 0;
+}
+
+static int __mlxsw_sp_trap_policer_set(struct mlxsw_sp *mlxsw_sp, u16 hw_id,
+				       u64 rate, u64 burst, bool clear_counter,
+				       struct netlink_ext_ack *extack)
+{
+	char qpcr_pl[MLXSW_REG_QPCR_LEN];
+	u8 burst_size;
+	int err;
+
+	err = mlxsw_sp_trap_policer_params_check(rate, burst, &burst_size,
+						 extack);
+	if (err)
+		return err;
+
+	mlxsw_reg_qpcr_pack(qpcr_pl, hw_id, MLXSW_REG_QPCR_IR_UNITS_M, false,
+			    rate, burst_size);
+	mlxsw_reg_qpcr_clear_counter_set(qpcr_pl, clear_counter);
+	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
+}
+
+int mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
+			       const struct devlink_trap_policer *policer)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	struct mlxsw_sp_trap_policer_item *policer_item;
+	int err;
+
+	policer_item = mlxsw_sp_trap_policer_item_init(mlxsw_sp, policer->id);
+	if (IS_ERR(policer_item))
+		return PTR_ERR(policer_item);
+
+	err = __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
+					  policer->init_rate,
+					  policer->init_burst, true, NULL);
+	if (err)
+		goto err_trap_policer_set;
+
+	return 0;
+
+err_trap_policer_set:
+	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
+	return err;
+}
+
+void mlxsw_sp_trap_policer_fini(struct mlxsw_core *mlxsw_core,
+				const struct devlink_trap_policer *policer)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	struct mlxsw_sp_trap_policer_item *policer_item;
+
+	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
+	if (WARN_ON(!policer_item))
+		return;
+
+	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
+}
+
+int mlxsw_sp_trap_policer_set(struct mlxsw_core *mlxsw_core,
+			      const struct devlink_trap_policer *policer,
+			      u64 rate, u64 burst,
+			      struct netlink_ext_ack *extack)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	struct mlxsw_sp_trap_policer_item *policer_item;
+
+	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
+	if (WARN_ON(!policer_item))
+		return -EINVAL;
+
+	return __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
+					   rate, burst, false, extack);
+}
+
+int
+mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
+				  const struct devlink_trap_policer *policer,
+				  u64 *p_drops)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	struct mlxsw_sp_trap_policer_item *policer_item;
+	char qpcr_pl[MLXSW_REG_QPCR_LEN];
+	int err;
+
+	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
+	if (WARN_ON(!policer_item))
+		return -EINVAL;
+
+	mlxsw_reg_qpcr_pack(qpcr_pl, policer_item->hw_id,
+			    MLXSW_REG_QPCR_IR_UNITS_M, false, 0, 0);
+	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
+	if (err)
+		return err;
+
+	*p_drops = mlxsw_reg_qpcr_violate_count_get(qpcr_pl);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
index 05bb652b1a76..8c54897ba173 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h
@@ -4,13 +4,21 @@
 #ifndef _MLXSW_SPECTRUM_TRAP_H
 #define _MLXSW_SPECTRUM_TRAP_H
 
+#include <linux/list.h>
 #include <net/devlink.h>
 
 struct mlxsw_sp_trap {
 	struct devlink_trap_policer *policers_arr; /* Registered policers */
 	u64 policers_count; /* Number of registered policers */
+	struct list_head policer_item_list;
 	u64 max_policers;
 	unsigned long policers_usage[]; /* Usage bitmap */
 };
 
+struct mlxsw_sp_trap_policer_item {
+	u16 hw_id;
+	u32 id;
+	struct list_head list; /* Member of policer_item_list */
+};
+
 #endif
-- 
2.24.1


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

* [PATCH net-next 12/15] mlxsw: spectrum_trap: Do not initialize dedicated discard policer
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (10 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 13/15] mlxsw: spectrum_trap: Switch to use correct packet trap group Ido Schimmel
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

The policer is now initialized as part of the registration with devlink,
so there is no need to initialize it before the registration.

Remove the initialization.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index cc536d06b3ac..a603d11686f2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -300,8 +300,7 @@ static const u16 mlxsw_sp_listener_devlink_map[] = {
 	DEVLINK_TRAP_GENERIC_ID_EGRESS_FLOW_ACTION_DROP,
 };
 
-#define MLXSW_SP_DISCARD_POLICER_ID	(MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
-#define MLXSW_SP_THIN_POLICER_ID	(MLXSW_SP_DISCARD_POLICER_ID + 1)
+#define MLXSW_SP_THIN_POLICER_ID	(MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
 
 static struct mlxsw_sp_trap_policer_item *
 mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
@@ -320,13 +319,6 @@ mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
 static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
 {
 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
-	int err;
-
-	mlxsw_reg_qpcr_pack(qpcr_pl, MLXSW_SP_DISCARD_POLICER_ID,
-			    MLXSW_REG_QPCR_IR_UNITS_M, false, 10 * 1024, 7);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
-	if (err)
-		return err;
 
 	/* The purpose of "thin" policer is to drop as many packets
 	 * as possible. The dummy group is using it.
-- 
2.24.1


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

* [PATCH net-next 13/15] mlxsw: spectrum_trap: Switch to use correct packet trap group
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (11 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 12/15] mlxsw: spectrum_trap: Do not initialize dedicated discard policer Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 14/15] mlxsw: spectrum_trap: Add support for setting of packet trap group parameters Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 15/15] selftests: mlxsw: Add test cases for devlink-trap policers Ido Schimmel
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Some packet traps are currently exposed to user space as being member of
"l3_drops" trap group, but internally they are member of a different
group.

Switch these traps to use the correct group so that they are all subject
to the same policer, as exposed to user space.

Set the trap priority of packets trapped due to loopback error during
routing to the lowest priority. Such packets are not routed again by the
kernel and therefore should not mask other traps (e.g., host miss) that
should be routed.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  2 --
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  9 ++++----
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   | 23 ++++++++++---------
 3 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 192578632657..6af091840f3d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -5537,12 +5537,10 @@ enum mlxsw_reg_htgt_trap_group {
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP,
-	MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP,
-	MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_MLD,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index e8756c921b76..8e4f334695c0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4580,7 +4580,6 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
-		case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
 			rate = 128;
 			burst_size = 7;
@@ -4593,7 +4592,6 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
-		case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
@@ -4674,19 +4672,20 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
 			break;
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6_ND:
-		case MLXSW_REG_HTGT_TRAP_GROUP_SP_RPF:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1:
 			priority = 2;
 			tc = 2;
 			break;
-		case MLXSW_REG_HTGT_TRAP_GROUP_SP_HOST_MISS:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_MULTICAST:
-		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
 			priority = 1;
 			tc = 1;
 			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR:
+			priority = 0;
+			tc = 1;
+			break;
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT:
 			priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY;
 			tc = MLXSW_REG_HTGT_DEFAULT_TC;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index a603d11686f2..c1eac328607a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -233,23 +233,24 @@ static const struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_IPV4_SIP_BC, L3_DISCARDS),
 	MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_RESERVED_SCOPE, L3_DISCARDS),
 	MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, L3_DISCARDS),
-	MLXSW_SP_RXL_EXCEPTION(MTUERROR, ROUTER_EXP, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(TTLERROR, ROUTER_EXP, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(RPF, RPF, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, REMOTE_ROUTE, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, HOST_MISS, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, HOST_MISS, TRAP_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER3, REMOTE_ROUTE,
+	MLXSW_SP_RXL_EXCEPTION(MTUERROR, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(TTLERROR, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(RPF, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, L3_DISCARDS, TRAP_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER3, L3_DISCARDS,
 			       TRAP_EXCEPTION_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4, ROUTER_EXP,
+	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4, L3_DISCARDS,
 			       TRAP_EXCEPTION_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6, ROUTER_EXP,
+	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6, L3_DISCARDS,
 			       TRAP_EXCEPTION_TO_CPU),
 	MLXSW_SP_RXL_DISCARD(ROUTER_IRIF_EN, L3_DISCARDS),
 	MLXSW_SP_RXL_DISCARD(ROUTER_ERIF_EN, L3_DISCARDS),
 	MLXSW_SP_RXL_DISCARD(NON_ROUTABLE, L3_DISCARDS),
-	MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, ROUTER_EXP, TRAP_EXCEPTION_TO_CPU),
-	MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR, ROUTER_EXP,
+	MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, TUNNEL_DISCARDS,
+			       TRAP_EXCEPTION_TO_CPU),
+	MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR, TUNNEL_DISCARDS,
 			       TRAP_EXCEPTION_TO_CPU),
 	MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
 			       TRAP_EXCEPTION_TO_CPU),
-- 
2.24.1


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

* [PATCH net-next 14/15] mlxsw: spectrum_trap: Add support for setting of packet trap group parameters
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (12 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 13/15] mlxsw: spectrum_trap: Switch to use correct packet trap group Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  2020-03-24 19:32 ` [PATCH net-next 15/15] selftests: mlxsw: Add test cases for devlink-trap policers Ido Schimmel
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Implement support for setting of packet trap group parameters by
invoking the trap_group_init() callback with the new parameters.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.c    | 14 ++++++++++
 drivers/net/ethernet/mellanox/mlxsw/core.h    |  3 ++
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  3 ++
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  3 ++
 .../ethernet/mellanox/mlxsw/spectrum_trap.c   | 28 +++++++++++++++----
 5 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 6d0590375976..e9ccd333f61d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1198,6 +1198,19 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink,
 	return mlxsw_driver->trap_group_init(mlxsw_core, group);
 }
 
+static int
+mlxsw_devlink_trap_group_set(struct devlink *devlink,
+			     const struct devlink_trap_group *group,
+			     const struct devlink_trap_policer *policer)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->trap_group_set)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->trap_group_set(mlxsw_core, group, policer);
+}
+
 static int
 mlxsw_devlink_trap_policer_init(struct devlink *devlink,
 				const struct devlink_trap_policer *policer)
@@ -1273,6 +1286,7 @@ static const struct devlink_ops mlxsw_devlink_ops = {
 	.trap_fini			= mlxsw_devlink_trap_fini,
 	.trap_action_set		= mlxsw_devlink_trap_action_set,
 	.trap_group_init		= mlxsw_devlink_trap_group_init,
+	.trap_group_set			= mlxsw_devlink_trap_group_set,
 	.trap_policer_init		= mlxsw_devlink_trap_policer_init,
 	.trap_policer_fini		= mlxsw_devlink_trap_policer_fini,
 	.trap_policer_set		= mlxsw_devlink_trap_policer_set,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 035629bc035d..22b0dfa7cfae 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -327,6 +327,9 @@ struct mlxsw_driver {
 			       enum devlink_trap_action action);
 	int (*trap_group_init)(struct mlxsw_core *mlxsw_core,
 			       const struct devlink_trap_group *group);
+	int (*trap_group_set)(struct mlxsw_core *mlxsw_core,
+			      const struct devlink_trap_group *group,
+			      const struct devlink_trap_policer *policer);
 	int (*trap_policer_init)(struct mlxsw_core *mlxsw_core,
 				 const struct devlink_trap_policer *policer);
 	void (*trap_policer_fini)(struct mlxsw_core *mlxsw_core,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 8e4f334695c0..24ca8d5bc564 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -5674,6 +5674,7 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_group_set			= mlxsw_sp_trap_group_set,
 	.trap_policer_init		= mlxsw_sp_trap_policer_init,
 	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
 	.trap_policer_set		= mlxsw_sp_trap_policer_set,
@@ -5712,6 +5713,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_group_set			= mlxsw_sp_trap_group_set,
 	.trap_policer_init		= mlxsw_sp_trap_policer_init,
 	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
 	.trap_policer_set		= mlxsw_sp_trap_policer_set,
@@ -5749,6 +5751,7 @@ static struct mlxsw_driver mlxsw_sp3_driver = {
 	.trap_fini			= mlxsw_sp_trap_fini,
 	.trap_action_set		= mlxsw_sp_trap_action_set,
 	.trap_group_init		= mlxsw_sp_trap_group_init,
+	.trap_group_set			= mlxsw_sp_trap_group_set,
 	.trap_policer_init		= mlxsw_sp_trap_policer_init,
 	.trap_policer_fini		= mlxsw_sp_trap_policer_fini,
 	.trap_policer_set		= mlxsw_sp_trap_policer_set,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 9858edf7d2e8..060eba9f908c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -1017,6 +1017,9 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
 			     enum devlink_trap_action action);
 int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 			     const struct devlink_trap_group *group);
+int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core,
+			    const struct devlink_trap_group *group,
+			    const struct devlink_trap_policer *policer);
 int
 mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
 			   const struct devlink_trap_policer *policer);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index c1eac328607a..a73cd3db03ed 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -526,8 +526,10 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
 	return 0;
 }
 
-int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
-			     const struct devlink_trap_group *group)
+static int
+__mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
+			   const struct devlink_trap_group *group,
+			   u32 policer_id)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 	u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
@@ -559,11 +561,11 @@ int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 		return -EINVAL;
 	}
 
-	if (group->init_policer_id) {
+	if (policer_id) {
 		struct mlxsw_sp_trap_policer_item *policer_item;
-		u32 id = group->init_policer_id;
 
-		policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, id);
+		policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp,
+								 policer_id);
 		if (WARN_ON(!policer_item))
 			return -EINVAL;
 		hw_policer_id = policer_item->hw_id;
@@ -573,6 +575,22 @@ int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
 }
 
+int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
+			     const struct devlink_trap_group *group)
+{
+	return __mlxsw_sp_trap_group_init(mlxsw_core, group,
+					  group->init_policer_id);
+}
+
+int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core,
+			    const struct devlink_trap_group *group,
+			    const struct devlink_trap_policer *policer)
+{
+	u32 policer_id = policer ? policer->id : 0;
+
+	return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id);
+}
+
 static struct mlxsw_sp_trap_policer_item *
 mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp, u32 id)
 {
-- 
2.24.1


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

* [PATCH net-next 15/15] selftests: mlxsw: Add test cases for devlink-trap policers
  2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
                   ` (13 preceding siblings ...)
  2020-03-24 19:32 ` [PATCH net-next 14/15] mlxsw: spectrum_trap: Add support for setting of packet trap group parameters Ido Schimmel
@ 2020-03-24 19:32 ` Ido Schimmel
  14 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-24 19:32 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, kuba, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

Add test cases that verify that each registered packet trap policer:

* Honors that imposed limitations of rate and burst size
* Able to police trapped packets to the specified rate
* Able to police trapped packets to the specified burst size
* Able to be unbound from its trap group

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 .../drivers/net/mlxsw/devlink_trap_policer.sh | 384 ++++++++++++++++++
 .../selftests/net/forwarding/devlink_lib.sh   |   6 +
 2 files changed, 390 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh

diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh
new file mode 100755
index 000000000000..47edf099a17e
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh
@@ -0,0 +1,384 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test devlink-trap policer functionality over mlxsw.
+
+# +---------------------------------+
+# | H1 (vrf)                        |
+# |    + $h1                        |
+# |    | 192.0.2.1/24               |
+# |    |                            |
+# |    |  default via 192.0.2.2     |
+# +----|----------------------------+
+#      |
+# +----|----------------------------------------------------------------------+
+# | SW |                                                                      |
+# |    + $rp1                                                                 |
+# |        192.0.2.2/24                                                       |
+# |                                                                           |
+# |        198.51.100.2/24                                                    |
+# |    + $rp2                                                                 |
+# |    |                                                                      |
+# +----|----------------------------------------------------------------------+
+#      |
+# +----|----------------------------+
+# |    |  default via 198.51.100.2  |
+# |    |                            |
+# |    | 198.51.100.1/24            |
+# |    + $h2                        |
+# | H2 (vrf)                        |
+# +---------------------------------+
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+	rate_limits_test
+	burst_limits_test
+	rate_test
+	burst_test
+"
+NUM_NETIFS=4
+source $lib_dir/tc_common.sh
+source $lib_dir/lib.sh
+source $lib_dir/devlink_lib.sh
+
+h1_create()
+{
+	simple_if_init $h1 192.0.2.1/24
+	mtu_set $h1 10000
+
+	ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
+}
+
+h1_destroy()
+{
+	ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
+
+	mtu_restore $h1
+	simple_if_fini $h1 192.0.2.1/24
+}
+
+h2_create()
+{
+	simple_if_init $h2 198.51.100.1/24
+	mtu_set $h2 10000
+
+	ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
+}
+
+h2_destroy()
+{
+	ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
+
+	mtu_restore $h2
+	simple_if_fini $h2 198.51.100.1/24
+}
+
+router_create()
+{
+	ip link set dev $rp1 up
+	ip link set dev $rp2 up
+
+	__addr_add_del $rp1 add 192.0.2.2/24
+	__addr_add_del $rp2 add 198.51.100.2/24
+	mtu_set $rp1 10000
+	mtu_set $rp2 10000
+
+	ip -4 route add blackhole 198.51.100.100
+
+	devlink trap set $DEVLINK_DEV trap blackhole_route action trap
+}
+
+router_destroy()
+{
+	devlink trap set $DEVLINK_DEV trap blackhole_route action drop
+
+	ip -4 route del blackhole 198.51.100.100
+
+	mtu_restore $rp2
+	mtu_restore $rp1
+	__addr_add_del $rp2 del 198.51.100.2/24
+	__addr_add_del $rp1 del 192.0.2.2/24
+
+	ip link set dev $rp2 down
+	ip link set dev $rp1 down
+}
+
+setup_prepare()
+{
+	h1=${NETIFS[p1]}
+	rp1=${NETIFS[p2]}
+
+	rp2=${NETIFS[p3]}
+	h2=${NETIFS[p4]}
+
+	rp1_mac=$(mac_get $rp1)
+
+	vrf_prepare
+
+	h1_create
+	h2_create
+
+	router_create
+}
+
+cleanup()
+{
+	pre_cleanup
+
+	router_destroy
+
+	h2_destroy
+	h1_destroy
+
+	vrf_cleanup
+
+	# Reload to ensure devlink-trap settings are back to default.
+	devlink_reload
+}
+
+rate_limits_test()
+{
+	RET=0
+
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null
+	check_fail $? "Policer rate was changed to rate lower than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 \
+		rate 2000000001 &> /dev/null
+	check_fail $? "Policer rate was changed to rate higher than limit"
+
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 1
+	check_err $? "Failed to set policer rate to minimum"
+	devlink trap policer set $DEVLINK_DEV policer 1 rate 2000000000
+	check_err $? "Failed to set policer rate to maximum"
+
+	log_test "Trap policer rate limits"
+}
+
+burst_limits_test()
+{
+	RET=0
+
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 0 &> /dev/null
+	check_fail $? "Policer burst size was changed to 0"
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 17 &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size that is not power of 2"
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 8 &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size lower than limit"
+	devlink trap policer set $DEVLINK_DEV policer 1 \
+		burst $((2**25)) &> /dev/null
+	check_fail $? "Policer burst size was changed to burst size higher than limit"
+
+	devlink trap policer set $DEVLINK_DEV policer 1 burst 16
+	check_err $? "Failed to set policer burst size to minimum"
+	devlink trap policer set $DEVLINK_DEV policer 1 burst $((2**24))
+	check_err $? "Failed to set policer burst size to maximum"
+
+	log_test "Trap policer burst size limits"
+}
+
+trap_rate_get()
+{
+	local t0 t1
+
+	t0=$(devlink_trap_rx_packets_get blackhole_route)
+	sleep 10
+	t1=$(devlink_trap_rx_packets_get blackhole_route)
+
+	echo $(((t1 - t0) / 10))
+}
+
+policer_drop_rate_get()
+{
+	local id=$1; shift
+	local t0 t1
+
+	t0=$(devlink_trap_policer_rx_dropped_get $id)
+	sleep 10
+	t1=$(devlink_trap_policer_rx_dropped_get $id)
+
+	echo $(((t1 - t0) / 10))
+}
+
+__rate_test()
+{
+	local rate pct drop_rate
+	local id=$1; shift
+
+	RET=0
+
+	devlink trap policer set $DEVLINK_DEV policer $id rate 1000 burst 16
+	devlink trap group set $DEVLINK_DEV group l3_drops policer $id
+
+	# Send packets at highest possible rate and make sure they are dropped
+	# by the policer. Make sure measured received rate is about 1000 pps
+	log_info "=== Tx rate: Highest, Policer rate: 1000 pps ==="
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac
+
+	sleep 5 # Take measurements when rate is stable
+
+	rate=$(trap_rate_get)
+	pct=$((100 * (rate - 1000) / 1000))
+	((-5 <= pct && pct <= 5))
+	check_err $? "Expected rate 1000 pps, got $rate pps, which is $pct% off. Required accuracy is +-5%"
+	log_info "Expected rate 1000 pps, measured rate $rate pps"
+
+	drop_rate=$(policer_drop_rate_get $id)
+	(( drop_rate > 0 ))
+	check_err $? "Expected non-zero policer drop rate, got 0"
+	log_info "Measured policer drop rate of $drop_rate pps"
+
+	stop_traffic
+
+	# Send packets at a rate of 1000 pps and make sure they are not dropped
+	# by the policer
+	log_info "=== Tx rate: 1000 pps, Policer rate: 1000 pps ==="
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -d 1msec
+
+	sleep 5 # Take measurements when rate is stable
+
+	drop_rate=$(policer_drop_rate_get $id)
+	(( drop_rate == 0 ))
+	check_err $? "Expected zero policer drop rate, got a drop rate of $drop_rate pps"
+	log_info "Measured policer drop rate of $drop_rate pps"
+
+	stop_traffic
+
+	# Unbind the policer and send packets at highest possible rate. Make
+	# sure they are not dropped by the policer and that the measured
+	# received rate is higher than 1000 pps
+	log_info "=== Tx rate: Highest, Policer rate: No policer ==="
+
+	devlink trap group set $DEVLINK_DEV group l3_drops nopolicer
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac
+
+	rate=$(trap_rate_get)
+	(( rate > 1000 ))
+	check_err $? "Expected rate higher than 1000 pps, got $rate pps"
+	log_info "Measured rate $rate pps"
+
+	drop_rate=$(policer_drop_rate_get $id)
+	(( drop_rate == 0 ))
+	check_err $? "Expected zero policer drop rate, got a drop rate of $drop_rate pps"
+	log_info "Measured policer drop rate of $drop_rate pps"
+
+	stop_traffic
+
+	log_test "Trap policer rate"
+}
+
+rate_test()
+{
+	local id
+
+	for id in $(devlink_trap_policer_ids_get); do
+		echo
+		log_info "Running rate test for policer $id"
+		__rate_test $id
+	done
+}
+
+__burst_test()
+{
+	local t0_rx t0_drop t1_rx t1_drop rx drop
+	local id=$1; shift
+
+	RET=0
+
+	devlink trap policer set $DEVLINK_DEV policer $id rate 1000 burst 32
+	devlink trap group set $DEVLINK_DEV group l3_drops policer $id
+
+	# Send a burst of 64 packets and make sure that about 32 are received
+	# and the rest are dropped by the policer
+	log_info "=== Tx burst size: 64, Policer burst size: 32 pps ==="
+
+	t0_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t0_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 64
+
+	t1_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t1_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	rx=$((t1_rx - t0_rx))
+	pct=$((100 * (rx - 32) / 32))
+	((-20 <= pct && pct <= 20))
+	check_err $? "Expected burst size of 32 packets, got $rx packets, which is $pct% off. Required accuracy is +-20%"
+	log_info "Expected burst size of 32 packets, measured burst size of $rx packets"
+
+	drop=$((t1_drop - t0_drop))
+	(( drop > 0 ))
+	check_err $? "Expected non-zero policer drops, got 0"
+	log_info "Measured policer drops of $drop packets"
+
+	# Send a burst of 16 packets and make sure that 16 are received
+	# and that none are dropped by the policer
+	log_info "=== Tx burst size: 16, Policer burst size: 32 pps ==="
+
+	t0_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t0_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 16
+
+	t1_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t1_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	rx=$((t1_rx - t0_rx))
+	(( rx == 16 ))
+	check_err $? "Expected burst size of 16 packets, got $rx packets"
+	log_info "Expected burst size of 16 packets, measured burst size of $rx packets"
+
+	drop=$((t1_drop - t0_drop))
+	(( drop == 0 ))
+	check_err $? "Expected zero policer drops, got $drop"
+	log_info "Measured policer drops of $drop packets"
+
+	# Unbind the policer and send a burst of 64 packets. Make sure that
+	# 64 packets are received and that none are dropped by the policer
+	log_info "=== Tx burst size: 64, Policer burst size: No policer ==="
+
+	devlink trap group set $DEVLINK_DEV group l3_drops nopolicer
+
+	t0_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t0_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 64
+
+	t1_rx=$(devlink_trap_rx_packets_get blackhole_route)
+	t1_drop=$(devlink_trap_policer_rx_dropped_get $id)
+
+	rx=$((t1_rx - t0_rx))
+	(( rx == 64 ))
+	check_err $? "Expected burst size of 64 packets, got $rx packets"
+	log_info "Expected burst size of 64 packets, measured burst size of $rx packets"
+
+	drop=$((t1_drop - t0_drop))
+	(( drop == 0 ))
+	check_err $? "Expected zero policer drops, got $drop"
+	log_info "Measured policer drops of $drop packets"
+
+	log_test "Trap policer burst size"
+}
+
+burst_test()
+{
+	local id
+
+	for id in $(devlink_trap_policer_ids_get); do
+		echo
+		log_info "Running burst size test for policer $id"
+		__burst_test $id
+	done
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/forwarding/devlink_lib.sh b/tools/testing/selftests/net/forwarding/devlink_lib.sh
index c48645a344e2..155d48bd4d9e 100644
--- a/tools/testing/selftests/net/forwarding/devlink_lib.sh
+++ b/tools/testing/selftests/net/forwarding/devlink_lib.sh
@@ -457,6 +457,12 @@ devlink_trap_group_policer_get()
 		| jq '.[][][]["policer"]'
 }
 
+devlink_trap_policer_ids_get()
+{
+	devlink -j -p trap policer show \
+		| jq '.[]["'$DEVLINK_DEV'"][]["policer"]'
+}
+
 devlink_port_by_netdev()
 {
 	local if_name=$1
-- 
2.24.1


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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
@ 2020-03-25  3:31   ` Jakub Kicinski
  2020-03-25  9:41     ` Ido Schimmel
  2020-03-25  3:37   ` Jakub Kicinski
  1 sibling, 1 reply; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25  3:31 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:
> +/**
> + * devlink_trap_policers_register - Register packet trap policers with devlink.
> + * @devlink: devlink.
> + * @policers: Packet trap policers.
> + * @policers_count: Count of provided packet trap policers.
> + *
> + * Return: Non-zero value on failure.
> + */
> +int
> +devlink_trap_policers_register(struct devlink *devlink,
> +			       const struct devlink_trap_policer *policers,
> +			       size_t policers_count)
> +{
> +	int i, err;
> +
> +	mutex_lock(&devlink->lock);
> +	for (i = 0; i < policers_count; i++) {
> +		const struct devlink_trap_policer *policer = &policers[i];
> +
> +		if (WARN_ON(policer->id == 0)) {
> +			err = -EINVAL;
> +			goto err_trap_policer_verify;
> +		}
> +
> +		err = devlink_trap_policer_register(devlink, policer);
> +		if (err)
> +			goto err_trap_policer_register;
> +	}
> +	mutex_unlock(&devlink->lock);
> +
> +	return 0;
> +
> +err_trap_policer_register:
> +err_trap_policer_verify:

nit: as you probably know the label names are not really in compliance
with:
https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions
;)

> +	for (i--; i >= 0; i--)
> +		devlink_trap_policer_unregister(devlink, &policers[i]);
> +	mutex_unlock(&devlink->lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(devlink_trap_policers_register);

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

* Re: [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support
  2020-03-24 19:32 ` [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support Ido Schimmel
@ 2020-03-25  3:33   ` Jakub Kicinski
  2020-03-25 10:51     ` Ido Schimmel
  0 siblings, 1 reply; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25  3:33 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, 24 Mar 2020 21:32:46 +0200 Ido Schimmel wrote:
> +static int mlxsw_sp_trap_policer_params_check(u64 rate, u64 burst,
> +					      u8 *p_burst_size,
> +					      struct netlink_ext_ack *extack)
> +{
> +	int bs = fls64(burst);
> +
> +	if (rate < MLXSW_REG_QPCR_LOWEST_CIR) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
> +		return -EINVAL;
> +	}
> +
> +	if (rate > MLXSW_REG_QPCR_HIGHEST_CIR) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
> +		return -EINVAL;
> +	}
> +
> +	if (!bs) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> +		return -EINVAL;
> +	}
> +
> +	--bs;
> +
> +	if (burst != (1 << bs)) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
> +		return -EINVAL;
> +	}
> +
> +	if (bs < MLXSW_REG_QPCR_LOWEST_CBS) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> +		return -EINVAL;
> +	}
> +
> +	if (bs > MLXSW_REG_QPCR_HIGHEST_CBS) {
> +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
> +		return -EINVAL;
> +	}

Any chance we could make the min/max values part of the policer itself?
Are they dynamic? Seems like most drivers will have to repeat this
checking against constants while maybe core could have done it?

> +
> +	*p_burst_size = bs;
> +
> +	return 0;
> +}

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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
  2020-03-25  3:31   ` Jakub Kicinski
@ 2020-03-25  3:37   ` Jakub Kicinski
  2020-03-25  9:46     ` Ido Schimmel
  1 sibling, 1 reply; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25  3:37 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:
>  static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {

Hm. looks like devlink doesn't have .strict_start_type set, yet.
Should we set it?

>  	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
>  	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
> @@ -6064,6 +6309,9 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
>  	[DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
>  	[DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
>  	[DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
> +	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
> +	[DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
> +	[DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
>  };

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

* Re: [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters
  2020-03-24 19:32 ` [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters Ido Schimmel
@ 2020-03-25  3:53   ` Jakub Kicinski
  2020-03-25 10:37     ` Ido Schimmel
  0 siblings, 1 reply; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25  3:53 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, 24 Mar 2020 21:32:40 +0200 Ido Schimmel wrote:
> From: Ido Schimmel <idosch@mellanox.com>
> 
> The previous patch allowed device drivers to publish their default
> binding between packet trap policers and packet trap groups. However,
> some users might not be content with this binding and would like to
> change it.
> 
> In case user space passed a packet trap policer identifier when setting
> a packet trap group, invoke the appropriate device driver callback and
> pass the new policer identifier.
> 
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/devlink.h |  9 +++++++++
>  net/core/devlink.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/include/net/devlink.h b/include/net/devlink.h
> index 84c28e0f2d90..dea3c3fd9634 100644
> --- a/include/net/devlink.h
> +++ b/include/net/devlink.h
> @@ -847,6 +847,15 @@ struct devlink_ops {
>  	 */
>  	int (*trap_group_init)(struct devlink *devlink,
>  			       const struct devlink_trap_group *group);
> +	/**
> +	 * @trap_group_set: Trap group parameters set function.
> +	 *
> +	 * Note: @policer can be NULL when a policer is being unbound from
> +	 * @group.
> +	 */
> +	int (*trap_group_set)(struct devlink *devlink,
> +			      const struct devlink_trap_group *group,
> +			      const struct devlink_trap_policer *policer);
>  	/**
>  	 * @trap_policer_init: Trap policer initialization function.
>  	 *
> diff --git a/net/core/devlink.c b/net/core/devlink.c
> index 4ec7c7578709..e3042e131c1f 100644
> --- a/net/core/devlink.c
> +++ b/net/core/devlink.c
> @@ -6039,6 +6039,45 @@ devlink_trap_group_action_set(struct devlink *devlink,
>  	return 0;
>  }
>  
> +static int devlink_trap_group_set(struct devlink *devlink,
> +				  struct devlink_trap_group_item *group_item,
> +				  struct genl_info *info)
> +{
> +	struct devlink_trap_policer_item *policer_item;
> +	struct netlink_ext_ack *extack = info->extack;
> +	const struct devlink_trap_policer *policer;
> +	struct nlattr **attrs = info->attrs;
> +	int err;
> +

Why not:

	if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
		return 0?

> +	if (!devlink->ops->trap_group_set) {
> +		if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
> +			return -EOPNOTSUPP;
> +		return 0;
> +	}
> +
> +	policer_item = group_item->policer_item;
> +	if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
> +		u32 policer_id;
> +
> +		policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
> +		policer_item = devlink_trap_policer_item_lookup(devlink,
> +								policer_id);
> +		if (policer_id && !policer_item) {
> +			NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");

nit: is KBUILD_MODNAME still set if devlink can only be built-in now?

> +			return -ENOENT;
> +		}
> +	}
> +	policer = policer_item ? policer_item->policer : NULL;
> +
> +	err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
> +	if (err)
> +		return err;
> +
> +	group_item->policer_item = policer_item;
> +
> +	return 0;
> +}
> +
>  static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
>  					      struct genl_info *info)
>  {
> @@ -6060,6 +6099,10 @@ static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
>  	if (err)
>  		return err;
>  
> +	err = devlink_trap_group_set(devlink, group_item, info);
> +	if (err)
> +		return err;

Should this unwind the action changes? Are the changes supposed to be
atomic? :S 

Also could it potentially be a problem if trap is being enabled and
policer applied - if we enable first the CPU may get overloaded and it
may be hard to apply the policer? Making sure the ordering is right
requires some careful checking, so IDK if its worth it..

>  	return 0;
>  }
>  


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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-25  3:31   ` Jakub Kicinski
@ 2020-03-25  9:41     ` Ido Schimmel
  2020-03-25 10:41       ` Jiri Pirko
  2020-03-25 16:43       ` Jakub Kicinski
  0 siblings, 2 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-25  9:41 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, Mar 24, 2020 at 08:31:09PM -0700, Jakub Kicinski wrote:
> On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:
> > +/**
> > + * devlink_trap_policers_register - Register packet trap policers with devlink.
> > + * @devlink: devlink.
> > + * @policers: Packet trap policers.
> > + * @policers_count: Count of provided packet trap policers.
> > + *
> > + * Return: Non-zero value on failure.
> > + */
> > +int
> > +devlink_trap_policers_register(struct devlink *devlink,
> > +			       const struct devlink_trap_policer *policers,
> > +			       size_t policers_count)
> > +{
> > +	int i, err;
> > +
> > +	mutex_lock(&devlink->lock);
> > +	for (i = 0; i < policers_count; i++) {
> > +		const struct devlink_trap_policer *policer = &policers[i];
> > +
> > +		if (WARN_ON(policer->id == 0)) {
> > +			err = -EINVAL;
> > +			goto err_trap_policer_verify;
> > +		}
> > +
> > +		err = devlink_trap_policer_register(devlink, policer);
> > +		if (err)
> > +			goto err_trap_policer_register;
> > +	}
> > +	mutex_unlock(&devlink->lock);
> > +
> > +	return 0;
> > +
> > +err_trap_policer_register:
> > +err_trap_policer_verify:
> 
> nit: as you probably know the label names are not really in compliance
> with:
> https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions
> ;)

Hi Jakub, thanks for the thorough review!

I assume you're referring to the fact that the label does not say what
the goto does? It seems that the coding style guide also allows for
labels that indicate why the label exists: "Choose label names which say
what the goto does or why the goto exists".

This is the form I'm used to, but I do adjust the names in code that
uses the other form (such as in netdevsim).

I already used this form in previous devlink submissions, so I would
like to stick to it unless you/Jiri have strong preference here.

> 
> > +	for (i--; i >= 0; i--)
> > +		devlink_trap_policer_unregister(devlink, &policers[i]);
> > +	mutex_unlock(&devlink->lock);
> > +	return err;
> > +}
> > +EXPORT_SYMBOL_GPL(devlink_trap_policers_register);

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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-25  3:37   ` Jakub Kicinski
@ 2020-03-25  9:46     ` Ido Schimmel
  0 siblings, 0 replies; 28+ messages in thread
From: Ido Schimmel @ 2020-03-25  9:46 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, Mar 24, 2020 at 08:37:23PM -0700, Jakub Kicinski wrote:
> On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:
> >  static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
> 
> Hm. looks like devlink doesn't have .strict_start_type set, yet.
> Should we set it?

Good point. Will add.

> 
> >  	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
> >  	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
> > @@ -6064,6 +6309,9 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
> >  	[DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
> >  	[DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
> >  	[DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
> > +	[DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
> > +	[DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
> > +	[DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
> >  };

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

* Re: [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters
  2020-03-25  3:53   ` Jakub Kicinski
@ 2020-03-25 10:37     ` Ido Schimmel
  2020-03-25 16:45       ` Jakub Kicinski
  0 siblings, 1 reply; 28+ messages in thread
From: Ido Schimmel @ 2020-03-25 10:37 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, Mar 24, 2020 at 08:53:14PM -0700, Jakub Kicinski wrote:
> On Tue, 24 Mar 2020 21:32:40 +0200 Ido Schimmel wrote:
> > From: Ido Schimmel <idosch@mellanox.com>
> > 
> > The previous patch allowed device drivers to publish their default
> > binding between packet trap policers and packet trap groups. However,
> > some users might not be content with this binding and would like to
> > change it.
> > 
> > In case user space passed a packet trap policer identifier when setting
> > a packet trap group, invoke the appropriate device driver callback and
> > pass the new policer identifier.
> > 
> > Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> > Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> > ---
> >  include/net/devlink.h |  9 +++++++++
> >  net/core/devlink.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 52 insertions(+)
> > 
> > diff --git a/include/net/devlink.h b/include/net/devlink.h
> > index 84c28e0f2d90..dea3c3fd9634 100644
> > --- a/include/net/devlink.h
> > +++ b/include/net/devlink.h
> > @@ -847,6 +847,15 @@ struct devlink_ops {
> >  	 */
> >  	int (*trap_group_init)(struct devlink *devlink,
> >  			       const struct devlink_trap_group *group);
> > +	/**
> > +	 * @trap_group_set: Trap group parameters set function.
> > +	 *
> > +	 * Note: @policer can be NULL when a policer is being unbound from
> > +	 * @group.
> > +	 */
> > +	int (*trap_group_set)(struct devlink *devlink,
> > +			      const struct devlink_trap_group *group,
> > +			      const struct devlink_trap_policer *policer);
> >  	/**
> >  	 * @trap_policer_init: Trap policer initialization function.
> >  	 *
> > diff --git a/net/core/devlink.c b/net/core/devlink.c
> > index 4ec7c7578709..e3042e131c1f 100644
> > --- a/net/core/devlink.c
> > +++ b/net/core/devlink.c
> > @@ -6039,6 +6039,45 @@ devlink_trap_group_action_set(struct devlink *devlink,
> >  	return 0;
> >  }
> >  
> > +static int devlink_trap_group_set(struct devlink *devlink,
> > +				  struct devlink_trap_group_item *group_item,
> > +				  struct genl_info *info)
> > +{
> > +	struct devlink_trap_policer_item *policer_item;
> > +	struct netlink_ext_ack *extack = info->extack;
> > +	const struct devlink_trap_policer *policer;
> > +	struct nlattr **attrs = info->attrs;
> > +	int err;
> > +
> 
> Why not:
> 
> 	if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
> 		return 0?

Trying to come up with a good reason why I didn't do it, but don't have
any :p

> 
> > +	if (!devlink->ops->trap_group_set) {
> > +		if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
> > +			return -EOPNOTSUPP;
> > +		return 0;
> > +	}
> > +
> > +	policer_item = group_item->policer_item;
> > +	if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
> > +		u32 policer_id;
> > +
> > +		policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
> > +		policer_item = devlink_trap_policer_item_lookup(devlink,
> > +								policer_id);
> > +		if (policer_id && !policer_item) {
> > +			NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
> 
> nit: is KBUILD_MODNAME still set if devlink can only be built-in now?

It seems fine:

NL_SET_ERR_MSG_MOD:

# devlink trap policer set pci/0000:01:00.0 policer 1337
Error: devlink: Device did not register this trap policer.
devlink answers: No such file or directory

NL_SET_ERR_MSG:

# devlink trap policer set pci/0000:01:00.0 policer 1337
Error: Device did not register this trap policer.
devlink answers: No such file or directory

> 
> > +			return -ENOENT;
> > +		}
> > +	}
> > +	policer = policer_item ? policer_item->policer : NULL;
> > +
> > +	err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
> > +	if (err)
> > +		return err;
> > +
> > +	group_item->policer_item = policer_item;
> > +
> > +	return 0;
> > +}
> > +
> >  static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
> >  					      struct genl_info *info)
> >  {
> > @@ -6060,6 +6099,10 @@ static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
> >  	if (err)
> >  		return err;
> >  
> > +	err = devlink_trap_group_set(devlink, group_item, info);
> > +	if (err)
> > +		return err;
> 
> Should this unwind the action changes? Are the changes supposed to be
> atomic? :S 

I used do_setlink() as reference and it seems that it does not unwind
the changes. I can add extack message in case we did set action and
devlink_trap_group_set() failed.

> Also could it potentially be a problem if trap is being enabled and
> policer applied - if we enable first the CPU may get overloaded and it
> may be hard to apply the policer? Making sure the ordering is right
> requires some careful checking, so IDK if its worth it..

I'm not sure it's really an issue, but I can flip the order just to be
on the safe side.

> 
> >  	return 0;
> >  }
> >  
> 

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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-25  9:41     ` Ido Schimmel
@ 2020-03-25 10:41       ` Jiri Pirko
  2020-03-25 16:43       ` Jakub Kicinski
  1 sibling, 0 replies; 28+ messages in thread
From: Jiri Pirko @ 2020-03-25 10:41 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: Jakub Kicinski, netdev, davem, jiri, andrew, f.fainelli,
	vivien.didelot, roopa, nikolay, mlxsw, Ido Schimmel

Wed, Mar 25, 2020 at 10:41:43AM CET, idosch@idosch.org wrote:
>On Tue, Mar 24, 2020 at 08:31:09PM -0700, Jakub Kicinski wrote:
>> On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:
>> > +/**
>> > + * devlink_trap_policers_register - Register packet trap policers with devlink.
>> > + * @devlink: devlink.
>> > + * @policers: Packet trap policers.
>> > + * @policers_count: Count of provided packet trap policers.
>> > + *
>> > + * Return: Non-zero value on failure.
>> > + */
>> > +int
>> > +devlink_trap_policers_register(struct devlink *devlink,
>> > +			       const struct devlink_trap_policer *policers,
>> > +			       size_t policers_count)
>> > +{
>> > +	int i, err;
>> > +
>> > +	mutex_lock(&devlink->lock);
>> > +	for (i = 0; i < policers_count; i++) {
>> > +		const struct devlink_trap_policer *policer = &policers[i];
>> > +
>> > +		if (WARN_ON(policer->id == 0)) {
>> > +			err = -EINVAL;
>> > +			goto err_trap_policer_verify;
>> > +		}
>> > +
>> > +		err = devlink_trap_policer_register(devlink, policer);
>> > +		if (err)
>> > +			goto err_trap_policer_register;
>> > +	}
>> > +	mutex_unlock(&devlink->lock);
>> > +
>> > +	return 0;
>> > +
>> > +err_trap_policer_register:
>> > +err_trap_policer_verify:
>> 
>> nit: as you probably know the label names are not really in compliance
>> with:
>> https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions
>> ;)
>
>Hi Jakub, thanks for the thorough review!
>
>I assume you're referring to the fact that the label does not say what
>the goto does? It seems that the coding style guide also allows for
>labels that indicate why the label exists: "Choose label names which say
>what the goto does or why the goto exists".
>
>This is the form I'm used to, but I do adjust the names in code that
>uses the other form (such as in netdevsim).
>
>I already used this form in previous devlink submissions, so I would
>like to stick to it unless you/Jiri have strong preference here.

Yeah, let's have this per-code. In devlink, this is how it's done. Let's
be consistent.


>
>> 
>> > +	for (i--; i >= 0; i--)
>> > +		devlink_trap_policer_unregister(devlink, &policers[i]);
>> > +	mutex_unlock(&devlink->lock);
>> > +	return err;
>> > +}
>> > +EXPORT_SYMBOL_GPL(devlink_trap_policers_register);

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

* Re: [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support
  2020-03-25  3:33   ` Jakub Kicinski
@ 2020-03-25 10:51     ` Ido Schimmel
  2020-03-25 16:45       ` Jakub Kicinski
  0 siblings, 1 reply; 28+ messages in thread
From: Ido Schimmel @ 2020-03-25 10:51 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Tue, Mar 24, 2020 at 08:33:49PM -0700, Jakub Kicinski wrote:
> On Tue, 24 Mar 2020 21:32:46 +0200 Ido Schimmel wrote:
> > +static int mlxsw_sp_trap_policer_params_check(u64 rate, u64 burst,
> > +					      u8 *p_burst_size,
> > +					      struct netlink_ext_ack *extack)
> > +{
> > +	int bs = fls64(burst);
> > +
> > +	if (rate < MLXSW_REG_QPCR_LOWEST_CIR) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (rate > MLXSW_REG_QPCR_HIGHEST_CIR) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!bs) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> > +		return -EINVAL;
> > +	}
> > +
> > +	--bs;
> > +
> > +	if (burst != (1 << bs)) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (bs < MLXSW_REG_QPCR_LOWEST_CBS) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (bs > MLXSW_REG_QPCR_HIGHEST_CBS) {
> > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
> > +		return -EINVAL;
> > +	}
> 
> Any chance we could make the min/max values part of the policer itself?
> Are they dynamic? Seems like most drivers will have to repeat this
> checking against constants while maybe core could have done it?

Yea, it's a good idea. We can also expose these values to user space,
but I think it's not really necessary and I prefer not to extend uAPI
unless we really have to.

> 
> > +
> > +	*p_burst_size = bs;
> > +
> > +	return 0;
> > +}

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

* Re: [PATCH net-next 01/15] devlink: Add packet trap policers support
  2020-03-25  9:41     ` Ido Schimmel
  2020-03-25 10:41       ` Jiri Pirko
@ 2020-03-25 16:43       ` Jakub Kicinski
  1 sibling, 0 replies; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25 16:43 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Wed, 25 Mar 2020 11:41:43 +0200 Ido Schimmel wrote:
> On Tue, Mar 24, 2020 at 08:31:09PM -0700, Jakub Kicinski wrote:
> > On Tue, 24 Mar 2020 21:32:36 +0200 Ido Schimmel wrote:  
> > > +/**
> > > + * devlink_trap_policers_register - Register packet trap policers with devlink.
> > > + * @devlink: devlink.
> > > + * @policers: Packet trap policers.
> > > + * @policers_count: Count of provided packet trap policers.
> > > + *
> > > + * Return: Non-zero value on failure.
> > > + */
> > > +int
> > > +devlink_trap_policers_register(struct devlink *devlink,
> > > +			       const struct devlink_trap_policer *policers,
> > > +			       size_t policers_count)
> > > +{
> > > +	int i, err;
> > > +
> > > +	mutex_lock(&devlink->lock);
> > > +	for (i = 0; i < policers_count; i++) {
> > > +		const struct devlink_trap_policer *policer = &policers[i];
> > > +
> > > +		if (WARN_ON(policer->id == 0)) {
> > > +			err = -EINVAL;
> > > +			goto err_trap_policer_verify;
> > > +		}
> > > +
> > > +		err = devlink_trap_policer_register(devlink, policer);
> > > +		if (err)
> > > +			goto err_trap_policer_register;
> > > +	}
> > > +	mutex_unlock(&devlink->lock);
> > > +
> > > +	return 0;
> > > +
> > > +err_trap_policer_register:
> > > +err_trap_policer_verify:  
> > 
> > nit: as you probably know the label names are not really in compliance
> > with:
> > https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions
> > ;)  
> 
> Hi Jakub, thanks for the thorough review!
> 
> I assume you're referring to the fact that the label does not say what
> the goto does? It seems that the coding style guide also allows for
> labels that indicate why the label exists: "Choose label names which say
> what the goto does or why the goto exists".

Hm, why the label exists to me does not mean identify the source of the
jump. It's quite logical to name the label after the target, because
then you can just read the body of the function, and validate the jumps
undo the right things based on their names. Is the reason to name
labels after source so that the label doesn't have to be renamed if
steps are inserted in the middle? Can't think of anything else.

Anyway, it's not a big deal, but please be prepared for me to keep
bringing this up :)

> This is the form I'm used to, but I do adjust the names in code that
> uses the other form (such as in netdevsim).
> 
> I already used this form in previous devlink submissions, so I would
> like to stick to it unless you/Jiri have strong preference here.

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

* Re: [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters
  2020-03-25 10:37     ` Ido Schimmel
@ 2020-03-25 16:45       ` Jakub Kicinski
  0 siblings, 0 replies; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25 16:45 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Wed, 25 Mar 2020 12:37:43 +0200 Ido Schimmel wrote:
> > > +		if (policer_id && !policer_item) {
> > > +			NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");  
> > 
> > nit: is KBUILD_MODNAME still set if devlink can only be built-in now?  
> 
> It seems fine:
> 
> NL_SET_ERR_MSG_MOD:
> 
> # devlink trap policer set pci/0000:01:00.0 policer 1337
> Error: devlink: Device did not register this trap policer.
> devlink answers: No such file or directory
> 
> NL_SET_ERR_MSG:
> 
> # devlink trap policer set pci/0000:01:00.0 policer 1337
> Error: Device did not register this trap policer.
> devlink answers: No such file or directory

GTK!

> > > +			return -ENOENT;
> > > +		}
> > > +	}
> > > +	policer = policer_item ? policer_item->policer : NULL;
> > > +
> > > +	err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
> > > +	if (err)
> > > +		return err;
> > > +
> > > +	group_item->policer_item = policer_item;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
> > >  					      struct genl_info *info)
> > >  {
> > > @@ -6060,6 +6099,10 @@ static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
> > >  	if (err)
> > >  		return err;
> > >  
> > > +	err = devlink_trap_group_set(devlink, group_item, info);
> > > +	if (err)
> > > +		return err;  
> > 
> > Should this unwind the action changes? Are the changes supposed to be
> > atomic? :S   
> 
> I used do_setlink() as reference and it seems that it does not unwind
> the changes. I can add extack message in case we did set action and
> devlink_trap_group_set() failed.

Okay.

> > Also could it potentially be a problem if trap is being enabled and
> > policer applied - if we enable first the CPU may get overloaded and it
> > may be hard to apply the policer? Making sure the ordering is right
> > requires some careful checking, so IDK if its worth it..  
> 
> I'm not sure it's really an issue, but I can flip the order just to be
> on the safe side.

No, no, flipping doesn't do anything. It will just move the problem
from enable to disable. You can leave as is if it's not expected to 
be an issue.

> >   
> > >  	return 0;
> > >  }
> > >    
> >   


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

* Re: [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support
  2020-03-25 10:51     ` Ido Schimmel
@ 2020-03-25 16:45       ` Jakub Kicinski
  0 siblings, 0 replies; 28+ messages in thread
From: Jakub Kicinski @ 2020-03-25 16:45 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, davem, jiri, andrew, f.fainelli, vivien.didelot, roopa,
	nikolay, mlxsw, Ido Schimmel

On Wed, 25 Mar 2020 12:51:21 +0200 Ido Schimmel wrote:
> On Tue, Mar 24, 2020 at 08:33:49PM -0700, Jakub Kicinski wrote:
> > On Tue, 24 Mar 2020 21:32:46 +0200 Ido Schimmel wrote:  
> > > +static int mlxsw_sp_trap_policer_params_check(u64 rate, u64 burst,
> > > +					      u8 *p_burst_size,
> > > +					      struct netlink_ext_ack *extack)
> > > +{
> > > +	int bs = fls64(burst);
> > > +
> > > +	if (rate < MLXSW_REG_QPCR_LOWEST_CIR) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (rate > MLXSW_REG_QPCR_HIGHEST_CIR) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (!bs) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	--bs;
> > > +
> > > +	if (burst != (1 << bs)) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (bs < MLXSW_REG_QPCR_LOWEST_CBS) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (bs > MLXSW_REG_QPCR_HIGHEST_CBS) {
> > > +		NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
> > > +		return -EINVAL;
> > > +	}  
> > 
> > Any chance we could make the min/max values part of the policer itself?
> > Are they dynamic? Seems like most drivers will have to repeat this
> > checking against constants while maybe core could have done it?  
> 
> Yea, it's a good idea. We can also expose these values to user space,
> but I think it's not really necessary and I prefer not to extend uAPI
> unless we really have to.

SGTM, thanks!

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

end of thread, other threads:[~2020-03-25 16:45 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-24 19:32 [PATCH net-next 00/15] Add packet trap policers support Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 01/15] devlink: " Ido Schimmel
2020-03-25  3:31   ` Jakub Kicinski
2020-03-25  9:41     ` Ido Schimmel
2020-03-25 10:41       ` Jiri Pirko
2020-03-25 16:43       ` Jakub Kicinski
2020-03-25  3:37   ` Jakub Kicinski
2020-03-25  9:46     ` Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 02/15] Documentation: Add description of packet trap policers Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 03/15] netdevsim: Add devlink-trap policer support Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 04/15] devlink: Add packet trap group parameters support Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 05/15] devlink: Allow setting of packet trap group parameters Ido Schimmel
2020-03-25  3:53   ` Jakub Kicinski
2020-03-25 10:37     ` Ido Schimmel
2020-03-25 16:45       ` Jakub Kicinski
2020-03-24 19:32 ` [PATCH net-next 06/15] netdevsim: Add support for " Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 07/15] selftests: netdevsim: Add test cases for devlink-trap policers Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 08/15] mlxsw: reg: Extend QPCR register Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 09/15] mlxsw: spectrum: Track used packet trap policer IDs Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 10/15] mlxsw: spectrum_trap: Prepare policers for registration with devlink Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 11/15] mlxsw: spectrum_trap: Add devlink-trap policer support Ido Schimmel
2020-03-25  3:33   ` Jakub Kicinski
2020-03-25 10:51     ` Ido Schimmel
2020-03-25 16:45       ` Jakub Kicinski
2020-03-24 19:32 ` [PATCH net-next 12/15] mlxsw: spectrum_trap: Do not initialize dedicated discard policer Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 13/15] mlxsw: spectrum_trap: Switch to use correct packet trap group Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 14/15] mlxsw: spectrum_trap: Add support for setting of packet trap group parameters Ido Schimmel
2020-03-24 19:32 ` [PATCH net-next 15/15] selftests: mlxsw: Add test cases for devlink-trap policers Ido Schimmel

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.