Skip to content

Commit 23dd831

Browse files
committed
Merge branch 'mlxsw-fixes'
Jiri Pirko says: ==================== mlxsw: Couple of router fixes v1->v2: - patch2: - use net_eq ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2ce0af8 + 0e3715c commit 23dd831

File tree

1 file changed

+37
-61
lines changed

1 file changed

+37
-61
lines changed

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

Lines changed: 37 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -600,15 +600,13 @@ static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
600600
}
601601

602602
struct mlxsw_sp_neigh_key {
603-
unsigned char addr[sizeof(struct in6_addr)];
604-
struct net_device *dev;
603+
struct neighbour *n;
605604
};
606605

607606
struct mlxsw_sp_neigh_entry {
608607
struct rhash_head ht_node;
609608
struct mlxsw_sp_neigh_key key;
610609
u16 rif;
611-
struct neighbour *n;
612610
bool offloaded;
613611
struct delayed_work dw;
614612
struct mlxsw_sp_port *mlxsw_sp_port;
@@ -646,19 +644,15 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
646644
static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work);
647645

648646
static struct mlxsw_sp_neigh_entry *
649-
mlxsw_sp_neigh_entry_create(const void *addr, size_t addr_len,
650-
struct net_device *dev, u16 rif,
651-
struct neighbour *n)
647+
mlxsw_sp_neigh_entry_create(struct neighbour *n, u16 rif)
652648
{
653649
struct mlxsw_sp_neigh_entry *neigh_entry;
654650

655651
neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_ATOMIC);
656652
if (!neigh_entry)
657653
return NULL;
658-
memcpy(neigh_entry->key.addr, addr, addr_len);
659-
neigh_entry->key.dev = dev;
654+
neigh_entry->key.n = n;
660655
neigh_entry->rif = rif;
661-
neigh_entry->n = n;
662656
INIT_DELAYED_WORK(&neigh_entry->dw, mlxsw_sp_router_neigh_update_hw);
663657
INIT_LIST_HEAD(&neigh_entry->nexthop_list);
664658
return neigh_entry;
@@ -671,13 +665,11 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp_neigh_entry *neigh_entry)
671665
}
672666

673667
static struct mlxsw_sp_neigh_entry *
674-
mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, const void *addr,
675-
size_t addr_len, struct net_device *dev)
668+
mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
676669
{
677-
struct mlxsw_sp_neigh_key key = {{ 0 } };
670+
struct mlxsw_sp_neigh_key key;
678671

679-
memcpy(key.addr, addr, addr_len);
680-
key.dev = dev;
672+
key.n = n;
681673
return rhashtable_lookup_fast(&mlxsw_sp->router.neigh_ht,
682674
&key, mlxsw_sp_neigh_ht_params);
683675
}
@@ -689,26 +681,20 @@ int mlxsw_sp_router_neigh_construct(struct net_device *dev,
689681
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
690682
struct mlxsw_sp_neigh_entry *neigh_entry;
691683
struct mlxsw_sp_rif *r;
692-
u32 dip;
693684
int err;
694685

695686
if (n->tbl != &arp_tbl)
696687
return 0;
697688

698-
dip = ntohl(*((__be32 *) n->primary_key));
699-
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip),
700-
n->dev);
701-
if (neigh_entry) {
702-
WARN_ON(neigh_entry->n != n);
689+
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
690+
if (neigh_entry)
703691
return 0;
704-
}
705692

706693
r = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
707694
if (WARN_ON(!r))
708695
return -EINVAL;
709696

710-
neigh_entry = mlxsw_sp_neigh_entry_create(&dip, sizeof(dip), n->dev,
711-
r->rif, n);
697+
neigh_entry = mlxsw_sp_neigh_entry_create(n, r->rif);
712698
if (!neigh_entry)
713699
return -ENOMEM;
714700
err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
@@ -727,14 +713,11 @@ void mlxsw_sp_router_neigh_destroy(struct net_device *dev,
727713
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
728714
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
729715
struct mlxsw_sp_neigh_entry *neigh_entry;
730-
u32 dip;
731716

732717
if (n->tbl != &arp_tbl)
733718
return;
734719

735-
dip = ntohl(*((__be32 *) n->primary_key));
736-
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip),
737-
n->dev);
720+
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
738721
if (!neigh_entry)
739722
return;
740723
mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
@@ -862,7 +845,7 @@ static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
862845
* is active regardless of the traffic.
863846
*/
864847
if (!list_empty(&neigh_entry->nexthop_list))
865-
neigh_event_send(neigh_entry->n, NULL);
848+
neigh_event_send(neigh_entry->key.n, NULL);
866849
}
867850
rtnl_unlock();
868851
}
@@ -908,9 +891,9 @@ static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
908891
rtnl_lock();
909892
list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list,
910893
nexthop_neighs_list_node) {
911-
if (!(neigh_entry->n->nud_state & NUD_VALID) &&
894+
if (!(neigh_entry->key.n->nud_state & NUD_VALID) &&
912895
!list_empty(&neigh_entry->nexthop_list))
913-
neigh_event_send(neigh_entry->n, NULL);
896+
neigh_event_send(neigh_entry->key.n, NULL);
914897
}
915898
rtnl_unlock();
916899

@@ -927,7 +910,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
927910
{
928911
struct mlxsw_sp_neigh_entry *neigh_entry =
929912
container_of(work, struct mlxsw_sp_neigh_entry, dw.work);
930-
struct neighbour *n = neigh_entry->n;
913+
struct neighbour *n = neigh_entry->key.n;
931914
struct mlxsw_sp_port *mlxsw_sp_port = neigh_entry->mlxsw_sp_port;
932915
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
933916
char rauht_pl[MLXSW_REG_RAUHT_LEN];
@@ -1030,11 +1013,8 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
10301013

10311014
mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
10321015
dip = ntohl(*((__be32 *) n->primary_key));
1033-
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp,
1034-
&dip,
1035-
sizeof(__be32),
1036-
dev);
1037-
if (WARN_ON(!neigh_entry) || WARN_ON(neigh_entry->n != n)) {
1016+
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
1017+
if (WARN_ON(!neigh_entry)) {
10381018
mlxsw_sp_port_dev_put(mlxsw_sp_port);
10391019
return NOTIFY_DONE;
10401020
}
@@ -1343,33 +1323,26 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
13431323
struct fib_nh *fib_nh)
13441324
{
13451325
struct mlxsw_sp_neigh_entry *neigh_entry;
1346-
u32 gwip = ntohl(fib_nh->nh_gw);
13471326
struct net_device *dev = fib_nh->nh_dev;
13481327
struct neighbour *n;
13491328
u8 nud_state;
13501329

1351-
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip,
1352-
sizeof(gwip), dev);
1353-
if (!neigh_entry) {
1354-
__be32 gwipn = htonl(gwip);
1355-
1356-
n = neigh_create(&arp_tbl, &gwipn, dev);
1330+
/* Take a reference of neigh here ensuring that neigh would
1331+
* not be detructed before the nexthop entry is finished.
1332+
* The reference is taken either in neigh_lookup() or
1333+
* in neith_create() in case n is not found.
1334+
*/
1335+
n = neigh_lookup(&arp_tbl, &fib_nh->nh_gw, dev);
1336+
if (!n) {
1337+
n = neigh_create(&arp_tbl, &fib_nh->nh_gw, dev);
13571338
if (IS_ERR(n))
13581339
return PTR_ERR(n);
13591340
neigh_event_send(n, NULL);
1360-
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip,
1361-
sizeof(gwip), dev);
1362-
if (!neigh_entry) {
1363-
neigh_release(n);
1364-
return -EINVAL;
1365-
}
1366-
} else {
1367-
/* Take a reference of neigh here ensuring that neigh would
1368-
* not be detructed before the nexthop entry is finished.
1369-
* The second branch takes the reference in neith_create()
1370-
*/
1371-
n = neigh_entry->n;
1372-
neigh_clone(n);
1341+
}
1342+
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
1343+
if (!neigh_entry) {
1344+
neigh_release(n);
1345+
return -EINVAL;
13731346
}
13741347

13751348
/* If that is the first nexthop connected to that neigh, add to
@@ -1403,7 +1376,7 @@ static void mlxsw_sp_nexthop_fini(struct mlxsw_sp *mlxsw_sp,
14031376
if (list_empty(&nh->neigh_entry->nexthop_list))
14041377
list_del(&nh->neigh_entry->nexthop_neighs_list_node);
14051378

1406-
neigh_release(neigh_entry->n);
1379+
neigh_release(neigh_entry->key.n);
14071380
}
14081381

14091382
static struct mlxsw_sp_nexthop_group *
@@ -1463,11 +1436,11 @@ static bool mlxsw_sp_nexthop_match(struct mlxsw_sp_nexthop *nh,
14631436

14641437
for (i = 0; i < fi->fib_nhs; i++) {
14651438
struct fib_nh *fib_nh = &fi->fib_nh[i];
1466-
u32 gwip = ntohl(fib_nh->nh_gw);
1439+
struct neighbour *n = nh->neigh_entry->key.n;
14671440

1468-
if (memcmp(nh->neigh_entry->key.addr,
1469-
&gwip, sizeof(u32)) == 0 &&
1470-
nh->neigh_entry->key.dev == fib_nh->nh_dev)
1441+
if (memcmp(n->primary_key, &fib_nh->nh_gw,
1442+
sizeof(fib_nh->nh_gw)) == 0 &&
1443+
n->dev == fib_nh->nh_dev)
14711444
return true;
14721445
}
14731446
return false;
@@ -1958,6 +1931,9 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
19581931
struct fib_entry_notifier_info *fen_info = ptr;
19591932
int err;
19601933

1934+
if (!net_eq(fen_info->info.net, &init_net))
1935+
return NOTIFY_DONE;
1936+
19611937
switch (event) {
19621938
case FIB_EVENT_ENTRY_ADD:
19631939
err = mlxsw_sp_router_fib4_add(mlxsw_sp, fen_info);

0 commit comments

Comments
 (0)