Skip to content

DaynaPORT: outbound EtherTalk (AppleTalk Phase 2) frames have a padded 802.3 length field → AppleTalk zones/servers never appear in Chooser (regression since v2024.12.08 / pico-sdk 2.0.0) #400

Description

@deltro68

Summary

On WiFi/DaynaPORT builds, every outbound AppleTalk-over-802.3 (EtherTalk Phase 2)
frame the Mac transmits leaves BlueSCSI with an 802.3/LLC length field that has been
rounded up to a multiple of 4
, instead of the true length (8 + DDP length).

For IP/Ethernet-II traffic those two bytes are an EtherType and the padded value is
ignored, so AFP-over-AppleTalk to a known/stored address still works (disks mount on
boot). But for 802.3 AppleTalk the field is a real length: AppleTalk routers and
atalkd/netatalk validate it against the DDP datagram's own length field, find they
disagree, and reject the datagram. The rejected frames are exactly the broadcast
ZIP GetNetInfo and NBP BrRq requests used for discovery, so:

  • Chooser zone list is empty (ZIP GetNetInfo reply never comes back)
  • AppleShare server list is empty (NBP LkUp replies never come back)
  • Network control panels are slow (blocking on discovery timeouts)

This is a regression: older firmware transmitted the correct length and works fine.

Affected / not affected

  • Broken: current firmware (tested up to the latest release), both Pico 1W and
    Pico 2W
    (RP2040 and RP2350). So it is not board-specific.
  • Works: v2024.10.26 and earlier.
  • First broken: v2024.12.08.

Root cause (bisected)

Bisected to commit d3f3db2 "chore: update to pico-sdk 2.0.0" (the SDK 1.x → 2.0.0 /
framework e139b9c7v4.1.1-DaynaPORT bump). BlueSCSI's own network.c /
BlueSCSI_platform_network.cpp are byte-identical across the boundary; the behavior
change comes in with the new SDK/cyw43 TX path. The 802.3 length field ends up rounded up
to a 4‑byte boundary somewhere between platform_network_send()
cyw43_send_ethernet() and the wire.

Evidence (on-the-wire captures)

Captured with tcpdump on the AppleTalk router (Raspberry Pi running tashrouter +
netatalk 4.4.2), filtering the BlueSCSI MAC. Comparing the exact same frames from the same
Mac, only the firmware changed:

Firmware DDP length correct 802.3 len (8+ddp) actual 802.3 len field delta
v2024.10.26 (OLD, works) 21 29 29 0
v2024.10.26 (OLD, works) 50 58 58 0
SDK-2 (current, broken) 21 29 32 +3
SDK-2 (current, broken) 37 45 48 +3
SDK-2 (current, broken) 50 58 60 +2

Formula: broken 802.3_len == round_up(8 + ddp_len, 4). Across a full session the OLD
firmware was correct on 15/15 AppleTalk frames; the SDK-2 firmware was padded on 36/36.

Same ATP request frame, first 16 bytes (note bytes 12–13, the 802.3 length):

OLD fw (correct): aa c7 61 cf ae e7 00 80 19 5f 00 5f 00 1d aa aa   <- 0x001d = 29
NEW fw (padded):  aa c7 61 cf ae e7 00 80 19 5f 00 5f 00 20 aa aa   <- 0x0020 = 32

The DDP header's own length field is unchanged/correct (21) in both; only the outer
802.3 length is wrong on the SDK-2 build.

What the router sees

  • Broken: Mac sends nbp-brRq "=:AFPServer@EtherTalk Network" and repeated
    at-#6 (ZIP GetNetInfo); the router drops them (length mismatch) and never fans them
    out → 0 replies → Chooser stays empty; the Mac re-sends GetNetInfo indefinitely.
  • Working (old fw or after workaround): the same requests are accepted, the router
    replies (atp-resp carrying zone info), and zones/servers appear.

Confirmation / workaround

Patching the router to tolerate the padding immediately makes zones appear, which
confirms the length field is the sole cause. In tashrouter's datagram.py
(from_long_header_bytes / from_short_header_bytes) I changed the strict check:

# was:
if length != len(data):
    raise ValueError(...)
# to (accept trailing padding, then trim to the declared length):
if length > len(data):
    raise ValueError(...)
if length < len(data):
    data = data[:length]

With this, both Pico 1W and Pico 2W on the latest firmware work. This is a router-side
workaround only; it is not appropriate upstream for tashrouter (its strict check is
spec-correct — the 802.3 length should equal the LLC payload length), and every other
AppleTalk router / real netatalk will still reject BlueSCSI's frames.

Suggested fix

BlueSCSI should transmit the true 802.3 length for outbound frames rather than a
4‑byte‑padded value — i.e. do not let the SDK/cyw43 TX byte-alignment leak into the
802.3 length field. (Ethernet minimum-frame padding is fine, but the 802.3 length field
must remain the real LLC payload length for AppleTalk to route.)

Environment

  • Board: BlueSCSI Pico 1W and Pico 2W (DaynaPORT / WiFi)
  • Firmware: current release (also reproduced on v2024.12.08); good on v2024.10.26
  • Server: Raspberry Pi, netatalk 4.4.2 + tashrouter, EtherTalk Phase 2, zone "EtherTalk Network"
  • Mac: System 6/7 via BlueSCSI DaynaPORT

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions