mlxsw: spectrum_router: Replay IP NETDEV_UP on device deslavement
When a netdevice is removed from a bridge or a LAG, and it has an IP address, it should join the router and gain a RIF. Do that by replaying address addition event on the netdevice. When handling deslavement of LAG or its upper from a bridge device, the replay should be done after all the lowers of the LAG have left the bridge. Thus these scenarios are handled by passing replay_deslavement of false, and by invoking, after the lowers have been processed, a new helper, mlxsw_sp_netdevice_post_lag_event(), which does the per-LAG / -upper handling, and in particular invokes the replay. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Danielle Ratson <danieller@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
31618b22f2
commit
4560cf408e
|
@ -4838,15 +4838,20 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
|
|||
case NETDEV_CHANGEUPPER:
|
||||
upper_dev = info->upper_dev;
|
||||
if (netif_is_bridge_master(upper_dev)) {
|
||||
if (info->linking)
|
||||
if (info->linking) {
|
||||
err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
|
||||
lower_dev,
|
||||
upper_dev,
|
||||
extack);
|
||||
else
|
||||
} else {
|
||||
mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
|
||||
lower_dev,
|
||||
upper_dev);
|
||||
if (!replay_deslavement)
|
||||
break;
|
||||
mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp,
|
||||
lower_dev);
|
||||
}
|
||||
} else if (netif_is_lag_master(upper_dev)) {
|
||||
if (info->linking) {
|
||||
err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
|
||||
|
@ -4855,6 +4860,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
|
|||
mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
|
||||
mlxsw_sp_port_lag_leave(mlxsw_sp_port,
|
||||
upper_dev);
|
||||
mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp,
|
||||
dev);
|
||||
}
|
||||
} else if (netif_is_ovs_master(upper_dev)) {
|
||||
if (info->linking)
|
||||
|
@ -4924,6 +4931,30 @@ static int mlxsw_sp_netdevice_port_event(struct net_device *lower_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called for LAG or its upper VLAN after the per-LAG-lower processing was done,
|
||||
* to do any per-LAG / per-LAG-upper processing.
|
||||
*/
|
||||
static int mlxsw_sp_netdevice_post_lag_event(struct net_device *dev,
|
||||
unsigned long event,
|
||||
void *ptr)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(dev);
|
||||
struct netdev_notifier_changeupper_info *info = ptr;
|
||||
|
||||
if (!mlxsw_sp)
|
||||
return 0;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_CHANGEUPPER:
|
||||
if (info->linking)
|
||||
break;
|
||||
if (netif_is_bridge_master(info->upper_dev))
|
||||
mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp, dev);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
|
@ -4940,7 +4971,7 @@ static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev,
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return mlxsw_sp_netdevice_post_lag_event(lag_dev, event, ptr);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
|
||||
|
@ -4984,15 +5015,20 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
|
|||
case NETDEV_CHANGEUPPER:
|
||||
upper_dev = info->upper_dev;
|
||||
if (netif_is_bridge_master(upper_dev)) {
|
||||
if (info->linking)
|
||||
if (info->linking) {
|
||||
err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
|
||||
vlan_dev,
|
||||
upper_dev,
|
||||
extack);
|
||||
else
|
||||
} else {
|
||||
mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
|
||||
vlan_dev,
|
||||
upper_dev);
|
||||
if (!replay_deslavement)
|
||||
break;
|
||||
mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp,
|
||||
vlan_dev);
|
||||
}
|
||||
} else if (netif_is_macvlan(upper_dev)) {
|
||||
if (!info->linking)
|
||||
mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
|
||||
|
@ -5022,7 +5058,7 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev,
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return mlxsw_sp_netdevice_post_lag_event(vlan_dev, event, ptr);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_bridge_vlan_event(struct mlxsw_sp *mlxsw_sp,
|
||||
|
|
|
@ -9785,12 +9785,14 @@ struct mlxsw_sp_router_replay_inetaddr_up {
|
|||
struct mlxsw_sp *mlxsw_sp;
|
||||
struct netlink_ext_ack *extack;
|
||||
unsigned int done;
|
||||
bool deslavement;
|
||||
};
|
||||
|
||||
static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev,
|
||||
struct netdev_nested_priv *priv)
|
||||
{
|
||||
struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
|
||||
bool nomaster = ctx->deslavement;
|
||||
struct mlxsw_sp_crif *crif;
|
||||
int err;
|
||||
|
||||
|
@ -9805,7 +9807,7 @@ static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev,
|
|||
return 0;
|
||||
|
||||
err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP,
|
||||
false, ctx->extack);
|
||||
nomaster, ctx->extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -9817,6 +9819,7 @@ static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev,
|
|||
struct netdev_nested_priv *priv)
|
||||
{
|
||||
struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
|
||||
bool nomaster = ctx->deslavement;
|
||||
struct mlxsw_sp_crif *crif;
|
||||
|
||||
if (!ctx->done)
|
||||
|
@ -9833,7 +9836,8 @@ static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev,
|
|||
if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
|
||||
return 0;
|
||||
|
||||
__mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, false, NULL);
|
||||
__mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, nomaster,
|
||||
NULL);
|
||||
|
||||
ctx->done--;
|
||||
return 0;
|
||||
|
@ -9846,6 +9850,7 @@ int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
|
|||
struct mlxsw_sp_router_replay_inetaddr_up ctx = {
|
||||
.mlxsw_sp = mlxsw_sp,
|
||||
.extack = extack,
|
||||
.deslavement = false,
|
||||
};
|
||||
struct netdev_nested_priv priv = {
|
||||
.data = &ctx,
|
||||
|
@ -9872,6 +9877,20 @@ err_replay_up:
|
|||
return err;
|
||||
}
|
||||
|
||||
void mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct mlxsw_sp_router_replay_inetaddr_up ctx = {
|
||||
.mlxsw_sp = mlxsw_sp,
|
||||
.deslavement = true,
|
||||
};
|
||||
struct netdev_nested_priv priv = {
|
||||
.data = &ctx,
|
||||
};
|
||||
|
||||
mlxsw_sp_router_replay_inetaddr_up(dev, &priv);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
u16 vid, struct net_device *dev,
|
||||
|
|
|
@ -183,5 +183,7 @@ void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
|
|||
int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *upper_dev,
|
||||
struct netlink_ext_ack *extack);
|
||||
void mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *dev);
|
||||
|
||||
#endif /* _MLXSW_ROUTER_H_*/
|
||||
|
|
Loading…
Reference in New Issue