ipv6: Store route neighbour in rt6_info struct.

This makes for a simplified conversion away from dst_get_neighbour*().

All code outside of ipv6 will use neigh lookups via dst_neigh_lookup*().

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2012-07-02 22:43:47 -07:00
parent 534cb283ef
commit 97cac0821a
4 changed files with 35 additions and 18 deletions

View File

@ -86,6 +86,8 @@ struct fib6_table;
struct rt6_info { struct rt6_info {
struct dst_entry dst; struct dst_entry dst;
struct neighbour *n;
/* /*
* Tail elements of dst_entry (__refcnt etc.) * Tail elements of dst_entry (__refcnt etc.)
* and these elements (rarely used in hot path) are in * and these elements (rarely used in hot path) are in

View File

@ -88,6 +88,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
struct neighbour *neigh; struct neighbour *neigh;
struct rt6_info *rt;
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev; skb->dev = dev;
@ -123,7 +124,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
} }
rcu_read_lock(); rcu_read_lock();
neigh = dst_get_neighbour_noref(dst); rt = (struct rt6_info *) dst;
neigh = rt->n;
if (neigh) { if (neigh) {
int res = dst_neigh_output(dst, neigh, skb); int res = dst_neigh_output(dst, neigh, skb);
@ -944,6 +946,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
struct neighbour *n; struct neighbour *n;
struct rt6_info *rt;
#endif #endif
int err; int err;
@ -972,7 +975,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
* dst entry of the nexthop router * dst entry of the nexthop router
*/ */
rcu_read_lock(); rcu_read_lock();
n = dst_get_neighbour_noref(*dst); rt = (struct rt6_info *) dst;
n = rt->n;
if (n && !(n->nud_state & NUD_VALID)) { if (n && !(n->nud_state & NUD_VALID)) {
struct inet6_ifaddr *ifp; struct inet6_ifaddr *ifp;
struct flowi6 fl_gw6; struct flowi6 fl_gw6;

View File

@ -155,7 +155,7 @@ static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev)
if (IS_ERR(n)) if (IS_ERR(n))
return PTR_ERR(n); return PTR_ERR(n);
} }
dst_set_neighbour(&rt->dst, n); rt->n = n;
return 0; return 0;
} }
@ -285,6 +285,9 @@ static void ip6_dst_destroy(struct dst_entry *dst)
struct rt6_info *rt = (struct rt6_info *)dst; struct rt6_info *rt = (struct rt6_info *)dst;
struct inet6_dev *idev = rt->rt6i_idev; struct inet6_dev *idev = rt->rt6i_idev;
if (rt->n)
neigh_release(rt->n);
if (!(rt->dst.flags & DST_HOST)) if (!(rt->dst.flags & DST_HOST))
dst_destroy_metrics_generic(dst); dst_destroy_metrics_generic(dst);
@ -335,12 +338,19 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
struct net_device *loopback_dev = struct net_device *loopback_dev =
dev_net(dev)->loopback_dev; dev_net(dev)->loopback_dev;
if (dev != loopback_dev && idev && idev->dev == dev) { if (dev != loopback_dev) {
struct inet6_dev *loopback_idev = if (idev && idev->dev == dev) {
in6_dev_get(loopback_dev); struct inet6_dev *loopback_idev =
if (loopback_idev) { in6_dev_get(loopback_dev);
rt->rt6i_idev = loopback_idev; if (loopback_idev) {
in6_dev_put(idev); rt->rt6i_idev = loopback_idev;
in6_dev_put(idev);
}
}
if (rt->n && rt->n->dev == dev) {
rt->n->dev = loopback_dev;
dev_hold(loopback_dev);
dev_put(dev);
} }
} }
} }
@ -430,7 +440,7 @@ static void rt6_probe(struct rt6_info *rt)
* to no more than one per minute. * to no more than one per minute.
*/ */
rcu_read_lock(); rcu_read_lock();
neigh = rt ? dst_get_neighbour_noref(&rt->dst) : NULL; neigh = rt ? rt->n : NULL;
if (!neigh || (neigh->nud_state & NUD_VALID)) if (!neigh || (neigh->nud_state & NUD_VALID))
goto out; goto out;
read_lock_bh(&neigh->lock); read_lock_bh(&neigh->lock);
@ -477,7 +487,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
int m; int m;
rcu_read_lock(); rcu_read_lock();
neigh = dst_get_neighbour_noref(&rt->dst); neigh = rt->n;
if (rt->rt6i_flags & RTF_NONEXTHOP || if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY)) !(rt->rt6i_flags & RTF_GATEWAY))
m = 1; m = 1;
@ -824,7 +834,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
if (rt) { if (rt) {
rt->rt6i_flags |= RTF_CACHE; rt->rt6i_flags |= RTF_CACHE;
dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_noref_raw(&ort->dst))); rt->n = neigh_clone(ort->n);
} }
return rt; return rt;
} }
@ -858,7 +868,7 @@ restart:
dst_hold(&rt->dst); dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock); read_unlock_bh(&table->tb6_lock);
if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
else if (!(rt->dst.flags & DST_HOST)) else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl6->daddr); nrt = rt6_alloc_clone(rt, &fl6->daddr);
@ -1178,7 +1188,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
rt->dst.flags |= DST_HOST; rt->dst.flags |= DST_HOST;
rt->dst.output = ip6_output; rt->dst.output = ip6_output;
dst_set_neighbour(&rt->dst, neigh); rt->n = neigh;
atomic_set(&rt->dst.__refcnt, 1); atomic_set(&rt->dst.__refcnt, 1);
rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.addr = fl6->daddr;
rt->rt6i_dst.plen = 128; rt->rt6i_dst.plen = 128;
@ -1715,7 +1725,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
dst_confirm(&rt->dst); dst_confirm(&rt->dst);
/* Duplicate redirect: silently ignore. */ /* Duplicate redirect: silently ignore. */
old_neigh = dst_get_neighbour_noref_raw(&rt->dst); old_neigh = rt->n;
if (neigh == old_neigh) if (neigh == old_neigh)
goto out; goto out;
@ -1728,7 +1738,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
nrt->rt6i_flags &= ~RTF_GATEWAY; nrt->rt6i_flags &= ~RTF_GATEWAY;
nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); nrt->n = neigh_clone(neigh);
if (ip6_ins_rt(nrt)) if (ip6_ins_rt(nrt))
goto out; goto out;
@ -2442,7 +2452,7 @@ static int rt6_fill_node(struct net *net,
goto nla_put_failure; goto nla_put_failure;
rcu_read_lock(); rcu_read_lock();
n = dst_get_neighbour_noref(&rt->dst); n = rt->n;
if (n) { if (n) {
if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) {
rcu_read_unlock(); rcu_read_unlock();
@ -2666,7 +2676,7 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
seq_puts(m, "00000000000000000000000000000000 00 "); seq_puts(m, "00000000000000000000000000000000 00 ");
#endif #endif
rcu_read_lock(); rcu_read_lock();
n = dst_get_neighbour_noref(&rt->dst); n = rt->n;
if (n) { if (n) {
seq_printf(m, "%pi6", n->primary_key); seq_printf(m, "%pi6", n->primary_key);
} else { } else {

View File

@ -103,6 +103,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
/* Sheit... I remember I did this right. Apparently, /* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */ * it was magically lost, so this code needs audit */
xdst->u.rt6.n = neigh_clone(rt->n);
xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST |
RTF_LOCAL); RTF_LOCAL);
xdst->u.rt6.rt6i_metric = rt->rt6i_metric; xdst->u.rt6.rt6i_metric = rt->rt6i_metric;