Commit 25ed8088 authored by Ido Schimmel's avatar Ido Schimmel Committed by Jakub Kicinski

mlxsw: spectrum_switchdev: Add locked bridge port support

Add locked bridge port support by reacting to changes in the
'BR_PORT_LOCKED' flag. When set, enable security checks on the local
port via the previously added SPFSR register.

When security checks are enabled, an incoming packet will trigger an FDB
lookup with the packet's source MAC and the FID it was classified to. If
an FDB entry was not found or was found to be pointing to a different
port, the packet will be dropped. Such packets increment the
"discard_ingress_general" ethtool counter. For added visibility, user
space can trap such packets to the CPU by enabling the "locked_port"
trap. Example:

 # devlink trap set pci/0000:06:00.0 trap locked_port action trap

Unlike other configurations done via bridge port flags (e.g., learning,
flooding), security checks are enabled in the device on a per-port basis
and not on a per-{port, VLAN} basis. As such, scenarios where user space
can configure different locking settings for different VLANs configured
on a port need to be vetoed. To that end, veto the following scenarios:

1. Locking is set on a bridge port that is a VLAN upper

2. Locking is set on a bridge port that has VLAN uppers

3. VLAN upper is configured on a locked bridge port

Examples:

 # bridge link set dev swp1.10 locked on
 Error: mlxsw_spectrum: Locked flag cannot be set on a VLAN upper.

 # ip link add link swp1 name swp1.10 type vlan id 10
 # bridge link set dev swp1 locked on
 Error: mlxsw_spectrum: Locked flag cannot be set on a bridge port that has VLAN uppers.

 # bridge link set dev swp1 locked on
 # ip link add link swp1 name swp1.10 type vlan id 10
 Error: mlxsw_spectrum: VLAN uppers are not supported on a locked port.
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 136b8dfb
...@@ -4760,6 +4760,10 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, ...@@ -4760,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;
......
...@@ -782,14 +782,26 @@ mlxsw_sp_bridge_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -782,14 +782,26 @@ 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,
const struct net_device *orig_dev,
struct switchdev_brport_flags flags, struct switchdev_brport_flags flags,
struct netlink_ext_ack *extack) 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"); 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;
} }
...@@ -822,6 +834,13 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -822,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;
...@@ -1189,6 +1208,7 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, const void *ctx, ...@@ -1189,6 +1208,7 @@ 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->orig_dev,
attr->u.brport_flags, attr->u.brport_flags,
extack); extack);
break; break;
...@@ -2787,6 +2807,7 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -2787,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);
} }
......
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