# Current state

## Committed tree
AF_PACKET raw sockets everywhere (`sock.go`), flow-director steering, read-time-stamped rate buckets, framebuffer UI, harness. The zero-copy AF_XDP conversion (both directions, hand-rolled XSK + hand-assembled XDP program, per-frame MAC-stamp buckets via rx metadata) lives uncommitted in `stash@{0}`; it was built for the era when the test path ran on the E810, whose datapath delivers per-packet MAC timestamps. It is an experiment, not a requirement.

`stash@{1}` holds the phydiag campaign: python transport clients (`i40e_aq.py`, `rollball_i40e.py`, `sff.py`), scanners, and a STATUS.md campaign log. Working copies extracted to `~/work/phydiag-work/` during the module work. The knowledge from that campaign is now in these docs; the code should eventually move into the repo properly.

## Hardware in flight
- **Intel X520-DA2 ordered** — replaces the E810 in the box's single PCIe slot. Chosen because ixgbe bit-bangs module I2C from the host (no firmware policy layer), enabling in-product module-PHY diagnostics; see transports.md.
- **Replacement Wiitek (Marvell CUX3610) modules ordered.** Both original units were bricked by register exploration — see modules.md for the trap before ever touching one.
- **In hand** (all copper RJ45 10GBASE-T modules with cloned/lying fiber EEPROMs — see hardware.md; none are actually fiber):
  - 2× FS SFP-10G-T-100 (Broadcom BCM84891L, fully documented diagnostics).
  - 1× Fibergaga SFP-10G-T-30M (Aquantia, RollBall, the proven oracle module).
  - 1× 10Gtek, EEPROM claims SFP-10G-SR — still a copper RJ45 module; filler, not part of the test set.

## X520 prep — built ahead of the card, untested (no hardware yet)
In `~/work/` alongside the ice-sff/phydiag-work artifacts, ready to fold into the repo's `kernel/` once validated on real hardware:
- **Patched ixgbe** (`~/work/ixgbe-sff/`, built against the running kernel, vermagic matches): adds `ixgbe_i2c_raw_write`/`ixgbe_i2c_raw_read` in `ixgbe_phy.c` (arbitrary START…STOP transactions built from the existing bit-bang primitives, swfw-semaphore bracketed) and an `sff_i2c` debugfs file with `w <addr8> <bytes…>` / `r <addr8> <n>` commands, result read back from the fd. Modeled on the proven ice `sff_i2c`; ixgbe has no firmware to refuse, so arbitrary framing works. `load-ixgbe` rebuilds + swaps the module.
- **BCM client** (`~/work/phydiag-work/bcm_ixgbe.py`): BCM SMI framing on those two ops (read = write `[001+devad,RegH,RegL]`, >1 ms delay, read 2 B; write = 5-byte frame) plus the full command handler (`_wait_idle` → DATA → CMD|bit15 → poll PASS/ERROR → read DATA), `CMD_GET_SNR` decoded to per-pair dB, and EEPROM/PHY-ID/STATUS sanity reads.
- **RollBall client for the Wiiteks** (`~/work/phydiag-work/rollball_ixgbe.py`): the same `sff_i2c` transport, RollBall unlock/page/mailbox, per-pair IEEE SNR (PMA 1.133–1.136). The `*.0x??64` (high-byte ≥ 0x80) brick blacklist is a hard guard that raises *before* touching hardware — the client structurally cannot repeat the kill.

## Bringup plan when the X520 arrives
1. Install card, move FS modules in, `./load-ixgbe`, confirm `sff_i2c` appears.
2. FS/BCM modules first: `bcm_ixgbe.py` sanity reads (EEPROM, PHY ID, STATUS) to prove the SMI transport, then the command handler (CMD_GET_SNR vs the IEEE registers) on the test cable set.
3. Replacement Wiiteks: IEEE-standard registers only (SNR, latches) unless/until a documented recipe exists for more; the VCT templates in modules.md are candidates for single-shot targeted probes on a sacrificial unit only.
4. Re-derive host tuning on ixgbe (coalescing/ring syntax differs).

## Open: RX flow-steering on ixgbe needs serious investigation before the X520 carries test traffic
cabletest fans RX across queues by steering **raw ethertype** (0x88b5 base) to distinct queues with Flow Director rules (`system.go`, ETHTOOL_SRXCLSRLINS, ETHER_FLOW). The obvious path fails: ixgbe/82599's `ixgbe_flowspec_to_flow_type` accepts only TCP/UDP/SCTP-v4 and IPv4 — **no ETHER_FLOW** — so an ETHER_FLOW rule insert is rejected (EINVAL) and the tool fails at startup (no fallback, by design). This is a datapath issue affecting *both* module types, independent of diagnostics.

But 82599 has hardware steering machinery the current code doesn't use, and **there is good reason to think we can keep true raw-L2 ethertype steering without falling back to encapsulation.** This needs bench investigation on the actual card; do not assume the answer is UDP encap. Leads, most promising first:
- **Flow Director flex-byte match.** The driver exposes a 2-byte `flex_bytes` filter (via the `user-def`/FLOW_EXT `vlan_etype` field), and `ixgbe_reinit_fdir_tables_82599` already programs `FDIRCTRL_FLEX_SHIFT = 0x6` — offset 12 bytes, **exactly the ethertype field** of an Ethernet frame. So the hardware is already sampling the ethertype. Open question to settle on hardware: whether a non-IP raw frame classifies into an fdir flow_type the rule engine will match, given the driver requires an IP base flow_type in the rule spec — may need a small driver change to pair flex_bytes with a permissive/L2 flow type.
- **MAC → VMDq pool steering.** 82599 assigns unicast MAC (RAR) entries to VMDq pools and pools to RX queues (`hw_set_rar` VMDq pool/queue selection). Distinct dest MACs per stream → distinct queues, fully raw Ethernet, no IP at all. Worth prototyping alongside the flex-byte path.
- **RSS on a flexible field** — 82599 RSS hashes IP tuples, not raw L2, so unlikely to help without encap; noted only to rule out.

Fallbacks if raw-L2 steering genuinely can't be made to work: minimal bare-IPv4 framing (no UDP) steered by IP_USER_FLOW src/dst IP (lighter than the old UDP-encap plan), or single-queue RX (caps near the old ~1.6 Mpps single-NAPI ceiling, loses small-frame headroom and per-stream isolation). These are last resorts, not the plan.

## Open items
- **ECD register chapter**: the one missing document for BCM cable length. FS has been responsive; the narrow ask is "which registers invoke ECD / report the DSP cable-length estimate, and does it run with link up?"
- **Pre-FEC classification** on the Aquantia (3.e820): needs a marginal channel; cabletest's noise stress will provide one once diagnostics are integrated.
- **X710 PTP path-delay length measurement**: viable fallback for linked-cable length (PTP-latch timestamps both ports, same oscillator, 1 ft calibration cancels PHY latency); scoped but unbuilt. Superseded for the product if BCM ECD/DSP length pans out.
- E810 leaves the box when the X520 arrives; the patched ice + `sff_i2c` remains useful only if an E810 returns for read-side work.
