FluxVM Set 6 — XDP Shield + TCP Intelligence
Set 6 adds a high-speed, VM-aware protection/observation layer without taking ownership of Cilium, Fabric routing, or shared node network policy.
XDP Shield ownership boundary
fluxvm-shield is opt-in and requires an explicitly selected interface.
The loader uses XDP_FLAGS_UPDATE_IF_NOEXIST and first queries native and
generic XDP ownership. It refuses to replace an existing program. That means a
Cilium-owned shared uplink is left untouched.
Use it on a dedicated VM ingress/uplink (for example a direct-attached veth, macvlan/macvtap/SR-IOV representor under your control). On a shared Cilium uplink, keep Set 6 XDP disabled and use FluxVM's VM-edge TC/TCX policy instead.
A policy example:
{
"mode": "enforce",
"protected_ips": ["10.66.0.10", "2001:db8:66::10"],
"allow_sources": ["10.0.0.0/8"],
"deny_sources": ["198.51.100.0/24"],
"syn_pps": 5000,
"udp_pps": 20000,
"icmp_pps": 2000,
"other_pps": 50000,
"burst_seconds": 2,
"sample_rate": 1000,
"xdp_mode": "auto"
}
protect_all=true is available only for a genuinely dedicated interface. The
userspace policy validator otherwise requires at least one protected IP.
Policy entries are keyed by a monotonically rotating generation. Userspace populates the new generation first, then publishes the single config-map value last. Old known policy entries are removed only after publication, so readers never see a half-updated allow/deny generation.
Per-source SYN, UDP, ICMP and catch-all classes use token buckets. Their state
lives in a bounded regular HASH map because BPF spin locks are supported there.
If the source-state map is exhausted, enforce mode fails closed for protected
traffic and reports bucket-exhausted; audit mode reports the event but passes.
TCP Intelligence
fluxvm-tcpintel attaches two passive SCHED_CLS programs to the same VM edge:
- ingress: guest -> remote;
- egress: remote -> guest.
TCX/BPF-link multiprogram attachment is preferred on Linux 6.6+. On older
kernels the helper falls back to a dedicated classic-TC handle/priority. The
observer always returns TC_ACT_OK and never makes policy decisions.
It records:
- guest- and remote-initiated SYNs;
- SYN retransmission signals;
- SYN -> opposite-direction SYN/ACK response latency;
- repeated payload sequence ranges in both directions;
- packet-observed data -> ACK RTT samples in both directions;
- FIN/RST counts;
- bounded LRU flow state and latency histograms;
- sampled JSONL ring-buffer events.
The RTT/retransmit values are deliberately exposed as packet-level estimates.
They are not claimed to be the guest kernel's TCP srtt, RTO, congestion-window
or authoritative retransmission counters. Sequence wrap, SACK and offload can
make a passive estimate differ from the guest stack's internal accounting.
Commands
fluxvm-shield apply <vm-uuid> <iface> --policy shield.json
fluxvm-shield status <vm-uuid>
fluxvm-shield events <vm-uuid> 5 128
fluxvm-shield metrics <vm-uuid>
fluxvm-shield remove <vm-uuid>
fluxvm-tcpintel attach <vm-uuid> <iface> 100
fluxvm-tcpintel snapshot <vm-uuid> 128
fluxvm-tcpintel events <vm-uuid> 5 128
fluxvm-tcpintel metrics <vm-uuid>
fluxvm-tcpintel detach <vm-uuid>
fluxvm-netintel snapshot <vm-uuid>
fluxvm-netintel metrics
fluxvm-netintel serve 127.0.0.1:7792
The local API exposes:
GET /healthzGET /v1/netintel/vms/{uuid}GET /metrics
No XDP or TCP observer is automatically attached by the service.