summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2017-04-30 19:47:14 +0300
committerDavid S. Miller <davem@davemloft.net>2017-05-01 18:47:58 +0300
commitb1e455260c9187b16dd4ebc428b817ebac322043 (patch)
tree7dbe01616807c5c4eb3523326f003c13692f5919 /drivers/net/ethernet/mellanox/mlxsw/spectrum.c
parentcedf90c0cc1250cfb95905b61dc36b37ec9d5395 (diff)
downloadlinux-b1e455260c9187b16dd4ebc428b817ebac322043.tar.xz
mlxsw: spectrum_router: Simplify VRF enslavement
When a netdev is enslaved to a VRF master, its router interface (RIF) needs to be destroyed (if exists) and a new one created using the corresponding virtual router (VR). >From the driver's perspective, the above is equivalent to an inetaddr event sent for this netdev. Therefore, when a port netdev (or its uppers) are enslaved to a VRF master, call the same function that would've been called had a NETDEV_UP was sent for this netdev in the inetaddr notification chain. This patch also fixes a bug when a LAG netdev with an existing RIF is enslaved to a VRF. Before this patch, each LAG port would drop the reference on the RIF, but would re-join the same one (in the wrong VR) soon after. With this patch, the corresponding RIF is first destroyed and a new one is created using the correct VR. Fixes: 7179eb5acd59 ("mlxsw: spectrum_router: Add support for VRFs") Signed-off-by: Ido Schimmel <idosch@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/spectrum.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c77
1 files changed, 13 insertions, 64 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 20c1b6c2dba0..88357cee7679 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4106,7 +4106,6 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
if (!is_vlan_dev(upper_dev) &&
!netif_is_lag_master(upper_dev) &&
!netif_is_bridge_master(upper_dev) &&
- !netif_is_l3_master(upper_dev) &&
!netif_is_ovs_master(upper_dev))
return -EINVAL;
if (!info->linking)
@@ -4151,11 +4150,6 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
else
mlxsw_sp_port_lag_leave(mlxsw_sp_port,
upper_dev);
- } else if (netif_is_l3_master(upper_dev)) {
- if (info->linking)
- err = mlxsw_sp_port_vrf_join(mlxsw_sp_port);
- else
- mlxsw_sp_port_vrf_leave(mlxsw_sp_port);
} else if (netif_is_ovs_master(upper_dev)) {
if (info->linking)
err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
@@ -4275,7 +4269,7 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
switch (event) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
- if (!is_vlan_dev(upper_dev) && !netif_is_l3_master(upper_dev))
+ if (!is_vlan_dev(upper_dev))
return -EINVAL;
if (is_vlan_dev(upper_dev) &&
br_dev != mlxsw_sp->master_bridge.dev)
@@ -4290,12 +4284,6 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
else
mlxsw_sp_master_bridge_vlan_unlink(mlxsw_sp,
upper_dev);
- } else if (netif_is_l3_master(upper_dev)) {
- if (info->linking)
- err = mlxsw_sp_bridge_vrf_join(mlxsw_sp,
- br_dev);
- else
- mlxsw_sp_bridge_vrf_leave(mlxsw_sp, br_dev);
} else {
err = -EINVAL;
WARN_ON(1);
@@ -4529,8 +4517,7 @@ static int mlxsw_sp_netdevice_vport_event(struct net_device *dev,
switch (event) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
- if (!netif_is_bridge_master(upper_dev) &&
- !netif_is_l3_master(upper_dev))
+ if (!netif_is_bridge_master(upper_dev))
return -EINVAL;
if (!info->linking)
break;
@@ -4550,11 +4537,6 @@ static int mlxsw_sp_netdevice_vport_event(struct net_device *dev,
upper_dev);
else
mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport);
- } else if (netif_is_l3_master(upper_dev)) {
- if (info->linking)
- err = mlxsw_sp_vport_vrf_join(mlxsw_sp_vport);
- else
- mlxsw_sp_vport_vrf_leave(mlxsw_sp_vport);
} else {
err = -EINVAL;
WARN_ON(1);
@@ -4585,47 +4567,6 @@ static int mlxsw_sp_netdevice_lag_vport_event(struct net_device *lag_dev,
return 0;
}
-static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
- unsigned long event, void *ptr)
-{
- struct netdev_notifier_changeupper_info *info;
- struct mlxsw_sp *mlxsw_sp;
- int err = 0;
-
- mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
- if (!mlxsw_sp)
- return 0;
-
- info = ptr;
-
- switch (event) {
- case NETDEV_PRECHANGEUPPER:
- /* VLAN devices are only allowed on top of the
- * VLAN-aware bridge.
- */
- if (WARN_ON(vlan_dev_real_dev(vlan_dev) !=
- mlxsw_sp->master_bridge.dev))
- return -EINVAL;
- if (!netif_is_l3_master(info->upper_dev))
- return -EINVAL;
- break;
- case NETDEV_CHANGEUPPER:
- if (netif_is_l3_master(info->upper_dev)) {
- if (info->linking)
- err = mlxsw_sp_bridge_vrf_join(mlxsw_sp,
- vlan_dev);
- else
- mlxsw_sp_bridge_vrf_leave(mlxsw_sp, vlan_dev);
- } else {
- err = -EINVAL;
- WARN_ON(1);
- }
- break;
- }
-
- return err;
-}
-
static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
unsigned long event, void *ptr)
{
@@ -4638,13 +4579,19 @@ static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
else if (netif_is_lag_master(real_dev))
return mlxsw_sp_netdevice_lag_vport_event(real_dev, event, ptr,
vid);
- else if (netif_is_bridge_master(real_dev))
- return mlxsw_sp_netdevice_bridge_vlan_event(vlan_dev, event,
- ptr);
return 0;
}
+static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
+{
+ struct netdev_notifier_changeupper_info *info = ptr;
+
+ if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
+ return false;
+ return netif_is_l3_master(info->upper_dev);
+}
+
static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -4653,6 +4600,8 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
if (event == NETDEV_CHANGEADDR || event == NETDEV_CHANGEMTU)
err = mlxsw_sp_netdevice_router_port_event(dev);
+ else if (mlxsw_sp_is_vrf_event(event, ptr))
+ err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
else if (mlxsw_sp_port_dev_check(dev))
err = mlxsw_sp_netdevice_port_event(dev, event, ptr);
else if (netif_is_lag_master(dev))