Merge branch 'mlxsw-Add-support-for-buffer-drop-traps'
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 <davem@davemloft.net>
This commit is contained in:
commit
f8deaea06f
@ -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
|
||||
============================
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -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, \
|
||||
@ -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) \
|
||||
{ \
|
||||
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
@ -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:
|
||||
@ -1333,13 +1332,13 @@ err_analyzed_port_get:
|
||||
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,
|
||||
@ -1347,7 +1346,51 @@ static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
|
||||
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,
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
@ -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 *
|
||||
|
@ -21,6 +21,7 @@ struct mlxsw_sp_trap_group_item {
|
||||
struct devlink_trap_group group;
|
||||
u16 hw_group_id;
|
||||
u8 priority;
|
||||
u8 fixed_policer:1; /* Whether policer binding can change */
|
||||
};
|
||||
|
||||
#define MLXSW_SP_TRAP_LISTENERS_MAX 3
|
||||
@ -28,6 +29,7 @@ struct mlxsw_sp_trap_group_item {
|
||||
struct mlxsw_sp_trap_item {
|
||||
struct devlink_trap trap;
|
||||
struct mlxsw_listener listeners_arr[MLXSW_SP_TRAP_LISTENERS_MAX];
|
||||
u8 is_source:1;
|
||||
};
|
||||
|
||||
/* All driver-specific traps must be documented in
|
||||
@ -46,6 +48,11 @@ enum {
|
||||
|
||||
#define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
|
||||
|
||||
enum {
|
||||
/* Packet was early dropped. */
|
||||
MLXSW_SP_MIRROR_REASON_INGRESS_WRED = 9,
|
||||
};
|
||||
|
||||
static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
|
||||
u8 local_port,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port)
|
||||
@ -222,6 +229,11 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
|
||||
DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
|
||||
MLXSW_SP_TRAP_METADATA | (_metadata))
|
||||
|
||||
#define MLXSW_SP_TRAP_BUFFER_DROP(_id) \
|
||||
DEVLINK_TRAP_GENERIC(DROP, TRAP, _id, \
|
||||
DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS, \
|
||||
MLXSW_SP_TRAP_METADATA)
|
||||
|
||||
#define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id) \
|
||||
DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id, \
|
||||
DEVLINK_MLXSW_TRAP_NAME_##_id, \
|
||||
@ -248,6 +260,10 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
|
||||
TRAP_EXCEPTION_TO_CPU, false, SP_##_en_group_id, \
|
||||
SET_FW_DEFAULT, SP_##_dis_group_id)
|
||||
|
||||
#define MLXSW_SP_RXL_BUFFER_DISCARD(_mirror_reason) \
|
||||
MLXSW_RXL_MIRROR(mlxsw_sp_rx_drop_listener, 0, SP_BUFFER_DISCARDS, \
|
||||
MLXSW_SP_MIRROR_REASON_##_mirror_reason)
|
||||
|
||||
#define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action) \
|
||||
MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id, \
|
||||
_action, false, SP_##_group_id, SET_FW_DEFAULT)
|
||||
@ -331,6 +347,9 @@ mlxsw_sp_trap_policer_items_arr[] = {
|
||||
{
|
||||
.policer = MLXSW_SP_TRAP_POLICER(19, 1024, 512),
|
||||
},
|
||||
{
|
||||
.policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
|
||||
@ -1063,10 +1082,10 @@ static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
|
||||
|
||||
static int mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
size_t arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr);
|
||||
size_t elem_size = sizeof(struct mlxsw_sp_trap_policer_item);
|
||||
u64 arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr);
|
||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||
u64 free_policers = 0;
|
||||
size_t free_policers = 0;
|
||||
u32 last_id;
|
||||
int i;
|
||||
|
||||
@ -1159,6 +1178,43 @@ static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
size_t common_groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr);
|
||||
const struct mlxsw_sp_trap_group_item *spec_group_items_arr;
|
||||
size_t elem_size = sizeof(struct mlxsw_sp_trap_group_item);
|
||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||
size_t groups_count, spec_groups_count;
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp->trap_ops->groups_init(mlxsw_sp, &spec_group_items_arr,
|
||||
&spec_groups_count);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The group items array is created by concatenating the common trap
|
||||
* group items and the ASIC-specific trap group items.
|
||||
*/
|
||||
groups_count = common_groups_count + spec_groups_count;
|
||||
trap->group_items_arr = kcalloc(groups_count, elem_size, GFP_KERNEL);
|
||||
if (!trap->group_items_arr)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(trap->group_items_arr, mlxsw_sp_trap_group_items_arr,
|
||||
elem_size * common_groups_count);
|
||||
memcpy(trap->group_items_arr + common_groups_count,
|
||||
spec_group_items_arr, elem_size * spec_groups_count);
|
||||
|
||||
trap->groups_count = groups_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
kfree(mlxsw_sp->trap->group_items_arr);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
@ -1166,13 +1222,9 @@ static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp)
|
||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||
int err, i;
|
||||
|
||||
trap->group_items_arr = kmemdup(mlxsw_sp_trap_group_items_arr,
|
||||
sizeof(mlxsw_sp_trap_group_items_arr),
|
||||
GFP_KERNEL);
|
||||
if (!trap->group_items_arr)
|
||||
return -ENOMEM;
|
||||
|
||||
trap->groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr);
|
||||
err = mlxsw_sp_trap_group_items_arr_init(mlxsw_sp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < trap->groups_count; i++) {
|
||||
group_item = &trap->group_items_arr[i];
|
||||
@ -1189,7 +1241,7 @@ err_trap_group_register:
|
||||
group_item = &trap->group_items_arr[i];
|
||||
devlink_trap_groups_unregister(devlink, &group_item->group, 1);
|
||||
}
|
||||
kfree(trap->group_items_arr);
|
||||
mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1205,7 +1257,7 @@ static void mlxsw_sp_trap_groups_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
group_item = &trap->group_items_arr[i];
|
||||
devlink_trap_groups_unregister(devlink, &group_item->group, 1);
|
||||
}
|
||||
kfree(trap->group_items_arr);
|
||||
mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1214,6 +1266,43 @@ mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener *listener)
|
||||
return listener->trap_id != 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_trap_items_arr_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
size_t common_traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr);
|
||||
const struct mlxsw_sp_trap_item *spec_trap_items_arr;
|
||||
size_t elem_size = sizeof(struct mlxsw_sp_trap_item);
|
||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||
size_t traps_count, spec_traps_count;
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp->trap_ops->traps_init(mlxsw_sp, &spec_trap_items_arr,
|
||||
&spec_traps_count);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The trap items array is created by concatenating the common trap
|
||||
* items and the ASIC-specific trap items.
|
||||
*/
|
||||
traps_count = common_traps_count + spec_traps_count;
|
||||
trap->trap_items_arr = kcalloc(traps_count, elem_size, GFP_KERNEL);
|
||||
if (!trap->trap_items_arr)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(trap->trap_items_arr, mlxsw_sp_trap_items_arr,
|
||||
elem_size * common_traps_count);
|
||||
memcpy(trap->trap_items_arr + common_traps_count,
|
||||
spec_trap_items_arr, elem_size * spec_traps_count);
|
||||
|
||||
trap->traps_count = traps_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
kfree(mlxsw_sp->trap->trap_items_arr);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
@ -1221,13 +1310,9 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||
const struct mlxsw_sp_trap_item *trap_item;
|
||||
int err, i;
|
||||
|
||||
trap->trap_items_arr = kmemdup(mlxsw_sp_trap_items_arr,
|
||||
sizeof(mlxsw_sp_trap_items_arr),
|
||||
GFP_KERNEL);
|
||||
if (!trap->trap_items_arr)
|
||||
return -ENOMEM;
|
||||
|
||||
trap->traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr);
|
||||
err = mlxsw_sp_trap_items_arr_init(mlxsw_sp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < trap->traps_count; i++) {
|
||||
trap_item = &trap->trap_items_arr[i];
|
||||
@ -1244,7 +1329,7 @@ err_trap_register:
|
||||
trap_item = &trap->trap_items_arr[i];
|
||||
devlink_traps_unregister(devlink, &trap_item->trap, 1);
|
||||
}
|
||||
kfree(trap->trap_items_arr);
|
||||
mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1260,7 +1345,7 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
trap_item = &trap->trap_items_arr[i];
|
||||
devlink_traps_unregister(devlink, &trap_item->trap, 1);
|
||||
}
|
||||
kfree(trap->trap_items_arr);
|
||||
mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
|
||||
}
|
||||
|
||||
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||
@ -1352,7 +1437,8 @@ void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
|
||||
|
||||
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)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
|
||||
const struct mlxsw_sp_trap_item *trap_item;
|
||||
@ -1362,6 +1448,11 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
|
||||
if (WARN_ON(!trap_item))
|
||||
return -EINVAL;
|
||||
|
||||
if (trap_item->is_source) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changing the action of source traps is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) {
|
||||
const struct mlxsw_listener *listener;
|
||||
bool enabled;
|
||||
@ -1392,7 +1483,7 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
|
||||
static int
|
||||
__mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap_group *group,
|
||||
u32 policer_id)
|
||||
u32 policer_id, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
|
||||
u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
|
||||
@ -1403,6 +1494,11 @@ __mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
|
||||
if (WARN_ON(!group_item))
|
||||
return -EINVAL;
|
||||
|
||||
if (group_item->fixed_policer && policer_id != group->init_policer_id) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changing the policer binding of this group is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (policer_id) {
|
||||
struct mlxsw_sp_trap_policer_item *policer_item;
|
||||
|
||||
@ -1422,16 +1518,18 @@ 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);
|
||||
group->init_policer_id, NULL);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u32 policer_id = policer ? policer->id : 0;
|
||||
|
||||
return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id);
|
||||
return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id,
|
||||
extack);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1576,3 +1674,110 @@ mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
|
||||
bool *p_enabled, u16 *p_hw_id)
|
||||
{
|
||||
struct mlxsw_sp_trap_policer_item *pol_item;
|
||||
struct mlxsw_sp_trap_group_item *gr_item;
|
||||
u32 pol_id;
|
||||
|
||||
gr_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, id);
|
||||
if (!gr_item)
|
||||
return -ENOENT;
|
||||
|
||||
pol_id = gr_item->group.init_policer_id;
|
||||
if (!pol_id) {
|
||||
*p_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pol_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, pol_id);
|
||||
if (WARN_ON(!pol_item))
|
||||
return -ENOENT;
|
||||
|
||||
*p_enabled = true;
|
||||
*p_hw_id = pol_item->hw_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mlxsw_sp_trap_group_item
|
||||
mlxsw_sp1_trap_group_items_arr[] = {
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_trap_item
|
||||
mlxsw_sp1_trap_items_arr[] = {
|
||||
};
|
||||
|
||||
static int
|
||||
mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_group_item **arr,
|
||||
size_t *p_groups_count)
|
||||
{
|
||||
*arr = mlxsw_sp1_trap_group_items_arr;
|
||||
*p_groups_count = ARRAY_SIZE(mlxsw_sp1_trap_group_items_arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp1_traps_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_item **arr,
|
||||
size_t *p_traps_count)
|
||||
{
|
||||
*arr = mlxsw_sp1_trap_items_arr;
|
||||
*p_traps_count = ARRAY_SIZE(mlxsw_sp1_trap_items_arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = {
|
||||
.groups_init = mlxsw_sp1_trap_groups_init,
|
||||
.traps_init = mlxsw_sp1_traps_init,
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_trap_group_item
|
||||
mlxsw_sp2_trap_group_items_arr[] = {
|
||||
{
|
||||
.group = DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 20),
|
||||
.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,
|
||||
.priority = 0,
|
||||
.fixed_policer = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_trap_item
|
||||
mlxsw_sp2_trap_items_arr[] = {
|
||||
{
|
||||
.trap = MLXSW_SP_TRAP_BUFFER_DROP(EARLY_DROP),
|
||||
.listeners_arr = {
|
||||
MLXSW_SP_RXL_BUFFER_DISCARD(INGRESS_WRED),
|
||||
},
|
||||
.is_source = true,
|
||||
},
|
||||
};
|
||||
|
||||
static int
|
||||
mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_group_item **arr,
|
||||
size_t *p_groups_count)
|
||||
{
|
||||
*arr = mlxsw_sp2_trap_group_items_arr;
|
||||
*p_groups_count = ARRAY_SIZE(mlxsw_sp2_trap_group_items_arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp2_traps_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_item **arr,
|
||||
size_t *p_traps_count)
|
||||
{
|
||||
*arr = mlxsw_sp2_trap_items_arr;
|
||||
*p_traps_count = ARRAY_SIZE(mlxsw_sp2_trap_items_arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops = {
|
||||
.groups_init = mlxsw_sp2_trap_groups_init,
|
||||
.traps_init = mlxsw_sp2_traps_init,
|
||||
};
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
struct mlxsw_sp_trap {
|
||||
struct mlxsw_sp_trap_policer_item *policer_items_arr;
|
||||
u64 policers_count; /* Number of registered policers */
|
||||
size_t policers_count; /* Number of registered policers */
|
||||
|
||||
struct mlxsw_sp_trap_group_item *group_items_arr;
|
||||
u64 groups_count; /* Number of registered groups */
|
||||
size_t groups_count; /* Number of registered groups */
|
||||
|
||||
struct mlxsw_sp_trap_item *trap_items_arr;
|
||||
u64 traps_count; /* Number of registered traps */
|
||||
size_t traps_count; /* Number of registered traps */
|
||||
|
||||
u16 thin_policer_hw_id;
|
||||
|
||||
@ -23,4 +23,16 @@ struct mlxsw_sp_trap {
|
||||
unsigned long policers_usage[]; /* Usage bitmap */
|
||||
};
|
||||
|
||||
struct mlxsw_sp_trap_ops {
|
||||
int (*groups_init)(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_group_item **arr,
|
||||
size_t *p_groups_count);
|
||||
int (*traps_init)(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct mlxsw_sp_trap_item **arr,
|
||||
size_t *p_traps_count);
|
||||
};
|
||||
|
||||
extern const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops;
|
||||
extern const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops;
|
||||
|
||||
#endif
|
||||
|
@ -810,7 +810,8 @@ static int nsim_dev_devlink_trap_init(struct devlink *devlink,
|
||||
static int
|
||||
nsim_dev_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 nsim_dev *nsim_dev = devlink_priv(devlink);
|
||||
struct nsim_trap_item *nsim_trap_item;
|
||||
@ -829,7 +830,8 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink,
|
||||
static int
|
||||
nsim_dev_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 nsim_dev *nsim_dev = devlink_priv(devlink);
|
||||
|
||||
|
@ -703,6 +703,7 @@ enum devlink_trap_generic_id {
|
||||
DEVLINK_TRAP_GENERIC_ID_PTP_GENERAL,
|
||||
DEVLINK_TRAP_GENERIC_ID_FLOW_ACTION_SAMPLE,
|
||||
DEVLINK_TRAP_GENERIC_ID_FLOW_ACTION_TRAP,
|
||||
DEVLINK_TRAP_GENERIC_ID_EARLY_DROP,
|
||||
|
||||
/* Add new generic trap IDs above */
|
||||
__DEVLINK_TRAP_GENERIC_ID_MAX,
|
||||
@ -891,6 +892,8 @@ enum devlink_trap_group_generic_id {
|
||||
"flow_action_sample"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_FLOW_ACTION_TRAP \
|
||||
"flow_action_trap"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_EARLY_DROP \
|
||||
"early_drop"
|
||||
|
||||
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \
|
||||
"l2_drops"
|
||||
@ -1074,7 +1077,8 @@ struct devlink_ops {
|
||||
*/
|
||||
int (*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);
|
||||
/**
|
||||
* @trap_group_init: Trap group initialization function.
|
||||
*
|
||||
@ -1091,7 +1095,8 @@ struct devlink_ops {
|
||||
*/
|
||||
int (*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);
|
||||
/**
|
||||
* @trap_policer_init: Trap policer initialization function.
|
||||
*
|
||||
|
@ -6423,7 +6423,7 @@ static int __devlink_trap_action_set(struct devlink *devlink,
|
||||
}
|
||||
|
||||
err = devlink->ops->trap_action_set(devlink, trap_item->trap,
|
||||
trap_action);
|
||||
trap_action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -6713,7 +6713,8 @@ static int devlink_trap_group_set(struct devlink *devlink,
|
||||
}
|
||||
policer = policer_item ? policer_item->policer : NULL;
|
||||
|
||||
err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
|
||||
err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -8801,6 +8802,7 @@ static const struct devlink_trap devlink_trap_generic[] = {
|
||||
DEVLINK_TRAP(PTP_GENERAL, CONTROL),
|
||||
DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
|
||||
DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
|
||||
DEVLINK_TRAP(EARLY_DROP, DROP),
|
||||
};
|
||||
|
||||
#define DEVLINK_TRAP_GROUP(_id) \
|
||||
@ -9050,7 +9052,8 @@ static void devlink_trap_disable(struct devlink *devlink,
|
||||
if (WARN_ON_ONCE(!trap_item))
|
||||
return;
|
||||
|
||||
devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP);
|
||||
devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
|
||||
NULL);
|
||||
trap_item->action = DEVLINK_TRAP_ACTION_DROP;
|
||||
}
|
||||
|
||||
|
@ -568,17 +568,12 @@ do_drop_test()
|
||||
busywait 1100 until_counter_is ">= $((base + 1))" $fetch_counter >/dev/null
|
||||
check_fail $? "Spurious packets observed without buffer pressure"
|
||||
|
||||
qevent_rule_uninstall_$subtest
|
||||
|
||||
# Push to the queue until it's at the limit. The configured limit is
|
||||
# rounded by the qdisc and then by the driver, so this is the best we
|
||||
# can do to get to the real limit of the system. Do this with the rules
|
||||
# uninstalled so that the inevitable drops don't get counted.
|
||||
# can do to get to the real limit of the system.
|
||||
build_backlog $vlan $((3 * limit / 2)) udp >/dev/null
|
||||
|
||||
qevent_rule_install_$subtest
|
||||
base=$($fetch_counter)
|
||||
|
||||
send_packets $vlan udp 11
|
||||
|
||||
now=$(busywait 1100 until_counter_is ">= $((base + 10))" $fetch_counter)
|
||||
@ -631,3 +626,31 @@ do_drop_mirror_test()
|
||||
|
||||
tc filter del dev $h2 ingress pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
qevent_rule_install_trap()
|
||||
{
|
||||
tc filter add block 10 pref 1234 handle 102 matchall skip_sw \
|
||||
action trap hw_stats disabled
|
||||
}
|
||||
|
||||
qevent_rule_uninstall_trap()
|
||||
{
|
||||
tc filter del block 10 pref 1234 handle 102 matchall
|
||||
}
|
||||
|
||||
qevent_counter_fetch_trap()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
|
||||
devlink_trap_rx_packets_get "$trap_name"
|
||||
}
|
||||
|
||||
do_drop_trap_test()
|
||||
{
|
||||
local vlan=$1; shift
|
||||
local limit=$1; shift
|
||||
local trap_name=$1; shift
|
||||
|
||||
do_drop_test "$vlan" "$limit" "$trap_name" trap \
|
||||
"qevent_counter_fetch_trap $trap_name"
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ ALL_TESTS="
|
||||
red_test
|
||||
mc_backlog_test
|
||||
red_mirror_test
|
||||
red_trap_test
|
||||
"
|
||||
: ${QDISC:=ets}
|
||||
source sch_red_core.sh
|
||||
@ -94,6 +95,16 @@ red_mirror_test()
|
||||
uninstall_qdisc
|
||||
}
|
||||
|
||||
red_trap_test()
|
||||
{
|
||||
install_qdisc qevent early_drop block 10
|
||||
|
||||
do_drop_trap_test 10 $BACKLOG1 early_drop
|
||||
do_drop_trap_test 11 $BACKLOG2 early_drop
|
||||
|
||||
uninstall_qdisc
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
|
Loading…
x
Reference in New Issue
Block a user