Skip to content

Commit 31618b2

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum_router: Replay IP NETDEV_UP on device enslavement
Enslaving of front panel ports (and their uppers) to netdevices that already have uppers is currently forbidden. When this is permitted, any uppers with IP addresses need to have the NETDEV_UP inetaddr event replayed, so that any RIFs are created. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Danielle Ratson <danieller@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 8fdb09a commit 31618b2

4 files changed

Lines changed: 137 additions & 0 deletions

File tree

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4469,8 +4469,14 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
44694469
if (err)
44704470
goto err_router_join;
44714471

4472+
err = mlxsw_sp_netdevice_enslavement_replay(mlxsw_sp, lag_dev, extack);
4473+
if (err)
4474+
goto err_replay;
4475+
44724476
return 0;
44734477

4478+
err_replay:
4479+
mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev);
44744480
err_router_join:
44754481
lag->ref_count--;
44764482
mlxsw_sp_port->lagged = 0;

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9781,6 +9781,97 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
97819781
return err;
97829782
}
97839783

9784+
struct mlxsw_sp_router_replay_inetaddr_up {
9785+
struct mlxsw_sp *mlxsw_sp;
9786+
struct netlink_ext_ack *extack;
9787+
unsigned int done;
9788+
};
9789+
9790+
static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev,
9791+
struct netdev_nested_priv *priv)
9792+
{
9793+
struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
9794+
struct mlxsw_sp_crif *crif;
9795+
int err;
9796+
9797+
if (mlxsw_sp_dev_addr_list_empty(dev))
9798+
return 0;
9799+
9800+
crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
9801+
if (!crif || crif->rif)
9802+
return 0;
9803+
9804+
if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
9805+
return 0;
9806+
9807+
err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP,
9808+
false, ctx->extack);
9809+
if (err)
9810+
return err;
9811+
9812+
ctx->done++;
9813+
return 0;
9814+
}
9815+
9816+
static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev,
9817+
struct netdev_nested_priv *priv)
9818+
{
9819+
struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data;
9820+
struct mlxsw_sp_crif *crif;
9821+
9822+
if (!ctx->done)
9823+
return 0;
9824+
9825+
if (mlxsw_sp_dev_addr_list_empty(dev))
9826+
return 0;
9827+
9828+
crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev);
9829+
if (!crif || !crif->rif)
9830+
return 0;
9831+
9832+
/* We are rolling back NETDEV_UP, so ask for that. */
9833+
if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP))
9834+
return 0;
9835+
9836+
__mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, false, NULL);
9837+
9838+
ctx->done--;
9839+
return 0;
9840+
}
9841+
9842+
int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
9843+
struct net_device *upper_dev,
9844+
struct netlink_ext_ack *extack)
9845+
{
9846+
struct mlxsw_sp_router_replay_inetaddr_up ctx = {
9847+
.mlxsw_sp = mlxsw_sp,
9848+
.extack = extack,
9849+
};
9850+
struct netdev_nested_priv priv = {
9851+
.data = &ctx,
9852+
};
9853+
int err;
9854+
9855+
err = mlxsw_sp_router_replay_inetaddr_up(upper_dev, &priv);
9856+
if (err)
9857+
return err;
9858+
9859+
err = netdev_walk_all_upper_dev_rcu(upper_dev,
9860+
mlxsw_sp_router_replay_inetaddr_up,
9861+
&priv);
9862+
if (err)
9863+
goto err_replay_up;
9864+
9865+
return 0;
9866+
9867+
err_replay_up:
9868+
netdev_walk_all_upper_dev_rcu(upper_dev,
9869+
mlxsw_sp_router_unreplay_inetaddr_up,
9870+
&priv);
9871+
mlxsw_sp_router_unreplay_inetaddr_up(upper_dev, &priv);
9872+
return err;
9873+
}
9874+
97849875
static int
97859876
mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
97869877
u16 vid, struct net_device *dev,
@@ -9857,6 +9948,26 @@ static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
98579948
return err;
98589949
}
98599950

9951+
static void
9952+
__mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
9953+
struct net_device *lag_dev)
9954+
{
9955+
u16 default_vid = MLXSW_SP_DEFAULT_VID;
9956+
struct net_device *upper_dev;
9957+
struct list_head *iter;
9958+
u16 vid;
9959+
9960+
netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
9961+
if (!is_vlan_dev(upper_dev))
9962+
continue;
9963+
9964+
vid = vlan_dev_vlan_id(upper_dev);
9965+
mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev);
9966+
}
9967+
9968+
mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev);
9969+
}
9970+
98609971
int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
98619972
struct net_device *lag_dev,
98629973
struct netlink_ext_ack *extack)
@@ -9870,6 +9981,14 @@ int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
98709981
return err;
98719982
}
98729983

9984+
void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
9985+
struct net_device *lag_dev)
9986+
{
9987+
mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
9988+
__mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev);
9989+
mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
9990+
}
9991+
98739992
static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
98749993
unsigned long event, void *ptr)
98759994
{

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,10 @@ int mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp,
178178
int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
179179
struct net_device *lag_dev,
180180
struct netlink_ext_ack *extack);
181+
void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port,
182+
struct net_device *lag_dev);
183+
int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp,
184+
struct net_device *upper_dev,
185+
struct netlink_ext_ack *extack);
181186

182187
#endif /* _MLXSW_ROUTER_H_*/

drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,8 +2894,15 @@ int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
28942894
if (err)
28952895
goto err_port_join;
28962896

2897+
err = mlxsw_sp_netdevice_enslavement_replay(mlxsw_sp, br_dev, extack);
2898+
if (err)
2899+
goto err_replay;
2900+
28972901
return 0;
28982902

2903+
err_replay:
2904+
bridge_device->ops->port_leave(bridge_device, bridge_port,
2905+
mlxsw_sp_port);
28992906
err_port_join:
29002907
mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
29012908
return err;

0 commit comments

Comments
 (0)