Commit 27cf31dc authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlxsw-Introduce-ACL-traps'



Jiri Pirko says:

====================
mlxsw: Introduce ACL traps

This patchset allows to track packets that are dropped in HW by ACL.

Unlike the existing mlxsw traps, ACL traps are "source traps".
That means the action is not controlled by HPKT register but directly
in ACL TRAP action. When devlink user changes action from drop to trap
and vice versa, it would be needed to go over all instances of ACL TRAP
action and do change. That does not scale. Instead, resolve this
by introducing "dummy" group with "thin" policer. The purpose of
this policer is to drop as many packets as possible. The ones
that pass through are going to be dropped in devlink code - patch #6
takes care of that.

First four patches are preparation for introduction of ACL traps in mlxsw
so it possible to easily change from drop to trap for source traps
as well - by changing group to "dummy" and back.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3b0b4252 e3294d2b
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -238,6 +238,12 @@ be added to the following table:
     - ``drop``
     - Traps NVE packets that the device decided to drop because their overlay
       source MAC is multicast
   * - ``ingress_flow_action_drop``
     - ``drop``
     - Traps packets dropped during processing of ingress flow action drop
   * - ``egress_flow_action_drop``
     - ``drop``
     - Traps packets dropped during processing of egress flow action drop

Driver-specific Packet Traps
============================
@@ -277,6 +283,9 @@ narrow. The description of these groups must be added to the following table:
   * - ``tunnel_drops``
     - Contains packet traps for packets that were dropped by the device during
       tunnel encapsulation / decapsulation
   * - ``acl_drops``
     - Contains packet traps for packets that were dropped by the device during
       ACL processing

Testing
=======
+59 −18
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ struct mlxsw_rx_listener_item {
	struct list_head list;
	struct mlxsw_rx_listener rxl;
	void *priv;
	bool enabled;
};

struct mlxsw_event_listener_item {
@@ -1470,7 +1471,7 @@ __find_rx_listener_item(struct mlxsw_core *mlxsw_core,

int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
				    const struct mlxsw_rx_listener *rxl,
				    void *priv)
				    void *priv, bool enabled)
{
	struct mlxsw_rx_listener_item *rxl_item;

@@ -1482,6 +1483,7 @@ int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
		return -ENOMEM;
	rxl_item->rxl = *rxl;
	rxl_item->priv = priv;
	rxl_item->enabled = enabled;

	list_add_rcu(&rxl_item->list, &mlxsw_core->rx_listener_list);
	return 0;
@@ -1502,6 +1504,19 @@ void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_rx_listener_unregister);

static void
mlxsw_core_rx_listener_state_set(struct mlxsw_core *mlxsw_core,
				 const struct mlxsw_rx_listener *rxl,
				 bool enabled)
{
	struct mlxsw_rx_listener_item *rxl_item;

	rxl_item = __find_rx_listener_item(mlxsw_core, rxl);
	if (WARN_ON(!rxl_item))
		return;
	rxl_item->enabled = enabled;
}

static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port,
					   void *priv)
{
@@ -1563,7 +1578,7 @@ int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core,
	el_item->el = *el;
	el_item->priv = priv;

	err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item);
	err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item, true);
	if (err)
		goto err_rx_listener_register;

@@ -1601,16 +1616,18 @@ EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);

static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
					const struct mlxsw_listener *listener,
					void *priv)
					void *priv, bool enabled)
{
	if (listener->is_event)
	if (listener->is_event) {
		WARN_ON(!enabled);
		return mlxsw_core_event_listener_register(mlxsw_core,
						&listener->event_listener,
						priv);
	else
	} else {
		return mlxsw_core_rx_listener_register(mlxsw_core,
						&listener->rx_listener,
						priv);
						priv, enabled);
	}
}

static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
@@ -1628,15 +1645,22 @@ static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
			     const struct mlxsw_listener *listener, void *priv)
{
	enum mlxsw_reg_htgt_trap_group trap_group;
	enum mlxsw_reg_hpkt_action action;
	char hpkt_pl[MLXSW_REG_HPKT_LEN];
	int err;

	err = mlxsw_core_listener_register(mlxsw_core, listener, priv);
	err = mlxsw_core_listener_register(mlxsw_core, listener, priv,
					   listener->enabled_on_register);
	if (err)
		return err;

	mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id,
			    listener->trap_group, listener->is_ctrl);
	action = listener->enabled_on_register ? listener->en_action :
						 listener->dis_action;
	trap_group = listener->enabled_on_register ? listener->en_trap_group :
						     listener->dis_trap_group;
	mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
			    trap_group, listener->is_ctrl);
	err = mlxsw_reg_write(mlxsw_core,  MLXSW_REG(hpkt), hpkt_pl);
	if (err)
		goto err_trap_set;
@@ -1656,8 +1680,8 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
	char hpkt_pl[MLXSW_REG_HPKT_LEN];

	if (!listener->is_event) {
		mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action,
				    listener->trap_id, listener->trap_group,
		mlxsw_reg_hpkt_pack(hpkt_pl, listener->dis_action,
				    listener->trap_id, listener->dis_trap_group,
				    listener->is_ctrl);
		mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
	}
@@ -1666,17 +1690,33 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_trap_unregister);

int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core,
int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core,
			      const struct mlxsw_listener *listener,
			       enum mlxsw_reg_hpkt_action action)
			      bool enabled)
{
	enum mlxsw_reg_htgt_trap_group trap_group;
	enum mlxsw_reg_hpkt_action action;
	char hpkt_pl[MLXSW_REG_HPKT_LEN];
	int err;

	/* Not supported for event listener */
	if (WARN_ON(listener->is_event))
		return -EINVAL;

	action = enabled ? listener->en_action : listener->dis_action;
	trap_group = enabled ? listener->en_trap_group :
			       listener->dis_trap_group;
	mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
			    listener->trap_group, listener->is_ctrl);
	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
			    trap_group, listener->is_ctrl);
	err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
	if (err)
		return err;

	mlxsw_core_rx_listener_state_set(mlxsw_core, &listener->rx_listener,
					 enabled);
	return 0;
}
EXPORT_SYMBOL(mlxsw_core_trap_action_set);
EXPORT_SYMBOL(mlxsw_core_trap_state_set);

static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
{
@@ -1934,6 +1974,7 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
		if ((rxl->local_port == MLXSW_PORT_DONT_CARE ||
		     rxl->local_port == local_port) &&
		    rxl->trap_id == rx_info->trap_id) {
			if (rxl_item->enabled)
				found = true;
			break;
		}
+50 −33
Original line number Diff line number Diff line
@@ -76,15 +76,19 @@ struct mlxsw_listener {
		struct mlxsw_rx_listener rx_listener;
		struct mlxsw_event_listener event_listener;
	};
	enum mlxsw_reg_hpkt_action action;
	enum mlxsw_reg_hpkt_action unreg_action;
	u8 trap_group;
	enum mlxsw_reg_hpkt_action en_action; /* Action when enabled */
	enum mlxsw_reg_hpkt_action dis_action; /* Action when disabled */
	u8 en_trap_group; /* Trap group when enabled */
	u8 dis_trap_group; /* Trap group when disabled */
	u8 is_ctrl:1, /* should go via control buffer or not */
	   is_event:1;
	   is_event:1,
	   enabled_on_register:1; /* Trap should be enabled when listener
				   * is registered.
				   */
};

#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _trap_group,	\
		  _unreg_action)					\
#define __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group,	\
		    _dis_action, _enabled_on_register, _dis_trap_group)		\
	{									\
		.trap_id = MLXSW_TRAP_ID_##_trap_id,				\
		.rx_listener =							\
@@ -93,12 +97,24 @@ struct mlxsw_listener {
			.local_port = MLXSW_PORT_DONT_CARE,			\
			.trap_id = MLXSW_TRAP_ID_##_trap_id,			\
		},								\
		.action = MLXSW_REG_HPKT_ACTION_##_action,		\
		.unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action,	\
		.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group,	\
		.en_action = MLXSW_REG_HPKT_ACTION_##_en_action,		\
		.dis_action = MLXSW_REG_HPKT_ACTION_##_dis_action,		\
		.en_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_en_trap_group,	\
		.dis_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_dis_trap_group,	\
		.is_ctrl = _is_ctrl,						\
		.enabled_on_register = _enabled_on_register,			\
	}

#define MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group,		\
		  _dis_action)							\
	__MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group,		\
		    _dis_action, true, _trap_group)

#define MLXSW_RXL_DIS(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group,	\
		      _dis_action, _dis_trap_group)				\
	__MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group,	\
		    _dis_action, false, _dis_trap_group)

#define MLXSW_EVENTL(_func, _trap_id, _trap_group)				\
	{									\
		.trap_id = MLXSW_TRAP_ID_##_trap_id,				\
@@ -107,14 +123,15 @@ struct mlxsw_listener {
			.func = _func,						\
			.trap_id = MLXSW_TRAP_ID_##_trap_id,			\
		},								\
		.action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,		\
		.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group,	\
		.en_action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,			\
		.en_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group,	\
		.is_event = true,						\
		.enabled_on_register = true,					\
	}

int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
				    const struct mlxsw_rx_listener *rxl,
				    void *priv);
				    void *priv, bool enabled);
void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core,
				       const struct mlxsw_rx_listener *rxl);

@@ -130,9 +147,9 @@ int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
				const struct mlxsw_listener *listener,
				void *priv);
int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core,
int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core,
			      const struct mlxsw_listener *listener,
			       enum mlxsw_reg_hpkt_action action);
			      bool enabled);

typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
				  size_t payload_len, unsigned long cb_priv);
+5 −3
Original line number Diff line number Diff line
@@ -813,15 +813,17 @@ mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
	mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
}

int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
{
	char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAP_CODE,
						  MLXSW_AFA_TRAP_SIZE);

	if (IS_ERR(act))
		return PTR_ERR(act);
	mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_NOP,
			    MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD, 0);
	mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
			    MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
			    ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
				      MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
	return 0;
}
EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity);
int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress);
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
					    u16 trap_id);
Loading