diff options
| author | Antonio Pastor | 2024-12-20 16:28:45 +0000 |
|---|---|---|
| committer | Robert Marko | 2024-12-28 09:55:59 +0000 |
| commit | da7ab64f1f6d72597a1c8a8bb3b57409227bc635 (patch) | |
| tree | 8f16b980ad9b28a7c3361861fec5e430890c80ae | |
| parent | 0cba20f0820efa9ac7a728206a3bde43719ced6d (diff) | |
| download | openwrt-da7ab64f1f6d72597a1c8a8bb3b57409227bc635.tar.gz | |
kernel: generic: patch: 802.2+LLC - set transport_header offset
Conversion to DSA broke 802.2+LLC+SNAP packet processing. Frames
received by napi_complete_done with GRO and DSA have transport_header
set two bytes short, or pointing 2 bytes before network_header &
skb->data. As snap_rcv expects transport_header to point to SNAP
header (OID:PID) after LLC processing advances offset over LLC header
(llc_rcv & llc_fixup_skb), code doesn't find a match and packet is
dropped.
Image built at this commit operates properly:
86dadeba48 - generic: add patch for GPON-ONU-34-20BI quirk
Image built at following commit exhibits the issue:
337e36e0ef - ipq806x: convert each device to DSA implementation
As issue is LLC specific, to avoid impacting non-LLC traffic, and to
follow up on original assumption made on kernel commit fda55eca5a33
("net: introduce skb_transport_header_was_set()") stating "network
stacks usually reset the transport header anyway", llc_fixup_skb to
reset and advance the offset. llc_fixup_skb already assumes the LLC
header is at skb->data, and by definition SNAP header immediately
follows.
Signed-off-by: Antonio Pastor <antonio.pastor@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/17220
Signed-off-by: Robert Marko <robimarko@gmail.com>
| -rw-r--r-- | target/linux/generic/backport-6.6/902-net-llc-reset-skb-transport_header.patch | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/target/linux/generic/backport-6.6/902-net-llc-reset-skb-transport_header.patch b/target/linux/generic/backport-6.6/902-net-llc-reset-skb-transport_header.patch new file mode 100644 index 0000000000..b1f0b8fce7 --- /dev/null +++ b/target/linux/generic/backport-6.6/902-net-llc-reset-skb-transport_header.patch @@ -0,0 +1,52 @@ +From a024e377efed31ecfb39210bed562932321345b3 Mon Sep 17 00:00:00 2001 +From: Antonio Pastor <antonio.pastor@gmail.com> +Date: Tue, 24 Dec 2024 20:07:20 -0500 +Subject: [PATCH] net: llc: reset skb->transport_header + +802.2+LLC+SNAP frames received by napi_complete_done with GRO and DSA +have skb->transport_header set two bytes short, or pointing 2 bytes +before network_header & skb->data. As snap_rcv expects transport_header +to point to SNAP header (OID:PID) after LLC processing advances offset +over LLC header (llc_rcv & llc_fixup_skb), code doesn't find a match +and packet is dropped. + +Between napi_complete_done and snap_rcv, transport_header is not used +until __netif_receive_skb_core, where originally it was being reset. +Commit fda55eca5a33 ("net: introduce skb_transport_header_was_set()") +only does so if not set, on the assumption the value was set correctly +by GRO (and also on assumption that "network stacks usually reset the +transport header anyway"). Afterwards it is moved forward by +llc_fixup_skb. + +Locally generated traffic shows up at __netif_receive_skb_core with no +transport_header set and is processed without issue. On a setup with +GRO but no DSA, transport_header and network_header are both set to +point to skb->data which is also correct. + +As issue is LLC specific, to avoid impacting non-LLC traffic, and to +follow up on original assumption made on previous code change, +llc_fixup_skb to reset the offset after skb pull. llc_fixup_skb +assumes the LLC header is at skb->data, and by definition SNAP header +immediately follows. + +Fixes: fda55eca5a33 ("net: introduce skb_transport_header_was_set()") +Signed-off-by: Antonio Pastor <antonio.pastor@gmail.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Link: https://patch.msgid.link/20241225010723.2830290-1-antonio.pastor@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + net/llc/llc_input.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/llc/llc_input.c ++++ b/net/llc/llc_input.c +@@ -124,8 +124,8 @@ static inline int llc_fixup_skb(struct s + if (unlikely(!pskb_may_pull(skb, llc_len))) + return 0; + +- skb->transport_header += llc_len; + skb_pull(skb, llc_len); ++ skb_reset_transport_header(skb); + if (skb->protocol == htons(ETH_P_802_2)) { + __be16 pdulen; + s32 data_size; |