AOS Hub / Docs

Network faults

Crucible places guest-emitted frames on deterministic routes between declared VM interfaces. Network faults act inside that modeled route, so delay, loss, queue state, forwarding decisions, and delivery evidence use virtual time and survive checkpoint/replay. No host bridge impairment, tc, or netem setup is required.

#Start with an unfaulted route

Before adding bindings, prove that both guests exchange traffic through a LinkDef. The production example crucible-qemu-live-world-network.rs does this and verifies both scheduler delivery and a guest acknowledgement.

A logical world link supplies baseline one-way latency, subtractive jitter, loss probability, and optional bandwidth. Its loss choices are keyed to the scenario seed and frame identity. It is enough for simple transport tests.

Add WorldFaultTopology when faults need a physical target more precise than the logical link. A direct segment topology declares two endpoint interfaces and a segment; admission can derive the corresponding directed paths. Declare explicit paths when traffic traverses queues, forwarders, media, tunnels, or multiple segments.

#Choose the physical target

Intended failurePrefer this target
One VM cannot transmit or receiveInterface
Cable, direct virtual link, or shared conduit failsSegment
Wireless/bus contention affects all participantsMedium
Switch, router, firewall, NAT, tunnel, or load balancer failsForwarder
Congestion, overflow, priority, or backpressureQueue
Only one end-to-end route changes or failsPath
Authentication, roaming, handoff, or reconnect changesAttachment
Scheduled satellite/disrupted connectivityContact plan/contact
One physical cause affects several objectsFault domain resolving to those typed targets

Selectors resolve before execution. They cannot discover a host interface or create a route dynamically. Stable object IDs become part of fault evidence, search identity, and replay validation.

#Choose the effect family

ExperimentEffect
Directional outage or partitionnetwork.availability
Timed down/training/recovery sequencenetwork.flap
Negotiated rate, duplex, lanes, or trainingnetwork.negotiated_mode
Added latency, jitter, rate, or error profilenetwork.profile_delta, network.propagation_delay, network.access_delay, network.jitter
Bandwidth and burst constraintsnetwork.service_curve, network.token_bucket
Queue capacity, discipline, class, and overflownetwork.queue_policy
Independent or correlated frame lossnetwork.frame_loss, network.burst_error_state
Duplicate, reorder, truncate, corrupt, or report detected frame errornetwork.duplicate, network.reorder, network.payload_transform, network.detected_frame_error
MTU or pause behaviornetwork.mtu, network.pause_backpressure
Multicast/broadcast membership filteringnetwork.recipient_subset
Forwarder restart, wrong port, flood, blackhole, loop, or route convergencenetwork.forwarder_lifecycle, network.forwarding_mutation, network.route_transition
Firewall or state-table behaviornetwork.firewall_disposition, network.connection_state, network.control_plane_service
Shared bus/radio contentionnetwork.shared_medium
RF attenuation/interference and associationnetwork.rf_channel, network.association
Technology control-operation result mutationnetwork.control_result_transform
Satellite/disrupted contact and custodynetwork.contact, network.custody_queue

Use the effect registry for exact target kinds, phases, lifetimes, operations, and parameter definitions.

#Complete network effect contract

Every network effect uses semantic version 1. In the matrix, all means all eight network target kinds listed above. The narrower target sets are spelled out. Capability names are negotiated with the production adapter before guest execution.

EffectTargets; phases; lifetimes; compositionCapabilityComplete top-level parameters
network.availabilityall; admit, resolve; persistent; outage_ornetwork.availability.v1state, queued_policy, in_flight_policy
network.flapall; boundary; state_machine; state_machinenetwork.flap.v1positive down_nanos, training_nanos, recovery_nanos
network.negotiated_modeall; boundary; state_machine; compositenetwork.negotiation.v1positive rate_bps, duplex, positive bounded lanes, fec, positive training_nanos
network.profile_deltaall; resolve; persistent; compositenetwork.profile.v1optional signed latency_nanos, positive rate_cap_bps, loss_hazard, corruption_hazard, technology_metrics
network.propagation_delayall; resolve; persistent or opportunity; checked_sumnetwork.propagation.v1exactly one of positive delay_nanos and distance_velocity_lookup
network.access_delayall; resolve; opportunity; checked_sumnetwork.access-delay.v1positive delay_nanos, typed cause ID
network.jitterall; resolve; opportunity; checked_sumnetwork.jitter.v1positive maximum_nanos, integer distribution, required lookup for non-uniform distributions
network.service_curveall; queue; persistent; minimumnetwork.service-curve.v1ordered non-overlapping positive-rate segments
network.token_bucketall; queue; persistent or state_machine; minimumnetwork.token-bucket.v1positive rate_bps, positive burst_bits, initial_bits <= burst_bits
network.queue_policyall; admit, queue; persistent or state_machine; conflictnetwork.queue.v1positive byte/frame capacity, discipline, optional discipline parameters, overflow, typed error only when required
network.frame_lossall; resolve, deliver; opportunity; independent_hazardsnetwork.frame-loss.v1exactly one of probability and explicit outcome
network.burst_error_stateall; resolve; state_machine; conflictnetwork.burst-errors.v1good-to-bad and bad-to-good probabilities, registered per-state parameter table
network.duplicateall; deliver; opportunity; checked_sumnetwork.duplicate.v1probability, bounded additional copies, gap_nanos
network.reorderall; deliver; opportunity; compositenetwork.reorder.v1positive window_nanos, deterministic selection
network.payload_transformall; resolve; opportunity; ordered_transformnetwork.payload-transform.v1typed mutation including its selector
network.detected_frame_errorall; resolve; opportunity; severitynetwork.detected-error.v1error kind, receiver action; retry-only delay/limit/attempt/success fields; reset duration only for link reset
network.mtuall; admit; persistent; compositenetwork.mtu.v1positive mtu_bytes, oversize disposition; protocol only for fragment; result artifact only for typed error
network.pause_backpressureall; queue; persistent or state_machine; state_machinenetwork.backpressure.v1traffic class, optional positive pause duration (absent means until deactivation)
network.recipient_subsetall; deliver; opportunity; ordered_transformnetwork.recipient-subset.v1membership version; exactly one of explicit dropped members or keyed selection; retain count with selection
network.forwarder_lifecycleall; boundary; impulse or state_machine; severitynetwork.forwarder-lifecycle.v1transition, positive downtime, queue and table retention policies
network.forwarding_mutationall; resolve; persistent or impulse; ordered_transformnetwork.forwarding-mutation.v1typed lookup selector, mutation
network.route_transitionall; boundary, resolve; state_machine; state_machinenetwork.route-transition.v1old/new route IDs, convergence-event sequence, in-flight policy
network.control_plane_serviceforwarder/path/attachment/contact; boundary; persistent or state_machine; minimumnetwork.control-plane.v1service curve, positive queue bound, overflow policy, positive work bits per event
network.firewall_dispositionall; admit; opportunity or state_machine; severitynetwork.firewall.v1action, rejection only when required, rule, state machine, exhaustive transition event
network.connection_stateall; resolve; state_machine; state_machinenetwork.connection-state.v1function kind, positive table bound, flow key, state machine, transition event, overflow behavior
network.shared_mediummedium only; admit, queue, resolve; persistent or state_machine; conflictnetwork.shared-medium.v1complete resource set, policy artifact, positive transmit power
network.rf_channelall; resolve; persistent or opportunity; compositenetwork.rf-channel.v1positive carrier/bandwidth, transmit/noise power, propagation-field bundle, SINR transfer
network.associationattachment only; boundary; state_machine; conflictnetwork.association.v1complete association policy artifact
network.control_result_transformforwarder/path/attachment/contact; resolve; opportunity; ordered_transformnetwork.control-result-transform.v1technology, nonempty operations, transform kind, result artifact only for bias/replace/error
network.contactall; boundary, resolve; state_machine; outage_ornetwork.contact.v1interval artifact, range-delay lookup, beam set, gateway set
network.custody_queueall; queue; persistent or state_machine; conflictnetwork.custody.v1positive byte/bundle capacity and expiry, custody policy, route/contact plan, priority, positive hop bound

#Closed network parameter choices

  • Availability state is up, down, receive_only, or transmit_only. Queued/in-flight policy is preserve, reevaluate, drop, or typed_error.
  • Duplex is half or full. FEC is none, reed_solomon, ldpc, or convolutional.
  • Integer distributions are uniform, normal_lookup, or exponential_lookup; lookup forms require their registered table and non-uniform forms cannot depend on host floating point.
  • Queue discipline is FIFO, strict priority, weighted round robin, deficit round robin, or RED. Overflow is tail drop, head drop, keyed drop, or a registered typed error; required class/weight parameters live in the referenced policy object.
  • Payload mutations are bit flip, typed field mutation, truncation, or undetected corruption. Detected errors distinguish CRC, FCS, framing, and FEC and select corrected, retry, drop, or link-reset behavior.
  • MTU oversize behavior is drop, fragment, or typed error. Fragmentation names its parser/encoder protocol; arbitrary byte splitting is not admitted.
  • Forwarding mutation is wrong port, flood, blackhole, loop, or stale-age behavior. Firewall action is accept, reject, or drop. Connection state is scoped to NAT, conntrack, load-balancer, tunnel, or DNS behavior.
  • Control-result transforms are drop, stale, bias, replace, or typed error. Every referenced policy/table is a declared, content-addressed topology artifact and is included in the replay closure.

The complete nested network value vocabulary is:

Type/fieldAccepted variants and variant fields
availability stateup, down, receive_only, transmit_only
queued/in-flight policypreserve, reevaluate, drop, typed_error
bundle prioritybulk, normal, expedited, critical (highest)
duplex / FECduplex half, full; FEC none, reed_solomon, ldpc, convolutional
jitter distributionuniform, normal_lookup, exponential_lookup; lookup variants require distribution_lookup
service segmentat_nanos, positive rate_bps; first starts at zero and coordinates strictly increase
queue disciplinefifo, strict_priority, weighted_round_robin, deficit_round_robin, red
queue overflowtail_drop, head_drop, keyed_drop, typed_error; only typed error carries the adjacent response artifact
selectionkeyed_uniform, oldest, newest, canonical_order
explicit loss outcomepreserve, drop
payload mutationbit_flip { offset_bytes, length_bytes, mask }, field_mutation { field, replacement }, truncate { length_bytes }, undetected_corruption { transform }
detected errorkind crc, fcs, framing, fec_uncorrectable; action corrected, retry, drop, link_reset with the action-specific top-level fields in the matrix
MTU dispositiondrop, fragment, typed_error; the only fragmentation protocol is ethernet_ipv4
forwarder transition/statetransition restart, reset, power_loss; queue/table policy preserve, clear, drain
forwarding mutationwrong_port { recipient }, flood { recipients }, blackhole, loop { next_hop, hop_limit }, stale_age { age_nanos, expiration_nanos, expired }
stale-entry dispositionpreserve, blackhole, flood { recipients }
firewall actionaccept, reject, drop; rejection alone requires typed_reject
connection kindnat, conntrack, load_balancer, tunnel, dns
connection overflowdrop_newest, evict_oldest, keyed_eviction, typed_error { response }
control-result kinddrop, stale, bias, replace, error; bias/replace/error require the typed result artifact

All object IDs in this table resolve to the declared World topology. Object-ID fields never name host files or callbacks.

#Required replay evidence

The descriptor for every row also names mandatory evidence. Depending on the effect this includes old/new state, frame and draw identities, queue/service ledgers, contributor lists, before/after digests, retry state, route and convergence state, firewall/connection transitions, RF geometry and resolved profile, or contact/custody transitions. A backend capability acknowledgment without this evidence does not satisfy locked replay.

#Persistent outage versus one-frame loss

A partition normally uses:

Boolean step/pulse
  -> sample at boundary
  -> active_when_true
  -> exact segment/path/interface selector
  -> persistent network.availability

The effect declares direction and what happens to queued and in-flight frames. When the Boolean becomes false, the contribution is removed at a recorded boundary. There is no out-of-band “heal” command.

A one-frame loss instead uses an operation-domain or stochastic signal sampled at the frame opportunity, an impulse mapping, and network.frame_loss at the registry-approved phase. Do not model a partition as repeated probabilistic loss: that changes its causal identity, search space, and queue semantics.

#Direction and state treatment

Every outage or transition should answer three questions:

  1. Is the object down in both directions, transmit-only, or receive-only?
  2. What happens to frames already queued?
  3. What happens to frames already in flight?

The corresponding effect carries those policies. Defaults that silently depend on when the host happened to process a frame would break replay, so Crucible requires the treatment to be modeled.

Forwarder lifecycle and route transition effects similarly declare table, queue, and in-flight retention. Queue effects declare byte/frame limits, discipline, and overflow behavior. All mutable adapter state is included in an exact checkpoint.

#Shared causes and composition

Reuse one signal output when a rack, provider, power event, or environmental trace affects multiple network objects. Bind that output separately to each target or use an admitted fault-domain selector. At each opportunity the network adapter composes all active contributors using the effect family's closed rules and records both the contributors and final result.

The shared-cause production example powers down a forwarder while the same event crashes a VM and loses volatile storage cache: crucible-qemu-signal-shared-cause.rs.

#What to assert

Network adapter evidence proves that a frame was admitted, queued, transformed, dropped, or delivered to the QEMU input boundary. It does not by itself prove that an application accepted the data.

For end-to-end tests, combine:

  • transport/topology properties for modeled network behavior;
  • a guest marker or stable console assertion for application behavior;
  • a bounded recovery or failure deadline; and
  • canonical event-log retention on failure.

This distinction remains valid for encrypted protocols: the network adapter can prove delivery while the guest reports semantic success.

#Explore and reproduce

Baseline link loss, stochastic sources, and search-enabled bindings expose stable choices. Use search with depth/state bounds to find a counterfactual, then replay the emitted artifact through the ordinary production backend. Exact checkpoints retain frames, queues, forwarder state, route state, signal state, and keyed-choice history.

When a replay diverges, inspect evidence in this order: signal sample, selector resolution, route/opportunity identity, composed effect, frame decision, backend injection, guest assertion, and terminal fingerprint. See Reproduction and branching and Troubleshooting.