aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c50
1 files changed, 9 insertions, 41 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e4ba974f143c..fd9af60397b5 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -202,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);
202static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); 202static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
203#define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field) 203#define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
204 204
205static inline int rt_genid(struct net *net)
206{
207 return atomic_read(&net->ipv4.rt_genid);
208}
209
210#ifdef CONFIG_PROC_FS 205#ifdef CONFIG_PROC_FS
211static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) 206static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
212{ 207{
@@ -447,27 +442,9 @@ static inline bool rt_is_expired(const struct rtable *rth)
447 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 442 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
448} 443}
449 444
450/* 445void rt_cache_flush(struct net *net)
451 * Perturbation of rt_genid by a small quantity [1..256]
452 * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
453 * many times (2^24) without giving recent rt_genid.
454 * Jenkins hash is strong enough that litle changes of rt_genid are OK.
455 */
456static void rt_cache_invalidate(struct net *net)
457{
458 unsigned char shuffle;
459
460 get_random_bytes(&shuffle, sizeof(shuffle));
461 atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
462}
463
464/*
465 * delay < 0 : invalidate cache (fast : entries will be deleted later)
466 * delay >= 0 : invalidate & flush cache (can be long)
467 */
468void rt_cache_flush(struct net *net, int delay)
469{ 446{
470 rt_cache_invalidate(net); 447 rt_genid_bump(net);
471} 448}
472 449
473static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, 450static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -934,12 +911,14 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
934 if (mtu < ip_rt_min_pmtu) 911 if (mtu < ip_rt_min_pmtu)
935 mtu = ip_rt_min_pmtu; 912 mtu = ip_rt_min_pmtu;
936 913
914 rcu_read_lock();
937 if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { 915 if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
938 struct fib_nh *nh = &FIB_RES_NH(res); 916 struct fib_nh *nh = &FIB_RES_NH(res);
939 917
940 update_or_create_fnhe(nh, fl4->daddr, 0, mtu, 918 update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
941 jiffies + ip_rt_mtu_expires); 919 jiffies + ip_rt_mtu_expires);
942 } 920 }
921 rcu_read_unlock();
943 return mtu; 922 return mtu;
944} 923}
945 924
@@ -956,7 +935,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
956 dst->obsolete = DST_OBSOLETE_KILL; 935 dst->obsolete = DST_OBSOLETE_KILL;
957 } else { 936 } else {
958 rt->rt_pmtu = mtu; 937 rt->rt_pmtu = mtu;
959 dst_set_expires(&rt->dst, ip_rt_mtu_expires); 938 rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
960 } 939 }
961} 940}
962 941
@@ -1263,7 +1242,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
1263{ 1242{
1264 struct rtable *rt = (struct rtable *) dst; 1243 struct rtable *rt = (struct rtable *) dst;
1265 1244
1266 if (dst->flags & DST_NOCACHE) { 1245 if (!list_empty(&rt->rt_uncached)) {
1267 spin_lock_bh(&rt_uncached_lock); 1246 spin_lock_bh(&rt_uncached_lock);
1268 list_del(&rt->rt_uncached); 1247 list_del(&rt->rt_uncached);
1269 spin_unlock_bh(&rt_uncached_lock); 1248 spin_unlock_bh(&rt_uncached_lock);
@@ -2028,7 +2007,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
2028 } 2007 }
2029 dev_out = net->loopback_dev; 2008 dev_out = net->loopback_dev;
2030 fl4->flowi4_oif = dev_out->ifindex; 2009 fl4->flowi4_oif = dev_out->ifindex;
2031 res.fi = NULL;
2032 flags |= RTCF_LOCAL; 2010 flags |= RTCF_LOCAL;
2033 goto make_route; 2011 goto make_route;
2034 } 2012 }
@@ -2344,7 +2322,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
2344 2322
2345void ip_rt_multicast_event(struct in_device *in_dev) 2323void ip_rt_multicast_event(struct in_device *in_dev)
2346{ 2324{
2347 rt_cache_flush(dev_net(in_dev->dev), 0); 2325 rt_cache_flush(dev_net(in_dev->dev));
2348} 2326}
2349 2327
2350#ifdef CONFIG_SYSCTL 2328#ifdef CONFIG_SYSCTL
@@ -2353,16 +2331,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
2353 size_t *lenp, loff_t *ppos) 2331 size_t *lenp, loff_t *ppos)
2354{ 2332{
2355 if (write) { 2333 if (write) {
2356 int flush_delay; 2334 rt_cache_flush((struct net *)__ctl->extra1);
2357 ctl_table ctl;
2358 struct net *net;
2359
2360 memcpy(&ctl, __ctl, sizeof(ctl));
2361 ctl.data = &flush_delay;
2362 proc_dointvec(&ctl, write, buffer, lenp, ppos);
2363
2364 net = (struct net *)__ctl->extra1;
2365 rt_cache_flush(net, flush_delay);
2366 return 0; 2335 return 0;
2367 } 2336 }
2368 2337
@@ -2532,8 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
2532 2501
2533static __net_init int rt_genid_init(struct net *net) 2502static __net_init int rt_genid_init(struct net *net)
2534{ 2503{
2535 get_random_bytes(&net->ipv4.rt_genid, 2504 atomic_set(&net->rt_genid, 0);
2536 sizeof(net->ipv4.rt_genid));
2537 get_random_bytes(&net->ipv4.dev_addr_genid, 2505 get_random_bytes(&net->ipv4.dev_addr_genid,
2538 sizeof(net->ipv4.dev_addr_genid)); 2506 sizeof(net->ipv4.dev_addr_genid));
2539 return 0; 2507 return 0;