Skip to content

Commit dcd1f57

Browse files
dsaherndavem330
authored andcommitted
net/ipv6: Remove fib6_idev
fib6_idev can be obtained from __in6_dev_get on the nexthop device rather than caching it in the fib6_info. Remove it. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 647d4c1 commit dcd1f57

File tree

3 files changed

+47
-22
lines changed

3 files changed

+47
-22
lines changed

include/net/ip6_fib.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ struct fib6_info {
147147
unsigned int fib6_nsiblings;
148148

149149
atomic_t fib6_ref;
150-
struct inet6_dev *fib6_idev;
151150
unsigned long expires;
152151
struct dst_metrics *fib6_metrics;
153152
#define fib6_pmtu fib6_metrics->metrics[RTAX_MTU-1]

net/ipv6/ip6_fib.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,6 @@ void fib6_info_destroy(struct fib6_info *f6i)
197197
}
198198
}
199199

200-
if (f6i->fib6_idev)
201-
in6_dev_put(f6i->fib6_idev);
202200
if (f6i->fib6_nh.nh_dev)
203201
dev_put(f6i->fib6_nh.nh_dev);
204202

net/ipv6/route.c

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -525,15 +525,17 @@ static void rt6_probe(struct fib6_info *rt)
525525
rcu_read_lock_bh();
526526
neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
527527
if (neigh) {
528+
struct inet6_dev *idev;
529+
528530
if (neigh->nud_state & NUD_VALID)
529531
goto out;
530532

533+
idev = __in6_dev_get(dev);
531534
work = NULL;
532535
write_lock(&neigh->lock);
533536
if (!(neigh->nud_state & NUD_VALID) &&
534537
time_after(jiffies,
535-
neigh->updated +
536-
rt->fib6_idev->cnf.rtr_probe_interval)) {
538+
neigh->updated + idev->cnf.rtr_probe_interval)) {
537539
work = kmalloc(sizeof(*work), GFP_ATOMIC);
538540
if (work)
539541
__neigh_set_probe_once(neigh);
@@ -622,18 +624,32 @@ static int rt6_score_route(struct fib6_info *rt, int oif, int strict)
622624
return m;
623625
}
624626

627+
/* called with rc_read_lock held */
628+
static inline bool fib6_ignore_linkdown(const struct fib6_info *f6i)
629+
{
630+
const struct net_device *dev = fib6_info_nh_dev(f6i);
631+
bool rc = false;
632+
633+
if (dev) {
634+
const struct inet6_dev *idev = __in6_dev_get(dev);
635+
636+
rc = !!idev->cnf.ignore_routes_with_linkdown;
637+
}
638+
639+
return rc;
640+
}
641+
625642
static struct fib6_info *find_match(struct fib6_info *rt, int oif, int strict,
626643
int *mpri, struct fib6_info *match,
627644
bool *do_rr)
628645
{
629646
int m;
630647
bool match_do_rr = false;
631-
struct inet6_dev *idev = rt->fib6_idev;
632648

633649
if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
634650
goto out;
635651

636-
if (idev->cnf.ignore_routes_with_linkdown &&
652+
if (fib6_ignore_linkdown(rt) &&
637653
rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
638654
!(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
639655
goto out;
@@ -957,12 +973,12 @@ static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
957973

958974
static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort)
959975
{
976+
struct net_device *dev = fib6_info_nh_dev(ort);
977+
960978
ip6_rt_init_dst(rt, ort);
961979

962980
rt->rt6i_dst = ort->fib6_dst;
963-
rt->rt6i_idev = ort->fib6_idev;
964-
if (rt->rt6i_idev)
965-
in6_dev_hold(rt->rt6i_idev);
981+
rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
966982
rt->rt6i_gateway = ort->fib6_nh.nh_gw;
967983
rt->rt6i_flags = ort->fib6_flags;
968984
rt6_set_from(rt, ort);
@@ -1355,7 +1371,18 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
13551371
{
13561372
unsigned int mtu;
13571373

1358-
mtu = rt->fib6_pmtu ? : rt->fib6_idev->cnf.mtu6;
1374+
if (rt->fib6_pmtu) {
1375+
mtu = rt->fib6_pmtu;
1376+
} else {
1377+
struct net_device *dev = fib6_info_nh_dev(rt);
1378+
struct inet6_dev *idev;
1379+
1380+
rcu_read_lock();
1381+
idev = __in6_dev_get(dev);
1382+
mtu = idev->cnf.mtu6;
1383+
rcu_read_unlock();
1384+
}
1385+
13591386
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
13601387

13611388
return mtu - lwtunnel_headroom(rt->fib6_nh.nh_lwtstate, mtu);
@@ -2985,11 +3012,13 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
29853012
rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN;
29863013
rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
29873014
rt->fib6_nh.nh_dev = dev;
2988-
rt->fib6_idev = idev;
29893015
rt->fib6_table = table;
29903016

29913017
cfg->fc_nlinfo.nl_net = dev_net(dev);
29923018

3019+
if (idev)
3020+
in6_dev_put(idev);
3021+
29933022
return rt;
29943023
out:
29953024
if (dev)
@@ -3425,8 +3454,11 @@ static void __rt6_purge_dflt_routers(struct net *net,
34253454
restart:
34263455
rcu_read_lock();
34273456
for_each_fib6_node_rt_rcu(&table->tb6_root) {
3457+
struct net_device *dev = fib6_info_nh_dev(rt);
3458+
struct inet6_dev *idev = dev ? __in6_dev_get(dev) : NULL;
3459+
34283460
if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
3429-
(!rt->fib6_idev || rt->fib6_idev->cnf.accept_ra != 2)) {
3461+
(!idev || idev->cnf.accept_ra != 2)) {
34303462
fib6_info_hold(rt);
34313463
rcu_read_unlock();
34323464
ip6_del_rt(net, rt);
@@ -3585,10 +3617,6 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
35853617
return ERR_PTR(-ENOMEM);
35863618

35873619
f6i->dst_nocount = true;
3588-
3589-
in6_dev_hold(idev);
3590-
f6i->fib6_idev = idev;
3591-
35923620
f6i->dst_host = true;
35933621
f6i->fib6_protocol = RTPROT_KERNEL;
35943622
f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP;
@@ -3706,7 +3734,7 @@ static bool rt6_is_dead(const struct fib6_info *rt)
37063734
{
37073735
if (rt->fib6_nh.nh_flags & RTNH_F_DEAD ||
37083736
(rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN &&
3709-
rt->fib6_idev->cnf.ignore_routes_with_linkdown))
3737+
fib6_ignore_linkdown(rt)))
37103738
return true;
37113739

37123740
return false;
@@ -4424,8 +4452,11 @@ static int rt6_nexthop_info(struct sk_buff *skb, struct fib6_info *rt,
44244452

44254453
if (rt->fib6_nh.nh_flags & RTNH_F_LINKDOWN) {
44264454
*flags |= RTNH_F_LINKDOWN;
4427-
if (rt->fib6_idev->cnf.ignore_routes_with_linkdown)
4455+
4456+
rcu_read_lock();
4457+
if (fib6_ignore_linkdown(rt))
44284458
*flags |= RTNH_F_DEAD;
4459+
rcu_read_unlock();
44294460
}
44304461

44314462
if (rt->fib6_flags & RTF_GATEWAY) {
@@ -4800,7 +4831,6 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48004831

48014832
if (event == NETDEV_REGISTER) {
48024833
net->ipv6.fib6_null_entry->fib6_nh.nh_dev = dev;
4803-
net->ipv6.fib6_null_entry->fib6_idev = in6_dev_get(dev);
48044834
net->ipv6.ip6_null_entry->dst.dev = dev;
48054835
net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
48064836
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -4814,7 +4844,6 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48144844
/* NETDEV_UNREGISTER could be fired for multiple times by
48154845
* netdev_wait_allrefs(). Make sure we only call this once.
48164846
*/
4817-
in6_dev_put_clear(&net->ipv6.fib6_null_entry->fib6_idev);
48184847
in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
48194848
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
48204849
in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
@@ -5137,7 +5166,6 @@ void __init ip6_route_init_special_entries(void)
51375166
* the loopback reference in rt6_info will not be taken, do it
51385167
* manually for init_net */
51395168
init_net.ipv6.fib6_null_entry->fib6_nh.nh_dev = init_net.loopback_dev;
5140-
init_net.ipv6.fib6_null_entry->fib6_idev = in6_dev_get(init_net.loopback_dev);
51415169
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
51425170
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
51435171
#ifdef CONFIG_IPV6_MULTIPLE_TABLES

0 commit comments

Comments
 (0)