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.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a770df2493d2..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>
@@ -1097,7 +1098,7 @@ static int slow_chain_length(const struct rtable *head)
1097} 1098}
1098 1099
1099static int rt_intern_hash(unsigned hash, struct rtable *rt, 1100static int rt_intern_hash(unsigned hash, struct rtable *rt,
1100 struct rtable **rp, struct sk_buff *skb) 1101 struct rtable **rp, struct sk_buff *skb, int ifindex)
1101{ 1102{
1102 struct rtable *rth, **rthp; 1103 struct rtable *rth, **rthp;
1103 unsigned long now; 1104 unsigned long now;
@@ -1212,11 +1213,16 @@ restart:
1212 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) {
1213 struct net *net = dev_net(rt->u.dst.dev); 1214 struct net *net = dev_net(rt->u.dst.dev);
1214 int num = ++net->ipv4.current_rt_cache_rebuild_count; 1215 int num = ++net->ipv4.current_rt_cache_rebuild_count;
1215 if (!rt_caching(dev_net(rt->u.dst.dev))) { 1216 if (!rt_caching(net)) {
1216 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",
1217 rt->u.dst.dev->name, num); 1218 rt->u.dst.dev->name, num);
1218 } 1219 }
1219 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;
1220 } 1226 }
1221 } 1227 }
1222 1228
@@ -1441,7 +1447,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1441 dev_hold(rt->u.dst.dev); 1447 dev_hold(rt->u.dst.dev);
1442 if (rt->idev) 1448 if (rt->idev)
1443 in_dev_hold(rt->idev); 1449 in_dev_hold(rt->idev);
1444 rt->u.dst.obsolete = 0; 1450 rt->u.dst.obsolete = -1;
1445 rt->u.dst.lastuse = jiffies; 1451 rt->u.dst.lastuse = jiffies;
1446 rt->u.dst.path = &rt->u.dst; 1452 rt->u.dst.path = &rt->u.dst;
1447 rt->u.dst.neighbour = NULL; 1453 rt->u.dst.neighbour = NULL;
@@ -1477,7 +1483,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1477 &netevent); 1483 &netevent);
1478 1484
1479 rt_del(hash, rth); 1485 rt_del(hash, rth);
1480 if (!rt_intern_hash(hash, rt, &rt, NULL)) 1486 if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
1481 ip_rt_put(rt); 1487 ip_rt_put(rt);
1482 goto do_next; 1488 goto do_next;
1483 } 1489 }
@@ -1506,11 +1512,12 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1506 struct dst_entry *ret = dst; 1512 struct dst_entry *ret = dst;
1507 1513
1508 if (rt) { 1514 if (rt) {
1509 if (dst->obsolete) { 1515 if (dst->obsolete > 0) {
1510 ip_rt_put(rt); 1516 ip_rt_put(rt);
1511 ret = NULL; 1517 ret = NULL;
1512 } else if ((rt->rt_flags & RTCF_REDIRECTED) || 1518 } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
1513 rt->u.dst.expires) { 1519 (rt->u.dst.expires &&
1520 time_after_eq(jiffies, rt->u.dst.expires))) {
1514 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,
1515 rt->fl.oif, 1522 rt->fl.oif,
1516 rt_genid(dev_net(dst->dev))); 1523 rt_genid(dev_net(dst->dev)));
@@ -1726,7 +1733,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1726 1733
1727static 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)
1728{ 1735{
1729 return NULL; 1736 if (rt_is_expired((struct rtable *)dst))
1737 return NULL;
1738 return dst;
1730} 1739}
1731 1740
1732static void ipv4_dst_destroy(struct dst_entry *dst) 1741static void ipv4_dst_destroy(struct dst_entry *dst)
@@ -1888,7 +1897,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1888 if (!rth) 1897 if (!rth)
1889 goto e_nobufs; 1898 goto e_nobufs;
1890 1899
1891 rth->u.dst.output= ip_rt_bug; 1900 rth->u.dst.output = ip_rt_bug;
1901 rth->u.dst.obsolete = -1;
1892 1902
1893 atomic_set(&rth->u.dst.__refcnt, 1); 1903 atomic_set(&rth->u.dst.__refcnt, 1);
1894 rth->u.dst.flags= DST_HOST; 1904 rth->u.dst.flags= DST_HOST;
@@ -1927,7 +1937,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1927 1937
1928 in_dev_put(in_dev); 1938 in_dev_put(in_dev);
1929 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)));
1930 return rt_intern_hash(hash, rth, NULL, skb); 1940 return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
1931 1941
1932e_nobufs: 1942e_nobufs:
1933 in_dev_put(in_dev); 1943 in_dev_put(in_dev);
@@ -2054,6 +2064,7 @@ static int __mkroute_input(struct sk_buff *skb,
2054 rth->fl.oif = 0; 2064 rth->fl.oif = 0;
2055 rth->rt_spec_dst= spec_dst; 2065 rth->rt_spec_dst= spec_dst;
2056 2066
2067 rth->u.dst.obsolete = -1;
2057 rth->u.dst.input = ip_forward; 2068 rth->u.dst.input = ip_forward;
2058 rth->u.dst.output = ip_output; 2069 rth->u.dst.output = ip_output;
2059 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); 2070 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2093,7 +2104,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
2093 /* put it into the cache */ 2104 /* put it into the cache */
2094 hash = rt_hash(daddr, saddr, fl->iif, 2105 hash = rt_hash(daddr, saddr, fl->iif,
2095 rt_genid(dev_net(rth->u.dst.dev))); 2106 rt_genid(dev_net(rth->u.dst.dev)));
2096 return rt_intern_hash(hash, rth, NULL, skb); 2107 return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
2097} 2108}
2098 2109
2099/* 2110/*
@@ -2218,6 +2229,7 @@ local_input:
2218 goto e_nobufs; 2229 goto e_nobufs;
2219 2230
2220 rth->u.dst.output= ip_rt_bug; 2231 rth->u.dst.output= ip_rt_bug;
2232 rth->u.dst.obsolete = -1;
2221 rth->rt_genid = rt_genid(net); 2233 rth->rt_genid = rt_genid(net);
2222 2234
2223 atomic_set(&rth->u.dst.__refcnt, 1); 2235 atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2249,7 +2261,7 @@ local_input:
2249 } 2261 }
2250 rth->rt_type = res.type; 2262 rth->rt_type = res.type;
2251 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); 2263 hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
2252 err = rt_intern_hash(hash, rth, NULL, skb); 2264 err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
2253 goto done; 2265 goto done;
2254 2266
2255no_route: 2267no_route:
@@ -2444,6 +2456,7 @@ static int __mkroute_output(struct rtable **result,
2444 rth->rt_spec_dst= fl->fl4_src; 2456 rth->rt_spec_dst= fl->fl4_src;
2445 2457
2446 rth->u.dst.output=ip_output; 2458 rth->u.dst.output=ip_output;
2459 rth->u.dst.obsolete = -1;
2447 rth->rt_genid = rt_genid(dev_net(dev_out)); 2460 rth->rt_genid = rt_genid(dev_net(dev_out));
2448 2461
2449 RT_CACHE_STAT_INC(out_slow_tot); 2462 RT_CACHE_STAT_INC(out_slow_tot);
@@ -2495,7 +2508,7 @@ static int ip_mkroute_output(struct rtable **rp,
2495 if (err == 0) { 2508 if (err == 0) {
2496 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, 2509 hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
2497 rt_genid(dev_net(dev_out))); 2510 rt_genid(dev_net(dev_out)));
2498 err = rt_intern_hash(hash, rth, rp, NULL); 2511 err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
2499 } 2512 }
2500 2513
2501 return err; 2514 return err;