nlink - Rust IP utilities
A modern Rust implementation of Linux network management tools, providing both a library crate and CLI binaries.
Overview
nlink is a from-scratch implementation of Linux netlink-based network management. The primary goal is to provide a high-quality Rust library for programmatic network configuration, with CLI tools serving as proof-of-concept binaries.
Key design principles:
- Library-first: Core functionality lives in a single, well-designed crate
- Async/tokio-native: Built for async Rust from the ground up
- Custom netlink: No dependency on rtnetlink or netlink-packet-* crates
- Type-safe: Leverage Rust's type system for correctness
- High-level APIs: Declarative configuration, rate limiting DSL, diagnostics
Installation
# Core netlink functionality (always built — TC, link, address,
# route, namespace, GENL families, conntrack, XFRM, nftables, etc.
# all live in always-built modules). 0.16 bundles a re-export of
# `nlink-macros` so downstream code that wants to define its own
# GENL family pulls in only one dep.
= "0.16"
# With additional features
= { = "0.16", = ["sockdiag", "tuntap", "output"] }
# All features (including opt-in syscall_batch — 1.5x speedup on
# dump-heavy workloads via recvmmsg/sendmmsg, see Plan 158).
= { = "0.16", = ["full"] }
Upgrading from an earlier release? See
docs/migration_guide/for per-release upgrade notes.
Features
| Feature | Description |
|---|---|
sockdiag |
Socket diagnostics via NETLINK_SOCK_DIAG |
tuntap |
TUN/TAP device management |
output |
JSON/text output formatting |
namespace_watcher |
Namespace watching via inotify |
lab |
nlink::lab namespace + integration-test harness |
syscall_batch |
recvmmsg/sendmmsg batching on dumps + streams (0.16+, opt-in) |
full |
All features enabled |
Quick Start
use ;
use StreamExt;
async
High-Level APIs
Declarative Network Configuration
Define desired network state and let nlink compute and apply changes:
use ;
let config = new
.link
.link
.address;
// Compute diff and apply (idempotent)
config.apply.await?;
Rate Limiting DSL
Simple bandwidth management without TC complexity. Rates are typed
via Rate —
no more bits/sec vs bytes/sec confusion.
use Rate;
use ;
// Interface-wide rate limiting
let limiter = new
.egress
.ingress;
limiter.apply.await?;
// Per-IP rate limiting
let limiter = new
.limit_ip;
limiter.apply.await?;
Per-Peer Impairment
Different netem (delay/loss) settings per destination, for emulating
shared L2 segments where each peer-to-peer path needs distinct RTT
and loss characteristics. Recipe at
docs/recipes/per-peer-impairment.md.
use ;
use ;
use NetemConfig;
use Duration;
new
.impair_dst_ip
.impair_dst_ip
.apply.await?;
Network Diagnostics
Scan for issues, check connectivity, find bottlenecks:
use Diagnostics;
let diag = new;
// Full diagnostic scan
let report = diag.scan.await?;
for issue in &report.issues
// Check connectivity to destination
let report = diag.check_connectivity.await?;
// Find bottlenecks
if let Some = diag.find_bottleneck.await?
Documentation
- Library Usage - Detailed library examples: namespaces, TC, WireGuard, error handling
- Cookbook Recipes - End-to-end walkthroughs: per-peer impairment, VLAN-aware bridges, bidirectional rate limiting, WireGuard mesh in namespaces, multi-namespace event monitoring, ENOBUFS-resync event loops, connection pools, define-your-own-GENL-family
- CLI Tools - ip and tc command reference
- Migration Guides - Per-release upgrade notes (what was removed / behaviour-changed / typed-replacement-of)
- Examples - 40+ runnable examples
Library Modules
| Module | Description |
|---|---|
nlink::netlink |
Core netlink: Connection<Route>, EventStream, namespace, TC |
nlink::netlink::config |
Declarative network configuration |
nlink::netlink::nftables::config |
Declarative NftablesConfig — diff + atomic apply (0.16+) |
nlink::netlink::ratelimit |
High-level rate limiting API |
nlink::netlink::diagnostics |
Network diagnostics and issue detection |
nlink::netlink::dump_stream |
DumpStream<T> — O(1)-memory iteration over large dumps (0.16+) |
nlink::netlink::resync |
ResyncedEvent<T> + ResyncMarker — ENOBUFS overflow recovery (0.16+) |
nlink::netlink::pool |
ConnectionPool<P> + PooledConnection<'p, P> (0.16+) |
nlink::netlink::genl |
Generic Netlink: WireGuard, MACsec, MPTCP, Ethtool, nl80211, Devlink, DPLL, net_shaper (TX HW shaping) |
nlink::netlink::nexthop |
Nexthop objects and ECMP groups (Linux 5.3+) |
nlink::netlink::mpls |
MPLS routes and encapsulation |
nlink::netlink::srv6 |
SRv6 segment routing |
nlink::netlink::fdb |
Bridge FDB management |
nlink::netlink::bridge_vlan |
Bridge VLAN filtering |
nlink::netlink::uevent |
Device hotplug events: Connection<KobjectUevent> |
nlink::netlink::connector |
Process lifecycle events: Connection<Connector> |
nlink::netlink::netfilter |
Connection tracking: Connection<Netfilter> |
nlink::netlink::nftables |
nftables management + multicast events: Connection<Nftables> |
nlink::netlink::xfrm |
IPsec SA/SP management: Connection<Xfrm> (+ IPsec offload, 0.16+) |
nlink::netlink::fib_lookup |
FIB route lookups: Connection<FibLookup> |
nlink::netlink::audit |
Linux Audit subsystem: Connection<Audit> |
nlink::netlink::selinux |
SELinux events: Connection<SELinux> |
nlink::macros |
Proc-macro derives — define your own GENL family in ~30 lines (0.16+; re-exported from nlink-macros) |
nlink::sockdiag |
Socket diagnostics: Connection<SockDiag> (feature: sockdiag) |
nlink::util |
Parsing utilities, address helpers, name resolution |
nlink::tuntap |
TUN/TAP devices (feature: tuntap) |
Project Status
The library API is production-ready for network monitoring and configuration.
Implemented:
- Core netlink socket and connection handling
- Link operations (show, add, del, set) with 20+ link types
- Address, route, neighbor, and rule operations
- Event monitoring (link, address, route, neighbor, TC)
- TC qdisc operations with 18 typed qdisc kinds (every kind has
parse_params) - TC class management with typed builders (HTB, HFSC, DRR, QFQ)
- TC filter (9 typed kinds, all
parse_params-driven) and action (14 typed kinds) support - Standalone shared-action CRUD on
Connection<Route>(typedadd_action/del_action/get_action/dump_actions) - TC filter chains for complex classification
- Network namespace support
- Tunnel management (GRE, IPIP, SIT, VTI, VXLAN, Geneve)
- WireGuard, MACsec, MPTCP configuration via Generic Netlink
- Nexthop objects and ECMP groups (Linux 5.3+)
- MPLS routes and encapsulation
- SRv6 segment routing and local SIDs
- Bridge FDB and VLAN filtering
- Declarative network configuration
- Rate limiting DSL
- Network diagnostics
- VRF and XFRM/IPSec support
- Bond interface management with typed modes and slave info
- nftables firewall management (tables, chains, rules, sets, NAT, match expressions)
- nl80211 WiFi management (scan, connect, monitor)
- Devlink hardware device management (ports, health, firmware flash)
- BPF program attachment to TC hooks
- Socket statistics: summary mode, kill mode, expression filters
- Netlink batching for bulk operations
- Operation timeouts
- Ethtool configuration and event monitoring
- Async GENL namespace connections (WireGuard, MACsec, MPTCP, Ethtool, nl80211, Devlink)
- Interface name validation in link builders
- Typed error promotion (InterfaceNotFound, QdiscNotFound) with operation context
- Name-based address operations (add_address_by_name, replace_address_by_name)
- Bond/bridge enslavement helper (enslave/enslave_by_index)
New in 0.16 (in flight on the 0.16 branch):
nlink-macrosproc-macro crate — declare a custom Generic Netlink family + typed request/response structs in ~30 lines via#[genl_family(...)]+#[derive(GenlMessage / GenlCommand / GenlAttribute / GenlEnum / NetlinkAttrs)]and consume it throughConnection::<F>::send_typed(req).await?/dump_typed_stream. Seedocs/recipes/define-your-own-genl-family.md.- DPLL family (
Connection<Dpll>) — kernel 6.7+ clock-synchronization hardware (SyncE, PTP, GNSS-disciplined oscillators). First in-tree dogfood of the nlink-macros stack: ~430 lines of declarative Rust for the full family vs ~600+ lines hand-written per the WireGuard / MACsec / Devlink pattern. Includes push-based multicast monitor (subscribe_monitor()+DpllEventstream viaEventSource). Telco-RAN, time-sync, SmartNIC use case. Seedocs/recipes/dpll-monitor.md. net_shaperfamily (Connection<NetShaper>) — kernel 6.13+ TX hardware shaping: per-NIC, per-queue, or intermediate-node bandwidth/burst/priority/weight on shaper-capable drivers (InteliceE810/E830, Mellanoxmlx5ConnectX-7+, Broadcombnxt). Second in-tree macro dogfood — ~200 lines of declarative Rust for the full family. Seedocs/recipes/tx-hw-shaping.md.- Shared GENL multicast-group resolution —
GenlFamily::mcast_group(name) -> Option<u32>+Connection::<F>::subscribe_group(name).#[genl_family]populates the map automatically; Devlink/Nl80211/Ethtool also refactored to use it (−254 lines of duplicated wire parsing). - Streaming dump API (
dump_stream<T>+ typed wrappers for links/ routes/neighbors/addresses + qdiscs/classes/filters + XFRM SAs/SPs) — O(1) memory iteration on BGP/conntrack/IPsec-scale dumps ConnectionPool<P>+PooledConnection<'p, P>for parallel fanout- ENOBUFS-resync types (
ResyncedEvent<T>+ResyncMarker+ recipe) for multicast-overflow recovery - Declarative
NftablesConfigwith atomic single-batch apply - Nftables multicast event subscription
(
Connection::<Nftables>::events()) - Generic
Connection::<P: AsyncConstructible>::new_async()— collapsed six hand-rolled per-family constructors into one; macro-defined families plug in for free - Devlink rate-limit objects + port-function state
- XFRM IPsec hardware offload (
XFRMA_OFFLOAD_DEV) - nftables flowtables +
Expr::FlowOffload recvmmsg/sendmmsgsyscall batching (opt-insyscall_batchfeature — ≥1.5x speedup on dump-heavy workloads)- ext-ack error TLVs parsed into
Error::Kernel::ext_ack;enable_strict_checking+set_ext_acksockopts
Building
Requires Rust 1.95+ (edition 2024).
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.