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.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d9b40248b97f..cb562fdd9b9a 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -90,6 +90,7 @@
90#include <linux/jhash.h> 90#include <linux/jhash.h>
91#include <linux/rcupdate.h> 91#include <linux/rcupdate.h>
92#include <linux/times.h> 92#include <linux/times.h>
93#include <linux/slab.h>
93#include <net/dst.h> 94#include <net/dst.h>
94#include <net/net_namespace.h> 95#include <net/net_namespace.h>
95#include <net/protocol.h> 96#include <net/protocol.h>
@@ -932,10 +933,8 @@ static void rt_secret_rebuild_oneshot(struct net *net)
932{ 933{
933 del_timer_sync(&net->ipv4.rt_secret_timer); 934 del_timer_sync(&net->ipv4.rt_secret_timer);
934 rt_cache_invalidate(net); 935 rt_cache_invalidate(net);
935 if (ip_rt_secret_interval) { 936 if (ip_rt_secret_interval)
936 net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval; 937 mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);
937 add_timer(&net->ipv4.rt_secret_timer);
938 }
939} 938}
940 939
941static void rt_emergency_hash_rebuild(struct net *net) 940static void rt_emergency_hash_rebuild(struct net *net)
@@ -1099,7 +1098,7 @@ static int slow_chain_length(const struct rtable *head)
1099} 1098}
1100 1099
1101static int rt_intern_hash(unsigned hash, struct rtable *rt, 1100static int rt_intern_hash(unsigned hash, struct rtable *rt,
1102 struct rtable **rp, struct sk_buff *skb) 1101 struct rtable **rp, struct sk_buff *skb, int ifindex)
1103{ 1102{
1104 struct rtable *rth, **rthp; 1103 struct rtable *rth, **rthp;
1105 unsigned long now; 1104 unsigned long now;
@@ -1214,11 +1213,16 @@ restart:
1214 slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) { 1213 slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {
1215 struct net *net = dev_net(rt->u.dst.dev); 1214 struct net *net = dev_net(rt->u.dst.dev);
1216 int num = ++net->ipv4.current_rt_cache_rebuild_count; 1215 int num = ++net->ipv4.current_rt_cache_rebuild_count;
1217 if (!rt_caching(dev_net(rt->u.dst.dev))) { 1216 if (!rt_caching(net)) {
1218 printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n", 1217 printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",
1219 rt->u.dst.dev->name, num); 1218 rt->u.dst.dev->name, num);
1220 } 1219 }
1221 rt_emergency_hash_rebuild(dev_net(rt->u.dst.dev)); 1220 rt_emergency_hash_rebuild(net);
1221 spin_unlock_bh(rt_hash_lock_addr(hash));
1222
1223 hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
1224 ifindex, rt_genid(net));
1225 goto restart;
1222 } 1226 }
1223 } 1227 }
1224 1228
@@ -1443,7 +1447,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1443 dev_hold(rt->u.dst.dev); 1447 dev_hold(rt->u.dst.dev);
1444 if (rt->idev) 1448 if (rt->idev)
1445 in_dev_hold(rt->idev); 1449 in_dev_hold(rt->idev);
1446 rt->u.dst.obsolete = 0; 1450 rt->u.dst.obsolete = -1;
1447 rt->u.dst.lastuse = jiffies; 1451 rt->u.dst.lastuse = jiffies;
1448 rt->u.dst.path = &rt->u.dst; 1452 rt->u.dst.path = &rt->u.dst;
1449 rt->u.dst.neighbour = NULL; 1453 rt->u.dst.neighbour = NULL;
@@ -1479,7 +1483,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1479 &netevent); 1483 &netevent);
1480 1484
1481 rt_del(hash, rth); 1485 rt_del(hash, rth);
1482 if (!rt_intern_hash(hash, rt, &rt, NULL)) 1486 if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
1483 ip_rt_put(rt); 1487 ip_rt_put(rt);
1484 goto do_next; 1488 goto do_next;
1485 } 1489 }
@@ -1508,11 +1512,12 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1508 struct dst_entry *ret = dst; 1512 struct dst_entry *ret = dst;
1509 1513
1510 if (rt) { 1514 if (rt) {
1511 if (dst->obsolete) { 1515 if (dst->obsolete > 0) {
1512 ip_rt_put(rt); 1516 ip_rt_put(rt);
1513 ret = NULL; 1517 ret = NULL;
1514 } else if ((rt->rt_flags & RTCF_REDIRECTED) || 1518 } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
1515 rt->u.dst.expires) { 1519 (rt->u.dst.expires &&
1520 time_after_eq(jiffies, rt->u.dst.expires))) {
1516 unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src, 1521 unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
1517 rt->fl.oif, 1522 rt->fl.oif,
1518 rt_genid(dev_net(dst->dev))); 1523 rt_genid(dev_net(dst->dev)));
@@ -1728,7 +1733,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1728 1733
1729static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1734static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1730{ 1735{
1731 return NULL; 1736 if (rt_is_expired((struct rtable *)dst))
1737 return NULL;
1738 return dst;
1732} 1739}
1733 1740
1734static void ipv4_dst_destroy(struct dst_entry *dst) 1741static void ipv4_dst_destroy(struct dst_entry *dst)
@@ -1890,7 +1897,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1890 if (!rth) 1897 if (!rth)
1891 goto e_nobufs; 1898 goto e_nobufs;
1892 1899
1893 rth->u.dst.output= ip_rt_bug; 1900 rth->u.dst.output = ip_rt_bug;
1901 rth->u.dst.obsolete = -1;
1894 1902
1895 atomic_set(&rth->u.dst.__refcnt, 1); 1903 atomic_set(&rth->u.dst.__refcnt, 1);
1896 rth->u.dst.flags= DST_HOST; 1904 rth->u.dst.flags= DST_HOST;
@@ -1929,7 +1937,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1929 1937
1930 in_dev_put(in_dev); 1938 in_dev_put(in_dev);
1931 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); 1939 hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
1932 return rt_intern_hash(hash, rth, NULL, skb); 1940 return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
1933 1941
1934e_nobufs: 1942e_nobufs:
1935 in_dev_put(in_dev); 1943 in_dev_put(in_dev);
@@ -2056,6 +2064,7 @@ static int __mkroute_input(struct sk_buff *skb,
2056 rth->fl.oif = 0; 2064 rth->fl.oif = 0;
2057 rth->rt_spec_dst= spec_dst; 2065 rth->rt_spec_dst= spec_dst;
2058 2066
2067 rth->u.dst.obsolete = -1;
2059 rth->u.dst.input = ip_forward; 2068 rth->u.dst.input = ip_forward;
2060 rth->u.dst.output = ip_output; 2069 rth->u.dst.output = ip_output;
2061 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); 2070 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2095,7 +2104,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
2095 /* put it into the cache */ 2104 /* put it into the cache */
2096 hash = rt_hash(daddr, saddr, fl->iif, 2105 hash = rt_hash(daddr, saddr, fl->iif,
2097 rt_genid(dev_net(rth->u.dst.dev))); 2106 rt_genid(dev_net(rth->u.dst.dev)));
2098 return rt_intern_hash(hash, rth, NULL, skb); 2107 return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
2099} 2108}
2100 2109
2101/* 2110/*
@@ -2220,6 +2229,7 @@ local_input:
2220 goto e_nobufs; 2229 goto e_nobufs;
2221 2230
2222 rth->u.dst.output= ip_rt_bug; 2231 rth->u.dst.output= ip_rt_bug;
2232 rth->u.dst.obsolete = -1;
2223 rth->rt_genid = rt_genid(net); 2233 rth->rt_genid = rt_genid(net);
2224 2234
2225 atomic_set(&rth->u.dst.__refcnt, 1); 2235 atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2251,7 +2261,7 @@ local_input:
2251 } 2261 }
2252 rth->rt_type = res.type; 2262 rth->rt_type = res.type;
2253 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); 2263 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
2254 err = rt_intern_hash(hash, rth, NULL, skb); 2264 err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
2255 goto done; 2265 goto done;
2256 2266
2257no_route: 2267no_route:
@@ -2446,6 +2456,7 @@ static int __mkroute_output(struct rtable **result,
2446 rth->rt_spec_dst= fl->fl4_src; 2456 rth->rt_spec_dst= fl->fl4_src;
2447 2457
2448 rth->u.dst.output=ip_output; 2458 rth->u.dst.output=ip_output;
2459 rth->u.dst.obsolete = -1;
2449 rth->rt_genid = rt_genid(dev_net(dev_out)); 2460 rth->rt_genid = rt_genid(dev_net(dev_out));
2450 2461
2451 RT_CACHE_STAT_INC(out_slow_tot); 2462 RT_CACHE_STAT_INC(out_slow_tot);
@@ -2497,7 +2508,7 @@ static int ip_mkroute_output(struct rtable **rp,
2497 if (err == 0) { 2508 if (err == 0) {
2498 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, 2509 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
2499 rt_genid(dev_net(dev_out))); 2510 rt_genid(dev_net(dev_out)));
2500 err = rt_intern_hash(hash, rth, rp, NULL); 2511 err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
2501 } 2512 }
2502 2513
2503 return err; 2514 return err;
@@ -3103,22 +3114,20 @@ static void rt_secret_reschedule(int old)
3103 rtnl_lock(); 3114 rtnl_lock();
3104 for_each_net(net) { 3115 for_each_net(net) {
3105 int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); 3116 int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
3117 long time;
3106 3118
3107 if (!new) 3119 if (!new)
3108 continue; 3120 continue;
3109 3121
3110 if (deleted) { 3122 if (deleted) {
3111 long time = net->ipv4.rt_secret_timer.expires - jiffies; 3123 time = net->ipv4.rt_secret_timer.expires - jiffies;
3112 3124
3113 if (time <= 0 || (time += diff) <= 0) 3125 if (time <= 0 || (time += diff) <= 0)
3114 time = 0; 3126 time = 0;
3115
3116 net->ipv4.rt_secret_timer.expires = time;
3117 } else 3127 } else
3118 net->ipv4.rt_secret_timer.expires = new; 3128 time = new;
3119 3129
3120 net->ipv4.rt_secret_timer.expires += jiffies; 3130 mod_timer(&net->ipv4.rt_secret_timer, jiffies + time);
3121 add_timer(&net->ipv4.rt_secret_timer);
3122 } 3131 }
3123 rtnl_unlock(); 3132 rtnl_unlock();
3124} 3133}