NATA is a point-to-point networking stack that carries Ethernet/IP frames over a SATA link by presenting each host with a synthetic block device and mapping packets onto Logical Block Address (LBA) regions.
A dual-target FPGA bridge sits between two host SATA controllers. Each host believes it is talking to a drive. The bridge terminates Host-to-Device FIS traffic on both sides, emulates device responses, and exchanges payload through shared dual-port memory (the mailbox). A Linux kernel module registers virtual NICs (nata0 / nata1), encapsulates frames into fixed-size block writes, and rehydrates frames on the receive path.
The result is a full L2/L3-capable interface whose physical medium is the storage bus rather than a conventional Ethernet PHY.
| Layer | State |
|---|---|
| Linux simulation mode | Implemented — dual virtual NICs share an in-kernel mailbox (target_ata_port=-1) |
| Kernel module | module/ — net + block helpers, control device /dev/nata_ctl |
| User tools | tools/natactl, scripts/nata-ns-up.sh (recommended sim), scripts/nata-up.sh |
| FPGA RTL | firmware/rtl/ — dual-port RAM, SATA device IP stubs, top-level |
| PCB / schematic | hardware/ — KiCad bridge design |
| Hardware bring-up | In progress — dual SATA device PHY + Asynchronous Notification path |
Simulation mode is the supported development path today: no FPGA or second machine is required to exercise encapsulation, sequencing, and the virtual interfaces.
Two host AHCI controllers never speak Host-to-Host. The bridge appears as a SATA device on each port, so each side only ever exchanges legal Host↔Device Frame Information Structures. Packet data is written to and read from mailbox LBA ranges in dual-port BRAM (or a software stand-in of the same layout).
+-------------------+ +-----------------------+ +-------------------+
| Host PC A | | NATA bridge | | Host PC B |
| (Linux) | | (FPGA dual-target) | | (Linux) |
| | | | | |
| [ Virtual NIC ] | | +-------------------+ | | [ Virtual NIC ] |
| | | | | Device core 1 | | | | |
| [ AHCI / libata ]| | +---------+---------+ | | [ AHCI / libata ]|
| | | SATA cable | | | SATA cable | | |
| (host mode) +------------->| [ SRAM mailbox ] |<-------------+ (host mode) |
| | 3.0 Gbps | | | 3.0 Gbps | |
| | | +---------+---------+ | | |
| | | | Device core 2 | | | |
| | | +-------------------+ | | |
+-------------------+ +-----------------------+ +-------------------+
Mailbox layout (simulation defaults):
| Region | LBA range | Role |
|---|---|---|
| Lower 64 KiB | 0–127 | 32-slot ring: TX for nata1 / RX for nata0 |
| Upper 64 KiB | 128–255 | 32-slot ring: TX for nata0 / RX for nata1 |
Each half is a 32×2048-byte ring (slot = valid + nata_pkt_hdr + payload). Producer advances head; consumer advances tail. Full ring → NETDEV_TX_BUSY + stop queue (no overwrite). Publish order: payload+header, barrier, then valid=1. See docs/specs/03-mailbox-memory-map.md.
Further electrical and protocol rationale: docs/whitepaper.md.
As-built specifications (packet format, mailbox map, kernel module, control plane, netns sim, FPGA RTL stubs, measured performance): docs/specs/.
Relative to a conventional 1 GbE link on copper pair cabling:
- Point-to-point collision domain — SATA is a dedicated link between host and device. There is no shared CSMA/CD domain; collision rate on the wire is not a factor.
- Full-duplex at link rate — Each direction uses its own differential pair at SATA Gen1/Gen2 rates (up to 3.0 Gbps signaling on the PHY; effective payload rate is lower after FIS, sector, and software overhead).
- Security through obscurity — On the wire the medium is SATA FIS and block I/O, not Ethernet. Commodity packet sniffers do not attach to that path; use a SATA analyzer or capture on
nata0/nata1at the host.
module/ Linux out-of-tree kernel module (nata.ko)
tools/ natactl userspace control utility
scripts/ Bring-up helpers (simulation)
firmware/rtl/ Verilog sources (dual-port RAM, device IP, top)
firmware/sim/ Testbench
firmware/constraints/ FPGA pin constraints (Artix-7 example)
hardware/ KiCad schematic and PCB for the bridge
docs/ Whitepaper + as-built specs (docs/specs/)
Simulation (software only)
- Linux kernel headers matching the running kernel
- GCC or Clang toolchain capable of building out-of-tree modules
- Root privileges to load the module and configure interfaces
Hardware path (target)
- FPGA with two high-speed serial transceivers suitable for SATA device PHYs (e.g. Artix-7 / Kintex-class)
- Two host systems with free SATA ports (AHCI)
- Dual-device bridge firmware and board (see
firmware/,hardware/)
cd module
makeProduces nata.ko against /lib/modules/$(uname -r)/build.
Both virtual NICs register in one kernel. If nata0 and nata1 stay in the
default network namespace with 192.168.42.1 and 192.168.42.2 assigned there,
the stack treats both addresses as local. Frames still cross the simulated
mailbox (module TX/RX counters climb), but ARP and IP do not complete between
“two hosts” that are really one. Split them with network namespaces:
sudo ./scripts/nata-ns-up.shThat script:
- Loads
nata.koin simulation mode (target_ata_port=-1) - Creates netns
nata-aandnata-b - Moves
nata0→nata-a,nata1→nata-b - Assigns
192.168.42.1/24and192.168.42.2/24 - Runs
ping -c 3fromnata-ato192.168.42.2
Manual equivalent:
sudo insmod module/nata.ko target_ata_port=-1
sudo ip netns add nata-a
sudo ip netns add nata-b
sudo ip link set nata0 netns nata-a
sudo ip link set nata1 netns nata-b
sudo ip netns exec nata-a ip addr add 192.168.42.1/24 dev nata0
sudo ip netns exec nata-a ip link set nata0 up
sudo ip netns exec nata-b ip addr add 192.168.42.2/24 dev nata1
sudo ip netns exec nata-b ip link set nata1 up
sudo ip netns exec nata-a ping -c 3 192.168.42.2Override defaults if needed: NATA_ADDR_A, NATA_ADDR_B, NATA_PEER_B, NATA_NS_A, NATA_NS_B.
Same-namespace bring-up (sudo ./scripts/nata-up.sh) only loads the module and
configures both NICs in the root netns — useful for driver smoke tests, not for
end-to-end IP between the pair.
dmesg | grep -i nata
sudo ip netns exec nata-a ip link show nata0
sudo ip netns exec nata-a ip neigh show dev nata0
sudo ip netns exec nata-a ping -c 3 192.168.42.2Example kernel log:
nata: Initializing Software-Defined Simulation Environment...
nata: Operating in 100% Virtual Loopback Mode (no hardware required).
NATA: Registered virtual interfaces nata0 and nata1 successfully.
With namespaces up (nata-a = 192.168.42.1, nata-b = 192.168.42.2):
# Latency
sudo ip netns exec nata-a ping -c 50 -i 0.2 192.168.42.2
# Bandwidth (server in nata-b, client in nata-a)
sudo ip netns exec nata-b iperf3 -s
sudo ip netns exec nata-a iperf3 -c 192.168.42.2 -t 10
sudo ip netns exec nata-a iperf3 -c 192.168.42.2 -t 10 -R # reverse
sudo ip netns exec nata-a iperf3 -c 192.168.42.2 -u -b 0 -t 10Measured results (2026-07-15, Linux 6.8.0-134, 32-slot ring + NAPI + TX backpressure sim mailbox — not SATA hardware):
| Metric | Direction | Result |
|---|---|---|
| ICMP RTT | nata-a → nata-b |
min 0.023 ms / avg 0.037 ms / max 0.057 ms (50 pkts, 0% loss) |
| TCP throughput | nata-a → nata-b |
~7.26 Gbit/s (10 s; 0 retransmits) |
| TCP throughput | nata-b → nata-a (iperf3 -R) |
~8.02 Gbit/s (10 s; 0 retransmits) |
| UDP goodput | nata-a → nata-b |
~2.33 Gbit/s receiver (~0.012% loss at unlimited -b 0) |
| Ring pressure | after full suite | ring_full_drops 0, dropped_blocks 0 |
Path is 32-slot rings + per-netdev NAPI + NETDEV_TX_BUSY. Earlier same-day baselines: single-slot kthread ~0.6 Gbit/s TCP; 8-slot NAPI ~4.4–4.8 Gbit/s TCP with ~5e4 retransmits — see docs/specs/08-performance.md. One-shot remeasure: sudo ./scripts/nata-bench-once.sh. Hardware SATA rates will differ again.
sudo ./scripts/nata-ns-down.shOr manually: move interfaces back to the root netns, delete the namespaces, then
rmmod nata.
- Program an FPGA board with dual concurrent SATA device PHY cores and the NATA mailbox logic (
firmware/). - Connect Host A to bridge port 1 with a standard 7-pin SATA data cable.
- Connect Host B to bridge port 2 the same way.
- Power and ground the bridge according to the board design (
hardware/). Hosts may use independent PSUs.
SATA data pairs are AC-coupled. There is no intentional DC path through the high-speed pairs between host and device, which is why host-to-host data wiring does not create a supply short through the cable.
Still observe ordinary lab practice:
- Provide a solid common ground between the bridge board and each host chassis (or a single ground reference for the bench) so shield and logic reference potentials stay controlled.
- Do not rely on “floating” or deliberately ungrounded supplies as a design feature.
- Use only the I/O and PHY supply rails specified by the FPGA board design.
- Keep SATA data cables short and undamaged; treat the bridge as a high-speed digital system, not a passive crossover.
Electrical and FIS-level motivation for the middleman (why a direct host–host cable fails link init) is documented in docs/whitepaper.md.
When device binding is implemented, the same module will attach to a real target rather than the in-memory mailbox. Until then, use simulation mode for stack development. Control ioctls are exposed on /dev/nata_ctl (NATA_IOC_STATUS, bind/unbind placeholders).
| Item | Description |
|---|---|
Module param target_ata_port |
-1 = simulation (default development mode) |
/dev/nata_ctl |
Misc device for status / future bind operations |
tools/natactl |
Userspace helper (build with make -C tools) |
Why not use Ethernet?
NATA is for environments where the only free high-speed interconnect is a SATA port, or where the research goal is storage-bus packet transport. It is complementary to Ethernet, not a general replacement for datacenter NICs.
What is the effective throughput?
The SATA PHY may run at 3.0 Gbps. Usable bandwidth depends on sector size, FIS overhead, interrupt/notification path, and CPU cost of encapsulation. In simulation (same-host 32-slot mailbox rings + NAPI RX + TX backpressure), expect roughly ~7–8 Gbit/s TCP with 0 retransmits under the lab flood and sub-millisecond RTT — see Benchmark (simulation). Re-measure with iperf3 / ping on real hardware once the bridge path is live.
Can I boot over NATA?
Not supported. The module assumes a running kernel and registers virtual netdevs; it is not an iSCSI target or PXE path.
Is capture with Wireshark possible?
On the virtual interfaces, yes — nata0/nata1 are normal Linux netdevs. On the physical SATA cable, ordinary Ethernet sniffers do not apply; specialized SATA analyzers would see block traffic.
Is this safe for production storage controllers?
Treat it as experimental. Simulation mode never touches real disks. Hardware mode requires a dedicated bridge that emulates devices; do not point experimental firmware at disks holding data you care about.
- Prefer simulation-mode tests for kernel changes.
- Keep hot-path bounds checks and sequence consumption intact (invalid frames must not busy-loop NAPI).
- Do not commit Kbuild products (
*.o,*.ko,*.cmd,Module.symvers, etc.); see.gitignore. - Document hardware or RTL changes alongside software when the mailbox layout or header format shifts.
- Follow the agent/human work contract in AGENTS.md (DOX): as-built specs, named gaps, no oversell.
Licensed under the NATA License: You get nothing, it guarantees nothing.