From: David Ahern <dsah...@gmail.com>

Add ipv6 helpers to handle ndisc references via the stub. Update
bpf_ipv6_fib_lookup to use __ipv6_neigh_lookup_noref_stub instead of
the open code ___neigh_lookup_noref with the stub.

Signed-off-by: David Ahern <dsah...@gmail.com>
Reviewed-by: Ido Schimmel <ido...@mellanox.com>
---
 include/net/ndisc.h | 40 ++++++++++++++++++++++++++++++++++++++++
 net/core/filter.c   |  6 ++----
 2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index ddfbb591e2c5..366150053043 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -2,6 +2,8 @@
 #ifndef _NDISC_H
 #define _NDISC_H
 
+#include <net/ipv6_stubs.h>
+
 /*
  *     ICMP codes for neighbour discovery messages
  */
@@ -379,6 +381,14 @@ static inline struct neighbour 
*__ipv6_neigh_lookup_noref(struct net_device *dev
        return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, 
pkey, dev);
 }
 
+static inline
+struct neighbour *__ipv6_neigh_lookup_noref_stub(struct net_device *dev,
+                                                const void *pkey)
+{
+       return ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128,
+                                    ndisc_hashfn, pkey, dev);
+}
+
 static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, 
const void *pkey)
 {
        struct neighbour *n;
@@ -409,6 +419,36 @@ static inline void __ipv6_confirm_neigh(struct net_device 
*dev,
        rcu_read_unlock_bh();
 }
 
+static inline void __ipv6_confirm_neigh_stub(struct net_device *dev,
+                                            const void *pkey)
+{
+       struct neighbour *n;
+
+       rcu_read_lock_bh();
+       n = __ipv6_neigh_lookup_noref_stub(dev, pkey);
+       if (n) {
+               unsigned long now = jiffies;
+
+               /* avoid dirtying neighbour */
+               if (n->confirmed != now)
+                       n->confirmed = now;
+       }
+       rcu_read_unlock_bh();
+}
+
+/* uses ipv6_stub and is meant for use outside of IPv6 core */
+static inline struct neighbour *ip_neigh_gw6(struct net_device *dev,
+                                            const void *addr)
+{
+       struct neighbour *neigh;
+
+       neigh = __ipv6_neigh_lookup_noref_stub(dev, addr);
+       if (unlikely(!neigh))
+               neigh = __neigh_create(ipv6_stub->nd_tbl, addr, dev, false);
+
+       return neigh;
+}
+
 int ndisc_init(void);
 int ndisc_late_init(void);
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 8904e3407163..26d9cd785ae2 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4759,11 +4759,9 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct 
bpf_fib_lookup *params,
        params->rt_metric = f6i->fib6_metric;
 
        /* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
-        * not needed here. Can not use __ipv6_neigh_lookup_noref here
-        * because we need to get nd_tbl via the stub
+        * not needed here.
         */
-       neigh = ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128,
-                                     ndisc_hashfn, dst, dev);
+       neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
        if (!neigh)
                return BPF_FIB_LKUP_RET_NO_NEIGH;
 
-- 
2.11.0

Reply via email to