Skip to content

Commit

Permalink
Merge branch 'mlxsw-Add-support-for-buffer-drop-traps'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
mlxsw: Add support for buffer drop traps

Petr says:

A recent patch set added the ability to mirror buffer related drops
(e.g., early drops) through a netdev. This patch set adds the ability to
trap such packets to the local CPU for analysis.

The trapping towards the CPU is configured by using tc-trap action
instead of tc-mirred as was done when the packets were mirrored through
a netdev. A future patch set will also add the ability to sample the
dropped packets using tc-sample action.

The buffer related drop traps are added to devlink, which means that the
dropped packets can be reported to user space via the kernel's
drop_monitor module.

Patch set overview:

Patch #1 adds the early_drop trap to devlink

Patch #2 adds extack to a few devlink operations to facilitate better
error reporting to user space. This is necessary - among other things -
because the action of buffer drop traps cannot be changed in mlxsw

Patch #3 performs a small refactoring in mlxsw, patch #4 fixes a bug that
this patchset would trigger.

Patches #5-#6 add the infrastructure required to support different traps
/ trap groups in mlxsw per-ASIC. This is required because buffer drop
traps are not supported by Spectrum-1

Patch #7 extends mlxsw to register the early_drop trap

Patch #8 adds the offload logic for the "trap" action at a qevent block.

Patch #9 adds a mlxsw-specific selftest.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Aug 4, 2020
2 parents 80fbbb1 + 8fb6ac4 commit f8deaea
Show file tree
Hide file tree
Showing 15 changed files with 406 additions and 66 deletions.
4 changes: 4 additions & 0 deletions Documentation/networking/devlink/devlink-trap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,10 @@ be added to the following table:
- ``control``
- Traps packets logged during processing of flow action trap (e.g., via
tc's trap action)
* - ``early_drop``
- ``drop``
- Traps packets dropped due to the RED (Random Early Detection) algorithm
(i.e., early drops)

Driver-specific Packet Traps
============================
Expand Down
10 changes: 6 additions & 4 deletions drivers/net/ethernet/mellanox/mlxsw/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,14 +1177,15 @@ static void mlxsw_devlink_trap_fini(struct devlink *devlink,

static int mlxsw_devlink_trap_action_set(struct devlink *devlink,
const struct devlink_trap *trap,
enum devlink_trap_action action)
enum devlink_trap_action action,
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_action_set)
return -EOPNOTSUPP;
return mlxsw_driver->trap_action_set(mlxsw_core, trap, action);
return mlxsw_driver->trap_action_set(mlxsw_core, trap, action, extack);
}

static int
Expand All @@ -1202,14 +1203,15 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink,
static int
mlxsw_devlink_trap_group_set(struct devlink *devlink,
const struct devlink_trap_group *group,
const struct devlink_trap_policer *policer)
const struct devlink_trap_policer *policer,
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_group_set)
return -EOPNOTSUPP;
return mlxsw_driver->trap_group_set(mlxsw_core, group, policer);
return mlxsw_driver->trap_group_set(mlxsw_core, group, policer, extack);
}

static int
Expand Down
19 changes: 14 additions & 5 deletions drivers/net/ethernet/mellanox/mlxsw/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,15 @@ struct mlxsw_listener {
};

#define __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \
_dis_action, _enabled_on_register, _dis_trap_group) \
_dis_action, _enabled_on_register, _dis_trap_group, \
_mirror_reason) \
{ \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
.rx_listener = \
{ \
.func = _func, \
.local_port = MLXSW_PORT_DONT_CARE, \
.mirror_reason = _mirror_reason, \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
}, \
.en_action = MLXSW_REG_HPKT_ACTION_##_en_action, \
Expand All @@ -109,12 +111,17 @@ struct mlxsw_listener {
#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)
_dis_action, true, _trap_group, 0)

#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)
_dis_action, false, _dis_trap_group, 0)

#define MLXSW_RXL_MIRROR(_func, _session_id, _trap_group, _mirror_reason) \
__MLXSW_RXL(_func, MIRROR_SESSION##_session_id, TRAP_TO_CPU, false, \
_trap_group, TRAP_TO_CPU, true, _trap_group, \
_mirror_reason)

#define MLXSW_EVENTL(_func, _trap_id, _trap_group) \
{ \
Expand Down Expand Up @@ -326,12 +333,14 @@ struct mlxsw_driver {
const struct devlink_trap *trap, void *trap_ctx);
int (*trap_action_set)(struct mlxsw_core *mlxsw_core,
const struct devlink_trap *trap,
enum devlink_trap_action action);
enum devlink_trap_action action,
struct netlink_ext_ack *extack);
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);
const struct devlink_trap_policer *policer,
struct netlink_ext_ack *extack);
int (*trap_policer_init)(struct mlxsw_core *mlxsw_core,
const struct devlink_trap_policer *policer);
void (*trap_policer_fini)(struct mlxsw_core *mlxsw_core,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlxsw/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -5614,6 +5614,7 @@ enum mlxsw_reg_htgt_trap_group {
MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_EXCEPTIONS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,

__MLXSW_REG_HTGT_TRAP_GROUP_MAX,
MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -3055,6 +3055,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
mlxsw_sp->policer_core_ops = &mlxsw_sp1_policer_core_ops;
mlxsw_sp->trap_ops = &mlxsw_sp1_trap_ops;
mlxsw_sp->listeners = mlxsw_sp1_listener;
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
Expand Down Expand Up @@ -3084,6 +3085,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;

return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
Expand Down Expand Up @@ -3111,6 +3113,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;

return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
Expand Down
14 changes: 12 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct mlxsw_sp {
const struct mlxsw_sp_ptp_ops *ptp_ops;
const struct mlxsw_sp_span_ops *span_ops;
const struct mlxsw_sp_policer_core_ops *policer_core_ops;
const struct mlxsw_sp_trap_ops *trap_ops;
const struct mlxsw_listener *listeners;
size_t listeners_count;
u32 lowest_shaper_bs;
Expand Down Expand Up @@ -983,6 +984,10 @@ struct mlxsw_sp_mall_mirror_entry {
int span_id;
};

struct mlxsw_sp_mall_trap_entry {
int span_id;
};

struct mlxsw_sp_mall_entry {
struct list_head list;
unsigned long cookie;
Expand All @@ -991,6 +996,7 @@ struct mlxsw_sp_mall_entry {
bool ingress;
union {
struct mlxsw_sp_mall_mirror_entry mirror;
struct mlxsw_sp_mall_trap_entry trap;
struct mlxsw_sp_port_sample sample;
};
struct rcu_head rcu;
Expand Down Expand Up @@ -1177,12 +1183,14 @@ void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
const struct devlink_trap *trap, void *trap_ctx);
int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
const struct devlink_trap *trap,
enum devlink_trap_action action);
enum devlink_trap_action action,
struct netlink_ext_ack *extack);
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);
const struct devlink_trap_policer *policer,
struct netlink_ext_ack *extack);
int
mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
const struct devlink_trap_policer *policer);
Expand All @@ -1196,6 +1204,8 @@ int
mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
const struct devlink_trap_policer *policer,
u64 *p_drops);
int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
bool *p_enabled, u16 *p_hw_id);

static inline struct net *mlxsw_sp_net(struct mlxsw_sp *mlxsw_sp)
{
Expand Down
75 changes: 62 additions & 13 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,19 +1289,18 @@ struct mlxsw_sp_qevent_binding {

static LIST_HEAD(mlxsw_sp_qevent_block_cb_list);

static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding,
const struct mlxsw_sp_span_agent_parms *agent_parms,
int *p_span_id)
{
struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
struct mlxsw_sp_span_trigger_parms trigger_parms = {};
struct mlxsw_sp_span_agent_parms agent_parms = {
.to_dev = mall_entry->mirror.to_dev,
};
int span_id;
int err;

err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, &agent_parms);
err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, agent_parms);
if (err)
return err;

Expand All @@ -1320,7 +1319,7 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_trigger_enable;

mall_entry->mirror.span_id = span_id;
*p_span_id = span_id;
return 0;

err_trigger_enable:
Expand All @@ -1333,21 +1332,65 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
return err;
}

static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
static void mlxsw_sp_qevent_span_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_qevent_binding *qevent_binding,
int span_id)
{
struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
struct mlxsw_sp_span_trigger_parms trigger_parms = {
.span_id = mall_entry->mirror.span_id,
.span_id = span_id,
};

mlxsw_sp_span_trigger_disable(mlxsw_sp_port, qevent_binding->span_trigger,
qevent_binding->tclass_num);
mlxsw_sp_span_agent_unbind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
&trigger_parms);
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
mlxsw_sp_span_agent_put(mlxsw_sp, mall_entry->mirror.span_id);
mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
}

static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
{
struct mlxsw_sp_span_agent_parms agent_parms = {
.to_dev = mall_entry->mirror.to_dev,
};

return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding,
&agent_parms, &mall_entry->mirror.span_id);
}

static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
{
mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->mirror.span_id);
}

static int mlxsw_sp_qevent_trap_configure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
{
struct mlxsw_sp_span_agent_parms agent_parms = {};
int err;

err = mlxsw_sp_trap_group_policer_hw_id_get(mlxsw_sp,
DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS,
&agent_parms.policer_enable,
&agent_parms.policer_id);
if (err)
return err;

return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding,
&agent_parms, &mall_entry->trap.span_id);
}

static void mlxsw_sp_qevent_trap_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct mlxsw_sp_qevent_binding *qevent_binding)
{
mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->trap.span_id);
}

static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
Expand All @@ -1357,6 +1400,8 @@ static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
switch (mall_entry->type) {
case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
return mlxsw_sp_qevent_mirror_configure(mlxsw_sp, mall_entry, qevent_binding);
case MLXSW_SP_MALL_ACTION_TYPE_TRAP:
return mlxsw_sp_qevent_trap_configure(mlxsw_sp, mall_entry, qevent_binding);
default:
/* This should have been validated away. */
WARN_ON(1);
Expand All @@ -1371,6 +1416,8 @@ static void mlxsw_sp_qevent_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
switch (mall_entry->type) {
case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
return mlxsw_sp_qevent_mirror_deconfigure(mlxsw_sp, mall_entry, qevent_binding);
case MLXSW_SP_MALL_ACTION_TYPE_TRAP:
return mlxsw_sp_qevent_trap_deconfigure(mlxsw_sp, mall_entry, qevent_binding);
default:
WARN_ON(1);
return;
Expand Down Expand Up @@ -1490,6 +1537,8 @@ static int mlxsw_sp_qevent_mall_replace(struct mlxsw_sp *mlxsw_sp,
if (act->id == FLOW_ACTION_MIRRED) {
mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR;
mall_entry->mirror.to_dev = act->dev;
} else if (act->id == FLOW_ACTION_TRAP) {
mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_TRAP;
} else {
NL_SET_ERR_MSG(f->common.extack, "Unsupported action");
err = -EOPNOTSUPP;
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,8 @@ static int mlxsw_sp_span_policer_id_base_set(struct mlxsw_sp_span *span,

static void mlxsw_sp_span_policer_id_base_unset(struct mlxsw_sp_span *span)
{
refcount_dec(&span->policer_id_base_ref_count);
if (refcount_dec_and_test(&span->policer_id_base_ref_count))
span->policer_id_base = 0;
}

static struct mlxsw_sp_span_entry *
Expand Down
Loading

0 comments on commit f8deaea

Please sign in to comment.