diff options
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 54 |
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); | |||
206 | static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); | 202 | static 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 | ||
209 | static 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 |
215 | static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) | 206 | static 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 | /* | 445 | void 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 | */ | ||
460 | static 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 | */ | ||
472 | void rt_cache_flush(struct net *net, int delay) | ||
473 | { | 446 | { |
474 | rt_cache_invalidate(net); | 447 | rt_genid_bump(net); |
475 | } | 448 | } |
476 | 449 | ||
477 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, | 450 | static 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 | ||
2349 | void ip_rt_multicast_event(struct in_device *in_dev) | 2323 | void 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 | ||
2537 | static __net_init int rt_genid_init(struct net *net) | 2502 | static __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; |