diff options
author | Julian Anastasov <ja@ssi.bg> | 2012-10-08 07:41:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-08 17:42:36 -0400 |
commit | c92b96553a80c1dbe2ebe128bbe37c8f98f148bf (patch) | |
tree | 2c08aaddff418e7be5c0674aeb9e4b94ec538179 /net/ipv4/route.c | |
parent | 155e8336c373d14d87a7f91e356d85ef4b93b8f9 (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.c | 21 |
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 | |||
1827 | add: | ||
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 | ||