aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2012-10-08 07:41:19 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-08 17:42:36 -0400
commitc92b96553a80c1dbe2ebe128bbe37c8f98f148bf (patch)
tree2c08aaddff418e7be5c0674aeb9e4b94ec538179 /net/ipv4/route.c
parent155e8336c373d14d87a7f91e356d85ef4b93b8f9 (diff)
ipv4: Add FLOWI_FLAG_KNOWN_NH
Add flag to request that output route should be returned with known rt_gateway, in case we want to use it as nexthop for neighbour resolving. The returned route can be cached as follows: - in NH exception: because the cached routes are not shared with other destinations - in FIB NH: when using gateway because all destinations for NH share same gateway As last option, to return rt_gateway!=0 we have to set DST_NOCACHE. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3a116cb0991a..1a0da8dc8180 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1762,6 +1762,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
1762 struct in_device *in_dev; 1762 struct in_device *in_dev;
1763 u16 type = res->type; 1763 u16 type = res->type;
1764 struct rtable *rth; 1764 struct rtable *rth;
1765 bool do_cache;
1765 1766
1766 in_dev = __in_dev_get_rcu(dev_out); 1767 in_dev = __in_dev_get_rcu(dev_out);
1767 if (!in_dev) 1768 if (!in_dev)
@@ -1798,24 +1799,36 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
1798 } 1799 }
1799 1800
1800 fnhe = NULL; 1801 fnhe = NULL;
1802 do_cache = fi != NULL;
1801 if (fi) { 1803 if (fi) {
1802 struct rtable __rcu **prth; 1804 struct rtable __rcu **prth;
1805 struct fib_nh *nh = &FIB_RES_NH(*res);
1803 1806
1804 fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); 1807 fnhe = find_exception(nh, fl4->daddr);
1805 if (fnhe) 1808 if (fnhe)
1806 prth = &fnhe->fnhe_rth; 1809 prth = &fnhe->fnhe_rth;
1807 else 1810 else {
1808 prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output); 1811 if (unlikely(fl4->flowi4_flags &
1812 FLOWI_FLAG_KNOWN_NH &&
1813 !(nh->nh_gw &&
1814 nh->nh_scope == RT_SCOPE_LINK))) {
1815 do_cache = false;
1816 goto add;
1817 }
1818 prth = __this_cpu_ptr(nh->nh_pcpu_rth_output);
1819 }
1809 rth = rcu_dereference(*prth); 1820 rth = rcu_dereference(*prth);
1810 if (rt_cache_valid(rth)) { 1821 if (rt_cache_valid(rth)) {
1811 dst_hold(&rth->dst); 1822 dst_hold(&rth->dst);
1812 return rth; 1823 return rth;
1813 } 1824 }
1814 } 1825 }
1826
1827add:
1815 rth = rt_dst_alloc(dev_out, 1828 rth = rt_dst_alloc(dev_out,
1816 IN_DEV_CONF_GET(in_dev, NOPOLICY), 1829 IN_DEV_CONF_GET(in_dev, NOPOLICY),
1817 IN_DEV_CONF_GET(in_dev, NOXFRM), 1830 IN_DEV_CONF_GET(in_dev, NOXFRM),
1818 fi); 1831 do_cache);
1819 if (!rth) 1832 if (!rth)
1820 return ERR_PTR(-ENOBUFS); 1833 return ERR_PTR(-ENOBUFS);
1821 1834