diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-18 11:40:17 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-18 11:40:17 +0400 |
commit | d3aaeb38c40e5a6c08dd31a1b64da65c4352be36 (patch) | |
tree | 1c17b41d11edc7a7b3477a294cba440f2a14796c /net/ipv4/route.c | |
parent | 69cce1d1404968f78b177a0314f5822d5afdbbfb (diff) | |
download | linux-d3aaeb38c40e5a6c08dd31a1b64da65c4352be36.tar.xz |
net: Add ->neigh_lookup() operation to dst_ops
In the future dst entries will be neigh-less. In that environment we
need to have an easy transition point for current users of
dst->neighbour outside of the packet output fast path.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 1d4cd3b4fd69..33137307d52a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -185,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) return p; } +static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr); + static struct dst_ops ipv4_dst_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), @@ -199,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = { .link_failure = ipv4_link_failure, .update_pmtu = ip_rt_update_pmtu, .local_out = __ip_local_out, + .neigh_lookup = ipv4_neigh_lookup, }; #define ECN_OR_COST(class) TC_PRIO_##class @@ -1008,22 +1011,30 @@ static int slow_chain_length(const struct rtable *head) return length >> FRACT_BITS; } -static int rt_bind_neighbour(struct rtable *rt) +static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr) { - static const __be32 inaddr_any = 0; - struct net_device *dev = rt->dst.dev; struct neigh_table *tbl = &arp_tbl; - const __be32 *nexthop; + static const __be32 inaddr_any = 0; + struct net_device *dev = dst->dev; + const __be32 *pkey = daddr; struct neighbour *n; #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) if (dev->type == ARPHRD_ATM) tbl = clip_tbl_hook; #endif - nexthop = &rt->rt_gateway; if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) - nexthop = &inaddr_any; - n = ipv4_neigh_lookup(tbl, dev, nexthop); + pkey = &inaddr_any; + + n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey); + if (n) + return n; + return neigh_create(tbl, pkey, dev); +} + +static int rt_bind_neighbour(struct rtable *rt) +{ + struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); if (IS_ERR(n)) return PTR_ERR(n); dst_set_neighbour(&rt->dst, n); @@ -2734,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .default_advmss = ipv4_default_advmss, .update_pmtu = ipv4_rt_blackhole_update_pmtu, .cow_metrics = ipv4_rt_blackhole_cow_metrics, + .neigh_lookup = ipv4_neigh_lookup, }; struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) |