Repository navigation
Fabric leg EEPROM read grant, and the ethtool authority it folds - #11504
Conversation
The eight Spark fabric legs link at 50G because their QSFP28 coding attests no 100GBASE-CR2 (gunbc.spark.fabric_switch_observed). The operator re-flashed every leg with an FS BOX V4 on 2026-09-17, which invalidates the EEPROM half of that observation WITHOUT replacing it -- nothing has re-read the bytes, and that module's own standing says the re-flash outcome is an experiment only a post-change read settles. Measured on spark-a3ee the same day, gunbc-automation holds exactly enable-linger and reboot, so `ethtool -m` asks for a password and no principal this fleet runs as can read a leg's coding. This lands the capability that makes the read possible, and nothing wider. extdeps.ethtool is a new upstream authority: binary name, directory, path, and the module-information read rendered twice -- bare argv and absolute sudoers Cmnd_Spec -- from one set of rows. The directory is /usr/sbin, measured, NOT systemd's /usr/bin: sudo matches a Cmnd_Spec on the resolved path, so borrowing that row would install a grant that lists clean and authorizes nothing. `-m <dev> raw on` is modeled as its own command rather than a mode, because the decoded form is the one already recorded fabricating a measurement (byte 140 FFh printed as "25500 Mb/s") and only the raw bytes reach the SFF-8636 decoders. spark_fabric_leg_netdev is hoisted out of eight identical literals in fabric_switch_observed so the grant folds one authority instead of becoming a ninth copy. The disclosure axis needed a third arm. The read is not GrantReturnsNoHostData -- it returns vendor, serial and coding bytes, and widening to make the grant installable is the under-assertion DESIGN 4d names. It is not GrantDisclosureUnestablished either: what makes InspectServingContainer unclassifiable is that Config.Env is UNBOUNDED, while SFF-8636's layout is fixed by a published specification this repository already models. So GrantDisclosureSpecificationBounded carries the specification and, beside it, the residual -- SFF-8636's vendor-specific regions -- because quietly covering the part it cannot read would be the absorbing fallback. Spec-bounded admits without an operator risk decision, which keeps the accepted-risk basis meaning "proceed while blind". No set verb anywhere: no ethtool -s rows, no grant arm. Forcing a live fabric's link mode lands with the convergence that calls it. Evidence by execution, claim_batch on this tree: 119 claims green across the reconcile, pinned-base, grant-install, privileged-operation and fabric-switch witnesses. New discriminating claims go red in both directions on the disclosure arm, and red if the Cmnd_Spec borrows systemd's directory. Three count assertions moved because the desired set grew; a fourth was restated at identity grain, since its count was standing in for "no inspect grant" and only held while inspect was the sole basis-gated grant. docs/plans/fabric-switch-100g-convergence-gap-analysis.md carries the rest of the route: the switch has never been read (fabric_switch_subject passes readings: [], so every lane is Crs812LaneUnknown), and the transport, reading producer, management address, credential standing and apply path are all absent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both findings of review 67149 verified against the tree and fixed.
ENROLMENT. gunbc.extdeps_scope_frontier rules that every .dag under
dag/extdeps is EXACTLY ONE of scope_carrier_paths, the machinery
exemption, or the FROZEN legacy manifest, and that a new file's only
landing states are scope carrier or genuine machinery. The new file
declared extdeps_model_scope but appeared in none of the three -- its
sibling dag/extdeps/systemd/loginctl.dag is enrolled and it was not. It
is a scope carrier, so it joins scope_carrier_paths beside its
neighbours. The reviewer is also right about why this was not caught:
frontier_cover_of_live_extdeps_tree_holds refuses a walked file in none
of the three, but the per-PR placement gate is declared not running, so
a green required lane did not enrol it.
DANGLING BUILDERS. ethtool_module_info_argv and
ethtool_module_info_command had no call site anywhere in the corpus --
definitions only, with the grant importing the raw pair. That is the
red arm of DESIGN 3c, and the annotation beside them ("kept only
because it names the vendor and part") named a use nobody has rather
than a consumer or a trigger, which is exactly the frontier the rule
admits and which this was not. Deleted. A decoded reader lands with the
consumer that wants those fields.
The annotation is rewritten rather than trimmed: it opened "THE RAW FORM
IS A DIFFERENT COMMAND, NOT A MODE OF THE ONE ABOVE", and deleting the
builders left "the one above" pointing at nothing. A true deletion
beside a sentence that has quietly become false is the stale-prose class
this repository keeps paying for, so the block now says only what is
there and records why the decoded pair is absent.
Evidence: claim_batch --wet on this tree, 56 claims green, exit 0,
covering the external-model-scope witnesses (including the live cover
that walks the real dag/extdeps tree and the carrier-declares-scope read
of every enrolled path) and the grant reconcile witnesses.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Both findings of review 67149 verified against the tree and fixed in 2e02b70. Enrolment — confirmed. Dangling builders — confirmed. One thing I did beyond the finding, because deleting them created a second defect: the surrounding annotation opened "THE RAW FORM IS A DIFFERENT COMMAND, NOT A MODE OF THE ONE ABOVE", and with the builders gone "the one above" pointed at nothing. Removing the code while leaving prose that has quietly become false is a class this repo has been bitten by before, so the block is rewritten to say only what is there, and to record why the decoded pair is absent rather than leaving a future author to re-add it. Evidence: |
Why
The eight Spark fabric legs link at 50G.
gunbc.spark.fabric_switch_observedrecords why: the legs are QSFP28-coded (extended compliance byte 192 =0x0B, byte 116 =00h), nothing attests 100GBASE-CR2, and the ConnectX-7 derives50G_2Xand refuses100G_2X.The operator re-flashed every leg with an FS BOX V4 on 2026-09-17. That invalidates the EEPROM half of that observation without replacing it — nothing has re-read the bytes, and that module's own standing is explicit that the re-flash outcome is an experiment only a post-change read settles.
Measured on
spark-a3eethe same day,gunbc-automationholds exactlyenable-lingerandsystemctl reboot. Soethtool -masks for a password and no principal this fleet runs as can read a leg's coding. This PR lands the capability that makes the read possible, and nothing wider.Read live on both legs the same day: up, autoneg on, 50000Mb/s. That is deliberately not recorded as evidence the re-flash failed —
crs812_passive_dac_requires_forced_modeistrueand nothing has forced the mode on either end, so a correctly recoded leg could sit at 50G. Separating those two causes is what the grant is for.What
extdeps.ethtool— new upstream authority with the full pattern (authority anchor,ExternalModelScopeover aDeclarationRef, binary name/directory/path). The module-information read renders twice — bare argv and absolute sudoersCmnd_Spec— from one set of rows, so the fork measured on srv5/srv6 in August cannot recur.Two decisions worth reviewing:
/usr/sbin, measured, not systemd's/usr/bin. sudo matches aCmnd_Specon the resolved path, so borrowing that row installs a grant that lists clean and authorizes nothing. There is a claim that goes red if it is borrowed.-m <dev> raw onis its own command, not a mode. The decoded form is the one this repo already caught fabricating a measurement (byte 140FFh→ "BR, nominal: 25500 Mb/s", the escape sentinel × 100). Only the raw bytes reach theextdeps.transceiver.sff_8636decoders.spark_fabric_leg_netdev— hoisted out of eight identical literals infabric_switch_observed, so the grant folds one authority rather than becoming a ninth copy.ReadFabricModuleEeprom { device }— device required;-mwith no device authorizes the read on every interface the host has.The disclosure axis — a third arm. This is the part I'd most like reviewed. The read is not
GrantReturnsNoHostData(it returns vendor, serial and coding bytes; widening to make the grant installable is the §4d under-assertion). It is notGrantDisclosureUnestablishedeither — what makesInspectServingContainerunclassifiable is thatConfig.Envis unbounded, whereas SFF-8636's layout is fixed by a published specification this repo already models. SoGrantDisclosureSpecificationBoundedcarries the specification and the residual (SFF-8636's vendor-specific regions), because quietly covering the part it cannot read would be the absorbing fallback. Spec-bounded admits without an operator risk decision, keeping the accepted-risk basis meaning "proceed while blind" rather than drifting into "install this".No set verb anywhere — no
ethtool -srows, no grant arm. Forcing a live fabric's link mode lands with the convergence that calls it.Evidence by execution
claim_batchon this tree, 119 claims green, exit 0, across the reconcile, pinned-base, grant-install, privileged-operation and fabric-switch witnesses.New claims that discriminate:
fabric_eeprom_grant_is_specification_bounded_not_unestablished— red in both §4d directions (widened to no-host-data, or narrowed to unestablished).the_eeprom_grant_does_not_borrow_systemd_binary_directory— red on the available mistake.Four existing assertions moved, and how they moved is the honest part:
srv6_listing_with_inspect(an authored converged listing) did gain the ethtool line.accepted_risk_for_another_container_does_not_admit_inspectassertedlength() == 0, which said "no inspect grant" only while inspect was the sole basis-gated grant. Adding one unrelated grant that needs no basis turned a true claim red without its property changing.wider_than_desiredcount, which explained a 2-vs-1 split that is now 4-vs-3 — a true number beside a false sentence is the failure this repo has been bitten by.What this does not do
The switch is untouched.
fabric_switch_subject()still passesreadings: [], so every lane isCrs812LaneUnknown— nothing in this corpus has ever made a request to that switch. The transport, the reading producer, the management address, the credential standing and the apply path are all absent, and are laid out indocs/plans/fabric-switch-100g-convergence-gap-analysis.md, which this PR adds.Installing this grant is a separate act from merging it; the reconcile decides that.
🤖 Generated with Claude Code