6666#include <linux/iopoll.h>
6767#include <linux/notifier.h>
6868#include <linux/of.h>
69- #include <linux/rhashtable.h>
7069#include <linux/seq_file.h>
7170#include <net/arp.h>
7271#include <net/fib_notifier.h>
114113#define MAX_ROUTER_MACS 64
115114#define L3_EGRESS_DMACS 2048
116115
117- static const struct rhashtable_params otto_l3_route_ht_params = {
118- .key_len = sizeof (struct in6_addr ),
119- .key_offset = offsetof(struct otto_l3_route , gw_ip ),
120- .head_offset = offsetof(struct otto_l3_route , linkage ),
121- };
122-
123116struct otto_l3_net_event_work {
124117 struct work_struct work ;
125118 struct otto_l3_ctrl * ctrl ;
@@ -1440,29 +1433,18 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, u8 type, int ifinde
14401433 const struct in6_addr * gw , u64 mac , bool valid )
14411434{
14421435 struct otto_l3_route * r ;
1443- bool known ;
1444-
1445- /* The lookup runs in the section the rhashtable asks for and ends
1446- * there: on a kernel without preemptible RCU that section is
1447- * preempt_disable(), and every table op below it sleeps on a mutex.
1448- * Only whether the gateway is known leaves that section, so no
1449- * rhashtable pointer outlives it. The routes it would have walked are
1450- * the ones on the driver's own list with that gateway, and the work
1451- * queue that runs this is single threaded, which is what lets the rest
1452- * of the driver walk that list with no lock.
1453- */
1454- rcu_read_lock ();
1455- known = rhltable_lookup (& ctrl -> routes , gw , otto_l3_route_ht_params );
1456- rcu_read_unlock ();
1457- if (!known )
1458- return - ENOENT ;
1436+ bool known = false;
14591437
14601438 list_for_each_entry (r , & ctrl -> routes_list , list ) {
1439+ if (!ipv6_addr_equal (& r -> gw_ip , gw ))
1440+ continue ;
1441+
1442+ known = true;
1443+
14611444 /* An IPv4 gateway written v4-mapped is a valid IPv6 one, so
1462- * the key alone does not say whose route this is.
1445+ * the address alone does not say whose route this is.
14631446 */
1464- if (r -> attr .type != type || r -> gw_ifindex != ifindex ||
1465- !ipv6_addr_equal (& r -> gw_ip , gw ))
1447+ if (r -> attr .type != type || r -> gw_ifindex != ifindex )
14661448 continue ;
14671449
14681450 if (valid )
@@ -1471,17 +1453,20 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, u8 type, int ifinde
14711453 otto_l3_route_trap_hw (ctrl , r );
14721454 }
14731455
1456+ if (!known )
1457+ return - ENOENT ;
1458+
14741459 /* An address of one family can be written as an address of the other,
14751460 * so a neighbour of the wrong family reaches this far without having
14761461 * placed anything, and has nothing to report.
14771462 */
14781463 if (type != ROUTE_TYPE_IP6UC )
14791464 return 0 ;
14801465
1481- /* Reporting the offload allocates and can send a netlink message, so it
1482- * waits until the lookup above is over. It takes no lock of its own,
1483- * so unlike the FIB work this path needs no rtnl. The FIB notifier is
1484- * registered on init_net, which is where every route here comes from.
1466+ /* Reporting the offload allocates and can send a netlink message. It
1467+ * takes no lock of its own, so unlike the FIB work this path needs no
1468+ * rtnl. The FIB notifier is registered on init_net, which is where
1469+ * every route here comes from.
14851470 */
14861471 list_for_each_entry (r , & ctrl -> routes_list , list ) {
14871472 bool trap ;
@@ -1575,9 +1560,6 @@ static bool otto_l3_route_is_at(struct otto_l3_ctrl *ctrl, int id, struct otto_l
15751560 return false;
15761561}
15771562
1578- /* The routes are hashed on the gateway, which is the field a replace
1579- * changes, so a lookup by destination needs a list of its own.
1580- */
15811563static struct otto_l3_route * otto_l3_route_find (struct otto_l3_ctrl * ctrl , u32 tb_id , u8 type ,
15821564 u32 dst_ip , const struct in6_addr * dst_ip6 ,
15831565 int prefix_len )
@@ -1616,9 +1598,6 @@ static void otto_l3_route_free(struct otto_l3_ctrl *ctrl, struct otto_l3_route *
16161598{
16171599 struct otto_l3_route_src * s , * tmp ;
16181600
1619- if (rhltable_remove (& ctrl -> routes , & r -> linkage , otto_l3_route_ht_params ))
1620- dev_warn (ctrl -> dev , "Could not remove route\n" );
1621-
16221601 list_for_each_entry_safe (s , tmp , & r -> srcs , list )
16231602 kfree (s );
16241603
@@ -1729,7 +1708,7 @@ static struct otto_l3_route *otto_l3_route_alloc(struct otto_l3_ctrl *ctrl,
17291708 unsigned long * use_bm = host ? ctrl -> host_route_use_bm : ctrl -> route_use_bm ;
17301709 int size = host ? MAX_HOST_ROUTES : MAX_ROUTES ;
17311710 struct otto_l3_route * r ;
1732- int idx , err ;
1711+ int idx ;
17331712
17341713 mutex_lock (ctrl -> lock );
17351714
@@ -1759,14 +1738,6 @@ static struct otto_l3_route *otto_l3_route_alloc(struct otto_l3_ctrl *ctrl,
17591738 r -> is_host_route = host ;
17601739 INIT_LIST_HEAD (& r -> srcs );
17611740
1762- err = rhltable_insert (& ctrl -> routes , & r -> linkage , otto_l3_route_ht_params );
1763- if (err ) {
1764- dev_err (ctrl -> dev , "Could not insert new rule\n" );
1765- mutex_unlock (ctrl -> lock );
1766- kfree (r );
1767- return NULL ;
1768- }
1769-
17701741 list_add_tail (& r -> list , & ctrl -> routes_list );
17711742 set_bit (idx , use_bm );
17721743
@@ -1983,9 +1954,9 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
19831954 ROUTE_HOST : ROUTE_PREFIX );
19841955
19851956 if (route )
1986- dev_info (ctrl -> dev , "route hashtable extended for gw %pI4\n" , & nh -> fib_nh_gw4 );
1957+ dev_info (ctrl -> dev , "route allocated for gw %pI4\n" , & nh -> fib_nh_gw4 );
19871958 else {
1988- dev_err (ctrl -> dev , "could not extend route hashtable for gw %pI4\n" ,
1959+ dev_err (ctrl -> dev , "could not allocate a route for gw %pI4\n" ,
19891960 & nh -> fib_nh_gw4 );
19901961 return - ENOSPC ;
19911962 }
@@ -2062,9 +2033,7 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
20622033
20632034static int otto_l3_fib_del_v4 (struct otto_l3_ctrl * ctrl , struct fib_entry_notifier_info * info )
20642035{
2065- struct rhlist_head * tmp , * list ;
20662036 struct otto_l3_route * route ;
2067- bool found = false;
20682037 struct in6_addr gw ;
20692038 struct fib_nh * nh ;
20702039
@@ -2085,7 +2054,7 @@ static int otto_l3_fib_del_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
20852054 if (otto_l3_fib_check_v4 (ctrl , info , FIB_EVENT_ENTRY_DEL ))
20862055 return 0 ;
20872056
2088- /* The entry that traps for a route left out is keyed on no gateway,
2057+ /* The entry that traps for a route left out carries no gateway,
20892058 * whatever gateway the route itself names
20902059 */
20912060 route = otto_l3_route_find (ctrl , info -> tb_id , ROUTE_TYPE_IP4UC , info -> dst , NULL ,
@@ -2098,29 +2067,13 @@ static int otto_l3_fib_del_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
20982067
20992068 ipv6_addr_set_v4mapped (nh -> fib_nh_gw4 , & gw );
21002069
2101- rcu_read_lock ();
2102- list = rhltable_lookup (& ctrl -> routes , & gw , otto_l3_route_ht_params );
2103- if (!list ) {
2104- rcu_read_unlock ();
2105- dev_err (ctrl -> dev , "no such gateway: %pI4\n" , & nh -> fib_nh_gw4 );
2106- return - ENOENT ;
2107- }
2108- rhl_for_each_entry_rcu (route , tmp , list , linkage ) {
2109- if (route -> attr .type == ROUTE_TYPE_IP4UC &&
2110- route -> dst_ip == info -> dst && route -> prefix_len == info -> dst_len ) {
2111- dev_info (ctrl -> dev , "found a route with id %d, nh-id %d\n" ,
2112- route -> id , route -> nh .id );
2113- found = true;
2114- break ;
2115- }
2116- }
2117- rcu_read_unlock ();
2118-
2119- if (!found ) {
2070+ if (!route || !ipv6_addr_equal (& route -> gw_ip , & gw )) {
21202071 dev_err (ctrl -> dev , "no route %pI4/%d via %pI4\n" ,
21212072 & info -> dst , info -> dst_len , & nh -> fib_nh_gw4 );
21222073 return - ENOENT ;
21232074 }
2075+ dev_info (ctrl -> dev , "found a route with id %d, nh-id %d\n" ,
2076+ route -> id , route -> nh .id );
21242077
21252078 otto_l3_route_teardown (ctrl , route );
21262079
@@ -2477,7 +2430,7 @@ static int otto_l3_fib_add_v6(struct otto_l3_ctrl *ctrl, struct fib6_entry_notif
24772430
24782431 route = otto_l3_route_alloc (ctrl , gw , ROUTE_PREFIX );
24792432 if (!route ) {
2480- dev_err (ctrl -> dev , "could not extend route hashtable for gw %pI6c\n" , gw );
2433+ dev_err (ctrl -> dev , "could not allocate a route for gw %pI6c\n" , gw );
24812434 goto out_failed ;
24822435 }
24832436
@@ -3670,14 +3623,12 @@ void otto_l3_remove(struct rtl838x_switch_priv *priv)
36703623 flush_workqueue (priv -> wq );
36713624
36723625 /* Nothing takes a route out now, and a FIB entry one still names would
3673- * be kept alive by it. Destroying the hash table also waits for the
3674- * resize work it runs on its own.
3626+ * be kept alive by it.
36753627 */
36763628 rtnl_lock ();
36773629 list_for_each_entry_safe (r , tmp , & ctrl -> routes_list , list )
36783630 otto_l3_route_free (ctrl , r );
36793631 rtnl_unlock ();
3680- rhltable_destroy (& ctrl -> routes );
36813632}
36823633
36833634struct otto_l3_flush_work {
@@ -3781,11 +3732,7 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv)
37813732 return dev_err_probe (dev , err , "device specific L3 setup failed\n" );
37823733 }
37833734
3784- /* Initialize hash table for L3 routing */
37853735 INIT_LIST_HEAD (& ctrl -> routes_list );
3786- err = rhltable_init (& ctrl -> routes , & otto_l3_route_ht_params );
3787- if (err )
3788- return dev_err_probe (dev , err , "could not set up the route hash table\n" );
37893736
37903737 /* Before the notifiers, so no destination is dropped in the window
37913738 * where the tables are live and the routes have not arrived yet.
0 commit comments