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

The layer map

This is the orientation page: where everything lives, which way the arrows point, and where to start reading. If you have just cloned the workspace and want the shape of the thing before you dive into any one crate, read this first, then follow the links out to the deeper pages.

ndn-rs is a Cargo workspace of ~30 library crates. They are grouped on disk into seven directories under crates/, and they form a single directed acyclic graph in which dependencies only ever point toward the foundation. The crate graph page renders that graph visually; this page gives you the map in words and tables.

The seven directories

The crates/ tree groups crates by role, not by dependency layer — the two are related but not identical (a crate’s directory is where it lives; its layer is who may depend on it).

DirectoryRepresentative cratesResponsibility
crates/corendn-tlv, ndn-foundation-types, ndn-packet, ndn-crypto-core, ndn-signals-core, ndn-runtime, ndn-transport, ndn-storage, ndn-mgmt-wire, ndn-frame-io, ndn-ble-framingThe wire codec, packet and name/hash types, the no-alloc crypto core, the cross-layer signal taxonomy, the clock/runtime seam, the face/transport abstraction, and the storage-backend traits.
crates/forwardingndn-store, ndn-fwd-core, ndn-strategy, ndn-discovery-core, ndn-engine, ndn-ipc, ndn-mgmt, ndn-pathcontrolThe three forwarding tables, the sans-IO forwarding rules, the strategy framework, and ndn-engine — the crate that assembles the whole forwarding plane.
crates/facesndn-face, ndn-face-localConcrete faces: OS-socket transports (ndn-face) and the in-process channel face (ndn-face-local), split out so wasm consumers get the channel face without OS sockets.
crates/securityndn-security, ndn-cert, ndn-identityData-centric verification and signing (ndn-security), NDNCERT issuance (ndn-cert), and identity lifecycle / renewal (ndn-identity).
crates/appndn-app, ndn-rs-preludeThe developer-facing Node API and a prelude that re-exports the common surface.
crates/platformndn-config, ndn-observabilityForwarder configuration and NDN-native span publishing.
crates/protocolsndn-syncDataset synchronisation (SVS and PSync).

The face/transport abstraction (the Transport, LinkService, and Face types) lives in crates/core/ndn-transport; the concrete faces that implement it live in crates/faces. If you are writing a new face, start at Implementing a face.

The dependency layering

Logically the graph is four layers deep, and dependencies flow one way:

graph LR
    App[App and platform] --> Sec[Security]
    App --> Fwd[Forwarding and faces]
    Sec --> Found[Foundation]
    Fwd --> Found
    App --> Found

Arrows read as depends on. Nothing in the foundation reaches back up into forwarding, security, or app code — the foundation is the widest, most-depended-on layer and knows nothing of the layers above it. This is what lets the foundation crates compile for constrained targets that the upper layers never touch (see below).

The DAG is enforced, not merely observed

The layering is a checked invariant. Each crate declares a scope in its manifest:

[package.metadata.scope]
classification = "spec"

The spec set is the pure library we ship as ndn-rs. The rule the CI guard enforces is that the spec set is closed under dependency: a spec crate may only depend, at runtime, on other spec crates. Extension, research, and tooling crates are downstream consumers and may depend on anything. The guard lives at testbed/dep-direction-guard.py and runs on every PR; the moment a spec crate grows an edge into an unclassified or extension crate, the build fails with the offending crate -> dep pair named.

Classification is orthogonal to directory. Most crates are spec, but a few that live alongside them are deliberately extensionndn-storage (the pluggable KV backends), ndn-config, and ndn-pathcontrol — because they are downstream of, not part of, the closed library core. Do not assume a crate’s directory tells you its classification; the manifest does.

The four peer targets

The same code compiles for several very different machines. CI proves this on every PR by building the relevant crate subsets for each target:

TargetToolchain tripleWhat it isVerified in CI
Nativehost (Linux x86-64; macOS in nightly)the full stack: engine, faces, security, apptest, lint, docs jobs
Browserwasm32-unknown-unknownthe forwarding chain up to and including the engine, running in a browser tabwasm32 job
Bare metalriscv32imc-unknown-none-elfthe no_std seed chain on a microcontroller with no OS and no allocator-of-convenienceno_std job

“Native” itself spans more than one machine — the nightly matrix adds macOS for the ndrv/kqueue face paths — but the load-bearing claim is that the foundation and forwarding rules are written once and pass on all three architectures. How that is achieved (sans-IO seed crates, no_std+alloc wire types, portable-atomic for MCUs) is the subject of sans-IO and no_std, and the reasoning is recorded in ADR 0003. The browser build works because the time/spawn seam swaps a web-time clock in for Tokio; see the determinism seam and ADR 0004.

Where a contributor’s API starts

Application authors do not touch most of this graph. The developer-facing entry point is Node in crates/app/ndn-app/src/node.rs: one handle to a forwarder over which every NDN pattern is available with one vocabulary.

  • Node::connect(socket) dials a running ndn-fwd over its Unix socket; an in-process engine can supply a Node too.
  • node.fetch(name) / node.verifying(validator) / node.object(name) are the consumer side (unverified fetch, verifying fetch, and RDR object fetch).
  • node.serve(prefix, handler) answers Interests for a prefix.
  • node.publish / node.subscribe drive dataset sync; node.query runs a responder stream.

The per-pattern building blocks (Consumer, Producer, Publisher, Subscriber, Queryable) remain reachable through Node::connection() for code that needs the lower level. For the application-author’s view rather than the contributor’s, start at Building an app.

Reading order from here

The sibling repos that consume ndn-rs (the forwarder binary, the simulator, the embedded forwarder, the mobile app) sit outside this workspace; the surface they depend on is the cross-repo contract.