Netdev List
 help / color / mirror / Atom feed
From: Fernando Fernandez Mancera <fmancera@suse.de>
To: Kuniyuki Iwashima <kuniyu@google.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	David Ahern <dsahern@kernel.org>,
	Ido Schimmel <idosch@nvidia.com>
Cc: Simon Horman <horms@kernel.org>,
	Kuniyuki Iwashima <kuni1840@gmail.com>,
	netdev@vger.kernel.org,
	syzbot+5a8857f0b4a0a7b12c62@syzkaller.appspotmail.com,
	Saeed Mahameed <saeedm@nvidia.com>,
	Leon Romanovsky <leon@kernel.org>,
	Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
	Petr Machata <petrm@nvidia.com>,
	Edward Cree <ecree.xilinx@gmail.com>,
	Nikolay Aleksandrov <razor@blackwall.org>,
	Alexander Aring <alex.aring@gmail.com>,
	Stefan Schmidt <stefan@datenfreihafen.org>,
	Miquel Raynal <miquel.raynal@bootlin.com>
Subject: Re: [PATCH v2 net-next 6/9] ipv6: Use ipv6_neigh_lookup() and friends.
Date: Tue, 6 Oct 2026 19:53:15 +0200	[thread overview]
Message-ID: <da88c1e3-5445-4c0f-bdab-c7b451d74dd1@suse.de> (raw)
In-Reply-To: <20261003212336.1304988-7-kuniyu@google.com>

On 10/3/26 11:23 PM, Kuniyuki Iwashima wrote:
> 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/emlxsw_sp_ul_rif_getntry/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/
> 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);


Hi Kuniyuki,

I have checked Sashiko's feedback [0] and I think it is right.

mlxsw_sp_router_ul_rif_get() can be called with a NULL mlxsw_sp_crif 
pointer which then would call mlxsw_sp_ul_rif_create() and there during 
the alloc a rif with a NULL crif is created making this feedback being 
correct.

I think a simple NULL check here for dev should be enough.

[0] 
https://sashiko.dev/#/message/20261003212336.1304988-7-kuniyu%40google.com

Thanks!

>   	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);


  reply	other threads:[~2026-10-06 17:53 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-03 21:23 [PATCH v2 net-next 0/9] neighbour: Add IPv4/IPv6-specific wrappers for neigh_lookup() and friends Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 1/9] ipv4: Rename ipv4_neigh_lookup() to ipv4_dst_neigh_lookup() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 2/9] ipv6: Rename ip6_neigh_lookup() to __ip6_dst_neigh_lookup() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 3/9] ipv4: Add wrappers for neigh_lookup() and neigh_create() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 4/9] ipv6: Add wrappers for neigh_lookup() and (__)?neigh_create() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 5/9] mlxsw: spectrum: Resolve neigh_table right before neigh_lookup() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 6/9] ipv6: Use ipv6_neigh_lookup() and friends Kuniyuki Iwashima
2026-10-06 17:53   ` Fernando Fernandez Mancera [this message]
2026-10-06 18:01     ` Kuniyuki Iwashima
2026-10-06 20:34       ` Fernando Fernandez Mancera
2026-10-03 21:23 ` [PATCH v2 net-next 7/9] ipv4: Use ipv4_neigh_lookup() " Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 8/9] neighbour: Remove __neigh_lookup() and __neigh_lookup_errno() Kuniyuki Iwashima
2026-10-03 21:23 ` [PATCH v2 net-next 9/9] neighbour: Check n->parms->tbl under tbl->lock in ___neigh_create() Kuniyuki Iwashima
2026-10-06 20:39 ` [PATCH v2 net-next 0/9] neighbour: Add IPv4/IPv6-specific wrappers for neigh_lookup() and friends Fernando Fernandez Mancera
2026-10-07 16:35 ` Jakub Kicinski
2026-10-07 16:50   ` Ido Schimmel
2026-10-07 18:20     ` Jakub Kicinski
2026-10-07 23:20 ` patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=da88c1e3-5445-4c0f-bdab-c7b451d74dd1@suse.de \
    --to=fmancera@suse.de \
    --cc=alex.aring@gmail.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=ecree.xilinx@gmail.com \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=kuni1840@gmail.com \
    --cc=kuniyu@google.com \
    --cc=leon@kernel.org \
    --cc=mbloch@nvidia.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=petrm@nvidia.com \
    --cc=razor@blackwall.org \
    --cc=saeedm@nvidia.com \
    --cc=stefan@datenfreihafen.org \
    --cc=syzbot+5a8857f0b4a0a7b12c62@syzkaller.appspotmail.com \
    --cc=tariqt@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox