Commit 0cb9ed57 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mlxsw-add-802-1x-and-mab-offload-support'

Petr Machata says:

====================
mlxsw: Add 802.1X and MAB offload support

This patchset adds 802.1X [1] and MAB [2] offload support in mlxsw.

Patches #1-#3 add the required switchdev interfaces.

Patches #4-#5 add the required packet traps for 802.1X.

Patches #6-#10 are small preparations in mlxsw.

Patch #11 adds locked bridge port support in mlxsw.

Patches #12-#15 add mlxsw selftests. The patchset was also tested with
the generic forwarding selftest ('bridge_locked_port.sh').

[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=a21d9a670d81103db7f788de1a4a4a6e4b891a0b
[2] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=a35ec8e38cdd1766f29924ca391a01de20163931
====================

Link: https://lore.kernel.org/r/cover.1667902754.git.petrm@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents bf9b8556 cdbde7ed
...@@ -485,6 +485,16 @@ be added to the following table: ...@@ -485,6 +485,16 @@ be added to the following table:
- Traps incoming packets that the device decided to drop because - Traps incoming packets that the device decided to drop because
the destination MAC is not configured in the MAC table and the destination MAC is not configured in the MAC table and
the interface is not in promiscuous mode the interface is not in promiscuous mode
* - ``eapol``
- ``control``
- Traps "Extensible Authentication Protocol over LAN" (EAPOL) packets
specified in IEEE 802.1X
* - ``locked_port``
- ``drop``
- Traps packets that the device decided to drop because they failed the
locked bridge port check. That is, packets that were received via a
locked port and whose {SMAC, VID} does not correspond to an FDB entry
pointing to the port
Driver-specific Packet Traps Driver-specific Packet Traps
============================ ============================
...@@ -589,6 +599,9 @@ narrow. The description of these groups must be added to the following table: ...@@ -589,6 +599,9 @@ narrow. The description of these groups must be added to the following table:
* - ``parser_error_drops`` * - ``parser_error_drops``
- Contains packet traps for packets that were marked by the device during - Contains packet traps for packets that were marked by the device during
parsing as erroneous parsing as erroneous
* - ``eapol``
- Contains packet traps for "Extensible Authentication Protocol over LAN"
(EAPOL) packets specified in IEEE 802.1X
Packet Trap Policers Packet Trap Policers
==================== ====================
......
...@@ -2046,6 +2046,39 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u16 local_port, ...@@ -2046,6 +2046,39 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u16 local_port,
} }
} }
/* SPFSR - Switch Port FDB Security Register
* -----------------------------------------
* Configures the security mode per port.
*/
#define MLXSW_REG_SPFSR_ID 0x2023
#define MLXSW_REG_SPFSR_LEN 0x08
MLXSW_REG_DEFINE(spfsr, MLXSW_REG_SPFSR_ID, MLXSW_REG_SPFSR_LEN);
/* reg_spfsr_local_port
* Local port.
* Access: Index
*
* Note: not supported for CPU port.
*/
MLXSW_ITEM32_LP(reg, spfsr, 0x00, 16, 0x00, 12);
/* reg_spfsr_security
* Security checks.
* 0: disabled (default)
* 1: enabled
* Access: RW
*/
MLXSW_ITEM32(reg, spfsr, security, 0x04, 31, 1);
static inline void mlxsw_reg_spfsr_pack(char *payload, u16 local_port,
bool security)
{
MLXSW_REG_ZERO(spfsr, payload);
mlxsw_reg_spfsr_local_port_set(payload, local_port);
mlxsw_reg_spfsr_security_set(payload, security);
}
/* SPVC - Switch Port VLAN Classification Register /* SPVC - Switch Port VLAN Classification Register
* ----------------------------------------------- * -----------------------------------------------
* Configures the port to identify packets as untagged / single tagged / * Configures the port to identify packets as untagged / single tagged /
...@@ -6316,6 +6349,7 @@ enum mlxsw_reg_htgt_trap_group { ...@@ -6316,6 +6349,7 @@ enum mlxsw_reg_htgt_trap_group {
MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS, MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS, MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS, MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_EAPOL,
__MLXSW_REG_HTGT_TRAP_GROUP_MAX, __MLXSW_REG_HTGT_TRAP_GROUP_MAX,
MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1 MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
...@@ -12761,6 +12795,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { ...@@ -12761,6 +12795,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(svpe), MLXSW_REG(svpe),
MLXSW_REG(sfmr), MLXSW_REG(sfmr),
MLXSW_REG(spvmlr), MLXSW_REG(spvmlr),
MLXSW_REG(spfsr),
MLXSW_REG(spvc), MLXSW_REG(spvc),
MLXSW_REG(spevet), MLXSW_REG(spevet),
MLXSW_REG(smpe), MLXSW_REG(smpe),
......
...@@ -466,6 +466,24 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, ...@@ -466,6 +466,24 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
return err; return err;
} }
int mlxsw_sp_port_security_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char spfsr_pl[MLXSW_REG_SPFSR_LEN];
int err;
if (mlxsw_sp_port->security == enable)
return 0;
mlxsw_reg_spfsr_pack(spfsr_pl, mlxsw_sp_port->local_port, enable);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spfsr), spfsr_pl);
if (err)
return err;
mlxsw_sp_port->security = enable;
return 0;
}
int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type) int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type)
{ {
switch (ethtype) { switch (ethtype) {
...@@ -4742,6 +4760,10 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, ...@@ -4742,6 +4760,10 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are only supported with 802.1q VLAN protocol"); NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are only supported with 802.1q VLAN protocol");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (is_vlan_dev(upper_dev) && mlxsw_sp_port->security) {
NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are not supported on a locked port");
return -EOPNOTSUPP;
}
break; break;
case NETDEV_CHANGEUPPER: case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev; upper_dev = info->upper_dev;
......
...@@ -321,7 +321,8 @@ struct mlxsw_sp_port { ...@@ -321,7 +321,8 @@ struct mlxsw_sp_port {
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
u16 local_port; u16 local_port;
u8 lagged:1, u8 lagged:1,
split:1; split:1,
security:1;
u16 pvid; u16 pvid;
u16 lag_id; u16 lag_id;
struct { struct {
...@@ -687,6 +688,8 @@ int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, ...@@ -687,6 +688,8 @@ int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable); int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);
int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
bool learn_enable); bool learn_enable);
int mlxsw_sp_port_security_set(struct mlxsw_sp_port *mlxsw_sp_port,
bool enable);
int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type); int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type);
int mlxsw_sp_port_egress_ethtype_set(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_port_egress_ethtype_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 ethtype); u16 ethtype);
......
...@@ -782,10 +782,25 @@ mlxsw_sp_bridge_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -782,10 +782,25 @@ mlxsw_sp_bridge_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
static int static int
mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct switchdev_brport_flags flags) const struct net_device *orig_dev,
struct switchdev_brport_flags flags,
struct netlink_ext_ack *extack)
{ {
if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
BR_PORT_LOCKED | BR_PORT_MAB)) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported bridge port flag");
return -EINVAL; return -EINVAL;
}
if ((flags.mask & BR_PORT_LOCKED) && is_vlan_dev(orig_dev)) {
NL_SET_ERR_MSG_MOD(extack, "Locked flag cannot be set on a VLAN upper");
return -EINVAL;
}
if ((flags.mask & BR_PORT_LOCKED) && vlan_uses_dev(orig_dev)) {
NL_SET_ERR_MSG_MOD(extack, "Locked flag cannot be set on a bridge port that has VLAN uppers");
return -EINVAL;
}
return 0; return 0;
} }
...@@ -819,6 +834,13 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -819,6 +834,13 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
return err; return err;
} }
if (flags.mask & BR_PORT_LOCKED) {
err = mlxsw_sp_port_security_set(mlxsw_sp_port,
flags.val & BR_PORT_LOCKED);
if (err)
return err;
}
if (bridge_port->bridge_device->multicast_enabled) if (bridge_port->bridge_device->multicast_enabled)
goto out; goto out;
...@@ -1186,7 +1208,9 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, const void *ctx, ...@@ -1186,7 +1208,9 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, const void *ctx,
break; break;
case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port, err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port,
attr->u.brport_flags); attr->orig_dev,
attr->u.brport_flags,
extack);
break; break;
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port,
...@@ -2783,6 +2807,7 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -2783,6 +2807,7 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
bridge_device->ops->port_leave(bridge_device, bridge_port, bridge_device->ops->port_leave(bridge_device, bridge_port,
mlxsw_sp_port); mlxsw_sp_port);
mlxsw_sp_port_security_set(mlxsw_sp_port, false);
mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port); mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
} }
...@@ -2888,13 +2913,14 @@ static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev, ...@@ -2888,13 +2913,14 @@ static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev,
static void static void
mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type, mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
const char *mac, u16 vid, const char *mac, u16 vid,
struct net_device *dev, bool offloaded) struct net_device *dev, bool offloaded, bool locked)
{ {
struct switchdev_notifier_fdb_info info = {}; struct switchdev_notifier_fdb_info info = {};
info.addr = mac; info.addr = mac;
info.vid = vid; info.vid = vid;
info.offloaded = offloaded; info.offloaded = offloaded;
info.locked = locked;
call_switchdev_notifiers(type, dev, &info.info, NULL); call_switchdev_notifiers(type, dev, &info.info, NULL);
} }
...@@ -2941,6 +2967,12 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, ...@@ -2941,6 +2967,12 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0; vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
evid = mlxsw_sp_port_vlan->vid; evid = mlxsw_sp_port_vlan->vid;
if (adding && mlxsw_sp_port->security) {
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, mac,
vid, bridge_port->dev, false, true);
return;
}
do_fdb_op: do_fdb_op:
err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, evid, err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, evid,
adding, true); adding, true);
...@@ -2952,7 +2984,8 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, ...@@ -2952,7 +2984,8 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
if (!do_notification) if (!do_notification)
return; return;
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE; type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding); mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding,
false);
return; return;
...@@ -3004,6 +3037,12 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, ...@@ -3004,6 +3037,12 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0; vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
lag_vid = mlxsw_sp_port_vlan->vid; lag_vid = mlxsw_sp_port_vlan->vid;
if (adding && mlxsw_sp_port->security) {
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, mac,
vid, bridge_port->dev, false, true);
return;
}
do_fdb_op: do_fdb_op:
err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid, err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
adding, true); adding, true);
...@@ -3015,7 +3054,8 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, ...@@ -3015,7 +3054,8 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
if (!do_notification) if (!do_notification)
return; return;
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE; type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding); mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev, adding,
false);
return; return;
...@@ -3122,7 +3162,7 @@ static void mlxsw_sp_fdb_notify_mac_uc_tunnel_process(struct mlxsw_sp *mlxsw_sp, ...@@ -3122,7 +3162,7 @@ static void mlxsw_sp_fdb_notify_mac_uc_tunnel_process(struct mlxsw_sp *mlxsw_sp,
type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE :
SWITCHDEV_FDB_DEL_TO_BRIDGE; SWITCHDEV_FDB_DEL_TO_BRIDGE;
mlxsw_sp_fdb_call_notifiers(type, mac, vid, nve_dev, adding); mlxsw_sp_fdb_call_notifiers(type, mac, vid, nve_dev, adding, false);
mlxsw_sp_fid_put(fid); mlxsw_sp_fid_put(fid);
...@@ -3264,7 +3304,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp, ...@@ -3264,7 +3304,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp,
&vxlan_fdb_info.info, NULL); &vxlan_fdb_info.info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info.eth_addr, vxlan_fdb_info.eth_addr,
fdb_info->vid, dev, true); fdb_info->vid, dev, true, false);
break; break;
case SWITCHDEV_FDB_DEL_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE:
err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp, err = mlxsw_sp_port_fdb_tunnel_uc_op(mlxsw_sp,
...@@ -3359,7 +3399,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work) ...@@ -3359,7 +3399,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
break; break;
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
fdb_info->addr, fdb_info->addr,
fdb_info->vid, dev, true); fdb_info->vid, dev, true, false);
break; break;
case SWITCHDEV_FDB_DEL_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE:
fdb_info = &switchdev_work->fdb_info; fdb_info = &switchdev_work->fdb_info;
...@@ -3443,7 +3483,8 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, ...@@ -3443,7 +3483,8 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp,
call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev,
&vxlan_fdb_info->info, NULL); &vxlan_fdb_info->info, NULL);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info->eth_addr, vid, dev, true); vxlan_fdb_info->eth_addr, vid, dev, true,
false);
mlxsw_sp_fid_put(fid); mlxsw_sp_fid_put(fid);
...@@ -3493,7 +3534,8 @@ mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp, ...@@ -3493,7 +3534,8 @@ mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp,
false, false); false, false);
vid = bridge_device->ops->fid_vid(bridge_device, fid); vid = bridge_device->ops->fid_vid(bridge_device, fid);
mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
vxlan_fdb_info->eth_addr, vid, dev, false); vxlan_fdb_info->eth_addr, vid, dev, false,
false);
mlxsw_sp_fid_put(fid); mlxsw_sp_fid_put(fid);
} }
......
...@@ -510,6 +510,9 @@ mlxsw_sp_trap_policer_items_arr[] = { ...@@ -510,6 +510,9 @@ mlxsw_sp_trap_policer_items_arr[] = {
{ {
.policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096), .policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096),
}, },
{
.policer = MLXSW_SP_TRAP_POLICER(21, 128, 128),
},
}; };
static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = { static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
...@@ -628,6 +631,11 @@ static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = { ...@@ -628,6 +631,11 @@ static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_FLOW_LOGGING, .hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_FLOW_LOGGING,
.priority = 4, .priority = 4,
}, },
{
.group = DEVLINK_TRAP_GROUP_GENERIC(EAPOL, 21),
.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_EAPOL,
.priority = 5,
},
}; };
static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = { static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
...@@ -1160,6 +1168,23 @@ static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = { ...@@ -1160,6 +1168,23 @@ static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
MLXSW_SP_RXL_DISCARD(ROUTER3, L3_DISCARDS), MLXSW_SP_RXL_DISCARD(ROUTER3, L3_DISCARDS),
}, },
}, },
{
.trap = MLXSW_SP_TRAP_CONTROL(EAPOL, EAPOL, TRAP),
.listeners_arr = {
MLXSW_SP_RXL_NO_MARK(EAPOL, EAPOL, TRAP_TO_CPU, true),
},
},
{
.trap = MLXSW_SP_TRAP_DROP(LOCKED_PORT, L2_DROPS),
.listeners_arr = {
MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISS,
TRAP_EXCEPTION_TO_CPU, false,
SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISMATCH,
TRAP_EXCEPTION_TO_CPU, false,
SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
},
},
}; };
static struct mlxsw_sp_trap_policer_item * static struct mlxsw_sp_trap_policer_item *
......
...@@ -25,6 +25,8 @@ enum { ...@@ -25,6 +25,8 @@ enum {
MLXSW_TRAP_ID_IGMP_V2_LEAVE = 0x33, MLXSW_TRAP_ID_IGMP_V2_LEAVE = 0x33,
MLXSW_TRAP_ID_IGMP_V3_REPORT = 0x34, MLXSW_TRAP_ID_IGMP_V3_REPORT = 0x34,
MLXSW_TRAP_ID_PKT_SAMPLE = 0x38, MLXSW_TRAP_ID_PKT_SAMPLE = 0x38,
MLXSW_TRAP_ID_FDB_MISS = 0x3A,
MLXSW_TRAP_ID_FDB_MISMATCH = 0x3B,
MLXSW_TRAP_ID_FID_MISS = 0x3D, MLXSW_TRAP_ID_FID_MISS = 0x3D,
MLXSW_TRAP_ID_DECAP_ECN0 = 0x40, MLXSW_TRAP_ID_DECAP_ECN0 = 0x40,
MLXSW_TRAP_ID_MTUERROR = 0x52, MLXSW_TRAP_ID_MTUERROR = 0x52,
......
...@@ -894,6 +894,8 @@ enum devlink_trap_generic_id { ...@@ -894,6 +894,8 @@ enum devlink_trap_generic_id {
DEVLINK_TRAP_GENERIC_ID_ESP_PARSING, DEVLINK_TRAP_GENERIC_ID_ESP_PARSING,
DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_NEXTHOP, DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_NEXTHOP,
DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER, DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER,
DEVLINK_TRAP_GENERIC_ID_EAPOL,
DEVLINK_TRAP_GENERIC_ID_LOCKED_PORT,
/* Add new generic trap IDs above */ /* Add new generic trap IDs above */
__DEVLINK_TRAP_GENERIC_ID_MAX, __DEVLINK_TRAP_GENERIC_ID_MAX,
...@@ -930,6 +932,7 @@ enum devlink_trap_group_generic_id { ...@@ -930,6 +932,7 @@ enum devlink_trap_group_generic_id {
DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_SAMPLE, DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_SAMPLE,
DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_TRAP, DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_TRAP,
DEVLINK_TRAP_GROUP_GENERIC_ID_PARSER_ERROR_DROPS, DEVLINK_TRAP_GROUP_GENERIC_ID_PARSER_ERROR_DROPS,
DEVLINK_TRAP_GROUP_GENERIC_ID_EAPOL,
/* Add new generic trap group IDs above */ /* Add new generic trap group IDs above */
__DEVLINK_TRAP_GROUP_GENERIC_ID_MAX, __DEVLINK_TRAP_GROUP_GENERIC_ID_MAX,
...@@ -1121,6 +1124,10 @@ enum devlink_trap_group_generic_id { ...@@ -1121,6 +1124,10 @@ enum devlink_trap_group_generic_id {
"blackhole_nexthop" "blackhole_nexthop"
#define DEVLINK_TRAP_GENERIC_NAME_DMAC_FILTER \ #define DEVLINK_TRAP_GENERIC_NAME_DMAC_FILTER \
"dmac_filter" "dmac_filter"
#define DEVLINK_TRAP_GENERIC_NAME_EAPOL \
"eapol"
#define DEVLINK_TRAP_GENERIC_NAME_LOCKED_PORT \
"locked_port"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \ #define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \
"l2_drops" "l2_drops"
...@@ -1174,6 +1181,8 @@ enum devlink_trap_group_generic_id { ...@@ -1174,6 +1181,8 @@ enum devlink_trap_group_generic_id {
"acl_trap" "acl_trap"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_PARSER_ERROR_DROPS \ #define DEVLINK_TRAP_GROUP_GENERIC_NAME_PARSER_ERROR_DROPS \
"parser_error_drops" "parser_error_drops"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_EAPOL \
"eapol"
#define DEVLINK_TRAP_GENERIC(_type, _init_action, _id, _group_id, \ #define DEVLINK_TRAP_GENERIC(_type, _init_action, _id, _group_id, \
_metadata_cap) \ _metadata_cap) \
......
...@@ -248,6 +248,7 @@ struct switchdev_notifier_fdb_info { ...@@ -248,6 +248,7 @@ struct switchdev_notifier_fdb_info {
u16 vid; u16 vid;
u8 added_by_user:1, u8 added_by_user:1,
is_local:1, is_local:1,
locked:1,
offloaded:1; offloaded:1;
}; };
......
...@@ -166,13 +166,14 @@ static int br_switchdev_event(struct notifier_block *unused, ...@@ -166,13 +166,14 @@ static int br_switchdev_event(struct notifier_block *unused,
case SWITCHDEV_FDB_ADD_TO_BRIDGE: case SWITCHDEV_FDB_ADD_TO_BRIDGE:
fdb_info = ptr; fdb_info = ptr;
err = br_fdb_external_learn_add(br, p, fdb_info->addr, err = br_fdb_external_learn_add(br, p, fdb_info->addr,
fdb_info->vid, false); fdb_info->vid,
fdb_info->locked, false);
if (err) { if (err) {
err = notifier_from_errno(err); err = notifier_from_errno(err);
break; break;
} }
br_fdb_offloaded_set(br, p, fdb_info->addr, br_fdb_offloaded_set(br, p, fdb_info->addr,
fdb_info->vid, true); fdb_info->vid, fdb_info->offloaded);
break; break;
case SWITCHDEV_FDB_DEL_TO_BRIDGE: case SWITCHDEV_FDB_DEL_TO_BRIDGE:
fdb_info = ptr; fdb_info = ptr;
......
...@@ -1139,7 +1139,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br, ...@@ -1139,7 +1139,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
"FDB entry towards bridge must be permanent"); "FDB entry towards bridge must be permanent");
return -EINVAL; return -EINVAL;
} }
err = br_fdb_external_learn_add(br, p, addr, vid, true); err = br_fdb_external_learn_add(br, p, addr, vid, false, true);
} else { } else {
spin_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb); err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb);
...@@ -1377,7 +1377,7 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p) ...@@ -1377,7 +1377,7 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
} }
int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, const unsigned char *addr, u16 vid, bool locked,
bool swdev_notify) bool swdev_notify)
{ {
struct net_bridge_fdb_entry *fdb; struct net_bridge_fdb_entry *fdb;
...@@ -1386,6 +1386,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, ...@@ -1386,6 +1386,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
trace_br_fdb_external_learn_add(br, p, addr, vid); trace_br_fdb_external_learn_add(br, p, addr, vid);
if (locked && (!p || !(p->flags & BR_PORT_MAB)))
return -EINVAL;
spin_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
fdb = br_fdb_find(br, addr, vid); fdb = br_fdb_find(br, addr, vid);
...@@ -1398,6 +1401,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, ...@@ -1398,6 +1401,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
if (!p) if (!p)
flags |= BIT(BR_FDB_LOCAL); flags |= BIT(BR_FDB_LOCAL);
if (locked)
flags |= BIT(BR_FDB_LOCKED);
fdb = fdb_create(br, p, addr, vid, flags); fdb = fdb_create(br, p, addr, vid, flags);
if (!fdb) { if (!fdb) {
err = -ENOMEM; err = -ENOMEM;
...@@ -1405,6 +1411,13 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, ...@@ -1405,6 +1411,13 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
} }
fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify); fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
} else { } else {
if (locked &&
(!test_bit(BR_FDB_LOCKED, &fdb->flags) ||
READ_ONCE(fdb->dst) != p)) {
err = -EINVAL;
goto err_unlock;
}
fdb->updated = jiffies; fdb->updated = jiffies;
if (READ_ONCE(fdb->dst) != p) { if (READ_ONCE(fdb->dst) != p) {
...@@ -1421,6 +1434,11 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, ...@@ -1421,6 +1434,11 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
modified = true; modified = true;
} }
if (locked != test_bit(BR_FDB_LOCKED, &fdb->flags)) {
change_bit(BR_FDB_LOCKED, &fdb->flags);
modified = true;
}
if (swdev_notify) if (swdev_notify)
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags); set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
......
...@@ -811,7 +811,7 @@ int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); ...@@ -811,7 +811,7 @@ int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, const unsigned char *addr, u16 vid,
bool swdev_notify); bool locked, bool swdev_notify);
int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, const unsigned char *addr, u16 vid,
bool swdev_notify); bool swdev_notify);
......
...@@ -71,7 +71,7 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, ...@@ -71,7 +71,7 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
} }
/* Flags that can be offloaded to hardware */ /* Flags that can be offloaded to hardware */
#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \ #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | BR_PORT_MAB | \
BR_MCAST_FLOOD | BR_BCAST_FLOOD | BR_PORT_LOCKED | \ BR_MCAST_FLOOD | BR_BCAST_FLOOD | BR_PORT_LOCKED | \
BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST) BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST)
...@@ -136,6 +136,7 @@ static void br_switchdev_fdb_populate(struct net_bridge *br, ...@@ -136,6 +136,7 @@ static void br_switchdev_fdb_populate(struct net_bridge *br,
item->added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags); item->added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
item->offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags); item->offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags);
item->is_local = test_bit(BR_FDB_LOCAL, &fdb->flags); item->is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
item->locked = false;
item->info.dev = (!p || item->is_local) ? br->dev : p->dev; item->info.dev = (!p || item->is_local) ? br->dev : p->dev;
item->info.ctx = ctx; item->info.ctx = ctx;
} }
...@@ -146,6 +147,9 @@ br_switchdev_fdb_notify(struct net_bridge *br, ...@@ -146,6 +147,9 @@ br_switchdev_fdb_notify(struct net_bridge *br,
{ {
struct switchdev_notifier_fdb_info item; struct switchdev_notifier_fdb_info item;
if (test_bit(BR_FDB_LOCKED, &fdb->flags))
return;
br_switchdev_fdb_populate(br, &item, fdb, NULL); br_switchdev_fdb_populate(br, &item, fdb, NULL);
switch (type) { switch (type) {
......
...@@ -11734,6 +11734,8 @@ static const struct devlink_trap devlink_trap_generic[] = { ...@@ -11734,6 +11734,8 @@ static const struct devlink_trap devlink_trap_generic[] = {
DEVLINK_TRAP(ESP_PARSING, DROP), DEVLINK_TRAP(ESP_PARSING, DROP),
DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP), DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP),
DEVLINK_TRAP(DMAC_FILTER, DROP), DEVLINK_TRAP(DMAC_FILTER, DROP),
DEVLINK_TRAP(EAPOL, CONTROL),
DEVLINK_TRAP(LOCKED_PORT, DROP),
}; };
#define DEVLINK_TRAP_GROUP(_id) \ #define DEVLINK_TRAP_GROUP(_id) \
...@@ -11769,6 +11771,7 @@ static const struct devlink_trap_group devlink_trap_group_generic[] = { ...@@ -11769,6 +11771,7 @@ static const struct devlink_trap_group devlink_trap_group_generic[] = {
DEVLINK_TRAP_GROUP(ACL_SAMPLE), DEVLINK_TRAP_GROUP(ACL_SAMPLE),
DEVLINK_TRAP_GROUP(ACL_TRAP), DEVLINK_TRAP_GROUP(ACL_TRAP),
DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS), DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
DEVLINK_TRAP_GROUP(EAPOL),
}; };
static int devlink_trap_generic_verify(const struct devlink_trap *trap) static int devlink_trap_generic_verify(const struct devlink_trap *trap)
......
...@@ -83,6 +83,7 @@ ALL_TESTS=" ...@@ -83,6 +83,7 @@ ALL_TESTS="
ptp_general_test ptp_general_test
flow_action_sample_test flow_action_sample_test
flow_action_trap_test flow_action_trap_test
eapol_test
" "
NUM_NETIFS=4 NUM_NETIFS=4
source $lib_dir/lib.sh source $lib_dir/lib.sh
...@@ -677,6 +678,27 @@ flow_action_trap_test() ...@@ -677,6 +678,27 @@ flow_action_trap_test()
tc qdisc del dev $rp1 clsact tc qdisc del dev $rp1 clsact
} }
eapol_payload_get()
{
local source_mac=$1; shift
local p
p=$(:
)"01:80:C2:00:00:03:"$( : ETH daddr
)"$source_mac:"$( : ETH saddr
)"88:8E:"$( : ETH type
)
echo $p
}
eapol_test()
{
local h1mac=$(mac_get $h1)
devlink_trap_stats_test "EAPOL" "eapol" $MZ $h1 -c 1 \
$(eapol_payload_get $h1mac) -p 100 -q
}
trap cleanup EXIT trap cleanup EXIT
setup_prepare setup_prepare
......
...@@ -14,6 +14,7 @@ ALL_TESTS=" ...@@ -14,6 +14,7 @@ ALL_TESTS="
ingress_stp_filter_test ingress_stp_filter_test
port_list_is_empty_test port_list_is_empty_test
port_loopback_filter_test port_loopback_filter_test
locked_port_test
" "
NUM_NETIFS=4 NUM_NETIFS=4
source $lib_dir/tc_common.sh source $lib_dir/tc_common.sh
...@@ -420,6 +421,110 @@ port_loopback_filter_test() ...@@ -420,6 +421,110 @@ port_loopback_filter_test()
port_loopback_filter_uc_test port_loopback_filter_uc_test
} }
locked_port_miss_test()
{
local trap_name="locked_port"
local smac=00:11:22:33:44:55
bridge link set dev $swp1 learning off
bridge link set dev $swp1 locked on
RET=0
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased before setting action to \"trap\""
devlink_trap_action_set $trap_name "trap"
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_err $? "Trap stats did not increase when should"
devlink_trap_action_set $trap_name "drop"
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after setting action to \"drop\""
devlink_trap_action_set $trap_name "trap"
bridge fdb replace $smac dev $swp1 master static vlan 1
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after adding an FDB entry"
bridge fdb del $smac dev $swp1 master static vlan 1
bridge link set dev $swp1 locked off
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after unlocking port"
log_test "Locked port - FDB miss"
devlink_trap_action_set $trap_name "drop"
bridge link set dev $swp1 learning on
}
locked_port_mismatch_test()
{
local trap_name="locked_port"
local smac=00:11:22:33:44:55
bridge link set dev $swp1 learning off
bridge link set dev $swp1 locked on
RET=0
bridge fdb replace $smac dev $swp2 master static vlan 1
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased before setting action to \"trap\""
devlink_trap_action_set $trap_name "trap"
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_err $? "Trap stats did not increase when should"
devlink_trap_action_set $trap_name "drop"
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after setting action to \"drop\""
devlink_trap_action_set $trap_name "trap"
bridge link set dev $swp1 locked off
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after unlocking port"
bridge link set dev $swp1 locked on
bridge fdb replace $smac dev $swp1 master static vlan 1
devlink_trap_stats_check $trap_name $MZ $h1 -c 1 \
-a $smac -b $(mac_get $h2) -A 192.0.2.1 -B 192.0.2.2 -p 100 -q
check_fail $? "Trap stats increased after replacing an FDB entry"
bridge fdb del $smac dev $swp1 master static vlan 1
devlink_trap_action_set $trap_name "drop"
log_test "Locked port - FDB mismatch"
bridge link set dev $swp1 locked off
bridge link set dev $swp1 learning on
}
locked_port_test()
{
locked_port_miss_test
locked_port_mismatch_test
}
trap cleanup EXIT trap cleanup EXIT
setup_prepare setup_prepare
......
...@@ -34,6 +34,7 @@ ALL_TESTS=" ...@@ -34,6 +34,7 @@ ALL_TESTS="
nexthop_obj_bucket_offload_test nexthop_obj_bucket_offload_test
nexthop_obj_blackhole_offload_test nexthop_obj_blackhole_offload_test
nexthop_obj_route_offload_test nexthop_obj_route_offload_test
bridge_locked_port_test
devlink_reload_test devlink_reload_test
" "
NUM_NETIFS=2 NUM_NETIFS=2
...@@ -917,6 +918,36 @@ nexthop_obj_route_offload_test() ...@@ -917,6 +918,36 @@ nexthop_obj_route_offload_test()
simple_if_fini $swp1 192.0.2.1/24 2001:db8:1::1/64 simple_if_fini $swp1 192.0.2.1/24 2001:db8:1::1/64
} }
bridge_locked_port_test()
{
RET=0
ip link add name br1 up type bridge vlan_filtering 0
ip link add link $swp1 name $swp1.10 type vlan id 10
ip link set dev $swp1.10 master br1
bridge link set dev $swp1.10 locked on
check_fail $? "managed to set locked flag on a VLAN upper"
ip link set dev $swp1.10 nomaster
ip link set dev $swp1 master br1
bridge link set dev $swp1 locked on
check_fail $? "managed to set locked flag on a bridge port that has a VLAN upper"
ip link del dev $swp1.10
bridge link set dev $swp1 locked on
ip link add link $swp1 name $swp1.10 type vlan id 10
check_fail $? "managed to configure a VLAN upper on a locked port"
log_test "bridge locked port"
ip link del dev $swp1.10 &> /dev/null
ip link del dev br1
}
devlink_reload_test() devlink_reload_test()
{ {
# Test that after executing all the above configuration tests, a # Test that after executing all the above configuration tests, a
......
...@@ -503,25 +503,30 @@ devlink_trap_drop_cleanup() ...@@ -503,25 +503,30 @@ devlink_trap_drop_cleanup()
tc filter del dev $dev egress protocol $proto pref $pref handle $handle flower tc filter del dev $dev egress protocol $proto pref $pref handle $handle flower
} }
devlink_trap_stats_test() devlink_trap_stats_check()
{ {
local test_name=$1; shift
local trap_name=$1; shift local trap_name=$1; shift
local send_one="$@" local send_one="$@"
local t0_packets local t0_packets
local t1_packets local t1_packets
RET=0
t0_packets=$(devlink_trap_rx_packets_get $trap_name) t0_packets=$(devlink_trap_rx_packets_get $trap_name)
$send_one && sleep 1 $send_one && sleep 1
t1_packets=$(devlink_trap_rx_packets_get $trap_name) t1_packets=$(devlink_trap_rx_packets_get $trap_name)
if [[ $t1_packets -eq $t0_packets ]]; then [[ $t1_packets -ne $t0_packets ]]
check_err 1 "Trap stats did not increase" }
fi
devlink_trap_stats_test()
{
local test_name=$1; shift
RET=0
devlink_trap_stats_check "$@"
check_err $? "Trap stats did not increase"
log_test "$test_name" log_test "$test_name"
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment