Linux USB
 help / color / mirror / Atom feed
* 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