vs. NDNph / NDN-Lite (Embedded C/C++)
📝 Note: NDNph and NDN-Lite are the right answer for resource-constrained targets where ndn-rs cannot run: microcontrollers with under 8 KB RAM and no heap. This comparison is not about which project is better overall — it explains the design tradeoffs so you can pick the right implementation for your hardware target.
This page compares ndn-rs with two embedded NDN implementations: NDNph (a header-only C++ library targeting Arduino, ESP8266, and ESP32) and NDN-Lite (a C library targeting RIOT OS and bare-metal embedded systems). Both projects solve the same problem — running NDN on extremely resource-constrained devices — but from different starting points and with different design philosophies.
Comparison Table
| Aspect | NDNph / esp8266ndn | NDN-Lite | ndn-rs | Rationale |
|---|---|---|---|---|
| Language | C++ (header-only). Compiles with any Arduino-compatible C++ compiler. No build system required — include headers and compile. | C (C11). Targets GCC-based embedded toolchains (arm-none-eabi, RIOT OS build system). | Rust (edition 2024). Requires a Rust cross-compilation toolchain (rustup target add). | NDNph’s header-only approach minimises the barrier to entry on Arduino. NDN-Lite targets the existing C ecosystem in embedded RIOT OS projects. ndn-rs requires more toolchain setup but provides memory safety at compile time. |
| Minimum RAM | <8 KB for a basic consumer/producer. NDNph uses stack allocation and fixed-size arrays; there is no heap dependency. Runs on ATmega328 (the original Arduino Uno). | ~4–16 KB depending on feature set. NDN-Lite can be trimmed to a minimal footprint with compile-time feature flags, but is typically paired with devices larger than an ATmega. | Depends on no_std feature set. ndn-embedded targets Cortex-M with at least 64 KB RAM for a minimal forwarder. The TLV parser alone (ndn-tlv) can run in much less. | NDNph is unmatched for devices under 10 KB RAM. ndn-rs is appropriate for Cortex-M4/M33 and similar mid-range microcontrollers with a real-time OS or bare-metal async executor. |
| Dynamic allocation | None. NDNph avoids new/delete entirely; all buffers are fixed-size arrays declared on the stack or as class members. | Optional. NDN-Lite can work without malloc using static allocation pools, but some features use dynamic allocation. | no_std + alloc (optional). ndn-tlv and ndn-packet can operate without an allocator using fixed-size buffer slices; ndn-embedded uses a simple bump allocator for packet buffers. | Avoiding dynamic allocation prevents heap fragmentation and makes memory usage statically provable — critical for safety-critical embedded systems. ndn-rs’s no_std feature gates provide this property when needed, but are less deeply embedded in the design than NDNph. |
| Async model | None. NDNph is synchronous. Face I/O is polled in a main loop (face.loop()) with callback-based packet dispatch. | None. NDN-Lite uses synchronous callbacks and a simple event loop. No RTOS threading is assumed. | Async-first. ndn-rs is built on async/await with a pluggable executor. On embedded targets, ndn-embedded uses a cooperative async executor (embassy or a custom one). | Synchronous polling is simpler on microcontrollers with no RTOS and limited concurrency. ndn-rs’s async model is more expressive but requires more setup — an executor, task scheduling, and pinning — that pays off most on devices handling multiple concurrent Interests. |
| Security | Minimal. NDNph supports DigestSha256 signing and HMAC-SHA256. EdDSA/RSA is not supported in the base library. | Certificate-based security baked in. NDN-Lite includes ECDSA and HMAC signing, symmetric key scheduling, and certificate handling as core (not optional) features. This was a design priority from the start. | Modular. ndn-security provides a full signing and validation stack (DigestSha256, EdDSA, ECDSA, BLAKE3). On embedded targets, feature flags select a subset. | NDN-Lite’s strong security story was deliberate — IoT devices are a primary attack surface. ndn-rs matches the feature set but makes it opt-in via Cargo features, which reduces binary size for targets that do not need cryptographic validation. |
| Forwarder | None. NDNph is a consumer/producer library; it does not include a forwarding plane. Routing is implicit — the device has one face and no PIT-based multiplexing. | Minimal. NDN-Lite includes a simple forwarding table but is designed for end devices, not routers. | Full forwarding plane. ndn-embedded provides a real PIT, FIB, and Content Store running on bare-metal, with the same forwarding semantics as the full ndn-engine. | NDNph and NDN-Lite assume end-device roles. ndn-rs on embedded targets can act as a true NDN router (e.g., a Cortex-M33-based gateway that forwards between a BLE sensor network and an Ethernet uplink). |
| Code sharing with router | None. NDNph and NDN-Lite are independent codebases. A packet parsed by NDNph must be re-encoded if handed off to NFD or ndnd. | None. NDN-Lite is a separate codebase; its packet format is compatible but its API is not shared with any full forwarder. | Full sharing. ndn-tlv, ndn-packet, ndn-transport, and ndn-security are the same crates on embedded and server targets. The forwarder, tools, and embedded runtime all parse packets with the same code. | Divergent codebases accumulate divergent bugs. A format extension added to NFD and forgotten in NDN-Lite causes interoperability failures. Sharing a single codebase via no_std feature flags guarantees that the embedded device and the core router see identical wire format semantics. |
| Toolchain | Arduino IDE or PlatformIO. Familiar to the maker/embedded community; minimal setup. | GCC cross-compiler + RIOT OS build system, or CMake for bare-metal. More complex but standard in the embedded C world. | Rust cross-compiler via rustup. One command to add a target (rustup target add thumbv7em-none-eabihf), then cargo build. | NDNph’s Arduino IDE integration is the most accessible path for hobbyists. ndn-rs requires familiarity with Rust and cross-compilation toolchains, which is a higher bar. |
| Ecosystem / community | Small but active. NDNph is maintained by a single developer (yoursunny) with a focus on practical deployability on off-the-shelf hardware. | Maintained by the NDN project team, aligned with academic research. Published several papers on IoT security with NDN-Lite as the platform. | Shared with the ndn-rs full-stack community. Contributions to ndn-packet improve embedded and server paths simultaneously. | NDN-Lite has the strongest institutional backing for IoT NDN research. NDNph has the most real-world deployments on consumer hardware. ndn-rs benefits from a larger Rust ecosystem (crates.io) but has a smaller NDN-specific community. |
Where NDNph and NDN-Lite Have the Advantage
- Ultra-low RAM targets. On ATmega328 (2 KB SRAM), ATmega2560, or early ESP8266 modules with under 40 KB RAM, NDNph is the only practical option. ndn-rs’s
no_stdbuild currently requires more RAM than NDNph for an equivalent feature set. - Arduino ecosystem integration. NDNph works out of the box with Arduino libraries (Ethernet, WiFi, BLE). Mapping ndn-rs faces to Arduino network APIs requires custom glue code.
- Synchronous simplicity. For a device that does one thing (sense and produce data), NDNph’s synchronous main loop is far simpler to reason about than an async executor.
- NDN-Lite’s security framework. NDN-Lite’s key management and certificate scheduling primitives are more mature and better documented than ndn-rs’s embedded security story.
Code Sharing Benefit in Practice
The shared-codebase advantage becomes concrete when extending the NDN wire format. Adding a new TLV type to ndn-packet automatically makes it available on embedded targets without any additional porting work. A packet encoded by an ndn-embedded node and forwarded by an ndn-fwd server is parsed by the same ndn-packet::Data::from_wire() function — the same code path, the same validation logic, and the same test coverage on both platforms.