pub trait PlatformIvc {
// Required methods
fn channel_get(id: u32) -> *mut c_void;
fn frame_size(ch: *mut c_void) -> u32;
fn rx_get(ch: *mut c_void, len_out: *mut usize) -> *const u8;
fn rx_release(ch: *mut c_void);
fn tx_get(ch: *mut c_void, cap_out: *mut usize) -> *mut u8;
fn tx_commit(ch: *mut c_void, len: usize);
fn tx_abandon(ch: *mut c_void);
fn notify(ch: *mut c_void);
}Expand description
Inter-processor mailbox transport, modelled after NVIDIA Tegra IVC.
IVC (Inter-VM Communication on Tegra; in practice CCPLEX↔SPE on AGX Orin) is a header-prefixed lock-free SPSC ring in shared DRAM, paired with a hardware doorbell for wake. One channel is one peer — there is no discovery, naming, QoS, or fanout — which is why it’s a link transport (peer to TCP/UDP/Serial/RawEth inside zenoh-pico) rather than a new RMW backend.
Channel handles are opaque *mut c_void to match the shape zenoh-pico
passes across its FFI boundary. The driver crate (nvidia-ivc)
translates between this opaque handle and either NVIDIA’s FSP
tegra_ivc_* API (fsp feature) or a Unix-socket pair
(unix-mock feature, host dev + CI).
Zero-copy contract (Phase 11.3.A). NVIDIA’s FSP IVC API is fundamentally a “borrow ring slot, fill, commit / release” pattern. Both backends mirror that here so consumers don’t branch on backend:
Self::rx_getreturns a pointer into the channel’s RX slot (and writes the frame length to*len_out);Self::rx_releaseadvances the producer-visible cursor. Returns null +*len_out = 0if the ring is empty.Self::tx_getreturns a writable pointer to the next free TX slot (and writes the slot capacity to*cap_out);Self::tx_commitmakes the slot visible to the peer (and rings the per-frame doorbell on FSP — seenotifyfor batching).Self::tx_abandonfrees the slot without sending. Returns null +*cap_out = 0if the ring is full.
Single outstanding RX slot and single outstanding TX slot per
channel — borrow, finish, repeat. Multi-frame batching is the
caller’s job (loop tx_get / fill / tx_commit, then one
notify).
frame_size is the fixed per-channel frame size negotiated at
carveout setup (typical NVIDIA IVC: 64 bytes per frame, 16 frames
per channel). The link layer uses it to pick its reassembly buffer.
Required Methods§
Sourcefn channel_get(id: u32) -> *mut c_void
fn channel_get(id: u32) -> *mut c_void
Resolve a channel ID into an opaque handle. Returns null on
failure. The numeric ID matches the NVIDIA channel index
(channel 2 = aon_echo).
Sourcefn frame_size(ch: *mut c_void) -> u32
fn frame_size(ch: *mut c_void) -> u32
Fixed frame size negotiated for this channel, in bytes.
Sourcefn rx_get(ch: *mut c_void, len_out: *mut usize) -> *const u8
fn rx_get(ch: *mut c_void, len_out: *mut usize) -> *const u8
Borrow the next-available RX frame. Writes the frame length to
*len_out and returns a pointer into the ring. Returns null +
*len_out = 0 if no frame is available.
Sourcefn rx_release(ch: *mut c_void)
fn rx_release(ch: *mut c_void)
Release the most recently rx_get’d frame back to the
producer. Pair 1:1 with rx_get calls that returned non-null.
Sourcefn tx_get(ch: *mut c_void, cap_out: *mut usize) -> *mut u8
fn tx_get(ch: *mut c_void, cap_out: *mut usize) -> *mut u8
Borrow the next free TX slot. Writes the slot capacity to
*cap_out and returns a writable pointer. Returns null +
*cap_out = 0 if the ring is full.
Sourcefn tx_commit(ch: *mut c_void, len: usize)
fn tx_commit(ch: *mut c_void, len: usize)
Commit len bytes from the most recently tx_get’d slot.
Slot is then visible to the peer; per-frame doorbell may also
fire on FSP. Pair 1:1 with tx_get calls that returned
non-null.
Sourcefn tx_abandon(ch: *mut c_void)
fn tx_abandon(ch: *mut c_void)
Abandon the most recently tx_get’d slot without sending.
Pair 1:1 with tx_get calls that returned non-null.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.