diff options
4 files changed, 211 insertions, 109 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4609b13bda02b..25a01dafde1ba 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4337,8 +4337,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, 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); + err = mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, + extack); if (err) goto err_router_join; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 0b57c8d0cce0a..231e364cbb7c3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -755,10 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp, const struct net_device *macvlan_dev); -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, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index f9328e8410f52..43e8f19c7a0a5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -71,6 +71,11 @@ struct mlxsw_sp_rif { bool counter_egress_valid; }; +static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) +{ + return rif->dev; +} + struct mlxsw_sp_rif_params { struct net_device *dev; union { @@ -1560,6 +1565,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, u16 ul_rif_id, bool enable) { struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config; + struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common); enum mlxsw_reg_ritr_loopback_ipip_options ipip_options; struct mlxsw_sp_rif *rif = &lb_rif->common; struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; @@ -1572,7 +1578,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, case MLXSW_SP_L3_PROTO_IPV4: saddr4 = be32_to_cpu(lb_cf.saddr.addr4); mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); + rif->rif_index, rif->vr_id, dev->mtu); mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt, ipip_options, ul_vr_id, ul_rif_id, saddr4, @@ -1582,7 +1588,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, case MLXSW_SP_L3_PROTO_IPV6: saddr6 = &lb_cf.saddr.addr6; mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); + rif->rif_index, rif->vr_id, dev->mtu); mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt, ipip_options, ul_vr_id, ul_rif_id, saddr6, @@ -1645,6 +1651,17 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *old_rif, struct mlxsw_sp_rif *new_rif); +static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *old_rif, + struct mlxsw_sp_rif *new_rif, + bool migrate_nhs) +{ + if (migrate_nhs) + mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, old_rif, new_rif); + + mlxsw_sp_rif_destroy(old_rif); +} + static int mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_ipip_entry *ipip_entry, @@ -1662,12 +1679,8 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp, return PTR_ERR(new_lb_rif); ipip_entry->ol_lb = new_lb_rif; - if (keep_encap) - mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common, - &new_lb_rif->common); - - mlxsw_sp_rif_destroy(&old_lb_rif->common); - + mlxsw_sp_rif_migrate_destroy(mlxsw_sp, &old_lb_rif->common, + &new_lb_rif->common, keep_encap); return 0; } @@ -2332,7 +2345,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp, } dipn = htonl(dip); - dev = mlxsw_sp->router->rifs[rif]->dev; + dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); n = neigh_lookup(&arp_tbl, &dipn, dev); if (!n) return; @@ -2360,7 +2373,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, return; } - dev = mlxsw_sp->router->rifs[rif]->dev; + dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); n = neigh_lookup(&nd_tbl, &dip, dev); if (!n) return; @@ -2935,6 +2948,14 @@ struct mlxsw_sp_nexthop { bool counter_valid; }; +static struct net_device * +mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh) +{ + if (nh->rif) + return mlxsw_sp_rif_dev(nh->rif); + return NULL; +} + enum mlxsw_sp_nexthop_group_type { MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4, MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6, @@ -2952,9 +2973,14 @@ struct mlxsw_sp_nexthop_group_info { is_resilient:1; struct list_head list; /* member in nh_res_grp_list */ struct mlxsw_sp_nexthop nexthops[]; -#define nh_rif nexthops[0].rif }; +static struct mlxsw_sp_rif * +mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi) +{ + return nhgi->nexthops[0].rif; +} + struct mlxsw_sp_nexthop_group_vr_key { u16 vr_id; enum mlxsw_sp_l3proto proto; @@ -4008,16 +4034,18 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, { struct neighbour *n, *old_n = neigh_entry->key.n; struct mlxsw_sp_nexthop *nh; + struct net_device *dev; bool entry_connected; u8 nud_state, dead; int err; nh = list_first_entry(&neigh_entry->nexthop_list, struct mlxsw_sp_nexthop, neigh_list_node); + dev = mlxsw_sp_nexthop_dev(nh); - n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev); if (!n) { - n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev); if (IS_ERR(n)) return PTR_ERR(n); neigh_event_send(n, NULL); @@ -4104,21 +4132,23 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh) { struct mlxsw_sp_neigh_entry *neigh_entry; + struct net_device *dev; struct neighbour *n; u8 nud_state, dead; int err; if (!nh->nhgi->gateway || nh->neigh_entry) return 0; + dev = mlxsw_sp_nexthop_dev(nh); /* Take a reference of neigh here ensuring that neigh would * not be destructed before the nexthop entry is finished. * The reference is taken either in neigh_lookup() or * in neigh_create() in case n is not found. */ - n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev); if (!n) { - n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev); if (IS_ERR(n)) return PTR_ERR(n); neigh_event_send(n, NULL); @@ -4368,6 +4398,7 @@ static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_nexthop *nh; bool removing; @@ -4377,7 +4408,7 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, removing = false; break; case MLXSW_SP_NEXTHOP_TYPE_IPIP: - removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev); + removing = !mlxsw_sp_ipip_netdev_ul_up(dev); break; default: WARN_ON(1); @@ -5491,7 +5522,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry) case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE: return !!nh_group->nhgi->adj_index_valid; case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: - return !!nh_group->nhgi->nh_rif; + return !!mlxsw_sp_nhgi_rif(nh_group->nhgi); case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE: case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP: @@ -5509,9 +5540,10 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp, for (i = 0; i < nh_grp->nhgi->count; i++) { struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i]; + struct net_device *dev = mlxsw_sp_nexthop_dev(nh); struct fib6_info *rt = mlxsw_sp_rt6->rt; - if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev && + if (dev && dev == rt->fib6_nh->fib_nh_dev && ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr, &rt->fib6_nh->fib_nh_gw6)) return nh; @@ -5752,7 +5784,8 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp, trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; adjacency_index = nhgi->adj_index; ecmp_size = nhgi->ecmp_size; - } else if (!nhgi->adj_index_valid && nhgi->count && nhgi->nh_rif) { + } else if (!nhgi->adj_index_valid && nhgi->count && + mlxsw_sp_nhgi_rif(nhgi)) { trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; adjacency_index = mlxsw_sp->router->adj_trap_index; ecmp_size = 1; @@ -5771,7 +5804,7 @@ static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry, enum mlxsw_reg_ralue_op op) { - struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif; + struct mlxsw_sp_rif *rif = mlxsw_sp_nhgi_rif(fib_entry->nh_group->nhgi); enum mlxsw_reg_ralue_trap_action trap_action; char ralue_pl[MLXSW_REG_RALUE_LEN]; u16 trap_id = 0; @@ -7768,28 +7801,44 @@ static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif); } +static bool __mlxsw_sp_dev_addr_list_empty(const struct net_device *dev) +{ + struct inet6_dev *inet6_dev; + struct in_device *idev; + + idev = __in_dev_get_rcu(dev); + if (idev && idev->ifa_list) + return false; + + inet6_dev = __in6_dev_get(dev); + if (inet6_dev && !list_empty(&inet6_dev->addr_list)) + return false; + + return true; +} + +static bool mlxsw_sp_dev_addr_list_empty(const struct net_device *dev) +{ + bool addr_list_empty; + + rcu_read_lock(); + addr_list_empty = __mlxsw_sp_dev_addr_list_empty(dev); + rcu_read_unlock(); + + return addr_list_empty; +} + static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev, unsigned long event) { - struct inet6_dev *inet6_dev; - bool addr_list_empty = true; - struct in_device *idev; + bool addr_list_empty; switch (event) { case NETDEV_UP: return rif == NULL; case NETDEV_DOWN: - rcu_read_lock(); - idev = __in_dev_get_rcu(dev); - if (idev && idev->ifa_list) - addr_list_empty = false; - - inet6_dev = __in6_dev_get(dev); - if (addr_list_empty && inet6_dev && - !list_empty(&inet6_dev->addr_list)) - addr_list_empty = false; - rcu_read_unlock(); + addr_list_empty = mlxsw_sp_dev_addr_list_empty(dev); /* macvlans do not have a RIF, but rather piggy back on the * RIF of their lower device. @@ -7798,7 +7847,7 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev, return true; if (rif && addr_list_empty && - !netif_is_l3_slave(rif->dev)) + !netif_is_l3_slave(mlxsw_sp_rif_dev(rif))) return true; /* It is possible we already removed the RIF ourselves * if it was assigned to a netdev that is now a bridge @@ -7877,6 +7926,13 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index, return rif; } +static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif) +{ + WARN_ON(!list_empty(&rif->neigh_list)); + WARN_ON(!list_empty(&rif->nexthop_list)); + kfree(rif); +} + struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp, u16 rif_index) { @@ -7895,7 +7951,8 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif) u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) { - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev); + struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp_vr *ul_vr; ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL); @@ -8072,12 +8129,7 @@ mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev) int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) { - return rif->dev->ifindex; -} - -static const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) -{ - return rif->dev; + return mlxsw_sp_rif_dev(rif)->ifindex; } bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif) @@ -8096,7 +8148,7 @@ static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif) struct rtnl_hw_stats64 stats = {}; if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats)) - netdev_offload_xstats_push_delta(rif->dev, + netdev_offload_xstats_push_delta(mlxsw_sp_rif_dev(rif), NETDEV_OFFLOAD_XSTATS_TYPE_L3, &stats); } @@ -8135,7 +8187,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, err = -ENOMEM; goto err_rif_alloc; } - dev_hold(rif->dev); + dev_hold(params->dev); mlxsw_sp->router->rifs[rif_index] = rif; rif->mlxsw_sp = mlxsw_sp; rif->ops = ops; @@ -8163,12 +8215,12 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, goto err_mr_rif_add; } - if (netdev_offload_xstats_enabled(rif->dev, + if (netdev_offload_xstats_enabled(params->dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { err = mlxsw_sp_router_port_l3_stats_enable(rif); if (err) goto err_stats_enable; - mlxsw_sp_router_hwstats_notify_schedule(rif->dev); + mlxsw_sp_router_hwstats_notify_schedule(params->dev); } else { mlxsw_sp_rif_counters_alloc(rif); } @@ -8186,8 +8238,8 @@ err_configure: mlxsw_sp_fid_put(fid); err_fid_get: mlxsw_sp->router->rifs[rif_index] = NULL; - dev_put(rif->dev); - kfree(rif); + dev_put(params->dev); + mlxsw_sp_rif_free(rif); err_rif_alloc: mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); err_rif_index_alloc: @@ -8198,6 +8250,7 @@ err_rif_index_alloc: static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); const struct mlxsw_sp_rif_ops *ops = rif->ops; struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_fid *fid = rif->fid; @@ -8210,11 +8263,10 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); vr = &mlxsw_sp->router->vrs[rif->vr_id]; - if (netdev_offload_xstats_enabled(rif->dev, - NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { + if (netdev_offload_xstats_enabled(dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { mlxsw_sp_rif_push_l3_stats(rif); mlxsw_sp_router_port_l3_stats_disable(rif); - mlxsw_sp_router_hwstats_notify_schedule(rif->dev); + mlxsw_sp_router_hwstats_notify_schedule(dev); } else { mlxsw_sp_rif_counters_free(rif); } @@ -8226,8 +8278,8 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) /* Loopback RIFs are not associated with a FID. */ mlxsw_sp_fid_put(fid); mlxsw_sp->router->rifs[rif->rif_index] = NULL; - dev_put(rif->dev); - kfree(rif); + dev_put(dev); + mlxsw_sp_rif_free(rif); mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); vr->rif_count--; mlxsw_sp_vr_put(mlxsw_sp, vr); @@ -8562,25 +8614,20 @@ __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) +static int +mlxsw_sp_port_vlan_router_join_existing(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; + lockdep_assert_held(&mlxsw_sp->router->lock); - err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev, - extack); -out: - mutex_unlock(&mlxsw_sp->router->lock); - return err; + if (!mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev)) + return 0; + + return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev, + extack); } void @@ -9017,7 +9064,7 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { - struct net_device *dev = rif->dev; + struct net_device *dev = mlxsw_sp_rif_dev(rif); u8 old_mac_profile; u16 fid_index; int err; @@ -9267,6 +9314,46 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, return err; } +static int +mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid, struct net_device *dev, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; + + mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, + vid); + if (WARN_ON(!mlxsw_sp_port_vlan)) + return -EINVAL; + + return mlxsw_sp_port_vlan_router_join_existing(mlxsw_sp_port_vlan, + dev, extack); +} + +static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + u16 default_vid = MLXSW_SP_DEFAULT_VID; + + return mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, + default_vid, lag_dev, + extack); +} + +int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + int err; + + mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock); + err = __mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, extack); + mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock); + + return err; +} + static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -9313,15 +9400,16 @@ static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct netdev_nested_priv priv = { .data = (void *)rif, }; - if (!netif_is_macvlan_port(rif->dev)) + if (!netif_is_macvlan_port(dev)) return 0; - netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n"); - return netdev_walk_all_upper_dev_rcu(rif->dev, + netdev_warn(dev, "Router interface is deleted. Upper macvlans will not work\n"); + return netdev_walk_all_upper_dev_rcu(dev, __mlxsw_sp_rif_macvlan_flush, &priv); } @@ -9342,6 +9430,7 @@ static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif, static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_rif_subport *rif_subport; char ritr_pl[MLXSW_REG_RITR_LEN]; @@ -9349,8 +9438,8 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) rif_subport = mlxsw_sp_rif_subport_rif(rif); mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); - mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + rif->rif_index, rif->vr_id, dev->mtu); + mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr); mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); efid = mlxsw_sp_fid_index(rif->fid); mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag, @@ -9363,6 +9452,7 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u8 mac_profile; int err; @@ -9376,7 +9466,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, if (err) goto err_rif_subport_op; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9388,7 +9478,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_rif_subport_op(rif, false); @@ -9399,10 +9489,11 @@ err_rif_subport_op: static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_fid *fid = rif->fid; mlxsw_sp_fid_rif_unset(fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_rif_subport_op(rif, false); @@ -9428,12 +9519,13 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = { static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable) { enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF; + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; char ritr_pl[MLXSW_REG_RITR_LEN]; mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id, - rif->dev->mtu); - mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + dev->mtu); + mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr); mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid); @@ -9448,6 +9540,7 @@ u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; u16 fid_index = mlxsw_sp_fid_index(rif->fid); u8 mac_profile; @@ -9473,7 +9566,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, if (err) goto err_fid_bc_flood_set; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9485,7 +9578,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9502,12 +9595,13 @@ err_rif_fid_op: static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 fid_index = mlxsw_sp_fid_index(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_fid *fid = rif->fid; mlxsw_sp_fid_rif_unset(fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9522,7 +9616,9 @@ static struct mlxsw_sp_fid * mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { - return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex); + int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif); + + return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif_ifindex); } static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) @@ -9530,7 +9626,7 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) struct switchdev_notifier_fdb_info info = {}; struct net_device *dev; - dev = br_fdb_find_port(rif->dev, mac, 0); + dev = br_fdb_find_port(mlxsw_sp_rif_dev(rif), mac, 0); if (!dev) return; @@ -9553,17 +9649,18 @@ static struct mlxsw_sp_fid * mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct net_device *br_dev; u16 vid; int err; - if (is_vlan_dev(rif->dev)) { - vid = vlan_dev_vlan_id(rif->dev); - br_dev = vlan_dev_real_dev(rif->dev); + if (is_vlan_dev(dev)) { + vid = vlan_dev_vlan_id(dev); + br_dev = vlan_dev_real_dev(dev); if (WARN_ON(!netif_is_bridge_master(br_dev))) return ERR_PTR(-EINVAL); } else { - err = br_vlan_get_pvid(rif->dev, &vid); + err = br_vlan_get_pvid(dev, &vid); if (err < 0 || !vid) { NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); return ERR_PTR(-EINVAL); @@ -9575,12 +9672,13 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) { + struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct switchdev_notifier_fdb_info info = {}; u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct net_device *br_dev; struct net_device *dev; - br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev; + br_dev = is_vlan_dev(rif_dev) ? vlan_dev_real_dev(rif_dev) : rif_dev; dev = br_fdb_find_port(br_dev, mac, vid); if (!dev) return; @@ -9594,11 +9692,12 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid, bool enable) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; char ritr_pl[MLXSW_REG_RITR_LEN]; mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id, - rif->dev->mtu, rif->dev->dev_addr, + dev->mtu, dev->dev_addr, rif->mac_profile_id, vid, efid); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); @@ -9607,6 +9706,7 @@ static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid, static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; u8 mac_profile; @@ -9632,7 +9732,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, if (err) goto err_fid_bc_flood_set; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9644,7 +9744,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9661,11 +9761,12 @@ err_rif_vlan_fid_op: static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; mlxsw_sp_fid_rif_unset(rif->fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9732,7 +9833,8 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); + struct net_device *dev = mlxsw_sp_rif_dev(rif); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_vr *ul_vr; int err; @@ -9830,7 +9932,7 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, ul_rif_op_err: mlxsw_sp->router->rifs[rif_index] = NULL; - kfree(ul_rif); + mlxsw_sp_rif_free(ul_rif); err_rif_alloc: mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); return ERR_PTR(err); @@ -9845,7 +9947,7 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif) atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count); mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false); mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL; - kfree(ul_rif); + mlxsw_sp_rif_free(ul_rif); mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); } @@ -9931,7 +10033,8 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); + struct net_device *dev = mlxsw_sp_rif_dev(rif); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_rif *ul_rif; int err; @@ -10540,14 +10643,14 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_router_init; - err = mlxsw_sp_rifs_init(mlxsw_sp); - if (err) - goto err_rifs_init; - err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp); if (err) goto err_ipips_init; + err = mlxsw_sp_rifs_init(mlxsw_sp); + if (err) + goto err_rifs_init; + err = rhashtable_init(&mlxsw_sp->router->nexthop_ht, &mlxsw_sp_nexthop_ht_params); if (err) @@ -10673,10 +10776,10 @@ err_lpm_init: err_nexthop_group_ht_init: rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); err_nexthop_ht_init: - mlxsw_sp_ipips_fini(mlxsw_sp); -err_ipips_init: mlxsw_sp_rifs_fini(mlxsw_sp); err_rifs_init: + mlxsw_sp_ipips_fini(mlxsw_sp); +err_ipips_init: __mlxsw_sp_router_fini(mlxsw_sp); err_router_init: cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); @@ -10709,8 +10812,8 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_sp_lpm_fini(mlxsw_sp); rhashtable_destroy(&router->nexthop_group_ht); rhashtable_destroy(&router->nexthop_ht); - mlxsw_sp_ipips_fini(mlxsw_sp); mlxsw_sp_rifs_fini(mlxsw_sp); + mlxsw_sp_ipips_fini(mlxsw_sp); __mlxsw_sp_router_fini(mlxsw_sp); cancel_delayed_work_sync(&router->nh_grp_activity_dw); mutex_destroy(&router->lock); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 5ff443f27136e..5a0babc614b49 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -170,5 +170,8 @@ int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); struct net_device * mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev); +int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack); #endif /* _MLXSW_ROUTER_H_*/ |