Netdev List
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: jhs@mojatatu.com
Cc: Simon Horman <horms@kernel.org>,
	netdev@vger.kernel.org, victor@mojatatu.com, jiri@resnulli.us,
	davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org,
	pabeni@redhat.com, stable@vger.kernel.org,
	sashiko-bot@kernel.org
Subject: Re: [PATCH net 2/2 repost2] net/sched: sch_teql: keep skb->dev consistent on the arp-queue path
Date: Mon, 26 Oct 2026 16:07:47 +0000	[thread overview]
Message-ID: <20261026160747.283702-1-horms@kernel.org> (raw)
In-Reply-To: <QDISC-6HS9.v1.r2.20261020051718-2@mojatatu.com>

This is an AI-generated review of your patch. The human sending this
email says "Hi Jamal, passing this on for your consideration as it
seems to have got stuck somewhere."
Full review at: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/QDISC-6HS9.v1.r2.20261020051718-1@mojatatu.com?part=2
---
net/sched: sch_teql: keep skb->dev consistent on the arp-queue path

The patch sets skb->dev = slave before teql_resolve(). An skb parked on
the slave's neighbour arp_queue then names the slave, not the teql master.
It also adds skb->dev = n1->dev at the reinjection point in
neigh_update_process_arp_queue(), so parked teql skbs go back through
teql_master_xmit() when the neighbour resolves.

Link: https://lore.kernel.org/netdev/20260824115928.4099988-1-victor@mojatatu.com/

> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index 7448320f7ad52..5823f5007812b 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -1336,6 +1336,7 @@ static void neigh_update_process_arp_queue(struct neighbour *neigh)
>  			if (n2)
>  				n1 = n2;
>  		}
> +		skb->dev = n1->dev;
>  		READ_ONCE(n1->output)(n1, skb);
>  		if (n2)
>  			neigh_release(n2);

[Severity: Medium]
The commit message says this assignment "is the identity for every other
parker (neigh_resolve_output() parks with skb->dev == neigh->dev, ndisc
probes carry no skb)". Does that hold when the skb's dst points at a
different device than the neighbour it was parked on?

If the dst is not DST_OBSOLETE_DEAD, n1 is not the parking neighbour. It is
replaced by n2 from dst_neigh_lookup_skb(), and ipv4_neigh_lookup() looks
that neighbour up on the dst's device:

net/ipv4/route.c:ipv4_neigh_lookup() {
    ...
	dev = dst_dev_rcu(dst);
	if (likely(rt->rt_gw_family == AF_INET)) {
		n = ip_neigh_gw4(dev, rt->rt_gw4);
    ...
}

So the new line is only a no-op when dst->dev == skb->dev.
skb->dev == neigh->dev is not enough.

At least two parkers seem to break that. The first is bpf_redirect_neigh()
with explicit nexthop params. bpf_out_neigh_v4() moves skb->dev to the
redirect target B and resolves the nexthop on B:

net/core/filter.c:bpf_out_neigh_v4() {
    ...
	skb->dev = dev;
    ...
	} else if (nh->nh_family == AF_INET) {
		neigh = ip_neigh_gw4(dev, nh->ipv4_nh);
    ...
}

However, __bpf_redirect_neigh_v4() only replaces the dst in the !nh branch,
so the routed dst for the original device A stays attached:

net/core/filter.c:__bpf_redirect_neigh_v4() {
    ...
		skb_dst_drop(skb);
		skb_dst_set(skb, &rt->dst);
	}
    ...
}

bpf_out_neigh_v6() follows the same pattern with ip_neigh_gw6().

The second is nft fwd ... neigh in a netdev egress chain.
nft_fwd_neigh_eval() changes skb->dev and parks the skb without touching
the dst:

net/netfilter/nft_fwd_netdev.c:nft_fwd_neigh_eval() {
    ...
	skb->dev = dev;
	skb_clear_tstamp(skb);

	nf_dev_xmit_recursion_inc();
	neigh_xmit(neigh_table, dev, addr, skb);
    ...
}

In __dev_queue_xmit(), nf_hook_egress() and sch_handle_egress() run before
the IFF_XMIT_DST_RELEASE skb_dst_drop(), so A's routed dst is still
attached at these hooks. If B's neighbour is incomplete, the skb is parked
on B's arp_queue with skb->dev == B and dst->dev == A.

When B's neighbour resolves, n2 is A's neighbour. With this patch skb->dev
becomes A, and n1->output() builds A's link-layer header and calls
dev_queue_xmit() on A.

Before the patch, the frame still left on B, though with A's link-layer
header, which was already a pre-existing problem. After the patch, would
the packets queued during resolution go through A's egress qdisc, tc and
nft hooks a second time?

That could mean nft_fwd_neigh_eval() calls ip_decrease_ttl() or
decrements hop_limit again. Non-idempotent BPF programs (encap,
adjust_room) would run again, and counting or stateful rules would see
the packet twice. If the redirect is not applied again on A's path, the
packets would leave on A and bypass the configured BPF or nft steering.

Since this is a change to core neighbour code tagged for stable, could the
reinjection fix be limited to the teql case? Alternatively, could the
commit message describe the behaviour change for these other parkers?

  reply	other threads:[~2026-10-26 16:08 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20 10:38 [PATCH net 0/2 repost2] net/sched: sch_teql: fix shared headroom and header strip Jamal Hadi Salim
2026-10-20 10:38 ` [PATCH net 1/2 repost2] net/sched: sch_teql: fix shared headroom and header strip on slave retry Jamal Hadi Salim
2026-10-20 10:38   ` [PATCH net 2/2 repost2] net/sched: sch_teql: keep skb->dev consistent on the arp-queue path Jamal Hadi Salim
2026-10-26 16:07     ` Simon Horman [this message]
2026-10-26 23:51       ` Jamal Hadi Salim
2026-10-27  0:46         ` Jakub Kicinski
2026-10-27  7:25           ` Jamal Hadi Salim
2026-10-27  7:44             ` Jamal Hadi Salim
2026-10-27  8:04               ` Jamal Hadi Salim
2026-10-27 18:29                 ` Simon Horman
2026-10-27 19:45                   ` Jamal Hadi Salim
2026-10-27 21:03                     ` Jamal Hadi Salim

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=20261026160747.283702-1-horms@kernel.org \
    --to=horms@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sashiko-bot@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=victor@mojatatu.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