Refactor dst_neigh_lookup and create a new function that takes the
gateway and device. Since rt6_get_dflt_router returns a FIB entry,
change ndisc_router_discovery to use the new ip6_neigh_lookup.

Signed-off-by: David Ahern <dsah...@gmail.com>
---
 include/net/ip6_route.h |  5 +++++
 net/ipv6/ndisc.c        |  8 ++++++--
 net/ipv6/route.c        | 33 ++++++++++++++++++++-------------
 3 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index bd82ec4a57e6..aa59c6eb34e6 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -268,4 +268,9 @@ static inline bool rt6_duplicate_nexthop(struct rt6_info 
*a, struct rt6_info *b)
               ipv6_addr_equal(&a->fib6_nh.nh_gw, &b->fib6_nh.nh_gw) &&
               !lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, 
b->fib6_nh.nh_lwtstate);
 }
+
+struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
+                                  struct net_device *dev,
+                                  struct sk_buff *skb,
+                                  const void *daddr);
 #endif
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index bd804e8cd73c..023da106b682 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1276,7 +1276,9 @@ static void ndisc_router_discovery(struct sk_buff *skb)
        rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
 
        if (rt) {
-               neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
+               neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
+                                        rt->fib6_nh.nh_dev, NULL,
+                                         &ipv6_hdr(skb)->saddr);
                if (!neigh) {
                        ND_PRINTK(0, err,
                                  "RA: %s got default router without 
neighbour\n",
@@ -1304,7 +1306,9 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                        return;
                }
 
-               neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr);
+               neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
+                                        rt->fib6_nh.nh_dev, NULL,
+                                         &ipv6_hdr(skb)->saddr);
                if (!neigh) {
                        ND_PRINTK(0, err,
                                  "RA: %s got default router without 
neighbour\n",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 61f4f0333c73..ad7a80ad7b59 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -182,12 +182,10 @@ static void rt6_uncached_list_flush_dev(struct net *net, 
struct net_device *dev)
        }
 }
 
-static inline const void *choose_neigh_daddr(struct rt6_info *rt,
+static inline const void *choose_neigh_daddr(const struct in6_addr *p,
                                             struct sk_buff *skb,
                                             const void *daddr)
 {
-       struct in6_addr *p = &rt->rt6i_gateway;
-
        if (!ipv6_addr_any(p))
                return (const void *) p;
        else if (skb)
@@ -195,18 +193,27 @@ static inline const void *choose_neigh_daddr(struct 
rt6_info *rt,
        return daddr;
 }
 
-static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
-                                         struct sk_buff *skb,
-                                         const void *daddr)
+struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
+                                  struct net_device *dev,
+                                  struct sk_buff *skb,
+                                  const void *daddr)
 {
-       struct rt6_info *rt = (struct rt6_info *) dst;
        struct neighbour *n;
 
-       daddr = choose_neigh_daddr(rt, skb, daddr);
-       n = __ipv6_neigh_lookup(dst->dev, daddr);
+       daddr = choose_neigh_daddr(gw, skb, daddr);
+       n = __ipv6_neigh_lookup(dev, daddr);
        if (n)
                return n;
-       return neigh_create(&nd_tbl, daddr, dst->dev);
+       return neigh_create(&nd_tbl, daddr, dev);
+}
+
+static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
+                                             struct sk_buff *skb,
+                                             const void *daddr)
+{
+       const struct rt6_info *rt = container_of(dst, struct rt6_info, dst);
+
+       return ip6_neigh_lookup(&rt->rt6i_gateway, dst->dev, skb, daddr);
 }
 
 static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
@@ -214,7 +221,7 @@ static void ip6_confirm_neigh(const struct dst_entry *dst, 
const void *daddr)
        struct net_device *dev = dst->dev;
        struct rt6_info *rt = (struct rt6_info *)dst;
 
-       daddr = choose_neigh_daddr(rt, NULL, daddr);
+       daddr = choose_neigh_daddr(&rt->rt6i_gateway, NULL, daddr);
        if (!daddr)
                return;
        if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
@@ -239,7 +246,7 @@ static struct dst_ops ip6_dst_ops_template = {
        .update_pmtu            =       ip6_rt_update_pmtu,
        .redirect               =       rt6_do_redirect,
        .local_out              =       __ip6_local_out,
-       .neigh_lookup           =       ip6_neigh_lookup,
+       .neigh_lookup           =       ip6_dst_neigh_lookup,
        .confirm_neigh          =       ip6_confirm_neigh,
 };
 
@@ -269,7 +276,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
        .redirect               =       ip6_rt_blackhole_redirect,
        .cow_metrics            =       dst_cow_metrics_generic,
-       .neigh_lookup           =       ip6_neigh_lookup,
+       .neigh_lookup           =       ip6_dst_neigh_lookup,
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
-- 
2.11.0

Reply via email to