Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlxsw-fixes'

Jiri Pirko says:

====================
mlxsw: Couple of router fixes

v1->v2:
- patch2:
- use net_eq
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+37 -61
+37 -61
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
··· 600 600 } 601 601 602 602 struct mlxsw_sp_neigh_key { 603 - unsigned char addr[sizeof(struct in6_addr)]; 604 - struct net_device *dev; 603 + struct neighbour *n; 605 604 }; 606 605 607 606 struct mlxsw_sp_neigh_entry { 608 607 struct rhash_head ht_node; 609 608 struct mlxsw_sp_neigh_key key; 610 609 u16 rif; 611 - struct neighbour *n; 612 610 bool offloaded; 613 611 struct delayed_work dw; 614 612 struct mlxsw_sp_port *mlxsw_sp_port; ··· 644 646 static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work); 645 647 646 648 static struct mlxsw_sp_neigh_entry * 647 - mlxsw_sp_neigh_entry_create(const void *addr, size_t addr_len, 648 - struct net_device *dev, u16 rif, 649 - struct neighbour *n) 649 + mlxsw_sp_neigh_entry_create(struct neighbour *n, u16 rif) 650 650 { 651 651 struct mlxsw_sp_neigh_entry *neigh_entry; 652 652 653 653 neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_ATOMIC); 654 654 if (!neigh_entry) 655 655 return NULL; 656 - memcpy(neigh_entry->key.addr, addr, addr_len); 657 - neigh_entry->key.dev = dev; 656 + neigh_entry->key.n = n; 658 657 neigh_entry->rif = rif; 659 - neigh_entry->n = n; 660 658 INIT_DELAYED_WORK(&neigh_entry->dw, mlxsw_sp_router_neigh_update_hw); 661 659 INIT_LIST_HEAD(&neigh_entry->nexthop_list); 662 660 return neigh_entry; ··· 665 671 } 666 672 667 673 static struct mlxsw_sp_neigh_entry * 668 - mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, const void *addr, 669 - size_t addr_len, struct net_device *dev) 674 + mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n) 670 675 { 671 - struct mlxsw_sp_neigh_key key = {{ 0 } }; 676 + struct mlxsw_sp_neigh_key key; 672 677 673 - memcpy(key.addr, addr, addr_len); 674 - key.dev = dev; 678 + key.n = n; 675 679 return rhashtable_lookup_fast(&mlxsw_sp->router.neigh_ht, 676 680 &key, mlxsw_sp_neigh_ht_params); 677 681 } ··· 681 689 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 682 690 struct mlxsw_sp_neigh_entry *neigh_entry; 683 691 struct mlxsw_sp_rif *r; 684 - u32 dip; 685 692 int err; 686 693 687 694 if (n->tbl != &arp_tbl) 688 695 return 0; 689 696 690 - dip = ntohl(*((__be32 *) n->primary_key)); 691 - neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip), 692 - n->dev); 693 - if (neigh_entry) { 694 - WARN_ON(neigh_entry->n != n); 697 + neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 698 + if (neigh_entry) 695 699 return 0; 696 - } 697 700 698 701 r = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev); 699 702 if (WARN_ON(!r)) 700 703 return -EINVAL; 701 704 702 - neigh_entry = mlxsw_sp_neigh_entry_create(&dip, sizeof(dip), n->dev, 703 - r->rif, n); 705 + neigh_entry = mlxsw_sp_neigh_entry_create(n, r->rif); 704 706 if (!neigh_entry) 705 707 return -ENOMEM; 706 708 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry); ··· 713 727 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 714 728 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 715 729 struct mlxsw_sp_neigh_entry *neigh_entry; 716 - u32 dip; 717 730 718 731 if (n->tbl != &arp_tbl) 719 732 return; 720 733 721 - dip = ntohl(*((__be32 *) n->primary_key)); 722 - neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip), 723 - n->dev); 734 + neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 724 735 if (!neigh_entry) 725 736 return; 726 737 mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry); ··· 845 862 * is active regardless of the traffic. 846 863 */ 847 864 if (!list_empty(&neigh_entry->nexthop_list)) 848 - neigh_event_send(neigh_entry->n, NULL); 865 + neigh_event_send(neigh_entry->key.n, NULL); 849 866 } 850 867 rtnl_unlock(); 851 868 } ··· 891 908 rtnl_lock(); 892 909 list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list, 893 910 nexthop_neighs_list_node) { 894 - if (!(neigh_entry->n->nud_state & NUD_VALID) && 911 + if (!(neigh_entry->key.n->nud_state & NUD_VALID) && 895 912 !list_empty(&neigh_entry->nexthop_list)) 896 - neigh_event_send(neigh_entry->n, NULL); 913 + neigh_event_send(neigh_entry->key.n, NULL); 897 914 } 898 915 rtnl_unlock(); 899 916 ··· 910 927 { 911 928 struct mlxsw_sp_neigh_entry *neigh_entry = 912 929 container_of(work, struct mlxsw_sp_neigh_entry, dw.work); 913 - struct neighbour *n = neigh_entry->n; 930 + struct neighbour *n = neigh_entry->key.n; 914 931 struct mlxsw_sp_port *mlxsw_sp_port = neigh_entry->mlxsw_sp_port; 915 932 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 916 933 char rauht_pl[MLXSW_REG_RAUHT_LEN]; ··· 1013 1030 1014 1031 mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1015 1032 dip = ntohl(*((__be32 *) n->primary_key)); 1016 - neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, 1017 - &dip, 1018 - sizeof(__be32), 1019 - dev); 1020 - if (WARN_ON(!neigh_entry) || WARN_ON(neigh_entry->n != n)) { 1033 + neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 1034 + if (WARN_ON(!neigh_entry)) { 1021 1035 mlxsw_sp_port_dev_put(mlxsw_sp_port); 1022 1036 return NOTIFY_DONE; 1023 1037 } ··· 1323 1343 struct fib_nh *fib_nh) 1324 1344 { 1325 1345 struct mlxsw_sp_neigh_entry *neigh_entry; 1326 - u32 gwip = ntohl(fib_nh->nh_gw); 1327 1346 struct net_device *dev = fib_nh->nh_dev; 1328 1347 struct neighbour *n; 1329 1348 u8 nud_state; 1330 1349 1331 - neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip, 1332 - sizeof(gwip), dev); 1333 - if (!neigh_entry) { 1334 - __be32 gwipn = htonl(gwip); 1335 - 1336 - n = neigh_create(&arp_tbl, &gwipn, dev); 1350 + /* Take a reference of neigh here ensuring that neigh would 1351 + * not be detructed before the nexthop entry is finished. 1352 + * The reference is taken either in neigh_lookup() or 1353 + * in neith_create() in case n is not found. 1354 + */ 1355 + n = neigh_lookup(&arp_tbl, &fib_nh->nh_gw, dev); 1356 + if (!n) { 1357 + n = neigh_create(&arp_tbl, &fib_nh->nh_gw, dev); 1337 1358 if (IS_ERR(n)) 1338 1359 return PTR_ERR(n); 1339 1360 neigh_event_send(n, NULL); 1340 - neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip, 1341 - sizeof(gwip), dev); 1342 - if (!neigh_entry) { 1343 - neigh_release(n); 1344 - return -EINVAL; 1345 - } 1346 - } else { 1347 - /* Take a reference of neigh here ensuring that neigh would 1348 - * not be detructed before the nexthop entry is finished. 1349 - * The second branch takes the reference in neith_create() 1350 - */ 1351 - n = neigh_entry->n; 1352 - neigh_clone(n); 1361 + } 1362 + neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 1363 + if (!neigh_entry) { 1364 + neigh_release(n); 1365 + return -EINVAL; 1353 1366 } 1354 1367 1355 1368 /* If that is the first nexthop connected to that neigh, add to ··· 1376 1403 if (list_empty(&nh->neigh_entry->nexthop_list)) 1377 1404 list_del(&nh->neigh_entry->nexthop_neighs_list_node); 1378 1405 1379 - neigh_release(neigh_entry->n); 1406 + neigh_release(neigh_entry->key.n); 1380 1407 } 1381 1408 1382 1409 static struct mlxsw_sp_nexthop_group * ··· 1436 1463 1437 1464 for (i = 0; i < fi->fib_nhs; i++) { 1438 1465 struct fib_nh *fib_nh = &fi->fib_nh[i]; 1439 - u32 gwip = ntohl(fib_nh->nh_gw); 1466 + struct neighbour *n = nh->neigh_entry->key.n; 1440 1467 1441 - if (memcmp(nh->neigh_entry->key.addr, 1442 - &gwip, sizeof(u32)) == 0 && 1443 - nh->neigh_entry->key.dev == fib_nh->nh_dev) 1468 + if (memcmp(n->primary_key, &fib_nh->nh_gw, 1469 + sizeof(fib_nh->nh_gw)) == 0 && 1470 + n->dev == fib_nh->nh_dev) 1444 1471 return true; 1445 1472 } 1446 1473 return false; ··· 1930 1957 struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb); 1931 1958 struct fib_entry_notifier_info *fen_info = ptr; 1932 1959 int err; 1960 + 1961 + if (!net_eq(fen_info->info.net, &init_net)) 1962 + return NOTIFY_DONE; 1933 1963 1934 1964 switch (event) { 1935 1965 case FIB_EVENT_ENTRY_ADD: