Transport selection#
Transport::Unspec selects an eligible payload transport before admission.
EngineConfig::selector optionally applies ordered first-match policies to every
request, including explicit memory and file transport hints. Sync and async submissions use
the same selection in TransferEngine::prepare; the selected transport stays
fixed through queueing, execution and drain.
Configuration#
use orbite::{EngineConfig, TransportSelectorConfig};
let selector = TransportSelectorConfig::from_json(
r#"{
"policy": [
{"name": "small_host", "segment_type": "memory",
"local_memory": "cpu", "remote_memory": "cpu",
"max_size": 4096, "priority": "high", "transports": ["tcp"]},
{"name": "bulk", "segment_type": "memory",
"transports": ["nvlink", "rdma", "tcp"]}
]
}"#,
)?;
let config = {
let mut config = EngineConfig::default();
config.selector = Some(selector);
config
};
# Ok::<(), orbite::Error>(())
Pass Transport::Unspec to the request constructor to use candidate order.
use orbite::{IntentType, TransferRequest, Transport};
let request = TransferRequest::new(
Transport::Unspec,
local.base_address(),
remote.base_address(),
length,
).with_intent(IntentType::ForegroundGet);
// Bind to one known policy even when another rule would match first.
let named = request.with_policy_name("small_host")?;
An explicit transport must appear in the matching policy’s candidate list and
be eligible. A rejected or unavailable hint fails the request. With
selector: None, explicit routing keeps its existing behavior and Unspec
tries the configured MNNVL or NVLink profile, RDMA, SHM, then the configured socket transport for memory targets.
A file target tries eligible GDS, then io_uring.
An unnamed request uses the first matching rule. Within that rule, Unspec
skips ineligible candidates. An exhausted rule fails before admission. An
empty candidate list uses the segment default. A named request matches the
exact name and segment type, bypassing intent, size, priority, placement and
memory filters. Its transport still has to be authorized and eligible. Unknown
names, wrong segment types and unavailable hints fail before payload I/O or task
publication. Error::TransportPolicy carries the bound rule and reason.
When no custom rules exist the default names are memory_default and file_storage.
Policy field |
Consumed behavior |
|---|---|
|
Unique label of 1–256 UTF-8 bytes. The builder retains a bounded shared name. Preparation resolves the compiled rule index once |
|
|
|
|
|
Boolean. A memory peer is local only when both descriptors identify the same host boot. An absent identity gives no locality |
|
Inclusive byte bounds |
|
Exact effective QoS or request priority. Accepts high/medium/low or 0/1/2 |
|
Case-insensitive |
|
Ordered unique candidates. Memory accepts |
|
RDMA NIC names compiled to a 64-bit mask using stable discovered IDs and the custom topology’s verified mapping |
|
Selects a contiguous endpoint QP range. An omitted, empty or unknown name permits every index |
|
Policy values are diagnostic. Only the endpoint pool changes native SL/TC |
transports.force_tcp restricts memory requests to TCP. File selection keeps
its own rules. Automatic selection uses the compiled rules when present, otherwise the default owner order.
Explicit name binding remains strict. JSON input is bounded to 1 MiB and 256
policies. Unknown fields and invalid intent reject the configuration; frozen
TENT skips a rule with an invalid intent.
The removed fabric candidate and configuration key are rejected as unknown.
CUDA fabric-backed MNNVL remains a separate supported owner.
RDMA device and QP selection#
For example, these settings allow checkpoint writes on one NIC and the second segment of the endpoint’s QP array.
{
"transports": {"rdma": {"endpoint": {"qp_pools": [
{"name": "interactive", "num_qp": 2},
{"name": "bulk", "num_qp": 1, "service_level": 3, "traffic_class": 40}
]}}},
"policy": [{"name": "save", "segment_type": "memory", "intent_type": "checkpoint",
"devices": ["mlx5_1"], "qp_pool": "bulk", "transports": ["rdma"]}]
}
An unresolved or out-of-width NIC increments EngineStats::unresolved_policy_devices
when a topology is available. Partial resolution warns and keeps the resolved
subset. If none resolve, an error log identifies the names and the filter allows
all NICs. Without a topology the mask also allows all NICs. Both single grants
and multirail slice plans intersect this mask with the engine’s device mask,
location restrictions, healthy contexts and compatible peer paths. A mask never
overrides any of those checks.
Named pools have unique names and partition the data QPs in configuration order. Counts are positive
and their sum fits the endpoint limit of 64. With empty pools the flat width is
qp_mul_factor, defaulting to RdmaConfig::num_lanes. With pools the sum sets
the endpoint width independently of the worker/CQ lane count. Each selected
index inherits its pool’s SL (0–15) and TC (0–255), or the RDMA defaults when omitted or set to the TENT sentinel -1.
The requester folds its least-loaded worker’s index into the selected range.
The QP uses the CQ at that index modulo the lane count.
Unbound traffic can use a named pool’s QP and inherit its settings too. Both
ends use the selected index for fresh connections and cache reuse.
The selector runs on each original public range before merging. Two adjacent requests can fold only if their resolved results agree. A merged length cannot reroute them through a size rule or a different pool. See physical owners.
Owner-based eligibility#
open_segment receives source-owned memory type and IPC export consent, plus
configured segment capabilities. These are immutable descriptor snapshots,
not grants or health guarantees. Refresh explicitly after registration changes.
Every execution still checks epoch, permission, retained owner and provider
readiness. Closing or failing a provider does not authorize replay elsewhere.
Transport |
Required eligibility |
|---|---|
TCP |
Both ends’ normal TCP handlers; CUDA endpoints use their existing local host staging. A CPU-only requester can READ and WRITE a peer CUDA range. Only the peer needs a device runtime for its staged copy |
HP-TCP |
HP-TCP enabled at both ends, matching IPv4 rail counts, and an eligible host registration. The request must fit both endpoint frame limits |
SHM |
SHM enabled at both ends, matching host boot identity and backing namespace, local host memory and a source-published shared range |
RDMA |
Both engines configure RDMA. Each side’s existing host/CUDA Direct or Staged policy remains authoritative; this capability does not promise GPUDirect or current RNIC health |
MNNVL |
Matching handle kinds and fabric domains, a source-owned VMM export and a CUDA-capable local registration. POSIX fd also requires matching host boot identity. Both peers enable EGM for a remote host allocation |
NVLink |
Both engines opt in; equal host boot identity and different process nonces; remote |
Priority selects matching rules but does not make a transport ineligible. When the matching rule permits it, a Low prefetch can use TCP when RDMA is unavailable, or NVLink when both endpoints qualify for IPC. TCP and NVLink treat priority as advisory. RDMA workers use it to dispatch ready payloads.
remote_staging: true requires a remote CUDA range and
source Pin capability, and restricts selection to TCP/RDMA. It does not silently
turn an ordinary transfer into Pin/Delegate/Unpin. Policy memory filters always
inspect the original registered ranges, including when staging is selected.
CUDA IPC capability is captured from allocation construction. Describe and selection do not take payload locks, wait for producers, create exports or query CUDA. Same-host placement never follows from an IP address or equal CUDA ordinal. Process identity reuses the existing IPC handshake owner.
Correspondence with TENT#
The reference is frozen TENT commit
e1ea5d31bb5e46ff2df9f90e7c2fbaf52fcdee8c, specifically
runtime/transport_selector.h and runtime/transport_selector.cpp.
TENT owner/behavior |
OrbiTE implementation |
|---|---|
Ordered and named policies, request intent |
|
|
Original memory types and both segment descriptors, including boot identity and IPC consent |
|
One prepared route carried into TCP, HP-TCP, SHM, RDMA, NVLink, local file I/O and the TCP/RDMA CROSS leg |
|
One resolution per engine topology. Each prepared request retains its own mask and QP range through every child grant |
Endpoint |
Contiguous index segments and pool SL/TC on the physical RC QP. An individual grant retains its connection, range and native owner |
|
Physical merging compares the complete preselected route, including its policy, intent, mask and QP pool, along with hint, priority, QoS and registration authority. A larger physical span keeps its members’ selected route |
TENT’s automatic memory order follows the buffer’s registered transport list.
OrbiTE registrations advertise capabilities without an insertion order, so
automatic memory selection tries MNNVL, NVLink, RDMA, SHM, then the configured socket payload (TCP or HP-TCP). A policy can reverse
that order. TENT documents GDS → io_uring → RDMA for files. Its frozen
getDefaultPolicies lists GDS and io_uring. OrbiTE supports these two local
owners. RDMA-to-file needs a remote file segment. SHM merges respect the physical registration and segment transfer limits. Overlapping allocation offsets retain their public order. The smaller HP-TCP endpoint frame limit caps merging. The selected rule retains its bounded candidate order. Only the engine’s
physical retry owner advances that index. A rejected initial hint still fails
selection. An eligible hint moves to the front of the rule and its later
candidates can run only after a safe failure. Caller-supplied fallback indices,
local recompute and compression remain unsupported. See
transport attempts.
The selector scans at most 256 compiled rules and seven candidates, once per public request. The compiled rule scan allocates no strings, takes no selector lock and calls no driver; no selector work is added per slice, WR or CQ completion. Existing registration resolution, admission and transport owners keep their own costs. This is an implementation property, not a measured throughput comparison.
Protocol and qualification#
Describe replies carry a four-byte region count, 44 bytes of segment capabilities, then 32 bytes per region. Bits 0–2 of capability byte zero identify RDMA, remote staging and NVLink. Bit 3 denotes a boot-only identity when NVLink is disabled. Bit 4 disables ordinary TCP payloads and bit 5 announces the SHM trailer. Bit 6 announces MNNVL fabric capabilities. Bytes 4–19 hold the boot identity when known and 20–35 hold the process nonce only for NVLink. Bytes 36–43 give the maximum accepted transfer length as a big-endian unsigned integer. An unknown limit prevents folding two requests. Bytes 1–3 are reserved and must be zero. Region bytes 25–27 carry memory type, IPC export consent and registration flags (HP-TCP plus observed CUDA RDMA routes; see Describe layout). The Describe layout gives the trailer order and SHM fields.
The RDMA path reply carries the advertised endpoint width. The rendezvous hello carries the agreed reusable width and an optional pool index on both cached and transient QPs. Deploy the same build and endpoint layout on both peers. The header cannot detect a mismatch in pool definitions. See the wire policy.
CPU controls check TCP sync/async payloads, the RDMA verbs table’s per-NIC bytes and connection SL/TC, NVLink group boundaries, staging CROSS and local files. Physical NIC selection and link-layer QoS await the installed gate. See qualification.