Skip to content

Commit f93eb4b

Browse files
committed
Merge branch 'fib_trie-next'
Alexander Duyck says: ==================== ipv4/fib_trie: Cleanups to prepare for introduction of key vector This patch series is meant to mostly just clean up the fib_trie to prepare it for the introduction of the key_vector. As such there are a number of minor clean-ups such as reformatting the tnode to match the format once the key vector is introduced, some optimizations to drop the need for a leaf parent pointer, and some changes to remove duplication of effort such as the 2 look-ups that were essentially being done per node insertion. v2: Added code to cleanup idx >> n->bits and explain unsigned long logic Added code to prevent allocation when tnode size is larger than size_t ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3a65f63 + 1de3d87 commit f93eb4b

File tree

4 files changed

+433
-368
lines changed

4 files changed

+433
-368
lines changed

include/net/ip_fib.h

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ struct fib_table {
185185
u32 tb_id;
186186
int tb_default;
187187
int tb_num_default;
188+
struct rcu_head rcu;
188189
unsigned long tb_data[0];
189190
};
190191

@@ -206,12 +207,16 @@ void fib_free_table(struct fib_table *tb);
206207

207208
static inline struct fib_table *fib_get_table(struct net *net, u32 id)
208209
{
210+
struct hlist_node *tb_hlist;
209211
struct hlist_head *ptr;
210212

211213
ptr = id == RT_TABLE_LOCAL ?
212214
&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
213215
&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
214-
return hlist_entry(ptr->first, struct fib_table, tb_hlist);
216+
217+
tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr));
218+
219+
return hlist_entry(tb_hlist, struct fib_table, tb_hlist);
215220
}
216221

217222
static inline struct fib_table *fib_new_table(struct net *net, u32 id)
@@ -222,15 +227,19 @@ static inline struct fib_table *fib_new_table(struct net *net, u32 id)
222227
static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
223228
struct fib_result *res)
224229
{
225-
int err = -ENETUNREACH;
230+
struct fib_table *tb;
231+
int err;
226232

227233
rcu_read_lock();
228234

229-
if (!fib_table_lookup(fib_get_table(net, RT_TABLE_LOCAL), flp, res,
230-
FIB_LOOKUP_NOREF) ||
231-
!fib_table_lookup(fib_get_table(net, RT_TABLE_MAIN), flp, res,
232-
FIB_LOOKUP_NOREF))
233-
err = 0;
235+
for (err = 0; !err; err = -ENETUNREACH) {
236+
tb = fib_get_table(net, RT_TABLE_LOCAL);
237+
if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
238+
break;
239+
tb = fib_get_table(net, RT_TABLE_MAIN);
240+
if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
241+
break;
242+
}
234243

235244
rcu_read_unlock();
236245

@@ -249,28 +258,33 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res);
249258
static inline int fib_lookup(struct net *net, struct flowi4 *flp,
250259
struct fib_result *res)
251260
{
252-
if (!net->ipv4.fib_has_custom_rules) {
253-
int err = -ENETUNREACH;
254-
255-
rcu_read_lock();
256-
257-
res->tclassid = 0;
258-
if ((net->ipv4.fib_local &&
259-
!fib_table_lookup(net->ipv4.fib_local, flp, res,
260-
FIB_LOOKUP_NOREF)) ||
261-
(net->ipv4.fib_main &&
262-
!fib_table_lookup(net->ipv4.fib_main, flp, res,
263-
FIB_LOOKUP_NOREF)) ||
264-
(net->ipv4.fib_default &&
265-
!fib_table_lookup(net->ipv4.fib_default, flp, res,
266-
FIB_LOOKUP_NOREF)))
267-
err = 0;
268-
269-
rcu_read_unlock();
270-
271-
return err;
261+
struct fib_table *tb;
262+
int err;
263+
264+
if (net->ipv4.fib_has_custom_rules)
265+
return __fib_lookup(net, flp, res);
266+
267+
rcu_read_lock();
268+
269+
res->tclassid = 0;
270+
271+
for (err = 0; !err; err = -ENETUNREACH) {
272+
tb = rcu_dereference_rtnl(net->ipv4.fib_local);
273+
if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
274+
break;
275+
276+
tb = rcu_dereference_rtnl(net->ipv4.fib_main);
277+
if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
278+
break;
279+
280+
tb = rcu_dereference_rtnl(net->ipv4.fib_default);
281+
if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
282+
break;
272283
}
273-
return __fib_lookup(net, flp, res);
284+
285+
rcu_read_unlock();
286+
287+
return err;
274288
}
275289

276290
#endif /* CONFIG_IP_MULTIPLE_TABLES */

include/net/netns/ipv4.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <linux/uidgid.h>
99
#include <net/inet_frag.h>
10+
#include <linux/rcupdate.h>
1011

1112
struct tcpm_hash_bucket;
1213
struct ctl_table_header;
@@ -38,9 +39,9 @@ struct netns_ipv4 {
3839
#ifdef CONFIG_IP_MULTIPLE_TABLES
3940
struct fib_rules_ops *rules_ops;
4041
bool fib_has_custom_rules;
41-
struct fib_table *fib_local;
42-
struct fib_table *fib_main;
43-
struct fib_table *fib_default;
42+
struct fib_table __rcu *fib_local;
43+
struct fib_table __rcu *fib_main;
44+
struct fib_table __rcu *fib_default;
4445
#endif
4546
#ifdef CONFIG_IP_ROUTE_CLASSID
4647
int fib_num_tclassid_users;

net/ipv4/fib_frontend.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,14 @@ struct fib_table *fib_new_table(struct net *net, u32 id)
8989

9090
switch (id) {
9191
case RT_TABLE_LOCAL:
92-
net->ipv4.fib_local = tb;
92+
rcu_assign_pointer(net->ipv4.fib_local, tb);
9393
break;
94-
9594
case RT_TABLE_MAIN:
96-
net->ipv4.fib_main = tb;
95+
rcu_assign_pointer(net->ipv4.fib_main, tb);
9796
break;
98-
9997
case RT_TABLE_DEFAULT:
100-
net->ipv4.fib_default = tb;
98+
rcu_assign_pointer(net->ipv4.fib_default, tb);
10199
break;
102-
103100
default:
104101
break;
105102
}
@@ -132,13 +129,14 @@ struct fib_table *fib_get_table(struct net *net, u32 id)
132129
static void fib_flush(struct net *net)
133130
{
134131
int flushed = 0;
135-
struct fib_table *tb;
136-
struct hlist_head *head;
137132
unsigned int h;
138133

139134
for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
140-
head = &net->ipv4.fib_table_hash[h];
141-
hlist_for_each_entry(tb, head, tb_hlist)
135+
struct hlist_head *head = &net->ipv4.fib_table_hash[h];
136+
struct hlist_node *tmp;
137+
struct fib_table *tb;
138+
139+
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
142140
flushed += fib_table_flush(tb);
143141
}
144142

@@ -665,10 +663,12 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
665663
s_h = cb->args[0];
666664
s_e = cb->args[1];
667665

666+
rcu_read_lock();
667+
668668
for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
669669
e = 0;
670670
head = &net->ipv4.fib_table_hash[h];
671-
hlist_for_each_entry(tb, head, tb_hlist) {
671+
hlist_for_each_entry_rcu(tb, head, tb_hlist) {
672672
if (e < s_e)
673673
goto next;
674674
if (dumped)
@@ -682,6 +682,8 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
682682
}
683683
}
684684
out:
685+
rcu_read_unlock();
686+
685687
cb->args[1] = e;
686688
cb->args[0] = h;
687689

@@ -1117,14 +1119,34 @@ static void ip_fib_net_exit(struct net *net)
11171119

11181120
rtnl_lock();
11191121
for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
1120-
struct fib_table *tb;
1121-
struct hlist_head *head;
1122+
struct hlist_head *head = &net->ipv4.fib_table_hash[i];
11221123
struct hlist_node *tmp;
1124+
struct fib_table *tb;
1125+
1126+
/* this is done in two passes as flushing the table could
1127+
* cause it to be reallocated in order to accommodate new
1128+
* tnodes at the root as the table shrinks.
1129+
*/
1130+
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
1131+
fib_table_flush(tb);
11231132

1124-
head = &net->ipv4.fib_table_hash[i];
11251133
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
1134+
#ifdef CONFIG_IP_MULTIPLE_TABLES
1135+
switch (tb->tb_id) {
1136+
case RT_TABLE_LOCAL:
1137+
RCU_INIT_POINTER(net->ipv4.fib_local, NULL);
1138+
break;
1139+
case RT_TABLE_MAIN:
1140+
RCU_INIT_POINTER(net->ipv4.fib_main, NULL);
1141+
break;
1142+
case RT_TABLE_DEFAULT:
1143+
RCU_INIT_POINTER(net->ipv4.fib_default, NULL);
1144+
break;
1145+
default:
1146+
break;
1147+
}
1148+
#endif
11261149
hlist_del(&tb->tb_hlist);
1127-
fib_table_flush(tb);
11281150
fib_free_table(tb);
11291151
}
11301152
}

0 commit comments

Comments
 (0)