mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
mlxsw: spectrum: Resolve neigh_table right before neigh_lookup().
We will replace neigh_lookup() and neigh_create() with IPv4/IPv6-specific helpers. mlxsw has two paths where neigh_table is fetched in advance and passed down to a function which calls neigh_lookup() and neigh_create(). To keep the changes simple, let's prepare them beforehand by delaying the neigh_table resolution until right before neigh_lookup(). struct mlxsw_sp_nexthop caches neigh_tbl, so it is replaced with family, and a new helper, mlxsw_sp_nexthop_neigh_lookup(), resolves neigh_table and calls neigh_lookup() and neigh_create(). Similarly, mlxsw_sp_span_entry_gretap[46]_parms() now pass family to mlxsw_sp_span_dmac() to resolve neigh_table there just before neigh_lookup() and neigh_create(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20261003212336.1304988-6-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
616b2143f9
commit
98071355ff
|
|
@ -3073,9 +3073,9 @@ struct mlxsw_sp_nexthop {
|
|||
* this nexthop belongs to
|
||||
*/
|
||||
struct rhash_head ht_node;
|
||||
struct neigh_table *neigh_tbl;
|
||||
struct mlxsw_sp_nexthop_key key;
|
||||
unsigned char gw_addr[sizeof(struct in6_addr)];
|
||||
int family;
|
||||
int ifindex;
|
||||
int nh_weight;
|
||||
int norm_nh_weight;
|
||||
|
|
@ -4301,28 +4301,49 @@ static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
|
|||
nh->update = 1;
|
||||
}
|
||||
|
||||
static struct neighbour *
|
||||
mlxsw_sp_nexthop_neigh_lookup(struct mlxsw_sp_nexthop *nh)
|
||||
{
|
||||
struct neigh_table *tbl;
|
||||
struct net_device *dev;
|
||||
struct neighbour *n;
|
||||
struct net *net;
|
||||
|
||||
dev = mlxsw_sp_nexthop_dev(nh);
|
||||
net = dev_net(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (nh->family == AF_INET6)
|
||||
tbl = nd_table(net);
|
||||
else
|
||||
#endif
|
||||
tbl = arp_table(net);
|
||||
|
||||
n = neigh_lookup(tbl, &nh->gw_addr, dev);
|
||||
if (!n) {
|
||||
n = neigh_create(tbl, &nh->gw_addr, dev);
|
||||
if (!IS_ERR(n))
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
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, dev);
|
||||
if (!n) {
|
||||
n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
|
||||
if (IS_ERR(n))
|
||||
return PTR_ERR(n);
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
n = mlxsw_sp_nexthop_neigh_lookup(nh);
|
||||
if (IS_ERR(n))
|
||||
return PTR_ERR(n);
|
||||
|
||||
mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
|
||||
neigh_entry->key.n = n;
|
||||
|
|
@ -4403,7 +4424,6 @@ 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;
|
||||
|
|
@ -4413,20 +4433,16 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
|
|||
|
||||
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, dev);
|
||||
if (!n) {
|
||||
n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
|
||||
if (IS_ERR(n))
|
||||
return PTR_ERR(n);
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
n = mlxsw_sp_nexthop_neigh_lookup(nh);
|
||||
if (IS_ERR(n))
|
||||
return PTR_ERR(n);
|
||||
|
||||
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
|
||||
if (!neigh_entry) {
|
||||
neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
|
||||
|
|
@ -4631,7 +4647,7 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
|
|||
nh->nh_weight = 1;
|
||||
#endif
|
||||
memcpy(&nh->gw_addr, &fib_nh->fib_nh_gw4, sizeof(fib_nh->fib_nh_gw4));
|
||||
nh->neigh_tbl = arp_table(mlxsw_sp_net(mlxsw_sp));
|
||||
nh->family = AF_INET;
|
||||
err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -5121,7 +5137,6 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
|
|||
struct nh_notifier_single_info *nh_obj, int weight)
|
||||
{
|
||||
struct net_device *dev = nh_obj->dev;
|
||||
struct net *net = dev_net(dev);
|
||||
int err;
|
||||
|
||||
nh->nhgi = nh_grp->nhgi;
|
||||
|
|
@ -5130,12 +5145,12 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
|
|||
switch (nh_obj->gw_family) {
|
||||
case AF_INET:
|
||||
memcpy(&nh->gw_addr, &nh_obj->ipv4, sizeof(nh_obj->ipv4));
|
||||
nh->neigh_tbl = arp_table(net);
|
||||
nh->family = AF_INET;
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&nh->gw_addr, &nh_obj->ipv6, sizeof(nh_obj->ipv6));
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
nh->neigh_tbl = nd_table(net);
|
||||
nh->family = AF_INET6;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -6991,7 +7006,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
|
|||
nh->nh_weight = rt->fib6_nh->fib_nh_weight;
|
||||
memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
nh->neigh_tbl = nd_table(mlxsw_sp_net(mlxsw_sp));
|
||||
nh->family = AF_INET6;
|
||||
#endif
|
||||
|
||||
err = mlxsw_sp_nexthop_counter_enable(mlxsw_sp, nh);
|
||||
|
|
|
|||
|
|
@ -224,14 +224,24 @@ struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_phys = {
|
|||
.deconfigure = mlxsw_sp_span_entry_phys_deconfigure,
|
||||
};
|
||||
|
||||
static int mlxsw_sp_span_dmac(struct neigh_table *tbl,
|
||||
static int mlxsw_sp_span_dmac(int family,
|
||||
const void *pkey,
|
||||
struct net_device *dev,
|
||||
unsigned char dmac[ETH_ALEN])
|
||||
{
|
||||
struct neighbour *neigh = neigh_lookup(tbl, pkey, dev);
|
||||
struct net *net = dev_net(dev);
|
||||
struct neigh_table *tbl;
|
||||
struct neighbour *neigh;
|
||||
int err = 0;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6_GRE)
|
||||
if (family == AF_INET6)
|
||||
tbl = nd_table(net);
|
||||
else
|
||||
#endif
|
||||
tbl = arp_table(net);
|
||||
|
||||
neigh = neigh_lookup(tbl, pkey, dev);
|
||||
if (!neigh) {
|
||||
neigh = neigh_create(tbl, pkey, dev);
|
||||
if (IS_ERR(neigh))
|
||||
|
|
@ -355,8 +365,7 @@ mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *edev,
|
|||
union mlxsw_sp_l3addr saddr,
|
||||
union mlxsw_sp_l3addr daddr,
|
||||
union mlxsw_sp_l3addr gw,
|
||||
__u8 ttl,
|
||||
struct neigh_table *tbl,
|
||||
__u8 ttl, int family,
|
||||
struct mlxsw_sp_span_parms *sparmsp)
|
||||
{
|
||||
unsigned char dmac[ETH_ALEN];
|
||||
|
|
@ -365,7 +374,7 @@ mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *edev,
|
|||
if (mlxsw_sp_l3addr_is_zero(gw))
|
||||
gw = daddr;
|
||||
|
||||
if (!edev || mlxsw_sp_span_dmac(tbl, &gw, edev, dmac))
|
||||
if (!edev || mlxsw_sp_span_dmac(family, &gw, edev, dmac))
|
||||
goto unoffloadable;
|
||||
|
||||
if (is_vlan_dev(edev))
|
||||
|
|
@ -456,7 +465,6 @@ mlxsw_sp_span_entry_gretap4_parms(struct mlxsw_sp *mlxsw_sp,
|
|||
bool inherit_tos = tparm.iph.tos & 0x1;
|
||||
bool inherit_ttl = !tparm.iph.ttl;
|
||||
union mlxsw_sp_l3addr gw = daddr;
|
||||
struct neigh_table *tbl = NULL;
|
||||
struct net_device *l3edev;
|
||||
|
||||
if (!(to_dev->flags & IFF_UP) ||
|
||||
|
|
@ -470,11 +478,10 @@ mlxsw_sp_span_entry_gretap4_parms(struct mlxsw_sp *mlxsw_sp,
|
|||
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
|
||||
|
||||
l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
|
||||
if (l3edev)
|
||||
tbl = arp_table(dev_net(l3edev));
|
||||
|
||||
return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
|
||||
tparm.iph.ttl,
|
||||
tbl, sparmsp);
|
||||
AF_INET, sparmsp);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -564,7 +571,6 @@ mlxsw_sp_span_entry_gretap6_parms(struct mlxsw_sp *mlxsw_sp,
|
|||
union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr };
|
||||
bool inherit_ttl = !tparm.hop_limit;
|
||||
union mlxsw_sp_l3addr gw = daddr;
|
||||
struct neigh_table *tbl = NULL;
|
||||
struct net_device *l3edev;
|
||||
|
||||
if (!(to_dev->flags & IFF_UP) ||
|
||||
|
|
@ -578,11 +584,10 @@ mlxsw_sp_span_entry_gretap6_parms(struct mlxsw_sp *mlxsw_sp,
|
|||
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
|
||||
|
||||
l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6);
|
||||
if (l3edev)
|
||||
tbl = nd_table(dev_net(l3edev));
|
||||
|
||||
return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
|
||||
tparm.hop_limit,
|
||||
tbl, sparmsp);
|
||||
AF_INET6, sparmsp);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user