aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-11-10 13:02:25 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-10 13:02:25 -0500
commit23dd8315485acae0acf4452509e2be9fc587d72c (patch)
tree16ad24bbf7f30e4639d5864b9b7f012bda8137c9
parent2ce0af8fd0a6c2938e49630a0fdf3257464576e3 (diff)
parent0e3715c9c250747280b1757ea267c577e7591e31 (diff)
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c98
1 files changed, 37 insertions, 61 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 4573da2c5560..040737e14a3f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -600,15 +600,13 @@ static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
600} 600}
601 601
602struct mlxsw_sp_neigh_key { 602struct mlxsw_sp_neigh_key {
603 unsigned char addr[sizeof(struct in6_addr)]; 603 struct neighbour *n;
604 struct net_device *dev;
605}; 604};
606 605
607struct mlxsw_sp_neigh_entry { 606struct mlxsw_sp_neigh_entry {
608 struct rhash_head ht_node; 607 struct rhash_head ht_node;
609 struct mlxsw_sp_neigh_key key; 608 struct mlxsw_sp_neigh_key key;
610 u16 rif; 609 u16 rif;
611 struct neighbour *n;
612 bool offloaded; 610 bool offloaded;
613 struct delayed_work dw; 611 struct delayed_work dw;
614 struct mlxsw_sp_port *mlxsw_sp_port; 612 struct mlxsw_sp_port *mlxsw_sp_port;
@@ -646,19 +644,15 @@ mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
646static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work); 644static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work);
647 645
648static struct mlxsw_sp_neigh_entry * 646static struct mlxsw_sp_neigh_entry *
649mlxsw_sp_neigh_entry_create(const void *addr, size_t addr_len, 647mlxsw_sp_neigh_entry_create(struct neighbour *n, u16 rif)
650 struct net_device *dev, u16 rif,
651 struct neighbour *n)
652{ 648{
653 struct mlxsw_sp_neigh_entry *neigh_entry; 649 struct mlxsw_sp_neigh_entry *neigh_entry;
654 650
655 neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_ATOMIC); 651 neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_ATOMIC);
656 if (!neigh_entry) 652 if (!neigh_entry)
657 return NULL; 653 return NULL;
658 memcpy(neigh_entry->key.addr, addr, addr_len); 654 neigh_entry->key.n = n;
659 neigh_entry->key.dev = dev;
660 neigh_entry->rif = rif; 655 neigh_entry->rif = rif;
661 neigh_entry->n = n;
662 INIT_DELAYED_WORK(&neigh_entry->dw, mlxsw_sp_router_neigh_update_hw); 656 INIT_DELAYED_WORK(&neigh_entry->dw, mlxsw_sp_router_neigh_update_hw);
663 INIT_LIST_HEAD(&neigh_entry->nexthop_list); 657 INIT_LIST_HEAD(&neigh_entry->nexthop_list);
664 return neigh_entry; 658 return neigh_entry;
@@ -671,13 +665,11 @@ mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp_neigh_entry *neigh_entry)
671} 665}
672 666
673static struct mlxsw_sp_neigh_entry * 667static struct mlxsw_sp_neigh_entry *
674mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, const void *addr, 668mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
675 size_t addr_len, struct net_device *dev)
676{ 669{
677 struct mlxsw_sp_neigh_key key = {{ 0 } }; 670 struct mlxsw_sp_neigh_key key;
678 671
679 memcpy(key.addr, addr, addr_len); 672 key.n = n;
680 key.dev = dev;
681 return rhashtable_lookup_fast(&mlxsw_sp->router.neigh_ht, 673 return rhashtable_lookup_fast(&mlxsw_sp->router.neigh_ht,
682 &key, mlxsw_sp_neigh_ht_params); 674 &key, mlxsw_sp_neigh_ht_params);
683} 675}
@@ -689,26 +681,20 @@ int mlxsw_sp_router_neigh_construct(struct net_device *dev,
689 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 681 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
690 struct mlxsw_sp_neigh_entry *neigh_entry; 682 struct mlxsw_sp_neigh_entry *neigh_entry;
691 struct mlxsw_sp_rif *r; 683 struct mlxsw_sp_rif *r;
692 u32 dip;
693 int err; 684 int err;
694 685
695 if (n->tbl != &arp_tbl) 686 if (n->tbl != &arp_tbl)
696 return 0; 687 return 0;
697 688
698 dip = ntohl(*((__be32 *) n->primary_key)); 689 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
699 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip), 690 if (neigh_entry)
700 n->dev);
701 if (neigh_entry) {
702 WARN_ON(neigh_entry->n != n);
703 return 0; 691 return 0;
704 }
705 692
706 r = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev); 693 r = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
707 if (WARN_ON(!r)) 694 if (WARN_ON(!r))
708 return -EINVAL; 695 return -EINVAL;
709 696
710 neigh_entry = mlxsw_sp_neigh_entry_create(&dip, sizeof(dip), n->dev, 697 neigh_entry = mlxsw_sp_neigh_entry_create(n, r->rif);
711 r->rif, n);
712 if (!neigh_entry) 698 if (!neigh_entry)
713 return -ENOMEM; 699 return -ENOMEM;
714 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry); 700 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
@@ -727,14 +713,11 @@ void mlxsw_sp_router_neigh_destroy(struct net_device *dev,
727 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 713 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
728 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 714 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
729 struct mlxsw_sp_neigh_entry *neigh_entry; 715 struct mlxsw_sp_neigh_entry *neigh_entry;
730 u32 dip;
731 716
732 if (n->tbl != &arp_tbl) 717 if (n->tbl != &arp_tbl)
733 return; 718 return;
734 719
735 dip = ntohl(*((__be32 *) n->primary_key)); 720 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
736 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &dip, sizeof(dip),
737 n->dev);
738 if (!neigh_entry) 721 if (!neigh_entry)
739 return; 722 return;
740 mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry); 723 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)
862 * is active regardless of the traffic. 845 * is active regardless of the traffic.
863 */ 846 */
864 if (!list_empty(&neigh_entry->nexthop_list)) 847 if (!list_empty(&neigh_entry->nexthop_list))
865 neigh_event_send(neigh_entry->n, NULL); 848 neigh_event_send(neigh_entry->key.n, NULL);
866 } 849 }
867 rtnl_unlock(); 850 rtnl_unlock();
868} 851}
@@ -908,9 +891,9 @@ static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
908 rtnl_lock(); 891 rtnl_lock();
909 list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list, 892 list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list,
910 nexthop_neighs_list_node) { 893 nexthop_neighs_list_node) {
911 if (!(neigh_entry->n->nud_state & NUD_VALID) && 894 if (!(neigh_entry->key.n->nud_state & NUD_VALID) &&
912 !list_empty(&neigh_entry->nexthop_list)) 895 !list_empty(&neigh_entry->nexthop_list))
913 neigh_event_send(neigh_entry->n, NULL); 896 neigh_event_send(neigh_entry->key.n, NULL);
914 } 897 }
915 rtnl_unlock(); 898 rtnl_unlock();
916 899
@@ -927,7 +910,7 @@ static void mlxsw_sp_router_neigh_update_hw(struct work_struct *work)
927{ 910{
928 struct mlxsw_sp_neigh_entry *neigh_entry = 911 struct mlxsw_sp_neigh_entry *neigh_entry =
929 container_of(work, struct mlxsw_sp_neigh_entry, dw.work); 912 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;
931 struct mlxsw_sp_port *mlxsw_sp_port = neigh_entry->mlxsw_sp_port; 914 struct mlxsw_sp_port *mlxsw_sp_port = neigh_entry->mlxsw_sp_port;
932 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 915 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
933 char rauht_pl[MLXSW_REG_RAUHT_LEN]; 916 char rauht_pl[MLXSW_REG_RAUHT_LEN];
@@ -1030,11 +1013,8 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
1030 1013
1031 mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1014 mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1032 dip = ntohl(*((__be32 *) n->primary_key)); 1015 dip = ntohl(*((__be32 *) n->primary_key));
1033 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, 1016 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
1034 &dip, 1017 if (WARN_ON(!neigh_entry)) {
1035 sizeof(__be32),
1036 dev);
1037 if (WARN_ON(!neigh_entry) || WARN_ON(neigh_entry->n != n)) {
1038 mlxsw_sp_port_dev_put(mlxsw_sp_port); 1018 mlxsw_sp_port_dev_put(mlxsw_sp_port);
1039 return NOTIFY_DONE; 1019 return NOTIFY_DONE;
1040 } 1020 }
@@ -1343,33 +1323,26 @@ static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
1343 struct fib_nh *fib_nh) 1323 struct fib_nh *fib_nh)
1344{ 1324{
1345 struct mlxsw_sp_neigh_entry *neigh_entry; 1325 struct mlxsw_sp_neigh_entry *neigh_entry;
1346 u32 gwip = ntohl(fib_nh->nh_gw);
1347 struct net_device *dev = fib_nh->nh_dev; 1326 struct net_device *dev = fib_nh->nh_dev;
1348 struct neighbour *n; 1327 struct neighbour *n;
1349 u8 nud_state; 1328 u8 nud_state;
1350 1329
1351 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip, 1330 /* Take a reference of neigh here ensuring that neigh would
1352 sizeof(gwip), dev); 1331 * not be detructed before the nexthop entry is finished.
1353 if (!neigh_entry) { 1332 * The reference is taken either in neigh_lookup() or
1354 __be32 gwipn = htonl(gwip); 1333 * in neith_create() in case n is not found.
1355 1334 */
1356 n = neigh_create(&arp_tbl, &gwipn, dev); 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);
1357 if (IS_ERR(n)) 1338 if (IS_ERR(n))
1358 return PTR_ERR(n); 1339 return PTR_ERR(n);
1359 neigh_event_send(n, NULL); 1340 neigh_event_send(n, NULL);
1360 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, &gwip, 1341 }
1361 sizeof(gwip), dev); 1342 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
1362 if (!neigh_entry) { 1343 if (!neigh_entry) {
1363 neigh_release(n); 1344 neigh_release(n);
1364 return -EINVAL; 1345 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);
1373 } 1346 }
1374 1347
1375 /* If that is the first nexthop connected to that neigh, add to 1348 /* 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,
1403 if (list_empty(&nh->neigh_entry->nexthop_list)) 1376 if (list_empty(&nh->neigh_entry->nexthop_list))
1404 list_del(&nh->neigh_entry->nexthop_neighs_list_node); 1377 list_del(&nh->neigh_entry->nexthop_neighs_list_node);
1405 1378
1406 neigh_release(neigh_entry->n); 1379 neigh_release(neigh_entry->key.n);
1407} 1380}
1408 1381
1409static struct mlxsw_sp_nexthop_group * 1382static struct mlxsw_sp_nexthop_group *
@@ -1463,11 +1436,11 @@ static bool mlxsw_sp_nexthop_match(struct mlxsw_sp_nexthop *nh,
1463 1436
1464 for (i = 0; i < fi->fib_nhs; i++) { 1437 for (i = 0; i < fi->fib_nhs; i++) {
1465 struct fib_nh *fib_nh = &fi->fib_nh[i]; 1438 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;
1467 1440
1468 if (memcmp(nh->neigh_entry->key.addr, 1441 if (memcmp(n->primary_key, &fib_nh->nh_gw,
1469 &gwip, sizeof(u32)) == 0 && 1442 sizeof(fib_nh->nh_gw)) == 0 &&
1470 nh->neigh_entry->key.dev == fib_nh->nh_dev) 1443 n->dev == fib_nh->nh_dev)
1471 return true; 1444 return true;
1472 } 1445 }
1473 return false; 1446 return false;
@@ -1958,6 +1931,9 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
1958 struct fib_entry_notifier_info *fen_info = ptr; 1931 struct fib_entry_notifier_info *fen_info = ptr;
1959 int err; 1932 int err;
1960 1933
1934 if (!net_eq(fen_info->info.net, &init_net))
1935 return NOTIFY_DONE;
1936
1961 switch (event) { 1937 switch (event) {
1962 case FIB_EVENT_ENTRY_ADD: 1938 case FIB_EVENT_ENTRY_ADD:
1963 err = mlxsw_sp_router_fib4_add(mlxsw_sp, fen_info); 1939 err = mlxsw_sp_router_fib4_add(mlxsw_sp, fen_info);