From eca07a45d58d10cd8ab62ee43846f113d717b1e2dd22079cf4814db80c7acbea Mon Sep 17 00:00:00 2001 From: Tyler King Date: Thu, 26 Feb 2026 19:38:12 -0500 Subject: [PATCH] Add three-model CNI adapter pattern to HFL-Kedge integration doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New §8 documenting how Kedge CNI operates identically across all three Substrate deployment models (container-first, KVM/QEMU, multikernel). Covers the substrate:network WIT adapter, per-model attach-workload resolution, GovernedNetworkPolicy installation path, and the invariant that the same CNI binary works unchanged across all models. Co-Authored-By: Claude Opus 4.6 --- docs/hfl-kedge-integration.md | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/docs/hfl-kedge-integration.md b/docs/hfl-kedge-integration.md index 8d053e8..ae3e1cf 100644 --- a/docs/hfl-kedge-integration.md +++ b/docs/hfl-kedge-integration.md @@ -417,3 +417,82 @@ Quartermaster receives the `submit-proposal` RPC with the `RequestToken` in meta | Service token | `RequestToken` is valid, single-use, unexpired | Userspace (Quartermaster/Bascule) | RPC rejected with `PermissionDenied` | Five independent checks, three distinct trust domains (pod kernel, pod userspace, remote service), two cryptographic validations (SAT, RequestToken). No single point of compromise grants unauthorized access. + +--- + +## 8. Three-Model Adapter Pattern + +Kedge CNI operates identically across all three Substrate deployment models. The CNI binary is a thin adapter that marshals between the Kubernetes CNI JSON contract and `substrate:network` WIT host function calls. Only the host-side implementation of those WIT calls varies. + +### 8.1 The Adapter + +The CNI binary delegates all real work to three WIT calls: + +| CNI Operation | WIT Call | +|---------------|----------| +| `CNI ADD` | `substrate:network/workload-network.attach-workload()` | +| `CNI DEL` | `substrate:network/workload-network.detach-workload()` | +| `CNI CHECK` | `substrate:network/workload-network.check-workload()` | + +The `substrate:network@0.1.0` WIT package (`substrate/wit/substrate-network.wit`) defines four interfaces: `workload-network` (attach/detach/check), `routing` (governed BGP/OSPF), `firewall` (identity-based flow policy), and `telemetry` (governed flow records). + +### 8.2 Model A: Container-First (Vanilla Linux) + +This is the Phase 1 deployment. Single Linux kernel. All components are userspace processes. + +When Kedge calls `attach-workload`: + +1. WASM governance Component evaluates policy (is this pod authorized for the requested networks?) +2. WASM Component assigns identity (SAT binding for the network interface) +3. eBPF program installs flow policy in `shell_map` BPF map (§2) +4. Creates memif interface into VPP's processing graph +5. VPP handles data plane — packets never touch the kernel network stack +6. Returns IP + routes to kubelet via CNI JSON result + +VPP runs as a userspace process pinned to dedicated cores. NICs are assigned via VFIO/UIO (kernel bypass). FRR runs as a separate process for BGP/OSPF routing. The `substrate:network` WIT Components replace any VPP/FRR management interface — there is no vyconf, no SSH, no CLI. + +### 8.3 Model B: KVM/QEMU (Legacy) + +Each role kernel is a VM. The Network VM runs VyOS/VPP. + +When Kedge calls `attach-workload`: + +1. Call crosses virtio-vsock to the Network VM +2. Same WASM + eBPF logic runs inside the VM +3. VPP inside the Network VM configures a virtio-net interface +4. Returns IP to kubelet + +Model B is supported for compatibility but is not the recommended production data plane. The virtio serialization overhead undermines DPDK's zero-copy advantage. + +### 8.4 Model C: Multikernel/Bifrost (Target) + +Multiple minimal Linux kernels on bare metal, each owning dedicated CPU cores and devices via IOMMU. + +When Kedge calls `attach-workload`: + +1. Governance evaluation runs in **Workload Kernel** (same kernel as kubelet/Kedge) +2. Only datapath operations cross the IPI bus to the **Network Kernel**: "create memif 10.0.1.5, policies: [...]" +3. Network Kernel's VPP adds interface to its processing graph +4. Network Kernel's eBPF installs flow policy +5. Shared memory data path connects Workload Kernel ↔ Network Kernel (zero-copy) +6. Returns IP to kubelet + +**Key design decision:** Governance evaluation stays in the Workload Kernel. Only the result (interface creation + flow policies) crosses the IPI bus. This keeps the governance plane local, minimizes IPI traffic, and means the Network Kernel only handles datapath operations. + +The Network Kernel image is based on a stripped VyOS distribution: VPP + DPDK (data plane, owns NICs via IOMMU), FRR (control plane routing), WASM runtime + `substrate:network` Components (governance plane), eBPF programs (flow policy enforcement + telemetry). Stripped: vyconf, SSH server, web UI — replaced by WIT host functions accessed via IPI bus. + +### 8.5 GovernedNetworkPolicy Installation Path + +When SPIRE issues an SVID for a pod, the `ssh-credential-composer` embeds a `network-policy@guildhouse.dev` SSH certificate extension containing the SHA-256 hash of the applied GovernedNetworkPolicy. At CNI ADD time: + +1. Kedge reads the policy hash from the pod's SVID +2. Kedge calls `attach-workload` with the policy reference in `governance-context` +3. The WASM governance Component resolves the policy hash to a full `GovernedNetworkPolicy` (identity-based, SAT-claim-scoped firewall rules) +4. The Component calls `substrate:network/firewall.install-flow-policy` for each rule +5. eBPF programs in the VPP graph enforce the installed policies at wire speed + +The trust chain is continuous: SPIRE attests workload → composer embeds governance context → Kedge reads context → host functions install governed policy → eBPF enforces → Chronicle notarizes. + +### 8.6 The Invariant + +The same Go binary (`cmd/kedge-cni/main.go`) runs unchanged across all three models. The `substrate:network` WIT interface is the stable boundary. What changes between models is the host function implementation — memif vs. virtio vs. IPI — but the CNI adapter never sees this. The `ShellProgrammer` trait (shell-primitive.md §7) absorbs the model difference at the enforcement layer, and the WIT runtime absorbs it at the network operations layer.