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 | |
| 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')
| -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 | ||
