CPU Isolation Wire Format
Status: design decision. Commits the wire shape for per-lease CPU isolation policy. Implementation is a separate wave gated on this note.
Addendum to:
docs/spec/resource-isolation-and-exclusivity.md§6.2 (lease requests) and §7 (SDK consequences).
1. Problem recap
The resource isolation design establishes that CPU capacity,
execution mode, and isolation are three independent axes, and
that isolation must be a first-class request input rather than an
implicit consequence of wider leases. Today CpuIsolationPolicy exists
as a daemon-wide CLI knob (fabricbiosd --cpu-isolation-policy ...)
with three classes:
BestEffort— default; no pinning beyond cgroup quotaWholeCore— lease owns a full core; no SMT sibling sharingStrictIsolated—WholeCoreplus topology/NUMA constraints
Clients cannot currently request these per-lease. This note answers:
how should a LEASE_ALLOC request carry a per-lease CPU isolation
policy independent of execution width?
2. Decision
Extend the existing LeaseAllocRequest TLV params blob with a new
TLV_LEASE_CPU_ISOLATION (0x0902) tag carrying a single-byte policy
class. Mirror the shape already used by TLV_LEASE_INTENT_KV_CACHE
(0x0901), defined in the lease-intent parser.
2.1 TLV layout
+--------+--------+--------+--------+| tag=0x0902 (u16 BE) |+--------+--------+--------+--------+| len=0x0001 (u16 BE) |+--------+--------+--------+--------+| class (u8) |+--------+--------+--------+--------+Class encoding:
| Value | Class | Notes |
|---|---|---|
| 0x00 | BestEffort | Equivalent to omitting the TLV. |
| 0x01 | WholeCore | Exclusive core; no sibling sharing. |
| 0x02 | StrictIsolated | WholeCore + topology/NUMA constraints. |
| 0x03..0xFE | reserved | Fail closed per §3. |
| 0xFF | reserved sentinel | Never valid on the wire. |
2.2 Absent TLV
If the TLV is absent, the request inherits the daemon-wide default
set by --cpu-isolation-policy. This preserves backwards compatibility:
existing clients that never emit the TLV observe unchanged behavior.
3. Fail-closed rules
Per design note §6.2:
- Unknown class byte → reject with
LeaseError::InvalidIntent(reusing the existing error; no new variant required for this wave). - Class not supported by the runtime → reject with
LeaseError::InvalidArgsand a rejection-reason TLV naming the unsupported class. “Silently downgrade toBestEffort” is explicitly forbidden. - Bare-metal runtimes that cannot enforce
WholeCore/StrictIsolated→ reject the request. They MUST NOT accept-and-ignore. The runtime semantics for bare metal are addressed separately; this note only commits that the wire path fails closed until that decision lands. - Malformed TLV length → reject with
LeaseError::InvalidIntent, matching existing TLV parse behavior.
4. Rationale for the TLV approach
Four options were considered. This note chooses option 2 (TLV) for the following reasons.
4.1 Precedent already exists
TLV_LEASE_INTENT_KV_CACHE is the load-bearing precedent: optional,
advisory-but-validated, parsed via
lease_intent::parse_kv_cache_intent, carried on the same
LeaseAllocRequest params blob. CPU isolation is structurally
identical (optional classifier attached to a lease request) and
should not invent a second mechanism for the same shape.
4.2 Avoids a wire break
Option 1 (new struct field on LeaseAllocRequest) would require
regenerating all vectors/v0/ golden vectors per the Wire
Compatibility Discipline in CLAUDE.md, and every client/server
that decodes the struct would need synchronized updates. The TLV
path adds a new optional tag with zero impact on existing encoders.
4.3 Avoids op-code proliferation
Option 3 (dedicated LEASE_ALLOC_ISOLATED sub-op) duplicates handler
logic and forces the same daemon-wide vs per-lease policy merge on
two code paths. Rejected.
4.4 Cap-rights are the wrong granularity
Option 4 (encode via cap-entry rights bits) collapses three distinct
isolation classes into binary flags, which cannot represent
StrictIsolated without either a second flag (fragile) or
overloading WholeCore (dishonest). Rejected.
5. What this note does NOT commit to
- Runtime semantics on bare metal. Currently unsupported. This note only commits that unsupported classes fail closed.
- Inventory advertisement of which classes a node supports. Not yet
exposed. The TLV wire shape here is a precondition but the inventory
side is a separate design decision — specifically, how
RESOURCE_SUMMARYor an equivalent exposes the set of honored classes, which echoes the GPU exclusivity inventory question. - SDK knob. Not yet exposed in the SDK. The expected shape is
CpuBuilder::new().isolation(IsolationPolicy::WholeCore).acquire()per design note §7, but the builder change is a separate wave. - Scheduler admission using the class. Currently unsupported by the scheduler; the TLV is only honored by the node-side lease handler on the single-cell path.
- Interaction with
grafos_scheduler::tenant::Priority::Standard. These are unrelated concepts that share a name and must not be folded in.
6. Implementation checklist for the follow-on wave
When the implementation wave is picked up:
- Add
TLV_LEASE_CPU_ISOLATION = 0x0902to the lease-intent parser (or a new sibling module — prefer the sibling to keep KV-cache intent parsing narrow). - Add a
cpu_isolation: Option<CpuIsolationClass>field toLeaseAllocRequestpopulated byparse(). - Reject unknown class bytes and malformed TLVs per §3.
- Thread the class through to the node-side lease handler and apply
it via the existing Linux
CpuIsolationPolicyenforcement path. Bare-metal handlers reject (fail closed) until runtime support lands. - Add golden-vector coverage: one positive case per class, one
negative case for an unknown class byte, one negative case for a
truncated TLV. Regenerate
vectors/v0/per CLAUDE.md discipline. - Document the TLV in
docs/spec/fabricbios-wire-encoding-v0.md.
Out of scope for that wave: SDK builder knob, inventory advertisement, scheduler policy.
7. Cross-links
docs/spec/resource-isolation-and-exclusivity.md— the three-axis model this wire shape serves- The lease-intent TLV parser provides the precedent
LeaseAllocRequestcarries the params blob this TLV is added to- The Linux
CpuIsolationPolicyenum this TLV maps onto docs/spec/fabricbios-wire-encoding-v0.md— needs an entry forTLV_LEASE_CPU_ISOLATIONwhen implementation lands