Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Face transports

Catalogue of face transports shipped in ndn-rs, each row pointing at the implementation crate, the [[face]] kind value, and the typical use. For the Face = Transport + LinkService shape see Extend tier → Face; for writing a new transport see Implementing a face.

Catalogue

KindCrate[[face]] kindTypical use
UDPcrates/ndn-face/src/net/udp.rsudpNDN-over-UDP across hosts.
TCPcrates/ndn-face/src/net/tcp.rstcpNDN-over-TCP across hosts (firewall-friendlier).
Multicast UDPcrates/ndn-face/src/net/multicast.rsmulticastLink-local neighbour discovery (group 224.0.23.170); auto-created per interface via [face_system.udp] auto_multicast.
Unix socketcrates/ndn-face/src/local/unix.rsunixApp-to-forwarder IPC.
In-processcrates/ndn-face/src/local/in_proc.rs(programmatic)Embedded engine, tests.
Shared memorycrates/ndn-face-shm/src/spsc.rsshmHigh-throughput per-host IPC (feature spsc-shm).
Ethernet unicastcrates/ndn-face/src/l2/ether.rsether (TOML) or faces/create ether://[<mac>]/<iface>Point-to-point link to a known peer MAC. EtherType 0x8624; requires CAP_NET_RAW/root.
Ethernet multicastcrates/ndn-face/src/l2/multicast_ether.rsether-multicastGroup 01:00:5e:00:17:aa; auto-created per interface via [face_system.ether] auto_multicast (Linux).
802.11 monitor-modecrates/ndn-face-monitor-wifi/wfbConnectionless raw 802.11 injection (named-radio): MonitorWifiFace over a FrameIo backend (ndn-frame-io).
Bluetooth LE — centralcrates/ndn-face-bluetooth/src/central/ble://<name-or-addr> (via faces/create)Dial a peripheral as GATT client (Linux/macOS/Windows).
Bluetooth LE — peripheralcrates/ndn-face-bluetooth/src/lib.rs[listeners.ble]GATT server; advertises the NDN service (Linux/macOS).
Serial (UART)crates/ndn-face-serial/src/lib.rsserialEmbedded / microcontroller.
WebSocketcrates/ndn-face-websocket/wsBrowser-to-forwarder over WebSocket.
WebTransportcrates/ndn-face-webtransport/; wasm: crates/ndn-face-webtransport-wasm/[listeners.webtransport]; dial via [[face]] kind = "web-transport" or faces/create wts://…Browser↔forwarder and forwarder↔forwarder (NAT-traversing) over QUIC datagrams; oversized packets are NDNLPv2-fragmented to maxDatagramSize (interoperates with NDNts H3Transport).
QUICcrates/ndn-face-quic/[listeners.quic]; dial via [[face]] kind = "quic" or faces/create quic://…Forwarder-to-forwarder backbone over raw QUIC (TLS 1.3, connection migration, 0-RTT); one reliable bidi stream of NDN TLV. No HTTP/3 layer (does not reach browsers).
WebRTC datachannelcrates/ndn-face-webrtc/webrtcBrowser ↔ browser, browser ↔ relay.
SharedWorkercrates/ndn-face-shared-worker/(programmatic)Per-origin engine sharing across tabs.
Callback / Tapcrates/ndn-face/src/callback.rs(Instrument tier)Researcher: virtual face whose send-path is a closure.
BoltFFIcrates/ndn-boltffi/(programmatic)FFI bridge for non-Rust hosts.

Configuration shape

UDP unicast face listener:

[[face]]
kind = "udp"
bind = "0.0.0.0:6363"
# remote = "10.0.0.1:6363"  # optional: point-to-point only

TLS faces — WebTransport (browser↔forwarder and NAT-traversing forwarder↔forwarder over QUIC datagrams) and QUIC (native router-to-router backbone, TLS 1.3 with connection migration) — share one listener cert_source shape (self_signed_dev / pem / acme, resolved by ndn-acme) and one dialer trust policy (cert_sha256 leaf-pin or webpki):

[listeners.webtransport]    # or [listeners.quic]
enabled = true
listen = "0.0.0.0:4443"
cert_source = { type = "self_signed_dev", hostnames = ["localhost"] }

[[face]]                     # outbound dial
kind = "web-transport"       # or "quic"
remote = "wts://peer.example:4443"
cert_sha256 = "ab12…64hex"   # pin the peer's logged leaf hash; or webpki = true

A self-signed WebTransport cert is capped at 13 days (Chrome’s serverCertificateHashes limit); a self-signed QUIC cert is long-lived (a pinned dialer trusts the leaf hash, not the expiry). Listener cert status (notAfter, renewal state) is readable via /localhost/nfd/webtransport/cert-status. The WebTransport face interoperates with ndnd’s HTTP/3 face (witness testbed/tests/audit/wt02_ndnd_interop.sh); QUIC does not reach browsers — that is WebTransport’s role.

A shared-memory face (kind = "shm", path, capacity_mb) gives per-host IPC. The full per-kind option set is in examples/ndn-fwd.example.toml.

Ethernet faces (EtherType 0x8624, CAP_NET_RAW/root) come in three forms — a unicast link to a known peer MAC, a multicast group face, and per-interface auto-creation:

[[face]]                       # unicast point-to-point
kind = "ether"
interface = "eth0"
peer-mac = "aa:bb:cc:dd:ee:ff"

[[face]]                       # multicast group face (Linux)
kind = "ether-multicast"
interface = "eth0"

[face_system.ether]            # auto-create a multicast face per matching NIC
auto_multicast = true          # + add/remove on hotplug with watch_interfaces

A unicast Ethernet face can also be created at runtime: nfdc face create ether://[aa:bb:cc:dd:ee:ff]/eth0. The peer MAC is explicit — neighbour discovery is a separate path. As with every wire face, NDNLPv2 framing and fragmentation are owned by the paired LpLinkService: the face is payload-only and reports a 1500-byte send-MTU, so the link service fragments once at the Ethernet boundary (it does not re-frame at the transport).

Bluetooth LE

BLE has two roles, modelled as distinct faces (central and peripheral are distinct GATT roles, not a flag): a central dials a peripheral as GATT client, a peripheral runs the GATT server. Both use the NDNts web-bluetooth-transport GATT profile, so they interoperate with browser Web Bluetooth and esp8266ndn. Requires ndn-fwd --features bluetooth. The wire rules — UUIDs, the NDNLPv2-vs-NDNts framing split, and its automatic disambiguation — are normative in NDN over BLE — GATT profile.

A central is an outgoing face created at runtime via faces/create with a ble:// URI (ble://ndn-rs-esp32c3, ble://AA:BB:CC:DD:EE:FF); ?framing= and ?adapter= ride the query string, other per-face knobs go through the faces module. A peripheral is a listener ([listeners.ble]enabled = true) whose accept loop yields one face per connected central. Because the peripheral carries controller state it gets a small management module /localhost/nfd/ble/<verb>: list (status: advertising, adapter, central count), start and stop (toggle advertising at runtime). The module returns 404 without --features bluetooth.

Programmatic faces (not in ndn-fwd.toml)

Some faces are constructed by application code rather than by listener config:

  • InProcFace — created in the same process, paired between two engines. The pattern is in Develop tier → embedded engine.
  • CallbackFace / TapFace — Instrument tier. See Instrument tier.
  • SharedWorker face — crates/ndn-face-shared-worker/. Mounted via the dashboard’s browser-engine profile.

Connectionless named-radio faces — extension

These are ndn-rs extensions with no NDN community-spec basis; the wire is ordinary NDNLPv2 over the radio’s native broadcast primitive.

A node — especially a phone — can carry NDN over connectionless broadcast radios with no AP, no pairing, and no host addresses (the NDN name is the only addressing). Each is link_type() == AdHoc with a small MTU, so the LpLinkService fragments NDN across the radio’s frames automatically.

FaceCrateRadio primitiveNotes
Wi-Fi Aware (NAN)crates/ndn-face-wifi-aware/NAN follow-up messages (255 B)AP-less peer Wi-Fi; service pub/sub discovery; bulk over NDP (request_ndpUdpFace).
BLE advertisingcrates/ndn-face-ble-adv/BLE 5 extended advertisement (~245 B)Near-universal; pairless broadcast; presence + small Interest/Data (bulk wants a connection face).
802.11 monitorcrates/ndn-face-monitor-wifi/raw-injected 802.11 framesPer-frame MCS, no association/ARQ.

The physical radio sits behind a backend trait (NanBackend, AdvBackend) with a hardware-free Loopback*Bus for tests, so the face is exercised without hardware; a platform supplies the radio by implementing the trait (Android JNI, BlueZ, an MCU). These faces are not mutually exclusive — a node holds a set of them at once and a mesh strategy fans Interests over all (see the Face system section of ARCHITECTURE.md in the repo root). On mobile they’re attached at runtime via ndn-mobile (attach_wifi_aware / attach_ble) or the ndn-boltffi FFI seam (NdnNanBackend / NdnBleBackend + the engine’s *_deliver_* methods); nearby peers surface at the localhost dataset /localhost/discovery/peers.

Tap-to-share over these faces (extension). To send a file to a tapped peer, an app serves an offer board (NdnEngine/NdnClient::start_offer_board): a certificate at /ndn/node/<id>/cert (the TOFU pin target) and a signed manifest at /ndn/node/<id>/offers, both reached over the per-peer route with no hint. Each offered file (add_offer) is a signed RDR object under the offerer’s own identity, fetched by a peer with fetch_object_verified_hinted(name, "/ndn/node/<peerId>") — the ForwardingHint steers it to the peer, whose node strips the hint via its NetworkRegionTable (declared at discovery start) and serves it by name. See the Connectionless named-radio faces section of ARCHITECTURE.md for the full flow.

Wi-Fi Direct bulk upgrade — extension

The connectionless radios above are great for discovery and small control but are duty-cycled or small-MTU, so bulk transfer wants a real Wi-Fi link. The pattern (the same one Quick Share / AirDrop use) is discover over Wi-Fi Aware / BLE, then upgrade to Wi-Fi Direct for bulk. Crucially this stays data-centric: once a Wi-Fi P2P group forms it is just a multi-access IP subnet (the group owner runs DHCP on 192.168.49.0/24), so the host-centric group-owner election and DHCP live entirely below the Face. Above it there is no host — only FaceKind::WifiDirect faces carrying names:

UseFaceNotes
1:1 bulkUdpFace::with_kind(WifiDirect) (unicast)Full Wi-Fi MCS rate (5 GHz); LinkProfile cost 8 so cost-aware forwarding prefers it over NDP/LAN UDP (10), Wi-Fi Aware (20), BLE (50).
One-to-manyMulticastUdpFace::with_kind(WifiDirect)Join 224.0.23.170:56363 on the group interface; MulticastStrategy + PIT aggregation give one-Interest-to-many, one-Data-to-many — the “seed a file to the room” path. Wi-Fi multicast is basic-rate/un-ACKed, so it is for coordination + Interests (and FEC-coded bulk), not raw 1:1 throughput.

No new crate or Cargo feature — these are the existing UDP faces re-tagged to the real radio. On mobile they attach via ndn-mobile (attach_wifi_direct_face / attach_wifi_direct_multicast_face) or the ndn-boltffi FFI (attachWifiDirectFace / attachWifiDirectMulticastFace), mirroring the Wi-Fi Aware NDP bulk path (attach_ndp_face). The same shape maps to a Wi-Fi SoftAP “portable router” (one node provides the medium; peers join and multicast by name) and to Apple’s Wi-Fi Aware framework on iOS (the same NAN standard behind NanBackend).

The default LinkService is LpLinkService (NDNLPv2 framing); the high-throughput exceptions use PassthroughLinkServiceInProcFace always, and ShmFace by default (switch it to LpLinkService for cross-host wire compatibility). See crates/ndn-transport/src/link_service.rs for the trait.

Per-face NDNLPv2 local fields

IncomingFaceId and NextHopFaceId are NDNLPv2 local fields, gated per-face by the LocalFields flag (off by default). If IncomingFaceId always reads 0/absent, the face hasn’t enabled LocalFields — enable it first via faces/update (Flags+Mask bit 0 = LocalFields, 1 = LpReliability, 2 = CongestionMarking):

ndn-ctl faces update face-id 263 flags 0x1 mask 0x1   # LocalFields on

With it enabled: IncomingFaceId (0x032C) is attached to packets sent out that face — the face the packet arrived on (or the reserved Content-Store id 254 on a cache hit), readable from LpInfo (Consumer::fetch_with_meta); and NextHopFaceId (0x0330) is honoured on Interests arriving on it, pinning an Interest to an egress face past the FIB (Consumer::fetch_on). A face without LocalFields ignores NextHopFaceId, so an untrusted peer cannot steer forwarding. Local-scope only; the bundled routing protocol enables it on its own faces.

Compile-time gates

FeatureCarrier crateEffect
spsc-shmndn-face-shmEnable the shared-memory transport.
ether-linuxndn-faceLinux raw-Ethernet face.
ether-macosndn-facemacOS BPF face.
ether-windowsndn-faceWindows packet-driver face.
bluetoothndn-face-bluetoothBLE GATT central (ble://) + peripheral ([listeners.ble]).
serialndn-face-serialSerial face.
wasm32ndn-face (auto)WebTransport-wasm + WebRTC + SharedWorker.

See also