Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/netlink/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ If you are looking for the daemon as a whole, start at the
| [goip parity: link kinds](goip-link-kinds.md) | The plan after the gaps plan: every link kind a VM can create (bridge, the VLAN family, the UDP overlays, the IP tunnels and the rest), parsed, encoded and `-d`-rendered by goip, plus iproute2 7.2.0's `ip link set dev X inet …` devconf write. The per-kind inventory at `v7.2.0`, the exclusions, and the same three tiers: captures, parsers, then goip and the matrix. |
| [goip parity: link kinds — status](goip-link-kinds-status.md) | The tracker for that plan: the next action, the state of each phase from KC0 to KG5, the task checklist, the verification ledger and the decision log. |
| [vrf show NAME](vrf-show-name.md) | **Landed.** `goip vrf show NAME`, the refused `ipvrf_get_table` single lookup — the one netlink path left on the `vrf` object. Five tasks (VS0–VS4), each with its test table: pin the already-committed request bytes, the `VrfTableByName` accessor, the argv and output, the capture rows, and the three matrix rows — gated. |
| [vrf family forms](vrf-family-forms.md) | **Landed.** `goip -4/-6/-0 vrf show NAME`, the parked decision-8 family byte — the kernel resolves the name without consulting `ifi_family`, so the three forms are the 44-byte get with one byte changed. Three tasks (VF0–VF2): the captures with the family-byte pin, the guard deletion (the object change is one line), and the three matrix rows — gated. |
| [Upstream bug: bond partner state width](upstream/iproute2-bond-partner-state-width.md) | An iproute2 bug found while designing the link write path: `ip` reads the u16 `IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE` as a u8, so big-endian hosts always print `0 <>`. |

The last three are a chain — the audit finds the gaps, the roadmap decides the
Expand All @@ -41,9 +42,9 @@ each sent** and the **text each printed**. It is the strongest evidence in the
tree that `pkg/xtcpnl` decodes what the kernel actually said, because the
reference is iproute2 itself rather than our reading of iproute2.

510 commands are compared, 275 of them dry-run link, link property, route,
513 commands are compared, 275 of them dry-run link, link property, route,
address, neighbor, rule, nexthop, address label, neighbor table, statistics,
token, nsid, tcp_metrics, sr, ioam, mptcp, fou, ila, l2tp, macsec, XFRM state and XFRM policy writes, flushes and restores, and 509 are gated. The counts, what "gated" costs to earn, and the scope boundaries are
token, nsid, tcp_metrics, sr, ioam, mptcp, fou, ila, l2tp, macsec, XFRM state and XFRM policy writes, flushes and restores, and 512 are gated. The counts, what "gated" costs to earn, and the scope boundaries are
in [parity at a glance](coverage-status.md#goip--ip-parity-at-a-glance). The
comparator is `pkg/nlparity` (protocol level) and `internal/goipparity`
(command level); the accepted-divergence list is
Expand Down
8 changes: 4 additions & 4 deletions docs/netlink/coverage-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

## goip ↔ `ip` parity at a glance

Counted from the tree on 2026-11-01. Every number has a file behind it, named
Counted from the tree on 2026-11-04. Every number has a file behind it, named
in the last column; **if this table and the file disagree, the file is right
and this table is stale.** That has happened before in this document — see the
"no route command is in `gated_commands`" line that outlived its own truth by
several steps, further down under [Remaining](#remaining).

| | count | counted from |
|---|---|---|
| commands in the comparison matrix | **510** | `internal/goipparity/commands.go` — 235 read rows, the 3 `nexthop show` dev, master and vrf selector rows of the iproute2 7.2.0 move and the 3 `vrf show NAME` single-get rows of VS4 ([vrf show NAME](vrf-show-name.md)) among them, 8 of them G6-T01's `tcp_metrics` reads, each with a `Setup`, 4 G6-T02's `sr` reads, 4 G6-T03's `ioam` shows, 9 G6-T04's `mptcp` reads, 8 G6-T05's `fou` reads, 7 G6-T06's `ila` reads, 13 G6-T07's `l2tp` reads, 15 G6-T08's `macsec` reads, 9 G7-T01's `xfrm state` reads, G7-T02's `xfrm state delall` with no SA to delete, 10 G7-T03's `xfrm policy` reads and G7-T04's `xfrm policy delall` with no policy to delete, NETLINK_XFRM, (31 of them `addr show` state, selector and output-mode rows with a `Setup`, and 6 `route get`, 2 `neigh get`, 4 `nexthop get` and `nexthop bucket`, 3 `link xstats` and `link afstats`, 6 `mroute show`, 3 `token`, 4 `netns list-id`, 3 `route save` and `route showdump`, 1 `route flush`, 1 `neigh flush`, 1 `rule save` and 1 `nexthop flush` rows with one; the missing-table `route flush` row has none), the 21 link write rows, the 26 route write rows, the 27 address write rows, the 7 address flush rows, the 2 address restore rows, the route restore row, the 2 route flush write rows, the 6 neigh write rows, the 2 neigh flush write rows, the 17 rule write rows, the rule flush write row, the rule restore row, the 6 nexthop write rows, the nexthop flush write row, the 2 addrlabel write rows, the addrlabel flush write row, the 3 ntable write rows, the stats write row, the 3 link property write rows, the 2 token write rows, the netns set write row, the 6 `tcp_metrics` delete and flush write rows, the 7 `sr` set write rows, the 16 `ioam` namespace and schema write rows, the 19 `mptcp` endpoint and limits write rows, the 16 `fou` add and del write rows, the 11 `ila` add and del write rows, the 15 `l2tp` tunnel and session add and del write rows and the 24 `macsec` SA, receive channel and offload write rows, generic netlink, the 16 `xfrm state` add, update, delete, deleteall, flush and allocspi write rows and the 12 `xfrm policy` add, update, delete, deleteall, flush, set and setdefault write rows, NETLINK_XFRM |
| of those, `Implemented: true` | **510** | same file — every row: none is `SKIP` and, since G6-T08, none is an `ip` stand-in (`IPStandIn`), which is why the comparator's unimplemented branch and the stand-in's rendering are exercised by synthetic commands |
| of those, in `gated_commands` | **509** | `pkg/nlparity/goip-parity-allowlist.json` |
| commands in the comparison matrix | **513** | `internal/goipparity/commands.go` — 238 read rows, the 3 `nexthop show` dev, master and vrf selector rows of the iproute2 7.2.0 move, the 3 `vrf show NAME` single-get rows of VS4 ([vrf show NAME](vrf-show-name.md)) and the 3 `vrf show NAME` family rows of VF2 ([vrf family forms](vrf-family-forms.md)) among them, 8 of them G6-T01's `tcp_metrics` reads, each with a `Setup`, 4 G6-T02's `sr` reads, 4 G6-T03's `ioam` shows, 9 G6-T04's `mptcp` reads, 8 G6-T05's `fou` reads, 7 G6-T06's `ila` reads, 13 G6-T07's `l2tp` reads, 15 G6-T08's `macsec` reads, 9 G7-T01's `xfrm state` reads, G7-T02's `xfrm state delall` with no SA to delete, 10 G7-T03's `xfrm policy` reads and G7-T04's `xfrm policy delall` with no policy to delete, NETLINK_XFRM, (31 of them `addr show` state, selector and output-mode rows with a `Setup`, and 6 `route get`, 2 `neigh get`, 4 `nexthop get` and `nexthop bucket`, 3 `link xstats` and `link afstats`, 6 `mroute show`, 3 `token`, 4 `netns list-id`, 3 `route save` and `route showdump`, 1 `route flush`, 1 `neigh flush`, 1 `rule save` and 1 `nexthop flush` rows with one; the missing-table `route flush` row has none), the 21 link write rows, the 26 route write rows, the 27 address write rows, the 7 address flush rows, the 2 address restore rows, the route restore row, the 2 route flush write rows, the 6 neigh write rows, the 2 neigh flush write rows, the 17 rule write rows, the rule flush write row, the rule restore row, the 6 nexthop write rows, the nexthop flush write row, the 2 addrlabel write rows, the addrlabel flush write row, the 3 ntable write rows, the stats write row, the 3 link property write rows, the 2 token write rows, the netns set write row, the 6 `tcp_metrics` delete and flush write rows, the 7 `sr` set write rows, the 16 `ioam` namespace and schema write rows, the 19 `mptcp` endpoint and limits write rows, the 16 `fou` add and del write rows, the 11 `ila` add and del write rows, the 15 `l2tp` tunnel and session add and del write rows and the 24 `macsec` SA, receive channel and offload write rows, generic netlink, the 16 `xfrm state` add, update, delete, deleteall, flush and allocspi write rows and the 12 `xfrm policy` add, update, delete, deleteall, flush, set and setdefault write rows, NETLINK_XFRM |
| of those, `Implemented: true` | **513** | same file — every row: none is `SKIP` and, since G6-T08, none is an `ip` stand-in (`IPStandIn`), which is why the comparator's unimplemented branch and the stand-in's rendering are exercised by synthetic commands |
| of those, in `gated_commands` | **512** | `pkg/nlparity/goip-parity-allowlist.json` |
| allowlisted divergences | **5** | same file, `entries` |
| of those, `kind=version-skew` | **0** | the pin is `ip` 7.2.0 and goip follows it; the seven 7.1.0 entries were retired on 2026-10-21 (see [iproute2 7.2.0](#iproute2-720-the-pin-moves-and-goip-moves-with-it)) |
| of those, `kind=accepted-divergence` | **5** | the five `ip netns` rows' `NETNSA_FD`, the descriptor each process opened the namespace file as, a slot in its own table (G4-T04). Nothing else is: the nine wire divergences runs 8 and 9 measured **could not** be, because a transaction-count divergence is unsuppressible (`nlparity_allowlist.go:143`), and G0 retired every one by changing goip to send `ip`'s requests |
Expand Down
4 changes: 2 additions & 2 deletions docs/netlink/goip-parity-gaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ G4 delivered all six: goip runs `mroute`, `mrule`, `token`, `netns list-id` and
| monitor | Every NEW/DEL notification, across the multicast groups at `ip/ipmonitor.c:267-367` | `ip/ipmonitor.c:194` | each subsystem's notifier | The 10 decoded event types (`IsRtnetlinkEventType`, `RTM_NEWRULE`/`RTM_DELRULE` among them since G4-T05) were not rendered; `goip monitor` renders every type `accept_msg` prints since G4-T06 |
| prefix (in monitor) | `RTM_NEWPREFIX` (`prefixmsg`) | `ip/ipprefix.c:33` | `net/ipv6/addrconf.c` | Emitted only when a router advertisement is received |

**maddress depends on the version.** At the pin, `ip maddress show` reads `/proc/net/{dev_mcast,igmp,igmp6}` (`ip/ipmaddr.c:95-179`), and add/del are ioctls, so it is class F at 7.1.0. It is still class F at the 7.2.0 pin: `RTM_GETMULTICAST` reached `ip/ipmaddr.c` in `b8cdda55`, after the tag (`v7.2.0-34`), so maddress moves to this class at the pin bump after 7.2.0. This plan first said the 7.2 release made the move; the checkout was past the tag ([goip-link-kinds.md](goip-link-kinds.md#what-720-adds)).
**maddress depends on the version.** At the pin, `ip maddress show` reads `/proc/net/{dev_mcast,igmp,igmp6}` (`ip/ipmaddr.c:95-179`), and add/del are ioctls, so it is class F at 7.1.0. It is still class F at the 7.2.0 pin: `RTM_GETMULTICAST` reached `ip/ipmaddr.c` in `b8cdda55`, first released in v7.3.0 (the checkout was `v7.2.0-34`), so maddress moves to this class at the 7.3.0 pin bump. This plan first said the 7.2 release made the move; the checkout was past the tag ([goip-link-kinds.md](goip-link-kinds.md#what-720-adds)). At 7.2.0 every form reads /proc, family-filtered included: a capture run on 2026-11-04 recorded zero netlink datagrams for `ip -4/-6 maddress show`, which is what the rows' floors are for. The reply is already grounded either way: the addr plan's self-sent mcdump captures are the corpus's only `IFA_MULTICAST`/`IFA_MC_USERS` holders ([addr-write-path.md](addr-write-path.md), table 6).

### D. Generic-netlink objects goip does not run

Expand Down Expand Up @@ -144,7 +144,7 @@ These surfaces have no netlink message to capture, so they are out of scope for
|---|---|
| `tunnel`/`tunl6` parameters and add/change/del/prl/6rd | ioctls `SIOC{GET,ADD,CHG,DEL}TUNNEL`, `SIOC{ADD,DEL}PRL`, `SIOC{ADD,DEL}6RD` (`ip/tunnel.c:63`) |
| `tuntap` add/del, and its flags, owner and group | `/dev/net/tun` plus `TUNSETIFF` and related ioctls (`ip/iptuntap.c:62`), and sysfs |
| `maddress` at 7.1.0 and 7.2.0 | `/proc` reads and `SIOCADDMULTI`/`SIOCDELMULTI` |
| `maddress` through the 7.2.0 pin | `/proc` reads and `SIOCADDMULTI`/`SIOCDELMULTI`; `b8cdda55` (v7.3.0) moves `show` to an `RTM_GETMULTICAST` dump |
| `netns add/del/exec` | `unshare`, bind mount, `setns` |
| `vrf exec/identify/pids` | cgroup2 plus `bpf(BPF_PROG_LOAD)` (`ip/ipvrf.c:55`, `:288`) |
| `route flush cache` | a write to `/proc/sys/net/ipv4/route/flush` (`ip/iproute.c:1649`) |
Expand Down
Loading
Loading