Merge branch 'mlxsw-Add-devlink-trap-support'
Ido Schimmel says: ==================== mlxsw: Add devlink-trap support This patchset adds devlink-trap support in mlxsw. Patches #1-#4 add the necessary APIs and defines in mlxsw. Patch #5 implements devlink-trap support for layer 2 drops. More drops will be added in the future. Patches #6-#7 add selftests to make sure that all the new code paths are exercised and that the feature is working as expected. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
3a76edf28a
@ -29,7 +29,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
|
||||
spectrum_mr_tcam.o spectrum_mr.o \
|
||||
spectrum_qdisc.o spectrum_span.o \
|
||||
spectrum_nve.o spectrum_nve_vxlan.o \
|
||||
spectrum_dpipe.o
|
||||
spectrum_dpipe.o spectrum_trap.o
|
||||
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o
|
||||
mlxsw_spectrum-$(CONFIG_PTP_1588_CLOCK) += spectrum_ptp.o
|
||||
obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o
|
||||
|
@ -1017,6 +1017,54 @@ static int mlxsw_devlink_flash_update(struct devlink *devlink,
|
||||
component, extack);
|
||||
}
|
||||
|
||||
static int mlxsw_devlink_trap_init(struct devlink *devlink,
|
||||
const struct devlink_trap *trap,
|
||||
void *trap_ctx)
|
||||
{
|
||||
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
|
||||
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
|
||||
|
||||
if (!mlxsw_driver->trap_init)
|
||||
return -EOPNOTSUPP;
|
||||
return mlxsw_driver->trap_init(mlxsw_core, trap, trap_ctx);
|
||||
}
|
||||
|
||||
static void mlxsw_devlink_trap_fini(struct devlink *devlink,
|
||||
const struct devlink_trap *trap,
|
||||
void *trap_ctx)
|
||||
{
|
||||
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
|
||||
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
|
||||
|
||||
if (!mlxsw_driver->trap_fini)
|
||||
return;
|
||||
mlxsw_driver->trap_fini(mlxsw_core, trap, trap_ctx);
|
||||
}
|
||||
|
||||
static int mlxsw_devlink_trap_action_set(struct devlink *devlink,
|
||||
const struct devlink_trap *trap,
|
||||
enum devlink_trap_action action)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_devlink_trap_group_init(struct devlink *devlink,
|
||||
const struct devlink_trap_group *group)
|
||||
{
|
||||
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
|
||||
struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
|
||||
|
||||
if (!mlxsw_driver->trap_group_init)
|
||||
return -EOPNOTSUPP;
|
||||
return mlxsw_driver->trap_group_init(mlxsw_core, group);
|
||||
}
|
||||
|
||||
static const struct devlink_ops mlxsw_devlink_ops = {
|
||||
.reload = mlxsw_devlink_core_bus_device_reload,
|
||||
.port_type_set = mlxsw_devlink_port_type_set,
|
||||
@ -1034,6 +1082,10 @@ static const struct devlink_ops mlxsw_devlink_ops = {
|
||||
.sb_occ_tc_port_bind_get = mlxsw_devlink_sb_occ_tc_port_bind_get,
|
||||
.info_get = mlxsw_devlink_info_get,
|
||||
.flash_update = mlxsw_devlink_flash_update,
|
||||
.trap_init = mlxsw_devlink_trap_init,
|
||||
.trap_fini = mlxsw_devlink_trap_fini,
|
||||
.trap_action_set = mlxsw_devlink_trap_action_set,
|
||||
.trap_group_init = mlxsw_devlink_trap_group_init,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -1477,6 +1529,18 @@ 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,
|
||||
const struct mlxsw_listener *listener,
|
||||
enum mlxsw_reg_hpkt_action action)
|
||||
{
|
||||
char hpkt_pl[MLXSW_REG_HPKT_LEN];
|
||||
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_core_trap_action_set);
|
||||
|
||||
static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
|
||||
{
|
||||
return atomic64_inc_return(&mlxsw_core->emad.tid);
|
||||
|
@ -128,6 +128,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,
|
||||
const struct mlxsw_listener *listener,
|
||||
enum mlxsw_reg_hpkt_action action);
|
||||
|
||||
typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
|
||||
size_t payload_len, unsigned long cb_priv);
|
||||
@ -289,6 +292,15 @@ struct mlxsw_driver {
|
||||
int (*flash_update)(struct mlxsw_core *mlxsw_core,
|
||||
const char *file_name, const char *component,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*trap_init)(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap *trap, void *trap_ctx);
|
||||
void (*trap_fini)(struct mlxsw_core *mlxsw_core,
|
||||
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);
|
||||
int (*trap_group_init)(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap_group *group);
|
||||
void (*txhdr_construct)(struct sk_buff *skb,
|
||||
const struct mlxsw_tx_info *tx_info);
|
||||
int (*resources_register)(struct mlxsw_core *mlxsw_core);
|
||||
|
@ -5422,6 +5422,14 @@ enum mlxsw_reg_htgt_trap_group {
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
|
||||
|
||||
__MLXSW_REG_HTGT_TRAP_GROUP_MAX,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
|
||||
};
|
||||
|
||||
enum mlxsw_reg_htgt_discard_trap_group {
|
||||
MLXSW_REG_HTGT_DISCARD_TRAP_GROUP_BASE = MLXSW_REG_HTGT_TRAP_GROUP_MAX,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
|
||||
};
|
||||
|
||||
/* reg_htgt_trap_group
|
||||
@ -5559,6 +5567,8 @@ enum mlxsw_reg_hpkt_action {
|
||||
MLXSW_REG_HPKT_ACTION_DISCARD,
|
||||
MLXSW_REG_HPKT_ACTION_SOFT_DISCARD,
|
||||
MLXSW_REG_HPKT_ACTION_TRAP_AND_SOFT_DISCARD,
|
||||
MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU,
|
||||
MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT = 15,
|
||||
};
|
||||
|
||||
/* reg_hpkt_action
|
||||
@ -5569,6 +5579,8 @@ enum mlxsw_reg_hpkt_action {
|
||||
* 3 - Discard.
|
||||
* 4 - Soft discard (allow other traps to act on the packet).
|
||||
* 5 - Trap and soft discard (allow other traps to overwrite this trap).
|
||||
* 6 - Trap to CPU (CPU receives sole copy) and count it as error.
|
||||
* 15 - Restore the firmware's default action.
|
||||
* Access: RW
|
||||
*
|
||||
* Note: Must be set to 0 (forward) for event trap IDs, as they are already
|
||||
|
@ -4665,6 +4665,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
|
||||
goto err_traps_init;
|
||||
}
|
||||
|
||||
err = mlxsw_sp_devlink_traps_init(mlxsw_sp);
|
||||
if (err) {
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize devlink traps\n");
|
||||
goto err_devlink_traps_init;
|
||||
}
|
||||
|
||||
err = mlxsw_sp_buffers_init(mlxsw_sp);
|
||||
if (err) {
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n");
|
||||
@ -4798,6 +4804,8 @@ err_span_init:
|
||||
err_lag_init:
|
||||
mlxsw_sp_buffers_fini(mlxsw_sp);
|
||||
err_buffers_init:
|
||||
mlxsw_sp_devlink_traps_fini(mlxsw_sp);
|
||||
err_devlink_traps_init:
|
||||
mlxsw_sp_traps_fini(mlxsw_sp);
|
||||
err_traps_init:
|
||||
mlxsw_sp_fids_fini(mlxsw_sp);
|
||||
@ -4870,6 +4878,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
|
||||
mlxsw_sp_span_fini(mlxsw_sp);
|
||||
mlxsw_sp_lag_fini(mlxsw_sp);
|
||||
mlxsw_sp_buffers_fini(mlxsw_sp);
|
||||
mlxsw_sp_devlink_traps_fini(mlxsw_sp);
|
||||
mlxsw_sp_traps_fini(mlxsw_sp);
|
||||
mlxsw_sp_fids_fini(mlxsw_sp);
|
||||
mlxsw_sp_kvdl_fini(mlxsw_sp);
|
||||
@ -5251,6 +5260,10 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
|
||||
.sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get,
|
||||
.sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get,
|
||||
.flash_update = mlxsw_sp_flash_update,
|
||||
.trap_init = mlxsw_sp_trap_init,
|
||||
.trap_fini = mlxsw_sp_trap_fini,
|
||||
.trap_action_set = mlxsw_sp_trap_action_set,
|
||||
.trap_group_init = mlxsw_sp_trap_group_init,
|
||||
.txhdr_construct = mlxsw_sp_txhdr_construct,
|
||||
.resources_register = mlxsw_sp1_resources_register,
|
||||
.kvd_sizes_get = mlxsw_sp_kvd_sizes_get,
|
||||
@ -5281,6 +5294,10 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
|
||||
.sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get,
|
||||
.sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get,
|
||||
.flash_update = mlxsw_sp_flash_update,
|
||||
.trap_init = mlxsw_sp_trap_init,
|
||||
.trap_fini = mlxsw_sp_trap_fini,
|
||||
.trap_action_set = mlxsw_sp_trap_action_set,
|
||||
.trap_group_init = mlxsw_sp_trap_group_init,
|
||||
.txhdr_construct = mlxsw_sp_txhdr_construct,
|
||||
.resources_register = mlxsw_sp2_resources_register,
|
||||
.params_register = mlxsw_sp2_params_register,
|
||||
@ -5310,6 +5327,10 @@ static struct mlxsw_driver mlxsw_sp3_driver = {
|
||||
.sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get,
|
||||
.sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get,
|
||||
.flash_update = mlxsw_sp_flash_update,
|
||||
.trap_init = mlxsw_sp_trap_init,
|
||||
.trap_fini = mlxsw_sp_trap_fini,
|
||||
.trap_action_set = mlxsw_sp_trap_action_set,
|
||||
.trap_group_init = mlxsw_sp_trap_group_init,
|
||||
.txhdr_construct = mlxsw_sp_txhdr_construct,
|
||||
.resources_register = mlxsw_sp2_resources_register,
|
||||
.params_register = mlxsw_sp2_params_register,
|
||||
|
@ -958,4 +958,17 @@ void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp);
|
||||
int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp);
|
||||
void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp);
|
||||
|
||||
/* spectrum_trap.c */
|
||||
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp);
|
||||
void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp);
|
||||
int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap *trap, void *trap_ctx);
|
||||
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);
|
||||
int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap_group *group);
|
||||
|
||||
#endif
|
||||
|
267
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
Normal file
267
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
Normal file
@ -0,0 +1,267 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
/* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <net/devlink.h>
|
||||
#include <uapi/linux/devlink.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "reg.h"
|
||||
#include "spectrum.h"
|
||||
|
||||
#define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
|
||||
|
||||
static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
|
||||
void *priv);
|
||||
|
||||
#define MLXSW_SP_TRAP_DROP(_id, _group_id) \
|
||||
DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
|
||||
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
|
||||
MLXSW_SP_TRAP_METADATA)
|
||||
|
||||
#define MLXSW_SP_RXL_DISCARD(_id, _group_id) \
|
||||
MLXSW_RXL(mlxsw_sp_rx_drop_listener, DISCARD_##_id, SET_FW_DEFAULT, \
|
||||
false, SP_##_group_id, DISCARD)
|
||||
|
||||
static struct devlink_trap mlxsw_sp_traps_arr[] = {
|
||||
MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
|
||||
};
|
||||
|
||||
static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
|
||||
MLXSW_SP_RXL_DISCARD(ING_PACKET_SMAC_MC, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_SWITCH_VTAG_ALLOW, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_SWITCH_VLAN, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_SWITCH_STP, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS),
|
||||
};
|
||||
|
||||
/* Mapping between hardware trap and devlink trap. Multiple hardware traps can
|
||||
* be mapped to the same devlink trap. Order is according to
|
||||
* 'mlxsw_sp_listeners_arr'.
|
||||
*/
|
||||
static u16 mlxsw_sp_listener_devlink_map[] = {
|
||||
DEVLINK_TRAP_GENERIC_ID_SMAC_MC,
|
||||
DEVLINK_TRAP_GENERIC_ID_VLAN_TAG_MISMATCH,
|
||||
DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER,
|
||||
DEVLINK_TRAP_GENERIC_ID_INGRESS_STP_FILTER,
|
||||
DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
|
||||
DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
|
||||
DEVLINK_TRAP_GENERIC_ID_PORT_LOOPBACK_FILTER,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
|
||||
|
||||
if (unlikely(!mlxsw_sp_port)) {
|
||||
dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
|
||||
local_port);
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb->dev = mlxsw_sp_port->dev;
|
||||
|
||||
pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
|
||||
u64_stats_update_begin(&pcpu_stats->syncp);
|
||||
pcpu_stats->rx_packets++;
|
||||
pcpu_stats->rx_bytes += skb->len;
|
||||
u64_stats_update_end(&pcpu_stats->syncp);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
|
||||
void *trap_ctx)
|
||||
{
|
||||
struct devlink_port *in_devlink_port;
|
||||
struct mlxsw_sp_port *mlxsw_sp_port;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
struct devlink *devlink;
|
||||
|
||||
mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
|
||||
mlxsw_sp_port = mlxsw_sp->ports[local_port];
|
||||
|
||||
if (mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port))
|
||||
return;
|
||||
|
||||
devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
|
||||
local_port);
|
||||
devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port);
|
||||
consume_skb(skb);
|
||||
}
|
||||
|
||||
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
|
||||
if (WARN_ON(ARRAY_SIZE(mlxsw_sp_listener_devlink_map) !=
|
||||
ARRAY_SIZE(mlxsw_sp_listeners_arr)))
|
||||
return -EINVAL;
|
||||
|
||||
return devlink_traps_register(devlink, mlxsw_sp_traps_arr,
|
||||
ARRAY_SIZE(mlxsw_sp_traps_arr),
|
||||
mlxsw_sp);
|
||||
}
|
||||
|
||||
void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
|
||||
devlink_traps_unregister(devlink, mlxsw_sp_traps_arr,
|
||||
ARRAY_SIZE(mlxsw_sp_traps_arr));
|
||||
}
|
||||
|
||||
int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap *trap, void *trap_ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
|
||||
struct mlxsw_listener *listener;
|
||||
int err;
|
||||
|
||||
if (mlxsw_sp_listener_devlink_map[i] != trap->id)
|
||||
continue;
|
||||
listener = &mlxsw_sp_listeners_arr[i];
|
||||
|
||||
err = mlxsw_core_trap_register(mlxsw_core, listener, trap_ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap *trap, void *trap_ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
|
||||
struct mlxsw_listener *listener;
|
||||
|
||||
if (mlxsw_sp_listener_devlink_map[i] != trap->id)
|
||||
continue;
|
||||
listener = &mlxsw_sp_listeners_arr[i];
|
||||
|
||||
mlxsw_core_trap_unregister(mlxsw_core, listener, trap_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
|
||||
const struct devlink_trap *trap,
|
||||
enum devlink_trap_action action)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
|
||||
enum mlxsw_reg_hpkt_action hw_action;
|
||||
struct mlxsw_listener *listener;
|
||||
int err;
|
||||
|
||||
if (mlxsw_sp_listener_devlink_map[i] != trap->id)
|
||||
continue;
|
||||
listener = &mlxsw_sp_listeners_arr[i];
|
||||
|
||||
switch (action) {
|
||||
case DEVLINK_TRAP_ACTION_DROP:
|
||||
hw_action = MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT;
|
||||
break;
|
||||
case DEVLINK_TRAP_ACTION_TRAP:
|
||||
hw_action = MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = mlxsw_core_trap_action_set(mlxsw_core, listener,
|
||||
hw_action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MLXSW_SP_DISCARD_POLICER_ID (MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
|
||||
|
||||
static int
|
||||
mlxsw_sp_trap_group_policer_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct devlink_trap_group *group)
|
||||
{
|
||||
enum mlxsw_reg_qpcr_ir_units ir_units;
|
||||
char qpcr_pl[MLXSW_REG_QPCR_LEN];
|
||||
u16 policer_id;
|
||||
u8 burst_size;
|
||||
bool is_bytes;
|
||||
u32 rate;
|
||||
|
||||
switch (group->id) {
|
||||
case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS:
|
||||
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
|
||||
ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
|
||||
is_bytes = false;
|
||||
rate = 10 * 1024; /* 10Kpps */
|
||||
burst_size = 7;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mlxsw_reg_qpcr_pack(qpcr_pl, policer_id, ir_units, is_bytes, rate,
|
||||
burst_size);
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
|
||||
}
|
||||
|
||||
static int
|
||||
__mlxsw_sp_trap_group_init(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct devlink_trap_group *group)
|
||||
{
|
||||
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;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mlxsw_reg_htgt_pack(htgt_pl, group_id, policer_id, priority, tc);
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
|
||||
}
|
||||
|
||||
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);
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp_trap_group_policer_init(mlxsw_sp, group);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = __mlxsw_sp_trap_group_init(mlxsw_sp, group);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
@ -66,6 +66,13 @@ enum {
|
||||
MLXSW_TRAP_ID_NVE_ENCAP_ARP = 0xBD,
|
||||
MLXSW_TRAP_ID_ROUTER_ALERT_IPV4 = 0xD6,
|
||||
MLXSW_TRAP_ID_ROUTER_ALERT_IPV6 = 0xD7,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_PACKET_SMAC_MC = 0x140,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VTAG_ALLOW = 0x148,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VLAN = 0x149,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_SWITCH_STP = 0x14A,
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_UC = 0x150,
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_MC_NULL = 0x151,
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_LB = 0x152,
|
||||
MLXSW_TRAP_ID_ACL0 = 0x1C0,
|
||||
/* Multicast trap used for routes with trap action */
|
||||
MLXSW_TRAP_ID_ACL1 = 0x1C1,
|
||||
|
129
tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh
Executable file
129
tools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh
Executable file
@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Test generic devlink-trap functionality over mlxsw. These tests are not
|
||||
# specific to a single trap, but do not check the devlink-trap common
|
||||
# infrastructure either.
|
||||
|
||||
lib_dir=$(dirname $0)/../../../net/forwarding
|
||||
|
||||
ALL_TESTS="
|
||||
dev_del_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
|
||||
}
|
||||
|
||||
h1_destroy()
|
||||
{
|
||||
simple_if_fini $h1
|
||||
}
|
||||
|
||||
h2_create()
|
||||
{
|
||||
simple_if_init $h2
|
||||
}
|
||||
|
||||
h2_destroy()
|
||||
{
|
||||
simple_if_fini $h2
|
||||
}
|
||||
|
||||
switch_create()
|
||||
{
|
||||
ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
|
||||
|
||||
ip link set dev $swp1 master br0
|
||||
ip link set dev $swp2 master br0
|
||||
|
||||
ip link set dev br0 up
|
||||
ip link set dev $swp1 up
|
||||
ip link set dev $swp2 up
|
||||
}
|
||||
|
||||
switch_destroy()
|
||||
{
|
||||
ip link set dev $swp2 down
|
||||
ip link set dev $swp1 down
|
||||
|
||||
ip link del dev br0
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
swp1=${NETIFS[p2]}
|
||||
|
||||
swp2=${NETIFS[p3]}
|
||||
h2=${NETIFS[p4]}
|
||||
|
||||
vrf_prepare
|
||||
|
||||
h1_create
|
||||
h2_create
|
||||
|
||||
switch_create
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
||||
switch_destroy
|
||||
|
||||
h2_destroy
|
||||
h1_destroy
|
||||
|
||||
vrf_cleanup
|
||||
}
|
||||
|
||||
dev_del_test()
|
||||
{
|
||||
local trap_name="source_mac_is_multicast"
|
||||
local smac=01:02:03:04:05:06
|
||||
local num_iter=5
|
||||
local mz_pid
|
||||
local i
|
||||
|
||||
$MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -q &
|
||||
mz_pid=$!
|
||||
|
||||
# The purpose of this test is to make sure we correctly dismantle a
|
||||
# port while packets are trapped from it. This is done by reloading the
|
||||
# the driver while the 'ingress_smac_mc_drop' trap is triggered.
|
||||
RET=0
|
||||
|
||||
for i in $(seq 1 $num_iter); do
|
||||
log_info "Iteration $i / $num_iter"
|
||||
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
sleep 1
|
||||
|
||||
devlink_reload
|
||||
# Allow netdevices to be re-created following the reload
|
||||
sleep 20
|
||||
|
||||
cleanup
|
||||
setup_prepare
|
||||
setup_wait
|
||||
done
|
||||
|
||||
log_test "Device delete"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
484
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh
Executable file
484
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh
Executable file
@ -0,0 +1,484 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Test devlink-trap L2 drops functionality over mlxsw. Each registered L2 drop
|
||||
# packet trap is tested to make sure it is triggered under the right
|
||||
# conditions.
|
||||
|
||||
lib_dir=$(dirname $0)/../../../net/forwarding
|
||||
|
||||
ALL_TESTS="
|
||||
source_mac_is_multicast_test
|
||||
vlan_tag_mismatch_test
|
||||
ingress_vlan_filter_test
|
||||
ingress_stp_filter_test
|
||||
port_list_is_empty_test
|
||||
port_loopback_filter_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
|
||||
}
|
||||
|
||||
h1_destroy()
|
||||
{
|
||||
simple_if_fini $h1
|
||||
}
|
||||
|
||||
h2_create()
|
||||
{
|
||||
simple_if_init $h2
|
||||
}
|
||||
|
||||
h2_destroy()
|
||||
{
|
||||
simple_if_fini $h2
|
||||
}
|
||||
|
||||
switch_create()
|
||||
{
|
||||
ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
|
||||
|
||||
ip link set dev $swp1 master br0
|
||||
ip link set dev $swp2 master br0
|
||||
|
||||
ip link set dev br0 up
|
||||
ip link set dev $swp1 up
|
||||
ip link set dev $swp2 up
|
||||
|
||||
tc qdisc add dev $swp2 clsact
|
||||
}
|
||||
|
||||
switch_destroy()
|
||||
{
|
||||
tc qdisc del dev $swp2 clsact
|
||||
|
||||
ip link set dev $swp2 down
|
||||
ip link set dev $swp1 down
|
||||
|
||||
ip link del dev br0
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
swp1=${NETIFS[p2]}
|
||||
|
||||
swp2=${NETIFS[p3]}
|
||||
h2=${NETIFS[p4]}
|
||||
|
||||
vrf_prepare
|
||||
|
||||
h1_create
|
||||
h2_create
|
||||
|
||||
switch_create
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
||||
switch_destroy
|
||||
|
||||
h2_destroy
|
||||
h1_destroy
|
||||
|
||||
vrf_cleanup
|
||||
}
|
||||
|
||||
l2_drops_test()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
local group_name=$1; shift
|
||||
|
||||
# This is the common part of all the tests. It checks that stats are
|
||||
# initially idle, then non-idle after changing the trap action and
|
||||
# finally idle again. It also makes sure the packets are dropped and
|
||||
# never forwarded.
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle with initial drop action"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with initial drop action"
|
||||
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_fail $? "Trap stats idle after setting action to trap"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_fail $? "Trap group stats idle after setting action to trap"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle after setting action to drop"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle after setting action to drop"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_err $? "Packets were not dropped"
|
||||
}
|
||||
|
||||
l2_drops_cleanup()
|
||||
{
|
||||
local mz_pid=$1; shift
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
source_mac_is_multicast_test()
|
||||
{
|
||||
local trap_name="source_mac_is_multicast"
|
||||
local smac=01:02:03:04:05:06
|
||||
local group_name="l2_drops"
|
||||
local mz_pid
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower src_mac $smac action drop
|
||||
|
||||
$MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
RET=0
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
log_test "Source MAC is multicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
}
|
||||
|
||||
__vlan_tag_mismatch_test()
|
||||
{
|
||||
local trap_name="vlan_tag_mismatch"
|
||||
local dmac=de:ad:be:ef:13:37
|
||||
local group_name="l2_drops"
|
||||
local opt=$1; shift
|
||||
local mz_pid
|
||||
|
||||
# Remove PVID flag. This should prevent untagged and prio-tagged
|
||||
# packets from entering the bridge.
|
||||
bridge vlan add vid 1 dev $swp1 untagged master
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Add PVID and make sure packets are no longer dropped.
|
||||
bridge vlan add vid 1 dev $swp1 pvid untagged master
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
}
|
||||
|
||||
vlan_tag_mismatch_untagged_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
__vlan_tag_mismatch_test
|
||||
|
||||
log_test "VLAN tag mismatch - untagged packets"
|
||||
}
|
||||
|
||||
vlan_tag_mismatch_vid_0_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
__vlan_tag_mismatch_test "-Q 0"
|
||||
|
||||
log_test "VLAN tag mismatch - prio-tagged packets"
|
||||
}
|
||||
|
||||
vlan_tag_mismatch_test()
|
||||
{
|
||||
vlan_tag_mismatch_untagged_test
|
||||
vlan_tag_mismatch_vid_0_test
|
||||
}
|
||||
|
||||
ingress_vlan_filter_test()
|
||||
{
|
||||
local trap_name="ingress_vlan_filter"
|
||||
local dmac=de:ad:be:ef:13:37
|
||||
local group_name="l2_drops"
|
||||
local mz_pid
|
||||
local vid=10
|
||||
|
||||
bridge vlan add vid $vid dev $swp2 master
|
||||
# During initialization the firmware enables all the VLAN filters and
|
||||
# the driver does not turn them off since the traffic will be discarded
|
||||
# by the STP filter whose default is DISCARD state. Add the VID on the
|
||||
# ingress bridge port and then remove it to make sure it is not member
|
||||
# in the VLAN.
|
||||
bridge vlan add vid $vid dev $swp1 master
|
||||
bridge vlan del vid $vid dev $swp1 master
|
||||
|
||||
RET=0
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Add the VLAN on the bridge port and make sure packets are no longer
|
||||
# dropped.
|
||||
bridge vlan add vid $vid dev $swp1 master
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
log_test "Ingress VLAN filter"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
|
||||
bridge vlan del vid $vid dev $swp1 master
|
||||
bridge vlan del vid $vid dev $swp2 master
|
||||
}
|
||||
|
||||
__ingress_stp_filter_test()
|
||||
{
|
||||
local trap_name="ingress_spanning_tree_filter"
|
||||
local dmac=de:ad:be:ef:13:37
|
||||
local group_name="l2_drops"
|
||||
local state=$1; shift
|
||||
local mz_pid
|
||||
local vid=20
|
||||
|
||||
bridge vlan add vid $vid dev $swp2 master
|
||||
bridge vlan add vid $vid dev $swp1 master
|
||||
ip link set dev $swp1 type bridge_slave state $state
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Change STP state to forwarding and make sure packets are no longer
|
||||
# dropped.
|
||||
ip link set dev $swp1 type bridge_slave state 3
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
|
||||
bridge vlan del vid $vid dev $swp1 master
|
||||
bridge vlan del vid $vid dev $swp2 master
|
||||
}
|
||||
|
||||
ingress_stp_filter_listening_test()
|
||||
{
|
||||
local state=$1; shift
|
||||
|
||||
RET=0
|
||||
|
||||
__ingress_stp_filter_test $state
|
||||
|
||||
log_test "Ingress STP filter - listening state"
|
||||
}
|
||||
|
||||
ingress_stp_filter_learning_test()
|
||||
{
|
||||
local state=$1; shift
|
||||
|
||||
RET=0
|
||||
|
||||
__ingress_stp_filter_test $state
|
||||
|
||||
log_test "Ingress STP filter - learning state"
|
||||
}
|
||||
|
||||
ingress_stp_filter_test()
|
||||
{
|
||||
ingress_stp_filter_listening_test 1
|
||||
ingress_stp_filter_learning_test 2
|
||||
}
|
||||
|
||||
port_list_is_empty_uc_test()
|
||||
{
|
||||
local trap_name="port_list_is_empty"
|
||||
local dmac=de:ad:be:ef:13:37
|
||||
local group_name="l2_drops"
|
||||
local mz_pid
|
||||
|
||||
# Disable unicast flooding on both ports, so that packets cannot egress
|
||||
# any port.
|
||||
ip link set dev $swp1 type bridge_slave flood off
|
||||
ip link set dev $swp2 type bridge_slave flood off
|
||||
|
||||
RET=0
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Allow packets to be flooded to one port.
|
||||
ip link set dev $swp2 type bridge_slave flood on
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
log_test "Port list is empty - unicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
|
||||
ip link set dev $swp1 type bridge_slave flood on
|
||||
}
|
||||
|
||||
port_list_is_empty_mc_test()
|
||||
{
|
||||
local trap_name="port_list_is_empty"
|
||||
local dmac=01:00:5e:00:00:01
|
||||
local group_name="l2_drops"
|
||||
local dip=239.0.0.1
|
||||
local mz_pid
|
||||
|
||||
# Disable multicast flooding on both ports, so that packets cannot
|
||||
# egress any port. We also need to flush IP addresses from the bridge
|
||||
# in order to prevent packets from being flooded to the router port.
|
||||
ip link set dev $swp1 type bridge_slave mcast_flood off
|
||||
ip link set dev $swp2 type bridge_slave mcast_flood off
|
||||
ip address flush dev br0
|
||||
|
||||
RET=0
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Allow packets to be flooded to one port.
|
||||
ip link set dev $swp2 type bridge_slave mcast_flood on
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
log_test "Port list is empty - multicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
|
||||
ip link set dev $swp1 type bridge_slave mcast_flood on
|
||||
}
|
||||
|
||||
port_list_is_empty_test()
|
||||
{
|
||||
port_list_is_empty_uc_test
|
||||
port_list_is_empty_mc_test
|
||||
}
|
||||
|
||||
port_loopback_filter_uc_test()
|
||||
{
|
||||
local trap_name="port_loopback_filter"
|
||||
local dmac=de:ad:be:ef:13:37
|
||||
local group_name="l2_drops"
|
||||
local mz_pid
|
||||
|
||||
# Make sure packets can only egress the input port.
|
||||
ip link set dev $swp2 type bridge_slave flood off
|
||||
|
||||
RET=0
|
||||
|
||||
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_mac $dmac action drop
|
||||
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
|
||||
# Allow packets to be flooded.
|
||||
ip link set dev $swp2 type bridge_slave flood on
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle when packets should not be dropped"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with when packets should not be dropped"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_fail $? "Packets not forwarded when should"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
log_test "Port loopback filter - unicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
}
|
||||
|
||||
port_loopback_filter_test()
|
||||
{
|
||||
port_loopback_filter_uc_test
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
Loading…
x
Reference in New Issue
Block a user