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>
This commit is contained in:
David S. Miller 2011-07-18 00:40:17 -07:00
parent 69cce1d140
commit d3aaeb38c4
8 changed files with 52 additions and 16 deletions

View file

@ -38,15 +38,6 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct neigh_table *tbl, str
return n; return n;
} }
static inline struct neighbour *ipv4_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const __be32 *pkey)
{
struct neighbour *n = __ipv4_neigh_lookup(tbl, dev,
*(__force u32 *)pkey);
if (n)
return n;
return neigh_create(tbl, pkey, dev);
}
extern void arp_init(void); extern void arp_init(void);
extern int arp_find(unsigned char *haddr, struct sk_buff *skb); extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
extern int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg); extern int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);

View file

@ -387,6 +387,11 @@ static inline void dst_confirm(struct dst_entry *dst)
} }
} }
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return dst->ops->neigh_lookup(dst, daddr);
}
static inline void dst_link_failure(struct sk_buff *skb) static inline void dst_link_failure(struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);

View file

@ -26,6 +26,7 @@ struct dst_ops {
void (*link_failure)(struct sk_buff *); void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu); void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
int (*local_out)(struct sk_buff *skb); int (*local_out)(struct sk_buff *skb);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
struct kmem_cache *kmem_cachep; struct kmem_cache *kmem_cachep;

View file

@ -109,11 +109,17 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
return NULL; return NULL;
} }
static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return NULL;
}
static struct dst_ops fake_dst_ops = { static struct dst_ops fake_dst_ops = {
.family = AF_INET, .family = AF_INET,
.protocol = cpu_to_be16(ETH_P_IP), .protocol = cpu_to_be16(ETH_P_IP),
.update_pmtu = fake_update_pmtu, .update_pmtu = fake_update_pmtu,
.cow_metrics = fake_cow_metrics, .cow_metrics = fake_cow_metrics,
.neigh_lookup = fake_neigh_lookup,
}; };
/* /*

View file

@ -116,6 +116,7 @@ static void dn_dst_destroy(struct dst_entry *);
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
static void dn_dst_link_failure(struct sk_buff *); static void dn_dst_link_failure(struct sk_buff *);
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr);
static int dn_route_input(struct sk_buff *); static int dn_route_input(struct sk_buff *);
static void dn_run_flush(unsigned long dummy); static void dn_run_flush(unsigned long dummy);
@ -139,6 +140,7 @@ static struct dst_ops dn_dst_ops = {
.negative_advice = dn_dst_negative_advice, .negative_advice = dn_dst_negative_advice,
.link_failure = dn_dst_link_failure, .link_failure = dn_dst_link_failure,
.update_pmtu = dn_dst_update_pmtu, .update_pmtu = dn_dst_update_pmtu,
.neigh_lookup = dn_dst_neigh_lookup,
}; };
static void dn_dst_destroy(struct dst_entry *dst) static void dn_dst_destroy(struct dst_entry *dst)
@ -827,6 +829,11 @@ static unsigned int dn_dst_default_mtu(const struct dst_entry *dst)
return dst->dev->mtu; return dst->dev->mtu;
} }
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
}
static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
{ {
struct dn_fib_info *fi = res->fi; struct dn_fib_info *fi = res->fi;

View file

@ -185,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
return p; return p;
} }
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
static struct dst_ops ipv4_dst_ops = { static struct dst_ops ipv4_dst_ops = {
.family = AF_INET, .family = AF_INET,
.protocol = cpu_to_be16(ETH_P_IP), .protocol = cpu_to_be16(ETH_P_IP),
@ -199,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = {
.link_failure = ipv4_link_failure, .link_failure = ipv4_link_failure,
.update_pmtu = ip_rt_update_pmtu, .update_pmtu = ip_rt_update_pmtu,
.local_out = __ip_local_out, .local_out = __ip_local_out,
.neigh_lookup = ipv4_neigh_lookup,
}; };
#define ECN_OR_COST(class) TC_PRIO_##class #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; 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; 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; struct neighbour *n;
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
if (dev->type == ARPHRD_ATM) if (dev->type == ARPHRD_ATM)
tbl = clip_tbl_hook; tbl = clip_tbl_hook;
#endif #endif
nexthop = &rt->rt_gateway;
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
nexthop = &inaddr_any; pkey = &inaddr_any;
n = ipv4_neigh_lookup(tbl, dev, nexthop);
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)) if (IS_ERR(n))
return PTR_ERR(n); return PTR_ERR(n);
dst_set_neighbour(&rt->dst, n); dst_set_neighbour(&rt->dst, n);
@ -2734,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
.default_advmss = ipv4_default_advmss, .default_advmss = ipv4_default_advmss,
.update_pmtu = ipv4_rt_blackhole_update_pmtu, .update_pmtu = ipv4_rt_blackhole_update_pmtu,
.cow_metrics = ipv4_rt_blackhole_cow_metrics, .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) struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)

View file

@ -127,6 +127,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
return p; return p;
} }
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev);
}
static struct dst_ops ip6_dst_ops_template = { static struct dst_ops ip6_dst_ops_template = {
.family = AF_INET6, .family = AF_INET6,
.protocol = cpu_to_be16(ETH_P_IPV6), .protocol = cpu_to_be16(ETH_P_IPV6),
@ -142,6 +147,7 @@ static struct dst_ops ip6_dst_ops_template = {
.link_failure = ip6_link_failure, .link_failure = ip6_link_failure,
.update_pmtu = ip6_rt_update_pmtu, .update_pmtu = ip6_rt_update_pmtu,
.local_out = __ip6_local_out, .local_out = __ip6_local_out,
.neigh_lookup = ip6_neigh_lookup,
}; };
static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
@ -168,6 +174,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
.default_advmss = ip6_default_advmss, .default_advmss = ip6_default_advmss,
.update_pmtu = ip6_rt_blackhole_update_pmtu, .update_pmtu = ip6_rt_blackhole_update_pmtu,
.cow_metrics = ip6_rt_blackhole_cow_metrics, .cow_metrics = ip6_rt_blackhole_cow_metrics,
.neigh_lookup = ip6_neigh_lookup,
}; };
static const u32 ip6_template_metrics[RTAX_MAX] = { static const u32 ip6_template_metrics[RTAX_MAX] = {

View file

@ -2385,6 +2385,11 @@ static unsigned int xfrm_default_mtu(const struct dst_entry *dst)
return dst_mtu(dst->path); return dst_mtu(dst->path);
} }
static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return dst_neigh_lookup(dst->path, daddr);
}
int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{ {
struct net *net; struct net *net;
@ -2410,6 +2415,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->negative_advice = xfrm_negative_advice; dst_ops->negative_advice = xfrm_negative_advice;
if (likely(dst_ops->link_failure == NULL)) if (likely(dst_ops->link_failure == NULL))
dst_ops->link_failure = xfrm_link_failure; dst_ops->link_failure = xfrm_link_failure;
if (likely(dst_ops->neigh_lookup == NULL))
dst_ops->neigh_lookup = xfrm_neigh_lookup;
if (likely(afinfo->garbage_collect == NULL)) if (likely(afinfo->garbage_collect == NULL))
afinfo->garbage_collect = __xfrm_garbage_collect; afinfo->garbage_collect = __xfrm_garbage_collect;
xfrm_policy_afinfo[afinfo->family] = afinfo; xfrm_policy_afinfo[afinfo->family] = afinfo;