mlxsw: spectrum: Apply RIF configuration when joining a LAG
authorIdo Schimmel <idosch@nvidia.com>
Sun, 6 Dec 2020 08:22:21 +0000 (10:22 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Dec 2020 03:22:14 +0000 (19:22 -0800)
In case a router interface (RIF) is configured for a LAG, make sure its
configuration is applied on the new LAG member.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

index 385eb3c..65e8407 100644 (file)
@@ -3595,7 +3595,8 @@ static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
-                                 struct net_device *lag_dev)
+                                 struct net_device *lag_dev,
+                                 struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        struct mlxsw_sp_upper *lag;
@@ -3631,8 +3632,20 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
        if (mlxsw_sp_port->default_vlan->fid)
                mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
 
+       /* Join a router interface configured on the LAG, if exists */
+       err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan,
+                                            lag_dev, extack);
+       if (err)
+               goto err_router_join;
+
        return 0;
 
+err_router_join:
+       lag->ref_count--;
+       mlxsw_sp_port->lagged = 0;
+       mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
+                                    mlxsw_sp_port->local_port);
+       mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
 err_col_port_add:
        if (!lag->ref_count)
                mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -3997,7 +4010,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                } else if (netif_is_lag_master(upper_dev)) {
                        if (info->linking) {
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
-                                                            upper_dev);
+                                                            upper_dev, extack);
                        } else {
                                mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
index ce26cc4..6092243 100644 (file)
@@ -656,6 +656,10 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
                                 struct net_device *l3_dev,
                                 unsigned long event,
                                 struct netdev_notifier_info *info);
+int
+mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+                              struct net_device *l3_dev,
+                              struct netlink_ext_ack *extack);
 void
 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
 void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
index 8522364..20b141f 100644 (file)
@@ -7697,9 +7697,9 @@ static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif)
 }
 
 static int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
-                              struct net_device *l3_dev,
-                              struct netlink_ext_ack *extack)
+__mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+                                struct net_device *l3_dev,
+                                struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
@@ -7764,6 +7764,27 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
        mlxsw_sp_rif_subport_put(rif);
 }
 
+int
+mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+                              struct net_device *l3_dev,
+                              struct netlink_ext_ack *extack)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
+       struct mlxsw_sp_rif *rif;
+       int err = 0;
+
+       mutex_lock(&mlxsw_sp->router->lock);
+       rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
+       if (!rif)
+               goto out;
+
+       err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
+                                              extack);
+out:
+       mutex_unlock(&mlxsw_sp->router->lock);
+       return err;
+}
+
 void
 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 {
@@ -7788,8 +7809,8 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
 
        switch (event) {
        case NETDEV_UP:
-               return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
-                                                     l3_dev, extack);
+               return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
+                                                       l3_dev, extack);
        case NETDEV_DOWN:
                __mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
                break;