Skip to content

Commit 421842e

Browse files
dsaherndavem330
authored andcommitted
net/ipv6: Add fib6_null_entry
ip6_null_entry will stay a dst based return for lookups that fail to match an entry. Add a new fib6_null_entry which constitutes the root node and leafs for fibs. Replace existing references to ip6_null_entry with the new fib6_null_entry when dealing with FIBs. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1489568 commit 421842e

File tree

3 files changed

+58
-33
lines changed

3 files changed

+58
-33
lines changed

include/net/netns/ipv6.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ struct netns_ipv6 {
6060
#endif
6161
struct xt_table *ip6table_nat;
6262
#endif
63-
struct rt6_info *ip6_null_entry;
63+
struct rt6_info *fib6_null_entry;
64+
struct rt6_info *ip6_null_entry;
6465
struct rt6_statistics *rt6_stats;
6566
struct timer_list ip6_fib_timer;
6667
struct hlist_head *fib_table_hash;

net/ipv6/ip6_fib.c

+13-13
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static struct fib6_table *fib6_alloc_table(struct net *net, u32 id)
231231
if (table) {
232232
table->tb6_id = id;
233233
rcu_assign_pointer(table->tb6_root.leaf,
234-
net->ipv6.ip6_null_entry);
234+
net->ipv6.fib6_null_entry);
235235
table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
236236
inet_peer_base_init(&table->tb6_peers);
237237
}
@@ -369,7 +369,7 @@ struct fib6_dump_arg {
369369

370370
static void fib6_rt_dump(struct rt6_info *rt, struct fib6_dump_arg *arg)
371371
{
372-
if (rt == arg->net->ipv6.ip6_null_entry)
372+
if (rt == arg->net->ipv6.fib6_null_entry)
373373
return;
374374
call_fib6_entry_notifier(arg->nb, arg->net, FIB_EVENT_ENTRY_ADD, rt);
375375
}
@@ -658,7 +658,7 @@ static struct fib6_node *fib6_add_1(struct net *net,
658658
/* remove null_entry in the root node */
659659
} else if (fn->fn_flags & RTN_TL_ROOT &&
660660
rcu_access_pointer(fn->leaf) ==
661-
net->ipv6.ip6_null_entry) {
661+
net->ipv6.fib6_null_entry) {
662662
RCU_INIT_POINTER(fn->leaf, NULL);
663663
}
664664

@@ -1171,9 +1171,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
11711171
if (!sfn)
11721172
goto failure;
11731173

1174-
atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
1174+
atomic_inc(&info->nl_net->ipv6.fib6_null_entry->rt6i_ref);
11751175
rcu_assign_pointer(sfn->leaf,
1176-
info->nl_net->ipv6.ip6_null_entry);
1176+
info->nl_net->ipv6.fib6_null_entry);
11771177
sfn->fn_flags = RTN_ROOT;
11781178

11791179
/* Now add the first leaf node to new subtree */
@@ -1212,7 +1212,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
12121212
if (fn->fn_flags & RTN_TL_ROOT) {
12131213
/* put back null_entry for root node */
12141214
rcu_assign_pointer(fn->leaf,
1215-
info->nl_net->ipv6.ip6_null_entry);
1215+
info->nl_net->ipv6.fib6_null_entry);
12161216
} else {
12171217
atomic_inc(&rt->rt6i_ref);
12181218
rcu_assign_pointer(fn->leaf, rt);
@@ -1251,7 +1251,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
12511251
if (!pn_leaf) {
12521252
WARN_ON(!pn_leaf);
12531253
pn_leaf =
1254-
info->nl_net->ipv6.ip6_null_entry;
1254+
info->nl_net->ipv6.fib6_null_entry;
12551255
}
12561256
#endif
12571257
atomic_inc(&pn_leaf->rt6i_ref);
@@ -1494,7 +1494,7 @@ static struct rt6_info *fib6_find_prefix(struct net *net,
14941494
struct fib6_node *child_left, *child_right;
14951495

14961496
if (fn->fn_flags & RTN_ROOT)
1497-
return net->ipv6.ip6_null_entry;
1497+
return net->ipv6.fib6_null_entry;
14981498

14991499
while (fn) {
15001500
child_left = rcu_dereference_protected(fn->left,
@@ -1531,7 +1531,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net,
15311531

15321532
/* Set fn->leaf to null_entry for root node. */
15331533
if (fn->fn_flags & RTN_TL_ROOT) {
1534-
rcu_assign_pointer(fn->leaf, net->ipv6.ip6_null_entry);
1534+
rcu_assign_pointer(fn->leaf, net->ipv6.fib6_null_entry);
15351535
return fn;
15361536
}
15371537

@@ -1576,7 +1576,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net,
15761576
#if RT6_DEBUG >= 2
15771577
if (!new_fn_leaf) {
15781578
WARN_ON(!new_fn_leaf);
1579-
new_fn_leaf = net->ipv6.ip6_null_entry;
1579+
new_fn_leaf = net->ipv6.fib6_null_entry;
15801580
}
15811581
#endif
15821582
atomic_inc(&new_fn_leaf->rt6i_ref);
@@ -1726,7 +1726,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
17261726
return -ENOENT;
17271727
}
17281728
#endif
1729-
if (!fn || rt == net->ipv6.ip6_null_entry)
1729+
if (!fn || rt == net->ipv6.fib6_null_entry)
17301730
return -ENOENT;
17311731

17321732
WARN_ON(!(fn->fn_flags & RTN_RTINFO));
@@ -2087,7 +2087,7 @@ static int __net_init fib6_net_init(struct net *net)
20872087

20882088
net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
20892089
rcu_assign_pointer(net->ipv6.fib6_main_tbl->tb6_root.leaf,
2090-
net->ipv6.ip6_null_entry);
2090+
net->ipv6.fib6_null_entry);
20912091
net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
20922092
RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
20932093
inet_peer_base_init(&net->ipv6.fib6_main_tbl->tb6_peers);
@@ -2099,7 +2099,7 @@ static int __net_init fib6_net_init(struct net *net)
20992099
goto out_fib6_main_tbl;
21002100
net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
21012101
rcu_assign_pointer(net->ipv6.fib6_local_tbl->tb6_root.leaf,
2102-
net->ipv6.ip6_null_entry);
2102+
net->ipv6.fib6_null_entry);
21032103
net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
21042104
RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
21052105
inet_peer_base_init(&net->ipv6.fib6_local_tbl->tb6_peers);

net/ipv6/route.c

+43-19
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,15 @@ static const u32 ip6_template_metrics[RTAX_MAX] = {
276276
[RTAX_HOPLIMIT - 1] = 0,
277277
};
278278

279+
static const struct rt6_info fib6_null_entry_template = {
280+
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
281+
.rt6i_protocol = RTPROT_KERNEL,
282+
.rt6i_metric = ~(u32)0,
283+
.rt6i_ref = ATOMIC_INIT(1),
284+
.fib6_type = RTN_UNREACHABLE,
285+
.fib6_metrics = (struct dst_metrics *)&dst_default_metrics,
286+
};
287+
279288
static const struct rt6_info ip6_null_entry_template = {
280289
.dst = {
281290
.__refcnt = ATOMIC_INIT(1),
@@ -522,10 +531,10 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
522531
return local;
523532

524533
if (flags & RT6_LOOKUP_F_IFACE)
525-
return net->ipv6.ip6_null_entry;
534+
return net->ipv6.fib6_null_entry;
526535
}
527536

528-
return rt->fib6_nh.nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt;
537+
return rt->fib6_nh.nh_flags & RTNH_F_DEAD ? net->ipv6.fib6_null_entry : rt;
529538
}
530539

531540
#ifdef CONFIG_IPV6_ROUTER_PREF
@@ -758,8 +767,8 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
758767
bool do_rr = false;
759768
int key_plen;
760769

761-
if (!leaf || leaf == net->ipv6.ip6_null_entry)
762-
return net->ipv6.ip6_null_entry;
770+
if (!leaf || leaf == net->ipv6.fib6_null_entry)
771+
return net->ipv6.fib6_null_entry;
763772

764773
rt0 = rcu_dereference(fn->rr_ptr);
765774
if (!rt0)
@@ -776,7 +785,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
776785
key_plen = rt0->rt6i_src.plen;
777786
#endif
778787
if (fn->fn_bit != key_plen)
779-
return net->ipv6.ip6_null_entry;
788+
return net->ipv6.fib6_null_entry;
780789

781790
match = find_rr_leaf(fn, leaf, rt0, rt0->rt6i_metric, oif, strict,
782791
&do_rr);
@@ -797,7 +806,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
797806
}
798807
}
799808

800-
return match ? match : net->ipv6.ip6_null_entry;
809+
return match ? match : net->ipv6.fib6_null_entry;
801810
}
802811

803812
static bool rt6_is_gw_or_nonexthop(const struct rt6_info *rt)
@@ -1063,15 +1072,15 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
10631072
restart:
10641073
rt = rcu_dereference(fn->leaf);
10651074
if (!rt) {
1066-
rt = net->ipv6.ip6_null_entry;
1075+
rt = net->ipv6.fib6_null_entry;
10671076
} else {
10681077
rt = rt6_device_match(net, rt, &fl6->saddr,
10691078
fl6->flowi6_oif, flags);
10701079
if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
10711080
rt = rt6_multipath_select(net, rt, fl6, fl6->flowi6_oif,
10721081
skb, flags);
10731082
}
1074-
if (rt == net->ipv6.ip6_null_entry) {
1083+
if (rt == net->ipv6.fib6_null_entry) {
10751084
fn = fib6_backtrack(fn, &fl6->saddr);
10761085
if (fn)
10771086
goto restart;
@@ -1820,7 +1829,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
18201829
rt = rt6_select(net, fn, oif, strict);
18211830
if (rt->rt6i_nsiblings)
18221831
rt = rt6_multipath_select(net, rt, fl6, oif, skb, strict);
1823-
if (rt == net->ipv6.ip6_null_entry) {
1832+
if (rt == net->ipv6.fib6_null_entry) {
18241833
fn = fib6_backtrack(fn, &fl6->saddr);
18251834
if (fn)
18261835
goto redo_rt6_select;
@@ -1837,7 +1846,8 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
18371846
if (rt_cache)
18381847
rt = rt_cache;
18391848

1840-
if (rt == net->ipv6.ip6_null_entry) {
1849+
if (rt == net->ipv6.fib6_null_entry) {
1850+
rt = net->ipv6.ip6_null_entry;
18411851
rcu_read_unlock();
18421852
dst_hold(&rt->dst);
18431853
trace_fib6_table_lookup(net, rt, table, fl6);
@@ -2412,13 +2422,13 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
24122422
}
24132423

24142424
if (!rt)
2415-
rt = net->ipv6.ip6_null_entry;
2425+
rt = net->ipv6.fib6_null_entry;
24162426
else if (rt->rt6i_flags & RTF_REJECT) {
24172427
rt = net->ipv6.ip6_null_entry;
24182428
goto out;
24192429
}
24202430

2421-
if (rt == net->ipv6.ip6_null_entry) {
2431+
if (rt == net->ipv6.fib6_null_entry) {
24222432
fn = fib6_backtrack(fn, &fl6->saddr);
24232433
if (fn)
24242434
goto restart;
@@ -3051,7 +3061,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
30513061
struct fib6_table *table;
30523062
int err;
30533063

3054-
if (rt == net->ipv6.ip6_null_entry) {
3064+
if (rt == net->ipv6.fib6_null_entry) {
30553065
err = -ENOENT;
30563066
goto out;
30573067
}
@@ -3081,7 +3091,7 @@ static int __ip6_del_rt_siblings(struct rt6_info *rt, struct fib6_config *cfg)
30813091
struct fib6_table *table;
30823092
int err = -ENOENT;
30833093

3084-
if (rt == net->ipv6.ip6_null_entry)
3094+
if (rt == net->ipv6.fib6_null_entry)
30853095
goto out_put;
30863096
table = rt->rt6i_table;
30873097
spin_lock_bh(&table->tb6_lock);
@@ -3634,7 +3644,7 @@ static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
36343644
struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
36353645

36363646
if (((void *)rt->fib6_nh.nh_dev == dev || !dev) &&
3637-
rt != net->ipv6.ip6_null_entry &&
3647+
rt != net->ipv6.fib6_null_entry &&
36383648
ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
36393649
spin_lock_bh(&rt6_exception_lock);
36403650
/* remove prefsrc entry */
@@ -3789,7 +3799,7 @@ static int fib6_ifup(struct rt6_info *rt, void *p_arg)
37893799
const struct arg_netdev_event *arg = p_arg;
37903800
struct net *net = dev_net(arg->dev);
37913801

3792-
if (rt != net->ipv6.ip6_null_entry && rt->fib6_nh.nh_dev == arg->dev) {
3802+
if (rt != net->ipv6.fib6_null_entry && rt->fib6_nh.nh_dev == arg->dev) {
37933803
rt->fib6_nh.nh_flags &= ~arg->nh_flags;
37943804
fib6_update_sernum_upto_root(net, rt);
37953805
rt6_multipath_rebalance(rt);
@@ -3873,7 +3883,7 @@ static int fib6_ifdown(struct rt6_info *rt, void *p_arg)
38733883
const struct net_device *dev = arg->dev;
38743884
struct net *net = dev_net(dev);
38753885

3876-
if (rt == net->ipv6.ip6_null_entry)
3886+
if (rt == net->ipv6.fib6_null_entry)
38773887
return 0;
38783888

38793889
switch (arg->event) {
@@ -4624,7 +4634,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
46244634
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
46254635
struct net *net = arg->net;
46264636

4627-
if (rt == net->ipv6.ip6_null_entry)
4637+
if (rt == net->ipv6.fib6_null_entry)
46284638
return 0;
46294639

46304640
if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
@@ -4813,6 +4823,8 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48134823
return NOTIFY_OK;
48144824

48154825
if (event == NETDEV_REGISTER) {
4826+
net->ipv6.fib6_null_entry->fib6_nh.nh_dev = dev;
4827+
net->ipv6.fib6_null_entry->rt6i_idev = in6_dev_get(dev);
48164828
net->ipv6.ip6_null_entry->dst.dev = dev;
48174829
net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
48184830
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -4826,6 +4838,7 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48264838
/* NETDEV_UNREGISTER could be fired for multiple times by
48274839
* netdev_wait_allrefs(). Make sure we only call this once.
48284840
*/
4841+
in6_dev_put_clear(&net->ipv6.fib6_null_entry->rt6i_idev);
48294842
in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
48304843
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
48314844
in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
@@ -5009,11 +5022,17 @@ static int __net_init ip6_route_net_init(struct net *net)
50095022
if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
50105023
goto out_ip6_dst_ops;
50115024

5025+
net->ipv6.fib6_null_entry = kmemdup(&fib6_null_entry_template,
5026+
sizeof(*net->ipv6.fib6_null_entry),
5027+
GFP_KERNEL);
5028+
if (!net->ipv6.fib6_null_entry)
5029+
goto out_ip6_dst_entries;
5030+
50125031
net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
50135032
sizeof(*net->ipv6.ip6_null_entry),
50145033
GFP_KERNEL);
50155034
if (!net->ipv6.ip6_null_entry)
5016-
goto out_ip6_dst_entries;
5035+
goto out_fib6_null_entry;
50175036
net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
50185037
dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
50195038
ip6_template_metrics, true);
@@ -5060,6 +5079,8 @@ static int __net_init ip6_route_net_init(struct net *net)
50605079
out_ip6_null_entry:
50615080
kfree(net->ipv6.ip6_null_entry);
50625081
#endif
5082+
out_fib6_null_entry:
5083+
kfree(net->ipv6.fib6_null_entry);
50635084
out_ip6_dst_entries:
50645085
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
50655086
out_ip6_dst_ops:
@@ -5068,6 +5089,7 @@ static int __net_init ip6_route_net_init(struct net *net)
50685089

50695090
static void __net_exit ip6_route_net_exit(struct net *net)
50705091
{
5092+
kfree(net->ipv6.fib6_null_entry);
50715093
kfree(net->ipv6.ip6_null_entry);
50725094
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
50735095
kfree(net->ipv6.ip6_prohibit_entry);
@@ -5138,6 +5160,8 @@ void __init ip6_route_init_special_entries(void)
51385160
/* Registering of the loopback is done before this portion of code,
51395161
* the loopback reference in rt6_info will not be taken, do it
51405162
* manually for init_net */
5163+
init_net.ipv6.fib6_null_entry->fib6_nh.nh_dev = init_net.loopback_dev;
5164+
init_net.ipv6.fib6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
51415165
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
51425166
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
51435167
#ifdef CONFIG_IPV6_MULTIPLE_TABLES

0 commit comments

Comments
 (0)