[PATCH v2 net-next 6/9] ipv6: Use ipv6_neigh_lookup() and friends.
flat view
COOLING4d
IN NET-NEXT
From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-10-03 21:24:08
Subsystem:
ethernet bridge, ieee 802.15.4 subsystem, mellanox ethernet switch drivers, mellanox mlx5 core vpi driver, netronome ethernet drivers, networking drivers, networking [general], networking [ipv4/ipv6], sfc network driver, tc subsystem, the rest, vrf · Maintainers:
Nikolay Aleksandrov, Ido Schimmel, Alexander Aring, Stefan Schmidt, Miquel Raynal, Petr Machata, Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Edward Cree, Jamal Hadi Salim, Jiri Pirko, Linus Torvalds
Queued in net-next as 0e59523b440c on 2026-10-07.
syzbot reported the splat below in neigh_mark_dead() [0]
where tbl->lock was not held while neigh_ifdown() should
have acquired one.
This only happens when a neigh_table accidentally has a
neighbour from a different netns.
In ip6_finish_output2(), the net argument is the caller's and
does not always match dev_net(dev) fetched from dst. (e.g. xfrm)
It is error-prone to require callers to fetch netns and
neigh_table and pass it with dev to neigh_lookup(), etc.
Let's replace neigh_lookup() and friends with IPv6 helpers.
Note that __neigh_lookup() is split into ipv6_neigh_lookup()
and ipv6_neigh_create().
[0]:
debug_locks && !(lock_is_held(&(&n->tbl->lock)->dep_map) != 0)
WARNING: net/core/neighbour.c:154 at neigh_mark_dead+0x2fb/0x340 net/core/neighbour.c:154, CPU#0: syz.0.857/9765
Modules linked in:
CPU: 0 UID: 0 PID: 9765 Comm: syz.0.857 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
RIP: 0010:neigh_mark_dead+0x2fb/0x340 net/core/neighbour.c:154
Code: e8 03 42 80 3c 28 00 74 08 48 89 df e8 ee 9a 80 f8 4c 89 33 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 86 95 10 f8 90 <0f> 0b 90 e9 8f fd ff ff 48 c7 c1 80 9a 7a 90 80 e1 07 80 c1 03 38
RSP: 0018:ffffc90003726600 EFLAGS: 00010287
RAX: ffffffff89b7467a RBX: ffff888022e86000 RCX: 0000000000080000
RDX: ffffc900047fa000 RSI: 0000000000003e08 RDI: 0000000000003e09
RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffff520006e4cb8 R12: ffff888022e8613c
R13: dffffc0000000000 R14: ffff888022e86020 R15: ffff888022e86000
FS: 00007f9c30f046c0(0000) GS:ffff888124cc6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000076c56000 CR4: 00000000003526f0
Call Trace:
<TASK>
neigh_flush_one+0x27c/0x5a0 net/core/neighbour.c:388
neigh_flush_dev net/core/neighbour.c:432 [inline]
__neigh_ifdown+0x1fb/0xc70 net/core/neighbour.c:465
neigh_ifdown+0x1f/0x30 net/core/neighbour.c:487
rt6_disable_ip+0x751/0x7e0 net/ipv6/route.c:5058
addrconf_ifdown+0x155/0x1ad0 net/ipv6/addrconf.c:3892
addrconf_notify+0x1bc/0x1050 net/ipv6/addrconf.c:-1
notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
call_netdevice_notifiers_mtu net/core/dev.c:2350 [inline]
netif_set_mtu_ext+0x5ac/0x830 net/core/dev.c:9963
do_setlink+0xa81/0x47a0 net/core/rtnetlink.c:3247
rtnl_setlink+0x578/0x820 net/core/rtnetlink.c:3623
rtnetlink_rcv_msg+0x802/0xc00 net/core/rtnetlink.c:7159
netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2572
netlink_unicast_kernel net/netlink/af_netlink.c:1335 [inline]
netlink_unicast+0x7bd/0x940 net/netlink/af_netlink.c:1361
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1916
sock_sendmsg_nosec+0x13a/0x180 net/socket.c:800
__sock_sendmsg net/socket.c:815 [inline]
sock_write_iter+0x2de/0x3e0 net/socket.c:1266
do_iter_readv_writev+0x612/0x8c0 fs/read_write.c:-1
vfs_writev+0x343/0x990 fs/read_write.c:1058
do_writev+0x154/0x2e0 fs/read_write.c:1104
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f9c2ff9e159
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f9c30f04028 EFLAGS: 00000246 ORIG_RAX: 0000000000000014
RAX: ffffffffffffffda RBX: 00007f9c30225fa0 RCX: 00007f9c2ff9e159
RDX: 0000000000000001 RSI: 00002000000003c0 RDI: 0000000000000004
RBP: 00007f9c3003506b R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f9c30226038 R14: 00007f9c30225fa0 R15: 00007ffed3c74808
</TASK>
Fixes: df5f4f372de5 ("ipv6: Replace &nd_tbl with nd_table(net).")
Reported-by: syzbot+5a8857f0b4a0a7b12c62@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6abd69a9.80e1c6cc.22483f.0005.GAE@google.com/ (local)
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
v2: Convert __teql_resolve()
Cc: Saeed Mahameed <saeedm@nvidia.com>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Mark Bloch <mbloch@nvidia.com>
Cc: Petr Machata <petrm@nvidia.com>
Cc: Edward Cree <ecree.xilinx@gmail.com>
Cc: Nikolay Aleksandrov <razor@blackwall.org>
Cc: Alexander Aring <alex.aring@gmail.com>
Cc: Stefan Schmidt <stefan@datenfreihafen.org>
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
---
.../mellanox/mlx5/core/en/tc_tun_encap.c | 13 +++----
.../ethernet/mellanox/mlxsw/spectrum_router.c | 29 ++++++++-------
.../ethernet/mellanox/mlxsw/spectrum_span.c | 24 ++++++++-----
.../netronome/nfp/flower/tunnel_conf.c | 4 +--
drivers/net/ethernet/sfc/tc_counters.c | 5 ++-
drivers/net/vrf.c | 4 +--
drivers/net/vxlan/vxlan_core.c | 6 ++--
include/net/ndisc.h | 7 ++--
net/bridge/br_arp_nd_proxy.c | 2 +-
net/ieee802154/6lowpan/tx.c | 3 +-
net/ipv4/fib_semantics.c | 2 +-
net/ipv6/ip6_output.c | 2 +-
net/ipv6/ndisc.c | 36 ++++++++++++-------
net/ipv6/route.c | 11 +++---
net/sched/sch_teql.c | 12 ++++++-
15 files changed, 90 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index 67c12ca19d59..fe0258375ef6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c@@ -439,21 +439,18 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) if (neigh_used) { struct net_device *dev = READ_ONCE(nhe->neigh_dev); struct net *net = dev_net(dev); - struct neigh_table *tbl; nhe->reported_lastuse = jiffies; + /* find the relevant neigh according to the cached device and + * dst ip pair + */ #if IS_ENABLED(CONFIG_IPV6) if (m_neigh->family != AF_INET) - tbl = nd_table(net); + n = ipv6_neigh_lookup(dev, &m_neigh->dst_ip); else #endif - tbl = arp_table(net); - - /* find the relevant neigh according to the cached device and - * dst ip pair - */ - n = neigh_lookup(tbl, &m_neigh->dst_ip, dev); + n = neigh_lookup(arp_table(net), &m_neigh->dst_ip, dev); if (!n) return;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index ba8a7a44ce9e..1f4753213b9c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c@@ -2449,8 +2449,6 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, char *rauhtd_pl, int rec_index) { - struct net *net = mlxsw_sp_net(mlxsw_sp); - struct neigh_table *tbl; struct net_device *dev; struct neighbour *n; struct in6_addr dip;
@@ -2464,9 +2462,8 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, return; } - tbl = nd_table(net); dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); - n = neigh_lookup(tbl, &dip, dev); + n = ipv6_neigh_lookup(dev, &dip); if (!n) return;
@@ -4312,17 +4309,23 @@ mlxsw_sp_nexthop_neigh_lookup(struct mlxsw_sp_nexthop *nh) net = dev_net(dev); #if IS_ENABLED(CONFIG_IPV6) - if (nh->family == AF_INET6) - tbl = nd_table(net); - else + if (nh->family == AF_INET6) { + n = ipv6_neigh_lookup(dev, &nh->gw_addr); + if (!n) { + n = ipv6_neigh_create(dev, &nh->gw_addr); + if (!IS_ERR(n)) + neigh_event_send(n, NULL); + } + } else #endif + { tbl = arp_table(net); - - n = neigh_lookup(tbl, &nh->gw_addr, dev); - if (!n) { - n = neigh_create(tbl, &nh->gw_addr, dev); - if (!IS_ERR(n)) - neigh_event_send(n, NULL); + n = neigh_lookup(tbl, &nh->gw_addr, dev); + if (!n) { + n = neigh_create(tbl, &nh->gw_addr, dev); + if (!IS_ERR(n)) + neigh_event_send(n, NULL); + } } return n;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index d34d2040177b..79947f68b10d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c@@ -235,17 +235,23 @@ static int mlxsw_sp_span_dmac(int family, int err = 0; #if IS_ENABLED(CONFIG_IPV6_GRE) - if (family == AF_INET6) - tbl = nd_table(net); - else + if (family == AF_INET6) { + neigh = ipv6_neigh_lookup(dev, pkey); + if (!neigh) { + neigh = ipv6_neigh_create(dev, pkey); + if (IS_ERR(neigh)) + return PTR_ERR(neigh); + } + } else #endif + { tbl = arp_table(net); - - neigh = neigh_lookup(tbl, pkey, dev); - if (!neigh) { - neigh = neigh_create(tbl, pkey, dev); - if (IS_ERR(neigh)) - return PTR_ERR(neigh); + neigh = neigh_lookup(tbl, pkey, dev); + if (!neigh) { + neigh = neigh_create(tbl, pkey, dev); + if (IS_ERR(neigh)) + return PTR_ERR(neigh); + } } neigh_event_send(neigh, NULL);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index d650d33e3709..27d80ec8e895 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c@@ -253,7 +253,6 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb) #if IS_ENABLED(CONFIG_IPV6) struct nfp_tun_active_tuns_v6 *payload; struct net_device *netdev; - struct neigh_table *tbl; int count, i, pay_len; struct neighbour *n; void *ipv6_add;
@@ -280,8 +279,7 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb) if (!netdev) continue; - tbl = nd_table(dev_net(netdev)); - n = neigh_lookup(tbl, ipv6_add, netdev); + n = ipv6_neigh_lookup(netdev, ipv6_add); if (!n) continue;
diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c
index 793a562fc1f7..ae6cc6b93864 100644
--- a/drivers/net/ethernet/sfc/tc_counters.c
+++ b/drivers/net/ethernet/sfc/tc_counters.c@@ -116,9 +116,8 @@ static void efx_tc_counter_work(struct work_struct *work) encap->neigh->egdev); else #if IS_ENABLED(CONFIG_IPV6) - n = neigh_lookup(nd_table(net), - &encap->neigh->dst_ip6, - encap->neigh->egdev); + n = ipv6_neigh_lookup(encap->neigh->egdev, + &encap->neigh->dst_ip6); #else n = NULL; #endif
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 320f3584a43b..79d433f49f80 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c@@ -614,9 +614,9 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, rcu_read_lock(); nexthop = rt6_nexthop(dst_rt6_info(dst), &ipv6_hdr(skb)->daddr); - neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); + neigh = __ipv6_neigh_lookup_noref(dev, nexthop); if (unlikely(!neigh)) - neigh = __neigh_create(nd_table(net), nexthop, dst->dev, false); + neigh = ipv6_neigh_create_noref(dev, nexthop); if (!IS_ERR(neigh)) { sock_confirm_neigh(skb, neigh); ret = neigh_output(neigh, skb, false);
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 27b0b6567d52..513779c07621 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c@@ -2091,8 +2091,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, ipv6_addr_is_multicast(&msg->target)) goto out; - n = neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev); - + n = ipv6_neigh_lookup(dev, &msg->target); if (n) { struct vxlan_rdst *rdst = NULL; u8 ha[ETH_ALEN] __aligned(2);
@@ -2189,9 +2188,8 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb, if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) return false; - tbl = nd_table(dev_net(dev)); pip6 = ipv6_hdr(skb); - n = neigh_lookup(tbl, &pip6->daddr, dev); + n = ipv6_neigh_lookup(dev, &pip6->daddr); if (!n && (cfg->flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { .sin6.sin6_addr = pip6->daddr,
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 2fce6fccf55a..91898a2475e7 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h@@ -423,11 +423,8 @@ static inline struct neighbour *ip_neigh_gw6(struct net_device *dev, struct neighbour *neigh; neigh = __ipv6_neigh_lookup_noref(dev, addr); - if (unlikely(!neigh)) { - struct neigh_table *tbl = nd_table(dev_net(dev)); - - neigh = __neigh_create(tbl, addr, dev, false); - } + if (unlikely(!neigh)) + neigh = ipv6_neigh_create_noref(dev, addr); return neigh; #else
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index ba4a63840b21..c23b99517cd5 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c@@ -487,7 +487,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, return; } - n = neigh_lookup(nd_table(dev_net(vlandev)), &msg->target, vlandev); + n = ipv6_neigh_lookup(vlandev, &msg->target); if (n) { struct net_bridge_fdb_entry *f; u8 ha[ETH_ALEN] __aligned(2);
diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index 4f511476b992..b261daedc290 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c@@ -58,9 +58,8 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev, info->daddr.mode = IEEE802154_ADDR_SHORT; } else { __le16 short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC); - struct neigh_table *tbl = nd_table(dev_net(ldev)); - n = neigh_lookup(tbl, &hdr->daddr, ldev); + n = ipv6_neigh_lookup(ldev, &hdr->daddr); if (n) { llneigh = lowpan_802154_neigh(neighbour_priv(n)); read_lock_bh(&n->lock);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e3bcc25229b0..a98c7670d2ce 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c@@ -617,7 +617,7 @@ static int fib_detect_death(struct fib_info *fi, int order, if (likely(nhc->nhc_gw_family == AF_INET)) n = neigh_lookup(arp_table(net), &nhc->nhc_gw.ipv4, nhc->nhc_dev); else if (IS_ENABLED(CONFIG_IPV6) && nhc->nhc_gw_family == AF_INET6) - n = neigh_lookup(nd_table(net), &nhc->nhc_gw.ipv6, nhc->nhc_dev); + n = ipv6_neigh_lookup(nhc->nhc_dev, &nhc->nhc_gw.ipv6); else n = NULL;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 10146a57b69e..25fe0ba98b1a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c@@ -127,7 +127,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * if (IS_ERR_OR_NULL(neigh)) { if (unlikely(!neigh)) - neigh = __neigh_create(nd_table(net), nexthop, dev, false); + neigh = ipv6_neigh_create_noref(dev, nexthop); if (IS_ERR(neigh)) { IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index e1cbffaa0ad0..0ed1a619372b 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c@@ -947,8 +947,12 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb) * update / create cache entry * for the source address */ - neigh = __neigh_lookup(tbl, saddr, dev, - !inc || lladdr || !dev->addr_len); + neigh = ipv6_neigh_lookup(dev, saddr); + if (!neigh && (!inc || lladdr || !dev->addr_len)) { + neigh = ipv6_neigh_create(dev, saddr); + if (IS_ERR(neigh)) + neigh = NULL; + } if (neigh) ndisc_update(dev, neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE|
@@ -998,7 +1002,6 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) struct net *net = dev_net(dev); struct ndisc_options ndopts; struct inet6_ifaddr *ifp; - struct neigh_table *tbl; struct neighbour *neigh; struct inet6_dev *idev; u8 *lladdr = NULL;
@@ -1063,8 +1066,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) return reason; } - tbl = nd_table(net); - neigh = neigh_lookup(tbl, &msg->target, dev); + neigh = ipv6_neigh_lookup(dev, &msg->target); /* RFC 9131 updates original Neighbour Discovery RFC 4861. * NAs with Target LL Address option can now create a STALE neighbor
@@ -1093,7 +1095,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) return reason; } if (!neigh) - neigh = neigh_create(tbl, &msg->target, dev); + neigh = ipv6_neigh_create(dev, &msg->target); new_state = NUD_STALE; }
@@ -1108,7 +1110,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && READ_ONCE(net->ipv6.devconf_all->forwarding) && READ_ONCE(net->ipv6.devconf_all->proxy_ndp) && - pneigh_lookup(tbl, &msg->target, dev)) { + pneigh_lookup(nd_table(dev_net(dev)), &msg->target, dev)) { /* XXX: idev->cnf.proxy_ndp */ goto out; }
@@ -1141,7 +1143,6 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb) unsigned long ndoptlen = skb->len - sizeof(*rs_msg); struct net_device *dev = skb->dev; struct ndisc_options ndopts; - struct neigh_table *tbl; struct neighbour *neigh; struct inet6_dev *idev; u8 *lladdr = NULL;
@@ -1177,8 +1178,12 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb) goto out; } - tbl = nd_table(dev_net(dev)); - neigh = __neigh_lookup(tbl, saddr, dev, 1); + neigh = ipv6_neigh_lookup(dev, saddr); + if (!neigh) { + neigh = ipv6_neigh_create(dev, saddr); + if (IS_ERR(neigh)) + goto out; + } if (neigh) { ndisc_update(dev, neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE|
@@ -1478,9 +1483,14 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) * Process options. */ - if (!neigh) - neigh = __neigh_lookup(nd_table(net), &ipv6_hdr(skb)->saddr, - skb->dev, 1); + if (!neigh) { + neigh = ipv6_neigh_lookup(skb->dev, &ipv6_hdr(skb)->saddr); + if (!neigh) { + neigh = ipv6_neigh_create(skb->dev, &ipv6_hdr(skb)->saddr); + if (IS_ERR(neigh)) + neigh = NULL; + } + } if (neigh) { u8 *lladdr = NULL; if (ndopts.nd_opts_src_lladdr) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8baac4d85251..ea9f0a4c34f9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c@@ -218,7 +218,7 @@ struct neighbour *__ip6_dst_neigh_lookup(const struct in6_addr *gw, if (n) return n; - n = neigh_create(nd_table(dev_net(dev)), daddr, dev); + n = ipv6_neigh_create(dev, daddr); return IS_ERR(n) ? NULL : n; }
@@ -4277,9 +4277,12 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu */ dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr); - neigh = __neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev, 1); - if (!neigh) - return; + neigh = ipv6_neigh_lookup(dev, &msg->target); + if (!neigh) { + neigh = ipv6_neigh_create(dev, &msg->target); + if (IS_ERR(neigh)) + return; + } /* * We have finally decided to accept it.
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 409ce50cc0db..19ccf1a55988 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c@@ -16,6 +16,7 @@ #include <linux/skbuff.h> #include <linux/moduleparam.h> #include <net/dst.h> +#include <net/ndisc.h> #include <net/neighbour.h> #include <net/pkt_sched.h>
@@ -257,7 +258,16 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, if (dst->dev != dev) { struct neighbour *mn; - mn = __neigh_lookup_errno(n->tbl, n->primary_key, dev); +#if IS_ENABLED(CONFIG_IPV6) + if (n->tbl->family == AF_INET6) { + mn = ipv6_neigh_lookup(dev, n->primary_key); + if (!mn) + mn = ipv6_neigh_create(dev, n->primary_key); + } else +#endif + { + mn = __neigh_lookup_errno(n->tbl, n->primary_key, dev); + } neigh_release(n); if (IS_ERR(mn)) return PTR_ERR(mn);
--
2.56.0.rc1.315.gc6ed9934b7-goog