mlxsw: spectrum_router: Add support for VRFs
Allow port netdevs, LAG and VLAN devices stacked on top of these to be enslaved to a VRF master device. Upon enslavement, create a router interface (RIF) for the enslaved netdev and associate it with a virtual router (VR) based on the VRF's table ID. If a RIF already exists for the netdev (f.e., due to the existence of an IP address), then it's deleted and a new one is created with the appropriate VR binding. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9db032bb1e
commit
7179eb5acd
@ -3951,7 +3951,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
|
||||
upper_dev = info->upper_dev;
|
||||
if (!is_vlan_dev(upper_dev) &&
|
||||
!netif_is_lag_master(upper_dev) &&
|
||||
!netif_is_bridge_master(upper_dev))
|
||||
!netif_is_bridge_master(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev))
|
||||
return -EINVAL;
|
||||
if (!info->linking)
|
||||
break;
|
||||
@ -3991,6 +3992,11 @@ 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 {
|
||||
err = -EINVAL;
|
||||
WARN_ON(1);
|
||||
@ -4353,14 +4359,16 @@ 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))
|
||||
if (!netif_is_bridge_master(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev))
|
||||
return -EINVAL;
|
||||
if (!info->linking)
|
||||
break;
|
||||
/* We can't have multiple VLAN interfaces configured on
|
||||
* the same port and being members in the same bridge.
|
||||
*/
|
||||
if (!mlxsw_sp_port_master_bridge_check(mlxsw_sp_port,
|
||||
if (netif_is_bridge_master(upper_dev) &&
|
||||
!mlxsw_sp_port_master_bridge_check(mlxsw_sp_port,
|
||||
upper_dev))
|
||||
return -EINVAL;
|
||||
break;
|
||||
@ -4372,6 +4380,11 @@ 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);
|
||||
|
@ -578,6 +578,10 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr);
|
||||
void mlxsw_sp_rif_bridge_destroy(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *r);
|
||||
int mlxsw_sp_vport_vrf_join(struct mlxsw_sp_port *mlxsw_sp_vport);
|
||||
void mlxsw_sp_vport_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_vport);
|
||||
int mlxsw_sp_port_vrf_join(struct mlxsw_sp_port *mlxsw_sp_port);
|
||||
void mlxsw_sp_port_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_port);
|
||||
|
||||
int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count);
|
||||
void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index);
|
||||
|
@ -3226,6 +3226,47 @@ err_rif_edit:
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlxsw_sp_vport_vrf_join(struct mlxsw_sp_port *mlxsw_sp_vport)
|
||||
{
|
||||
struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
|
||||
struct net_device *dev = mlxsw_sp_vport->dev;
|
||||
|
||||
/* In case vPort already has a RIF, then we need to drop it.
|
||||
* A new one will be created using the VRF's VR.
|
||||
*/
|
||||
if (f && f->r)
|
||||
mlxsw_sp_vport_rif_sp_leave(mlxsw_sp_vport);
|
||||
|
||||
return mlxsw_sp_vport_rif_sp_join(mlxsw_sp_vport, dev);
|
||||
}
|
||||
|
||||
void mlxsw_sp_vport_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
|
||||
{
|
||||
mlxsw_sp_vport_rif_sp_leave(mlxsw_sp_vport);
|
||||
}
|
||||
|
||||
int mlxsw_sp_port_vrf_join(struct mlxsw_sp_port *mlxsw_sp_port)
|
||||
{
|
||||
struct mlxsw_sp_port *mlxsw_sp_vport;
|
||||
|
||||
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, 1);
|
||||
if (WARN_ON(!mlxsw_sp_vport))
|
||||
return -EINVAL;
|
||||
|
||||
return mlxsw_sp_vport_vrf_join(mlxsw_sp_vport);
|
||||
}
|
||||
|
||||
void mlxsw_sp_port_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_port)
|
||||
{
|
||||
struct mlxsw_sp_port *mlxsw_sp_vport;
|
||||
|
||||
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, 1);
|
||||
if (WARN_ON(!mlxsw_sp_vport))
|
||||
return;
|
||||
|
||||
mlxsw_sp_vport_vrf_leave(mlxsw_sp_vport);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
|
||||
|
Loading…
Reference in New Issue
Block a user