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.c54
1 files changed, 9 insertions, 45 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index c035251beb07..fd9af60397b5 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -70,7 +70,6 @@
70#include <linux/types.h> 70#include <linux/types.h>
71#include <linux/kernel.h> 71#include <linux/kernel.h>
72#include <linux/mm.h> 72#include <linux/mm.h>
73#include <linux/bootmem.h>
74#include <linux/string.h> 73#include <linux/string.h>
75#include <linux/socket.h> 74#include <linux/socket.h>
76#include <linux/sockios.h> 75#include <linux/sockios.h>
@@ -80,7 +79,6 @@
80#include <linux/netdevice.h> 79#include <linux/netdevice.h>
81#include <linux/proc_fs.h> 80#include <linux/proc_fs.h>
82#include <linux/init.h> 81#include <linux/init.h>
83#include <linux/workqueue.h>
84#include <linux/skbuff.h> 82#include <linux/skbuff.h>
85#include <linux/inetdevice.h> 83#include <linux/inetdevice.h>
86#include <linux/igmp.h> 84#include <linux/igmp.h>
@@ -88,11 +86,9 @@
88#include <linux/mroute.h> 86#include <linux/mroute.h>
89#include <linux/netfilter_ipv4.h> 87#include <linux/netfilter_ipv4.h>
90#include <linux/random.h> 88#include <linux/random.h>
91#include <linux/jhash.h>
92#include <linux/rcupdate.h> 89#include <linux/rcupdate.h>
93#include <linux/times.h> 90#include <linux/times.h>
94#include <linux/slab.h> 91#include <linux/slab.h>
95#include <linux/prefetch.h>
96#include <net/dst.h> 92#include <net/dst.h>
97#include <net/net_namespace.h> 93#include <net/net_namespace.h>
98#include <net/protocol.h> 94#include <net/protocol.h>
@@ -206,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);
206static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); 202static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
207#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)
208 204
209static inline int rt_genid(struct net *net)
210{
211 return atomic_read(&net->ipv4.rt_genid);
212}
213
214#ifdef CONFIG_PROC_FS 205#ifdef CONFIG_PROC_FS
215static 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)
216{ 207{
@@ -451,27 +442,9 @@ static inline bool rt_is_expired(const struct rtable *rth)
451 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 442 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
452} 443}
453 444
454/* 445void rt_cache_flush(struct net *net)
455 * Perturbation of rt_genid by a small quantity [1..256]
456 * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
457 * many times (2^24) without giving recent rt_genid.
458 * Jenkins hash is strong enough that litle changes of rt_genid are OK.
459 */
460static void rt_cache_invalidate(struct net *net)
461{
462 unsigned char shuffle;
463
464 get_random_bytes(&shuffle, sizeof(shuffle));
465 atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
466}
467
468/*
469 * delay < 0 : invalidate cache (fast : entries will be deleted later)
470 * delay >= 0 : invalidate & flush cache (can be long)
471 */
472void rt_cache_flush(struct net *net, int delay)
473{ 446{
474 rt_cache_invalidate(net); 447 rt_genid_bump(net);
475} 448}
476 449
477static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, 450static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -938,12 +911,14 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
938 if (mtu < ip_rt_min_pmtu) 911 if (mtu < ip_rt_min_pmtu)
939 mtu = ip_rt_min_pmtu; 912 mtu = ip_rt_min_pmtu;
940 913
914 rcu_read_lock();
941 if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { 915 if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
942 struct fib_nh *nh = &FIB_RES_NH(res); 916 struct fib_nh *nh = &FIB_RES_NH(res);
943 917
944 update_or_create_fnhe(nh, fl4->daddr, 0, mtu, 918 update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
945 jiffies + ip_rt_mtu_expires); 919 jiffies + ip_rt_mtu_expires);
946 } 920 }
921 rcu_read_unlock();
947 return mtu; 922 return mtu;
948} 923}
949 924
@@ -960,7 +935,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
960 dst->obsolete = DST_OBSOLETE_KILL; 935 dst->obsolete = DST_OBSOLETE_KILL;
961 } else { 936 } else {
962 rt->rt_pmtu = mtu; 937 rt->rt_pmtu = mtu;
963 dst_set_expires(&rt->dst, ip_rt_mtu_expires); 938 rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
964 } 939 }
965} 940}
966 941
@@ -1267,7 +1242,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
1267{ 1242{
1268 struct rtable *rt = (struct rtable *) dst; 1243 struct rtable *rt = (struct rtable *) dst;
1269 1244
1270 if (dst->flags & DST_NOCACHE) { 1245 if (!list_empty(&rt->rt_uncached)) {
1271 spin_lock_bh(&rt_uncached_lock); 1246 spin_lock_bh(&rt_uncached_lock);
1272 list_del(&rt->rt_uncached); 1247 list_del(&rt->rt_uncached);
1273 spin_unlock_bh(&rt_uncached_lock); 1248 spin_unlock_bh(&rt_uncached_lock);
@@ -2032,7 +2007,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
2032 } 2007 }
2033 dev_out = net->loopback_dev; 2008 dev_out = net->loopback_dev;
2034 fl4->flowi4_oif = dev_out->ifindex; 2009 fl4->flowi4_oif = dev_out->ifindex;
2035 res.fi = NULL;
2036 flags |= RTCF_LOCAL; 2010 flags |= RTCF_LOCAL;
2037 goto make_route; 2011 goto make_route;
2038 } 2012 }
@@ -2348,7 +2322,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
2348 2322
2349void ip_rt_multicast_event(struct in_device *in_dev) 2323void ip_rt_multicast_event(struct in_device *in_dev)
2350{ 2324{
2351 rt_cache_flush(dev_net(in_dev->dev), 0); 2325 rt_cache_flush(dev_net(in_dev->dev));
2352} 2326}
2353 2327
2354#ifdef CONFIG_SYSCTL 2328#ifdef CONFIG_SYSCTL
@@ -2357,16 +2331,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
2357 size_t *lenp, loff_t *ppos) 2331 size_t *lenp, loff_t *ppos)
2358{ 2332{
2359 if (write) { 2333 if (write) {
2360 int flush_delay; 2334 rt_cache_flush((struct net *)__ctl->extra1);
2361 ctl_table ctl;
2362 struct net *net;
2363
2364 memcpy(&ctl, __ctl, sizeof(ctl));
2365 ctl.data = &flush_delay;
2366 proc_dointvec(&ctl, write, buffer, lenp, ppos);
2367
2368 net = (struct net *)__ctl->extra1;
2369 rt_cache_flush(net, flush_delay);
2370 return 0; 2335 return 0;
2371 } 2336 }
2372 2337
@@ -2536,8 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
2536 2501
2537static __net_init int rt_genid_init(struct net *net) 2502static __net_init int rt_genid_init(struct net *net)
2538{ 2503{
2539 get_random_bytes(&net->ipv4.rt_genid, 2504 atomic_set(&net->rt_genid, 0);
2540 sizeof(net->ipv4.rt_genid));
2541 get_random_bytes(&net->ipv4.dev_addr_genid, 2505 get_random_bytes(&net->ipv4.dev_addr_genid,
2542 sizeof(net->ipv4.dev_addr_genid)); 2506 sizeof(net->ipv4.dev_addr_genid));
2543 return 0; 2507 return 0;