Skip to content

goip vrf show NAME family forms: the ifi_family byte (VF0–VF2) - #288

Merged
randomizedcoder merged 7 commits into
mainfrom
goip/vrf-family-forms
Nov 9, 2026
Merged

randomizedcoder merged 7 commits into
mainfrom
goip/vrf-family-forms

Conversation

@randomizedcoder

Copy link
Copy Markdown
Owner

Summary

Implements docs/netlink/vrf-family-forms.md end to end: the parked decision-8 increment reopened. goip -4/-6/-0 vrf show NAME — the family flag changes only the request's ifi_family byte (iplink_vrf.c:110-113), and the kernel resolves the name without consulting the family (rtnetlink.c:4346-4355), so the three forms print the plain form's own line. One commit per task, plus a corrective commit this work is built on:

  • Corrective (393cdb5a) — the gaps doc's class C note claimed "the 7.2 checkout dumps RTM_GETMULTICAST", citing a post-7.3.0 dev snapshot misread as 7.2. Measured: a capture run for two ip -4/-6 maddress show rows recorded zero netlink datagrams in all three namespaces — read_maddr_netlink is commit b8cdda55, first released in v7.3.0. At our 7.2.0 pin every maddress form reads /proc, family-filtered included; the note, the class F row and the mcdump helper's stale "in no release" comment are amended. maddress waits for the 7.3.0 pin bump.
  • VF0 — three capture rows (-4/-6/-0 vrf show goipvrf, 9 pcaps + sidecars, all datagrams=2 floor=2), with TestVrfFamilyFormsRequestIsTheNameGet as the fixture consumer: each recorded get is req.VrfCheckByName's 44 bytes with only the family byte (offset 16) differing, RTM_NEWLINK in the clean namespace, NLMSG_ERROR -ENODEV in mesh and tunnel.
  • VF1 — the object delta is deleting vrfShowName's family guard (obj_vrf.go; line 93 already passed c.family); the dump form's family refusal is untouched, the family genuinely changes that dump's shape. TestVrfShowName's -4 corner row flips positive, three replay rows replay their own captures through the family-blind dump fallback, three cleanOnly corpus rows walk all three namespaces.
  • VF2 — three matrix rows, gated on the doctrine pair.

Where coverage stands (counted from the tree on 2026-11-04)

  • Parity matrix: 513 rows (was 510), of which 512 are gated (was 509) — 238 reads and 275 dry-run writes.
  • Ungated surface: exactly one row, addr show dynamic, whose valid_lft ticks.
  • Allowlist: 5 entries, all the ip netns rows' NETNSA_FD descriptors.

Test plan

  • Every task: table-driven unit tests; go vet; nix build --no-link of .#test-focused-goip, netlink-audit, lint-baseline, quality-report and the nix hygiene checks; vm-lib-exp at VF0 (an .exp file changed); a mutation check per task in a scratch worktree, removed after — the AF_UNSPEC-hardcoding builder killed exactly the nine byte-compare subtests, the restored guard exactly the seven family rows, the dropped -6 row exactly its four pins.
  • The rows were gated only after two consecutive clean ungated goip-parity VM runs measured them, then confirmed by two back-to-back gated runs with no edit of any kind between them. All four runs: GOIP_PARITY_DRIVER_PASS, GOIP_PARITY_OVERALL_PASS, 513/513 GOIP_PARITY_PASS, GOIP_PARITY_UNGATED_CLEAN; each row txns: ip=1 goip=1, control: nl=0 stdout=0.

randomizedcoder and others added 7 commits November 4, 2026 02:25
…t 7.2.0

The gaps doc class C note claimed "the 7.2 checkout dumps
RTM_GETMULTICAST" (citing ipmaddr.c:276), which made maddress the
next object at the 7.2.0 pin. It was written against a post-7.3.0
dev snapshot misread as 7.2: read_maddr_netlink is commit b8cdda55,
first released in v7.3.0. At the 7.2.0 pin every maddress form reads
/proc, family-filtered included — measured 2026-11-04, when a capture
run for two ip -4/-6 maddress show rows recorded zero netlink
datagrams in all three namespaces and missed its floors, exactly the
failure the floors exist to catch. maddress moves to class C at the
7.3.0 pin bump, not the 7.2.0 one; the class F row and the mcdump
helper comment (which said b8cdda55 was "in no release") are amended
to the same truth. The reply decode needs no rework either way — the
addr plan mcdump captures already ground IFA_MULTICAST/IFA_MC_USERS.

A plan doc and builder started on the false premise were reverted;
nothing of it landed.
The parked decision-8 increment reopened: vrf-show-name.md refused the
family forms on the NAME path only because no capture grounds the
ifi_family byte. The kernel resolves the name without consulting the
family (rtnetlink.c:4346-4355), so the three forms are VS0's pinned
44-byte get with one byte changed, and the object delta is deleting
vrfShowName's guard (obj_vrf.go:89-91) — line 93 already passes
c.family.

Three tasks: VF0 the captures (three rows, three namespaces, the
ENODEV arm grounded for free where goipvrf does not exist) with the
family-byte pin as the fixture consumer; VF1 the guard deletion, the
flipped TestVrfShowName corner row and the family replay test, the
corpus rows; VF2 three matrix rows and gating.

Chosen after the maddress plan was reverted: a capture run measured
zero netlink datagrams for ip -4/-6 maddress show at the 7.2.0 pin —
read_maddr_netlink is commit b8cdda55, first released in v7.3.0 —
and the corrective commit 393cdb5 amended the gaps doc note that
had said otherwise. maddress waits for the 7.3.0 pin bump.
…e (VF0-T01)

Three capio rows in the dump-capture driver — ip -4/-6/-0 vrf show
goipvrf — floor 2, every namespace: the -4/-6/-0 flag changes only
the request ifi_family byte (iplink_vrf.c:110-113), and the kernel
resolves the name without consulting the family (rtnetlink.c
:4346-4355), so base answers the vrf link itself (goipvrf 100 on
stdout) and mesh and tunnel answer NLMSG_ERROR ENODEV (Invalid VRF on
stderr, dropped by read rows). 18 files under
pkg/xtcpnl/testdata/7_3_0/dumps/{,mesh/,tunnel/}.

TestVrfFamilyFormsRequestIsTheNameGet, the fixture consumer: each
recorded get is byte-identical to req.VrfCheckByName(family, goipvrf)
with seq/pid zeroed, the family byte at offset 16 is the only delta
from the plain form VS0 pinned, and the reply is the right shape per
namespace. Mutation check in a scratch worktree: VrfCheckByName
hardcoding AF_UNSPEC kills exactly the nine byte-compare subtests and
nothing else.

NLCAP_DRIVER_PASS; go test, go vet, test-focused-goip, vm-lib-exp,
netlink-audit, lint-baseline, quality-report and the nix hygiene
checks green. Ledger VF001; the plan doc flips VF0-T01.
vrfShowName's family refusal is gone: the -4/-6/-0 flag passes
through to the request ifi_family byte (iplink_vrf.c:110-113), and
the kernel resolves the name without consulting the family
(rtnetlink.c:4346-4355), so all three forms print the plain form
line. The dump form family refusal is untouched — the family
genuinely changes the dump shape there.

TestVrfShowName's -4 corner row flips to a positive row; three
family rows join TestVrfShowNameReplay, each replaying its own VF0
capture through the family-blind dump fallback; three cleanOnly
corpus rows walk the captures in all three namespaces, mesh and
tunnel refusing with Invalid VRF as the plain NAME row does.

Mutation check in a scratch worktree: the guard restored verbatim
failed exactly the seven family rows and nothing else. go test, go
vet, test-focused-goip, netlink-audit, lint-baseline, quality-report
and the nix hygiene checks green. Ledger VF002; the plan doc flips
VF1-T01.
…(VF2-T01)

Three read rows in internal/goipparity/commands.go vrf block: -4,
-6 and -0 vrf show goipvrf — the parked decision-8 family forms.
The family flag changes only the request ifi_family byte
(iplink_vrf.c:110-113); the kernel resolves the name without
consulting the family (rtnetlink.c:4346-4355), so the answer and
stdout are the plain NAME row own and the floor with it. All floor 2,
Implemented, no Setup, no Write.

Gated on the doctrine pair: two clean ungated runs measured the rows
(513/513 GOIP_PARITY_PASS, txns ip=1 goip=1, control nl=0 stdout=0,
the answer byte-identical), then two back-to-back gated runs with no
edit of any kind between them read the same. All four
GOIP_PARITY_DRIVER_PASS and GOIP_PARITY_OVERALL_PASS with
GOIP_PARITY_UNGATED_CLEAN. The three names join gated_commands (512
now) and the earned slice; TestVrfFamilyFormRowsGated pins the flip
and the three family rows join TestFamilyTableAndJSONRows;
TestUngatedSurfaceIsNotVacuous is back to exactly addr show dynamic.

coverage-status at-a-glance 510/509 to 513/512 (counted from
2026-11-04) and the README counts likewise; the plan doc flips VF2-T01
and records VF003. Mutation check: the -6 row dropped from commands.go
killed exactly its four pins.
Self-review follow-up on the VF rows, two findings and two nits:

- TestVrfShowName gains a wantTalkFamily assertion — the ifi_family
  byte read off the request vrfNameSource records (obj_vrf_test.go
  :392), offset NLMSG_HDRLEN — so the family pass-through is pinned on
  the object own Talk path, where the replay tests cannot see it
  (their dump fallback is family-blind). Two new rows cover -6 and -0;
  the mutant that hardcodes AF_UNSPEC in VrfCheckByName, previously
  invisible at this level, now kills exactly the three family rows.
- A boundary row composes decision 6 with the family flag: -4 vrf
  show of a 16-character name takes the ErrBadIfName arm — Invalid
  VRF, rc 1, nothing sent — proving the two paths meet.
- The obj_vrf.go doc comment is rewrapped so godoc renders the plan
  path whole (docs/netlink/vrf-family-forms.md was split across lines,
  joining with a space), and the pin test af0 row names why its file
  field is 0 and not af0.

go test -count=1 and -race green, go vet, test-focused-goip,
netlink-audit, lint-baseline, quality-report and the nix hygiene
checks green; the mutation check above re-verified in a scratch
worktree, removed after.
Resolve the maddress pin note in goip-parity-gaps.md: main's one-line form, plus b8cdda55 first released in v7.3.0 and the 2026-11-04 capture evidence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@randomizedcoder
randomizedcoder merged commit 3904f31 into main Nov 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant