* cdc_ncm: short frames not padded to ETH_ZLEN, ARP broken with strict routers
@ 2026-05-30 16:35 anonreporting
0 siblings, 0 replies; only message in thread
From: anonreporting @ 2026-05-30 16:35 UTC (permalink / raw)
To: linux-usb
Hi,
I've been chasing a connectivity issue with a USB-C dock (DisplayLink,
VID 17e9:6000,
driver cdc_ncm) and eventually tracked it down to the driver
transmitting Ethernet frames
shorter than ETH_ZLEN without zero-padding them.
== Symptom ==
The interface gets a DHCP lease fine (BOOTP frames are large enough),
but every attempt
to reach the default gateway fails with 100% packet loss. A Fritz!Box
router is involved
on the other end.
tcpdump on the cdc_ncm interface shows outgoing ARP requests at 42
bytes:
14:03:07.112233 00:xx:xx:xx:xx:xx > ff:ff:ff:ff:ff:ff, ethertype ARP
(0x0806), \
length 42: Request who-has 192.168.1.1 tell 192.168.1.x, length 28
Same ARP from an r8152 interface on the same machine (same cable, same
switch port):
14:03:07.112400 00:yy:yy:yy:yy:yy > ff:ff:ff:ff:ff:ff, ethertype ARP
(0x0806), \
length 58: Request who-has 192.168.1.1 tell 192.168.1.x, length 44
So r8152 pads the 28-byte ARP payload to 44 bytes (16 bytes of zeros),
giving a 58-byte
frame. cdc_ncm sends it raw at 42 bytes. IEEE 802.3 minimum is 60 bytes
without FCS.
The Fritz!Box drops anything below ~50 bytes; 58-byte frames are
accepted, 42-byte ones
are not.
== Root cause ==
The cdc_ncm TX path in cdc_ncm_fill_tx_frame() packs SKBs into NCM
Transfer Blocks
(NTBs) without ensuring each frame meets ETH_ZLEN. An ARP request
arrives as a
42-byte SKB and is placed into the NTB verbatim:
skb_put_data(skb_out, skb->data, skb->len);
ctx->tx_curr_frame_payload += skb->len;
dev_kfree_skb_any(skb);
Neither eth_skb_pad() nor ETH_ZLEN appears anywhere in the cdc_ncm TX
path
(verified against current tree). Other USB Ethernet drivers — r8152
being the
working reference here — call eth_skb_pad() before the frame reaches
hardware.
== Suggested fix (untested, no patch built) ==
The padding needs to happen before skb->len is first used for NDP space
reservation
(the cdc_ncm_ndp16/ndp32 call), not just before skb_put_data(). The
following is an
untested sketch:
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ cdc_ncm_fill_tx_frame(), before the NDP allocation block:
+ /* ensure frame meets IEEE 802.3 minimum; eth_skb_pad() frees skb on
failure */
+ if (skb->len < ETH_ZLEN && eth_skb_pad(skb)) {
+ skb = NULL;
+ dev->net->stats.tx_dropped++;
+ break;
+ }
+
/* get the appropriate NDP for this skb */
if (ctx->is_ndp16)
ndp.ndp16 = cdc_ncm_ndp16(ctx, skb_out, sign,
skb->len + ctx->tx_modulus + ctx->tx_remainder);
else
ndp.ndp32 = cdc_ncm_ndp32(ctx, skb_out, sign,
skb->len + ctx->tx_modulus + ctx->tx_remainder);
This placement ensures skb->len already reflects the padded length when
NDP space
is reserved, when the fit check runs, and when wDatagramLength is
written into the
NDP entry. The break is conservative on alloc failure — it sends the
current NTB
without the dropped frame rather than risking use-after-free.
I have not compiled or tested this — leaving it to someone who knows the
error
paths in cdc_ncm_fill_tx_frame() better than I do.
== Notes ==
- DHCP frames are unaffected (large enough), so the issue only shows up
after the
interface is up and the kernel starts sending ARP — which can make it
look like a
routing or ARP cache problem rather than a driver issue.
- The exact same hardware works correctly when the Fritz!Box is replaced
with a switch
that is more lenient about frame size, which was another red herring
during diagnosis.
- Kernel: 6.12.74+deb13+1-amd64 (Debian 13)
- Affected: DisplayLink USB-C Triple-4K Dock, 17e9:6000, cdc_ncm
- Working reference: Realtek RTL8153, 0bda:8153, r8152
I'm happy to test patches.
Regards,
anonreporting <anonreporting@disroot.org>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-30 16:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-30 16:35 cdc_ncm: short frames not padded to ETH_ZLEN, ARP broken with strict routers anonreporting
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox