amiga-bootcamp/12_networking/tcp_ip_stacks.md
2026-04-26 14:46:18 -04:00

12 KiB

← Home · Networking

TCP/IP Stacks — Architecture, Integration, and Configuration

Overview

AmigaOS has no built-in TCP/IP stack — networking is entirely provided by third-party software that installs as an Amiga shared library (bsdsocket.library). This is fundamentally different from every other major OS where TCP/IP is a kernel subsystem.


Architecture — How Amiga TCP/IP Differs

The Library Model vs. Kernel Sockets

flowchart TD
    subgraph "Unix / Windows / macOS"
        UAPP["Application"] -->|"syscall boundary<br/>(kernel trap)"| KERN["Kernel TCP/IP Stack"]
        KERN --> KDRV["Kernel NIC Driver"]
        KDRV --> HW1["Network Hardware"]
    end

    subgraph "AmigaOS"
        AAPP["Application"] -->|"Library call<br/>(JSR through LVO)"| BSL["bsdsocket.library<br/>(user-space process)"]
        BSL -->|"SANA-II IORequests"| SANA["SANA-II Driver<br/>(exec device)"]
        SANA --> HW2["Network Hardware"]
    end

    style KERN fill:#ffcdd2,stroke:#c62828,color:#333
    style BSL fill:#c8e6c9,stroke:#2e7d32,color:#333
Aspect Unix/Linux/Windows AmigaOS
Stack location Kernel (ring 0) User-space process (same address space)
Socket API System calls (trap to kernel) Library vector calls (JSR) — no context switch
Driver model Kernel module / NDIS SANA-II exec.device (user-space)
Multiple stacks One per kernel Multiple possible (only one active)
Per-process state fd table in kernel Socket "library base" per opener
Protection Full memory protection None — any process can corrupt stack state
Signal integration select/poll/epoll WaitSelect + Exec signal bits
Performance Optimized kernel path No syscall overhead, but no DMA offload

The Full Network Stack

flowchart TD
    subgraph "Applications"
        IBR["IBrowse<br/>(HTTP)"]
        FTP["AmiFTP<br/>(FTP)"]
        IRC["AmiRC<br/>(IRC)"]
        PING["ping<br/>(ICMP)"]
    end

    subgraph "bsdsocket.library"
        SOCK["Socket Layer<br/>(socket, bind, connect,<br/>send, recv, select)"]
        TCP["TCP"]
        UDP["UDP"]
        ICMP["ICMP"]
        IP["IP Layer<br/>(routing, fragmentation)"]
        ARP["ARP<br/>(address resolution)"]
    end

    subgraph "Link Layer"
        SANA2["SANA-II Interface<br/>(standardised IORequest API)"]
    end

    subgraph "Hardware Drivers"
        ETH["Ethernet Driver<br/>(e.g., ariadne.device)"]
        PPP["PPP Driver<br/>(e.g., ppp.device)"]
        SLIP["SLIP Driver"]
        LO["Loopback<br/>(lo0.device)"]
    end

    subgraph "Physical"
        NIC["Ethernet NIC<br/>(Zorro/PCMCIA)"]
        MODEM["Serial Modem<br/>(via serial.device)"]
        LOOP["Internal loopback"]
    end

    IBR --> SOCK
    FTP --> SOCK
    IRC --> SOCK
    PING --> SOCK

    SOCK --> TCP --> IP
    SOCK --> UDP --> IP
    SOCK --> ICMP --> IP
    IP --> ARP --> SANA2
    IP --> SANA2

    SANA2 --> ETH --> NIC
    SANA2 --> PPP --> MODEM
    SANA2 --> SLIP --> MODEM
    SANA2 --> LO --> LOOP

    style SOCK fill:#e8f4fd,stroke:#2196f3,color:#333
    style SANA2 fill:#fff9c4,stroke:#f9a825,color:#333
    style IP fill:#c8e6c9,stroke:#2e7d32,color:#333

Per-Opener Library Base

Each Amiga task that opens bsdsocket.library gets its own private library base with isolated socket state — there is no kernel fd table. This means SocketBase must never be shared between tasks. See bsdsocket.md for the full API reference and per-task setup pattern.


SANA-II — The Network Driver Layer

SANA-II (Standard Amiga Networking Architecture, version II) is the standardised interface between TCP/IP stacks and network hardware drivers. It's an exec.device protocol — drivers communicate via IORequests.

flowchart LR
    subgraph "TCP/IP Stack"
        IP["IP Layer"]
    end

    subgraph "SANA-II API"
        direction TB
        OPEN["OpenDevice<br/>(driver, unit)"]
        WRITE["CMD_WRITE<br/>(send frame)"]
        READ["CMD_READ<br/>(receive frame)"]
        ONLINE["S2_ONLINE<br/>(bring up link)"]
        CONFIG["S2_CONFIGINTERFACE<br/>(set HW address)"]
        QUERY["S2_DEVICEQUERY<br/>(get capabilities)"]
    end

    subgraph "Drivers"
        A2065["a2065.device<br/>(Commodore Ethernet)"]
        ARIADNE["ariadne.device<br/>(Village Tronic)"]
        CNET["cnet.device<br/>(Hydra/X-Surf)"]
        PPPDEV["ppp.device<br/>(dial-up modem)"]
    end

    IP --> OPEN
    IP --> WRITE
    IP --> READ
    OPEN --> A2065
    OPEN --> ARIADNE
    OPEN --> CNET
    OPEN --> PPPDEV

    style OPEN fill:#e8f4fd,stroke:#2196f3,color:#333

How the Stack Sends a Packet

  1. Application calls send(sock, data, len, 0)
  2. TCP/IP stack builds TCP segment + IP header
  3. ARP resolves destination MAC address (or uses cached entry)
  4. Stack fills a struct IOSana2Req with the complete Ethernet frame
  5. DoIO / SendIO to the SANA-II driver
  6. Driver writes frame to hardware registers / DMA buffer

How the Stack Receives a Packet

  1. Stack posts read requests (CMD_READ) to the SANA-II driver (kept outstanding)
  2. When a frame arrives, the driver completes the IORequest
  3. Stack parses the Ethernet frame → IP → TCP/UDP → delivers to socket buffer
  4. Application's recv() or WaitSelect() returns the data
  5. Stack immediately posts a new CMD_READ to keep the pipeline full

Dial-Up Networking — PPP and SLIP

Before broadband, most Amiga internet connections were via serial modem using PPP or SLIP over serial.device:

flowchart LR
    subgraph "Amiga"
        BSL2["bsdsocket.library"] --> PPP2["PPP/SLIP Driver"]
        PPP2 --> SER["serial.device<br/>(CIA UART)"]
    end

    SER -->|"RS-232<br/>up to 115200 baud"| MODEM["External Modem<br/>(AT commands)"]
    MODEM -->|"Phone line<br/>V.34/V.90"| ISP["ISP<br/>PPP Server"]

    style PPP2 fill:#fff9c4,stroke:#f9a825,color:#333
    style MODEM fill:#ffcdd2,stroke:#c62828,color:#333

PPP Connection Sequence

1. Modem initialization:
   → ATZ                    (reset modem)
   ← OK
   → AT&F1                  (factory defaults, hardware flow control)
   ← OK

2. Dial ISP:
   → ATDT 555-1234          (tone dial)
   ← CONNECT 33600          (connected at 33.6 kbps)

3. PPP negotiation (automatic):
   ← LCP Configure-Request
   → LCP Configure-Ack
   → LCP Configure-Request
   ← LCP Configure-Ack
   → PAP Authenticate (username/password)
   ← PAP Authenticate-Ack
   → IPCP Configure-Request
   ← IPCP Configure-Ack (IP=203.0.113.42, DNS=203.0.113.1)

4. Link up — IP traffic flows over PPP frames on serial line

PPP Configuration (Miami)

Miami had the most user-friendly dial-up setup:

Setting Value Notes
Serial device serial.device Or duart.device for A2232 multi-port
Unit 0
Baud rate 57600 or 115200 Must match modem's DTE rate
Flow control RTS/CTS (hardware) Required — XON/XOFF causes corruption
Init string ATZ then AT&F1 Hardware flow control defaults
Dial command ATDT <number>
Login PAP or script-based
VJ compression Yes Van Jacobson TCP header compression

PPP Configuration (AmiTCP)

; AmiTCP:db/interfaces
ppp0 DEV=DEVS:Networks/ppp.device UNIT=0

; AmiTCP:bin/startnet script must:
; 1. Open serial port
; 2. Send modem commands
; 3. Wait for CONNECT
; 4. Hand off to PPP

SLIP (Serial Line IP)

SLIP is the simpler, older protocol — no authentication, no compression, no error detection:

; AmiTCP:db/interfaces
sl0 DEV=DEVS:Networks/slip.device UNIT=0

; SLIP frames:
; Each IP packet is framed with END bytes (0xC0)
; ESC (0xDB) used to escape END and ESC within data
Feature SLIP PPP
Authentication None PAP, CHAP
IP negotiation Manual (both sides must know IPs) Automatic (IPCP)
Compression None VJ header compression
Error detection None FCS (frame check)
Multi-protocol IP only IP, IPX, AppleTalk

Stack Comparison (Detailed)

Feature AmiTCP 3.0b2 / Genesis Miami 3.2 Roadshow 1.15
License Free (Genesis fork) Commercial ($30) Commercial (demo: 5-min limit)
API version bsdsocket.library v3 v4 v4
Based on NetBSD TCP/IP stack Custom implementation Custom implementation
IPv6 No No No
PPP External (AmiPPP) Built-in dialer + PPP Via SANA-II PPP driver
SLIP Yes Yes Via SANA-II SLIP driver
DHCP External (dhclient) Built-in Built-in
DNS cache No Yes Yes
DNS over TCP No Yes Yes
Multi-homing Limited Yes Yes (multiple interfaces)
SANA-II v2 Yes Yes Yes
GUI config Genesis MUI prefs Miami prefs GUI Roadshow prefs editor
CLI config ifconfig, route Via GUI only Text file + CLI tools
Syslog Yes Yes Yes
Active development No (last: ~2002) No (last: ~2003) Yes (Olaf Barthel, ongoing)
Stability Good Good Excellent
MiSTer notes Free, easy to set up Requires registration Most capable, demo limit

Which Stack for MiSTer?

  • AmiTCP / Genesis: Free, works well for basic networking. Use Genesis.lha from Aminet.
  • Roadshow: Most capable and actively maintained. Demo works for 5 minutes at a time — sufficient for testing. Full license recommended for permanent setups.

Ethernet Cards (SANA-II Hardware)

Card Device Bus Chipset Speed
Commodore A2065 a2065.device Zorro II AMD LANCE 10 Mbps
Village Tronic Ariadne ariadne.device Zorro II AMD PCnet 10 Mbps
Village Tronic Ariadne II ariadne2.device Zorro II SMC 91C94 10 Mbps
Hydra Systems Amiganet amiganet.device Zorro II AMD LANCE 10 Mbps
X-Surf xsurf.device Clock port RTL8019AS 10 Mbps
X-Surf 100 xsurf100.device Zorro II/III AX88796B 100 Mbps
PCMCIA Ethernet cnet.device PCMCIA (A600/A1200) Various 10 Mbps

MiSTer Virtual NIC

MiSTer emulates a network interface that bridges to the Linux HPS network:

; DEVS:NetInterfaces/mister0  (Roadshow)
DEVICE=mister_eth.device
UNIT=0
IPTYPE=DHCP
MTU=1500

The virtual driver presents a standard SANA-II interface — the TCP/IP stack sees no difference from a real Ethernet card.


Configuration — Roadshow

Network Interface

; DEVS:NetInterfaces/eth0
DEVICE=ariadne.device       ; or your card's device name
UNIT=0
IPTYPE=DHCP                 ; or STATIC for manual

; Static configuration:
; ADDRESS=192.168.1.100
; NETMASK=255.255.255.0

Name Resolution

; DEVS:Internet/name_resolution
NAMESERVER 8.8.8.8
NAMESERVER 8.8.4.4
DOMAIN local
SEARCH local

Default Gateway

; DEVS:Internet/default_gateway
DEVICE=ariadne.device
UNIT=0
GATEWAY=192.168.1.1

Startup

; S:User-Startup
Run >NIL: C:AddNetInterface eth0
WaitForPort AMITCP
; Stack is now ready

Configuration — AmiTCP / Genesis

Interface Configuration

; AmiTCP:db/interfaces
eth0 DEV=DEVS:Networks/ariadne.device UNIT=0 IP=DHCP

; Static:
; eth0 DEV=DEVS:Networks/ariadne.device UNIT=0 IP=192.168.1.100 NETMASK=255.255.255.0

DNS and Hosts

; AmiTCP:db/netdb-myhost
HOST 127.0.0.1 localhost
HOST 192.168.1.1 gateway
NAMESERVER 8.8.8.8
DOMAIN local

Startup

; S:User-Startup
Run >NIL: AmiTCP:AmiTCP
WaitForPort AMITCP
; bsdsocket.library is now available

Verifying the Network

; CLI commands (provided by the stack):
ifconfig              ; show interface configuration
netstat -r            ; show routing table
netstat -a            ; show active connections
ping 8.8.8.8          ; test connectivity
nslookup amiga.org    ; test DNS resolution
traceroute 8.8.8.8    ; trace route to destination
/* Programmatic check: */
struct Library *SocketBase = OpenLibrary("bsdsocket.library", 4);
if (!SocketBase)
    Printf("No TCP/IP stack running — start AmiTCP or Roadshow\n");
else
    CloseLibrary(SocketBase);

References

  • Roadshow SDK: http://roadshow.apc-tcp.de/
  • AmiTCP SDK: Aminet comm/tcp/AmiTCP-SDK-4.3.lha
  • Genesis (free AmiTCP fork): Aminet comm/tcp/Genesis.lha
  • SANA-II specification: Aminet docs/hard/sana2.lha
  • See also: bsdsocket.md — socket API reference
  • See also: sana2.md — SANA-II driver specification
  • See also: protocols.md — DNS, HTTP, UDP implementation examples