<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>netmap-rs Documentation | High-Performance Kernel-Bypass Networking in Rust</title>
<meta name="description" content="netmap-rs provides safe, zero-cost abstractions for Netmap kernel-bypass networking in Rust. Achieve high-performance packet processing with direct memory access.">
<meta name="keywords" content="netmap, rust, networking, kernel-bypass, high-performance, packet-processing, zero-cost-abstractions">
<meta name="author" content="Meshack Bahati Ouma">
<meta property="og:title" content="netmap-rs Documentation | High-Performance Kernel-Bypass Networking">
<meta property="og:description" content="Safe, zero-cost abstractions for Netmap kernel-bypass networking in Rust. Achieve maximum packet processing performance.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://github.com/Kyle6012/netmap-rs">
<meta property="og:image" content="https://raw.githubusercontent.com/Kyle6012/netmap-rs/main/docs/netmap-rs-og.png">
<meta property="og:site_name" content="netmap-rs Documentation">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="netmap-rs Documentation | High-Performance Networking">
<meta name="twitter:description" content="Safe, zero-cost abstractions for Netmap kernel-bypass networking in Rust.">
<meta name="twitter:image" content="https://raw.githubusercontent.com/Kyle6012/netmap-rs/main/docs/netmap-rs-og.png">
<meta name="twitter:creator" content="@bealthguy">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📡</text></svg>">
<link rel="apple-touch-icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📡</text></svg>">
<link rel="canonical" href="https://github.com/Kyle6012/netmap-rs">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareSourceCode",
"name": "netmap-rs",
"description": "Safe, zero-cost abstractions for Netmap kernel-bypass networking in Rust",
"url": "https://github.com/Kyle6012/netmap-rs",
"codeRepository": "https://github.com/Kyle6012/netmap-rs",
"programmingLanguage": "Rust",
"runtimePlatform": "Linux",
"author": {
"@type": "Person",
"name": "Meshack Bahati"
},
"license": "https://opensource.org/licenses/MIT"
}
</script>
<style>
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--success-color: #28a745;
--danger-color: #dc3545;
--warning-color: #ffc107;
--info-color: #17a2b8;
--light-color: #f8f9fa;
--dark-color: #343a40;
--border-color: #e9ecef;
--shadow-color: rgba(0,0,0,0.08);
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
line-height: 1.6;
margin: 0;
background-color: var(--light-color);
color: var(--dark-color);
scroll-behavior: smooth;
}
.container {
max-width: 960px;
margin: 40px auto;
padding: 20px;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 12px var(--shadow-color);
}
h1, h2, h3 {
color: #212529;
border-bottom: 2px solid var(--border-color);
padding-bottom: 10px;
scroll-margin-top: 20px;
}
a {
color: var(--primary-color);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
code {
background-color: var(--border-color);
padding: 2px 6px;
border-radius: 4px;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 0.9em;
}
pre {
background-color: #212529;
color: #f8f9fa;
padding: 20px;
border-radius: 8px;
overflow-x: auto;
position: relative;
}
pre code {
background-color: transparent;
padding: 0;
color: inherit;
font-size: 0.9em;
}
.copy-btn {
position: absolute;
top: 10px;
right: 10px;
background: rgba(255, 255, 255, 0.2);
border: none;
color: white;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 0.8em;
transition: background 0.2s ease;
}
.copy-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.header {
text-align: center;
margin-bottom: 40px;
padding-bottom: 20px;
border-bottom: 1px solid var(--border-color);
}
.header h1 {
font-size: 2.5em;
border-bottom: none;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.header-icon {
font-size: 1.2em;
}
.links {
text-align: center;
margin-bottom: 40px;
}
.links a {
margin: 0 15px;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
background-color: var(--primary-color);
color: white;
display: inline-block;
}
.links a:hover {
background-color: #0056b3;
text-decoration: none;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
margin: 30px 0;
}
.feature-card {
background-color: var(--light-color);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px var(--shadow-color);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 8px var(--shadow-color);
}
.feature-card h3 {
border-bottom: none;
margin-top: 0;
color: var(--primary-color);
}
.toc {
background-color: var(--light-color);
border-radius: 8px;
padding: 20px;
margin-bottom: 30px;
}
.toc h3 {
margin-top: 0;
border-bottom: none;
}
.toc ul {
padding-left: 20px;
}
.toc li {
margin-bottom: 8px;
}
.breadcrumb {
margin-bottom: 20px;
font-size: 0.9em;
color: var(--secondary-color);
}
.breadcrumb a {
color: var(--secondary-color);
}
.breadcrumb a:hover {
color: var(--primary-color);
}
@media (max-width: 768px) {
.container {
margin: 20px;
padding: 15px;
}
.header h1 {
font-size: 2em;
}
.links a {
display: block;
margin: 10px 0;
}
.feature-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="breadcrumb">
<a href="https://crates.io">crates.io</a> > <a href="https://crates.io/categories/network-programming">Networking</a> > netmap-rs
</div>
<div class="header">
<h1><span class="header-icon">📡</span> netmap-rs</h1>
<p>Safe, zero-cost abstractions for Netmap kernel-bypass networking in Rust.</p>
</div>
<div class="toc">
<h3>Table of Contents</h3>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#getting-started">Getting Started</a></li>
<li><a href="#basic-usage">Basic Usage</a></li>
<li><a href="#public-api">Public API</a></li>
<li><a href="#advanced-usage">Advanced Usage</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
</ul>
</div>
<div class="links">
<a href="https://github.com/Kyle6012/netmap-rs">GitHub Repository</a>
<a href="https://crates.io/crates/netmap-rs">crates.io</a>
<a href="https://docs.rs/netmap-rs">API Documentation</a>
<a href="https://github.com/Kyle6012/netmap-rs/tree/main/examples">Examples</a>
</div>
<h2 id="introduction">Introduction</h2>
<p><code>netmap-rs</code> provides safe, zero-cost abstractions for <a href="http://info.iet.unipi.it/~luigi/netmap/">Netmap</a>, a high-performance packet I/O framework. It allows you to directly access packet buffers in memory shared with the kernel, eliminating copies and system call overhead for extremely fast networking.</p>
<h2 id="features">Features</h2>
<div class="feature-grid">
<div class="feature-card">
<h3>High Performance</h3>
<p>Direct memory access to packet buffers with zero-copy operations for maximum throughput.</p>
</div>
<div class="feature-card">
<h3>Memory Safe</h3>
<p>Leverages Rust's ownership model to ensure memory safety without performance penalties.</p>
</div>
<div class="feature-card">
<h3>Async Support</h3>
<p>Optional integration with Tokio for asynchronous packet processing.</p>
</div>
<div class="feature-card">
<h3>Cross-Platform</h3>
<p>Works on Linux, FreeBSD, and other platforms supported by Netmap.</p>
</div>
</div>
<h2 id="getting-started">Getting Started</h2>
<h3>Prerequisites</h3>
<p>You must have the Netmap C library installed. Follow the instructions in the <a href="https://github.com/luigirizzo/netmap">official Netmap repository</a> to build and install it on your system.</p>
<h3>Adding to Your Project</h3>
<p>Add <code>netmap-rs</code> to your <code>Cargo.toml</code>, enabling the <code>sys</code> feature for core functionality:</p>
<pre><code id="code-cargo-toml">[dependencies]
netmap-rs = { version = "0.3", features = ["sys"] }</code><button class="copy-btn" onclick="copyToClipboard('code-cargo-toml')">Copy</button></pre>
<h2 id="basic-usage">Basic Usage</h2>
<p>Here's a simple example of sending and receiving a packet on an interface:</p>
<pre><code id="code-basic-usage">use netmap_rs::prelude::*;
use std::thread::sleep;
use std::time::Duration;
fn main() -> Result<(), Error> {
let nm = NetmapBuilder::new("eth0")
.num_tx_rings(1)
.num_rx_rings(1)
.build()?;
let mut tx_ring = nm.tx_ring(0)?;
let mut rx_ring = nm.rx_ring(0)?;
let packet_data = b"hello netmap!";
tx_ring.send(packet_data)?;
tx_ring.sync();
println!("Sent packet: {:?}", packet_data);
// ... (receive logic) ...
Ok(())
}</code><button class="copy-btn" onclick="copyToClipboard('code-basic-usage')">Copy</button></pre>
<h2 id="public-api">Public API</h2>
<p>This section provides a detailed overview of the public API of <code>netmap-rs</code>.</p>
<h3><code>NetmapBuilder</code></h3>
<p>The <code>NetmapBuilder</code> is used to configure and create a <code>Netmap</code> instance.</p>
<ul>
<li><strong><code>NetmapBuilder::new(ifname_str: &str) -> Self</code></strong>: Creates a new builder for the given Netmap interface name. <code>ifname_str</code> can be a simple interface name like <code>"eth0"</code>, or <code>"eth0^"</code> to access the host stack.</li>
</ul>
<pre><code id="code-netmap-builder-new">use netmap_rs::NetmapBuilder;
let builder = NetmapBuilder::new("eth0");
</code><button class="copy-btn" onclick="copyToClipboard('code-netmap-builder-new')">Copy</button></pre>
<ul>
<li><strong><code>num_tx_rings(self, num: usize) -> Self</code></strong>: Sets the desired number of transmission (TX) rings.</li>
</ul>
<pre><code id="code-netmap-builder-num-tx-rings">use netmap_rs::NetmapBuilder;
let builder = NetmapBuilder::new("eth0").num_tx_rings(2);
</code><button class="copy-btn" onclick="copyToClipboard('code-netmap-builder-num-tx-rings')">Copy</button></pre>
<ul>
<li><strong><code>num_rx_rings(self, num: usize) -> Self</code></strong>: Sets the desired number of reception (RX) rings.</li>
</ul>
<pre><code id="code-netmap-builder-num-rx-rings">use netmap_rs::NetmapBuilder;
let builder = NetmapBuilder::new("eth0").num_rx_rings(2);
</code><button class="copy-btn" onclick="copyToClipboard('code-netmap-builder-num-rx-rings')">Copy</button></pre>
<ul>
<li><strong><code>flags(self, flags: u32) -> Self</code></strong>: Sets additional flags for the Netmap request. See <code><net/netmap_user.h></code> for available flags.</li>
<li><strong><code>build(self) -> Result<Netmap, Error></code></strong>: Consumes the builder and attempts to open the Netmap interface, returning a <code>Netmap</code> instance.</li>
</ul>
<pre><code id="code-netmap-builder-build">use netmap_rs::NetmapBuilder;
let nm = NetmapBuilder::new("eth0").build();
</code><button class="copy-btn" onclick="copyToClipboard('code-netmap-builder-build')">Copy</button></pre>
<h3><code>Netmap</code></h3>
<p>A <code>Netmap</code> instance represents an open Netmap interface.</p>
<ul>
<li><strong><code>num_tx_rings(&self) -> usize</code></strong>: Returns the number of configured TX rings.</li>
<li><strong><code>num_rx_rings(&self) -> usize</code></strong>: Returns the number of configured RX rings.</li>
<li><strong><code>is_host_if(&self) -> bool</code></strong>: Returns <code>true</code> if the <code>Netmap</code> instance is configured for host stack rings.</li>
<li><strong><code>tx_ring(&self, index: usize) -> Result<TxRing, Error></code></strong>: Returns a handle to a specific TX ring.</li>
<li><strong><code>rx_ring(&self, index: usize) -> Result<RxRing, Error></code></strong>: Returns a handle to a specific RX ring.</li>
</ul>
<h3><code>Ring</code></h3>
<p>Represents a generic Netmap ring.</p>
<ul>
<li><strong><code>index(&self) -> usize</code></strong>: Returns the index of the ring.</li>
<li><strong><code>num_slots(&self) -> usize</code></strong>: Returns the total number of slots in the ring.</li>
<li><strong><code>sync(&self)</code></strong>: Synchronizes the ring with the NIC, making sent packets available to the hardware and updating the ring's state to see new packets.</li>
</ul>
<h3><code>TxRing</code></h3>
<p>A handle to a transmission (TX) ring.</p>
<ul>
<li><strong><code>send(&mut self, buf: &[u8]) -> Result<(), Error></code></strong>: Sends a single packet. The data in <code>buf</code> is copied to a slot in the ring.</li>
<li><strong><code>max_payload_size(&self) -> usize</code></strong>: Returns the maximum payload size for a single packet in this ring.</li>
<li><strong><code>reserve_batch(&mut self, count: usize) -> Result<BatchReservation, Error></code></strong>: Reserves space for sending a batch of packets. Returns a <code>BatchReservation</code> instance.</li>
</ul>
<h3><code>BatchReservation</code></h3>
<p>A reservation for a batch of packets to be sent.</p>
<ul>
<li><strong><code>packet(&mut self, index: usize, len: usize) -> Result<&mut [u8], Error></code></strong>: Gets a mutable slice for a packet in the batch. You can write your packet data to this slice.</li>
<li><strong><code>commit(self)</code></strong>: Commits the batch, making the packets visible to the NIC.</li>
</ul>
<h3><code>RxRing</code></h3>
<p>A handle to a reception (RX) ring.</p>
<ul>
<li><strong><code>recv(&mut self) -> Option<Frame></code></strong>: Receives a single packet from the ring. Returns a <code>Frame</code> if a packet is available.</li>
<li><strong><code>recv_batch(&mut self, batch: &mut [Frame]) -> usize</code></strong>: Receives a batch of packets. The <code>batch</code> slice is filled with available frames, and the number of received frames is returned.</li>
</ul>
<h3><code>Frame</code></h3>
<p>A <code>Frame</code> represents a received packet. It can be either a zero-copy view of a packet buffer (from a <code>Netmap</code> ring) or an owned buffer (in fallback mode).</p>
<ul>
<li><strong><code>new(data: &'a [u8]) -> Self</code></strong>: Creates a new frame from a borrowed byte slice (zero-copy).</li>
<li><strong><code>new_owned(data: Vec<u8>) -> Self</code></strong>: Creates a new frame from an owned vector of bytes (for fallback).</li>
<li><strong><code>len(&self) -> usize</code></strong>: Returns the length of the frame.</li>
<li><strong><code>is_empty(&self) -> bool</code></strong>: Returns <code>true</code> if the frame is empty.</li>
<li><strong><code>payload(&self) -> &[u8]</code></strong>: Returns a slice containing the packet's payload.</li>
</ul>
<pre><code id="code-frame-payload">if let Some(frame) = rx_ring.recv() {
println!("Received packet of length {}: {:?}", frame.len(), frame.payload());
}
</code><button class="copy-btn" onclick="copyToClipboard('code-frame-payload')">Copy</button></pre>
<h3>Async API (<code>tokio-async</code> feature)</h3>
<p>When the <code>tokio-async</code> feature is enabled, you can use the following async wrappers for non-blocking I/O with Tokio.</p>
<h4><code>TokioNetmap</code></h4>
<p>The <code>TokioNetmap</code> is the entry point for async operations.</p>
<ul>
<li><strong><code>TokioNetmap::new(netmap: Netmap) -> io::Result<Self></code></strong>: Creates a new <code>TokioNetmap</code> by wrapping a <code>Netmap</code> instance.</li>
</ul>
<pre><code id="code-tokio-netmap-new">use netmap_rs::NetmapBuilder;
use netmap_rs::tokio_async::TokioNetmap;
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let nm = NetmapBuilder::new("eth0").build()?;
let tokio_nm = TokioNetmap::new(nm)?;
# Ok(())
# }
</code><button class="copy-btn" onclick="copyToClipboard('code-tokio-netmap-new')">Copy</button></pre>
<ul>
<li><strong><code>rx_ring(&self, ring_idx: usize) -> Result<AsyncNetmapRxRing, Error></code></strong>: Returns an async wrapper for a specific RX ring.</li>
<li><strong><code>tx_ring(&self, ring_idx: usize) -> Result<AsyncNetmapTxRing, Error></code></strong>: Returns an async wrapper for a specific TX ring.</li>
</ul>
<h4><code>AsyncNetmapRxRing</code></h4>
<p>An <code>AsyncRead</code> implementation for a Netmap RX ring. You can use the methods from <code>tokio::io::AsyncReadExt</code> to read from the ring.</p>
<pre><code id="code-async-rx-ring-read"># use netmap_rs::NetmapBuilder;
# use netmap_rs::tokio_async::TokioNetmap;
# use tokio::io::AsyncReadExt;
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
# let nm = NetmapBuilder::new("eth0").build()?;
# let tokio_nm = TokioNetmap::new(nm)?;
let mut rx_ring = tokio_nm.rx_ring(0)?;
let mut buf = [0; 1500];
let n = rx_ring.read(&mut buf).await?;
# Ok(())
# }
</code><button class="copy-btn" onclick="copyToClipboard('code-async-rx-ring-read')">Copy</button></pre>
<h4><code>AsyncNetmapTxRing</code></h4>
<p>An <code>AsyncWrite</code> implementation for a Netmap TX ring. You can use the methods from <code>tokio::io::AsyncWriteExt</code> to write to the ring.</p>
<pre><code id="code-async-tx-ring-write"># use netmap_rs::NetmapBuilder;
# use netmap_rs::tokio_async::TokioNetmap;
# use tokio::io::AsyncWriteExt;
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
# let nm = NetmapBuilder::new("eth0").build()?;
# let tokio_nm = TokioNetmap::new(nm)?;
let mut tx_ring = tokio_nm.tx_ring(0)?;
tx_ring.write_all(b"hello async netmap").await?;
tx_ring.flush().await?;
# Ok(())
# }
</code><button class="copy-btn" onclick="copyToClipboard('code-async-tx-ring-write')">Copy</button></pre>
<h3><code>Error</code> Enum</h3>
<p>The <code>Error</code> enum represents all possible errors that can occur in <code>netmap-rs</code>.</p>
<ul>
<li><code>Io(io::Error)</code>: An I/O error from the underlying system.</li>
<li><code>WouldBlock</code>: The operation would block.</li>
<li><code>BindFail(String)</code>: Failed to bind to a Netmap interface.</li>
<li><code>InvalidRingIndex(usize)</code>: The specified ring index is out of bounds.</li>
<li><code>PacketTooLarge(usize)</code>: The packet is too large for the ring buffer.</li>
<li><code>InsufficientSpace</code>: There is not enough space in the ring buffer.</li>
<li><code>UnsupportedPlatform(String)</code>: The platform is not supported.</li>
<li><code>FallbackUnsupported(String)</code>: The feature is not supported in fallback mode.</li>
</ul>
<h3>Fallback API</h3>
<p>For platforms without Netmap support, a fallback implementation is provided.</p>
<ul>
<li><strong><code>create_fallback_channel(max_size: usize) -> (FallbackTxRing, FallbackRxRing)</code></strong>: Creates a connected pair of fallback TX and RX rings that simulate a Netmap pipe.</li>
</ul>
<pre><code id="code-fallback-channel">use netmap_rs::fallback::create_fallback_channel;
let (tx, rx) = create_fallback_channel(64);
tx.send(b"hello fallback").unwrap();
if let Some(frame) = rx.recv() {
assert_eq!(frame.payload(), b"hello fallback");
}
</code><button class="copy-btn" onclick="copyToClipboard('code-fallback-channel')">Copy</button></pre>
<h2 id="advanced-usage">Advanced Usage</h2>
<h3>Thread-per-Ring</h3>
<p>For maximum performance, dedicate a thread to each transmission (TX) and reception (RX) ring. This pattern is ideal for multi-core systems.</p>
<pre><code id="code-thread-per-ring">use netmap_rs::prelude::*;
use std::thread;
fn main() -> Result<(), Error> {
let nm = NetmapBuilder::new("eth0")
.num_tx_rings(4)
.num_rx_rings(4)
.build()?;
// Spawn threads for each ring...
// See the full example in the repository.
Ok(())
}</code><button class="copy-btn" onclick="copyToClipboard('code-thread-per-ring')">Copy</button></pre>
<h3>Async Support with Tokio</h3>
<p>Enable the <code>tokio-async</code> feature for async/await support:</p>
<pre><code id="code-tokio-feature">[dependencies]
netmap-rs = { version = "0.3", features = ["sys", "tokio-async"] }</code><button class="copy-btn" onclick="copyToClipboard('code-tokio-feature')">Copy</button></pre>
<pre><code id="code-tokio-usage">use netmap_rs::tokio_async::*;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let nm = TokioNetmap::new("eth0").await?;
let mut rx_ring = nm.async_rx_ring(0).await?;
// ... (async receive logic) ...
Ok(())
}</code><button class="copy-btn" onclick="copyToClipboard('code-tokio-usage')">Copy</button></pre>
<h2 id="troubleshooting">Troubleshooting</h2>
<p>Common issues include "netmap_user.h not found" (install Netmap), permission errors (run with sudo), and "NetmapBuilder not found" (enable the <code>sys</code> feature).</p>
<h3>Performance Tips</h3>
<ul>
<li>Use multiple rings to distribute load across CPU cores</li>
<li>Pre-allocate packet buffers when possible</li>
<li>Batch operations to minimize synchronization overhead</li>
<li>Consider using huge pages for better memory performance</li>
</ul>
</div>
<script>
function copyToClipboard(elementId) {
const codeElement = document.getElementById(elementId);
const textArea = document.createElement('textarea');
textArea.value = codeElement.textContent;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
const button = event.target;
const originalText = button.textContent;
button.textContent = 'Copied!';
setTimeout(() => {
button.textContent = originalText;
}, 2000);
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
</script>
</body>
</html>