Skip to content

Networking

Networking in Ixolo is three kinds of user process talking by messages: a driver per network card, the lwIP server with the TCP/IP stack and the sockets, and the programs that use them. Configuration is NetBSD’s: /etc/rc.conf, one /etc/ifconfig.<interface> file per card, dhcpcd, ifconfig and route.

At boot, /usr/etc/rc reads the PCI IDs of the Ethernet devices in /proc/pci, matches them against the driver descriptions in /etc/system.conf.d/, and starts one driver instance per card (labels e1000_0, e1000_1…). Each driver names its interfaces:

DriverHardwareInterfaceStatus on amd64
e1000Intel PRO/1000 family (82540EM, 82574L…)em0Tested with QEMU’s e1000 (82540EM), used by the network benchmarks and the SSH tests. Other listed models, such as QEMU’s e1000e, are matched but less exercised.
igcIntel I225/I226 2.5 GbEigc0Initial driver: one queue, no offloads. Not verified on hardware.
virtio_netvirtio network (QEMU, KVM)vio0Built; untested on amd64.
rtl8139, rtl8169Realtekrl0, re0Built; untested on amd64.
fxp, 3c90x, atl2, dec21140A, ip1000, lance, vt6105Older PCI cardsvariousBuilt; untested on amd64.
dp8390, dpethOld ISA cards (NE2000, 3Com)dp0, dpe0Not detected automatically: set up with netconf, option Manually configure. Untested on amd64.

“Untested” means exactly that: the driver compiles for amd64, but nobody has reported it working. Reports are welcome in the issue tracker. There is no Wi-Fi support.

In QEMU, use an e1000 card (the default on -machine pc):

Terminal window
qemu-system-x86_64 ... -nic user,model=e1000

List the interfaces the system found:

Terminal window
ifconfig -l # em0 lo0
netconf -l # hardware interfaces, and whether they are configured

netconf is the interactive tool, also run by setup (step 8). It lists the interfaces and offers:

  1. DHCP, IPv4 and IPv6
  2. DHCP, IPv4 only
  3. A static IPv4 address, netmask, gateway and DNS servers

It writes /etc/ifconfig.<interface> (and, for a static setup, /etc/hostname.file and /etc/resolv.conf). Apply the result without rebooting:

Terminal window
service network restart

At boot, /etc/rc.d/network reads one file per interface (with auto_ifconfig=YES, the default). Each line is either arguments for ifconfig, or a shell command after !, where $int is the interface name. This is what netconf writes for DHCP:

up
!dhcpcd -qM $int

For a static address:

up
inet 192.168.1.20 netmask 255.255.255.0
!route -q add default 192.168.1.1

IPv6 addresses go on inet6 lines in the same file. The format is NetBSD’s ifconfig.if(5).

Defaults are in /etc/defaults/rc.conf; put your changes in /etc/rc.conf. The variables that matter for networking:

VariableDefaultMeaning
auto_ifconfigYESConfigure every interface that has an /etc/ifconfig.* file.
net_interfaces""The interfaces to configure, if auto_ifconfig=NO.
dhcpcdNORun dhcpcd as a daemon for all interfaces. Not needed when the interface file starts it, as netconf does.
dhcpcd_flags-qMFlags for that daemon.
ip6modehosthost, autohost (accept router advertisements) or router (forward IPv6).
hostname""Host name; /etc/hostname.file is also read at boot.
defaultroute, defaultroute6""A default gateway, as an alternative to a route line in the interface file.
sshdNOStart the SSH server.
certctl_initYESFill /etc/openssl/certs on the first boot that finds it empty.
inetdYESThe Internet super-server (/etc/inetd.conf).
namedNOThe BIND DNS server.

The resolver reads /etc/resolv.conf. With DHCP, dhcpcd fills it through resolvconf. For a static setup, write it yourself (or let netconf do it):

nameserver 192.168.1.1
nameserver 9.9.9.9

/etc/hosts works as usual. dig, host and nslookup (from BIND 9.20.24) are in base for testing.

The DHCP client is dhcpcd 10.3.1 (ISC’s dhclient was removed). It handles IPv4 leases, and IPv6 router solicitation and DHCPv6 when not limited with -4. Its hooks in /libexec/dhcpcd-hooks update resolv.conf and the host name. Configuration is in /etc/dhcpcd.conf; see dhcpcd.conf(5).

The stack is built with IPv6, including fragment reassembly and forwarding. ping6, traceroute6, ndp and rtadvd are in base. To get an address automatically, choose “DHCP (IPv4 + IPv6)” in netconf; for a static one, add an inet6 line to the interface file:

inet6 2001:db8::20 prefixlen 64

The TCP/IP stack is lwIP 2.2.1, with later upstream security fixes, running as an ordinary process, /service/lwip. It implements the BSD socket API for TCP, UDP, raw IP, routing sockets and BPF (/dev/bpf, used by tcpdump). Local (Unix-domain) sockets are a separate server, uds.

Ixolo has added to it:

  • TCP window scaling, SACK and timestamps (RFC 7323, RFC 2018), a 128 KB receive window and larger send buffers. On a link with 20 ms of round-trip time, throughput between two VMs went from 0.67 to 2.51 MB/s.
  • SO_REUSEPORT, which spreads incoming connections across several listening sockets (BIND’s multi-threaded named needs it).
  • NetBSD’s multicast socket options, link state in ifconfig, and accept4/paccept.

If lwIP crashes, RS restarts it like any other service, using the recovery script /etc/rs.lwip. A new lwIP has none of the old state, so:

  • every open socket is gone: established TCP connections break, and programs must reconnect;
  • the script stops and restarts the known network daemons (dhcpcd, inetd, sshd, syslogd, named, network…) so that they reopen their sockets and the interfaces are configured again.

A crashed network driver is cheaper: RS restarts it, lwIP reattaches the new process to the same interface, and the configuration and the sockets survive. At most some packets are lost and TCP resends them. Try it in the break-a-driver lab.

ToolUse
ifconfigAddresses, flags and link state of the interfaces
routeThe routing table: route show, route add default <gw>
netstatSockets and statistics: netstat -an, netstat -rn
ping, ping6Reachability
traceroute, traceroute6The path to a host
arp, ndpNeighbour caches (IPv4, IPv6)
tcpdumpPacket capture (4.99.6)
ftpDownloads over FTP, HTTP and HTTPS: ftp https://example.org/file
telnetTest a TCP port

OpenSSH 10.6 is in base: ssh, scp, sftp, ssh-keygen, ssh-agent and the server sshd. It is built without PAM and without FIDO security keys. The client works out of the box:

Terminal window
ssh alice@server.example.org

The server is off by default. Enable it and start it; the first start creates the ECDSA, Ed25519 and RSA host keys:

Terminal window
echo sshd=YES >> /etc/rc.conf
service sshd start

The configuration is /etc/ssh/sshd_config. As in stock OpenSSH, root may log in only with a key (PermitRootLogin prohibit-password). Users need a password set with passwd, or a key in ~/.ssh/authorized_keys.

To reach the guest’s SSH server from a QEMU host, forward a port:

Terminal window
qemu-system-x86_64 ... -nic user,model=e1000,hostfwd=tcp::2222-:22
ssh -p 2222 alice@localhost # on the host

The live ISO has a read-only /etc, so run the server on an installed system.

Programs that use OpenSSL (3.5.7) verify servers against the trust anchors in /etc/openssl/certs. They come from Mozilla’s CA list, installed in /usr/share/certs/mozilla, and certctl builds the directory from them:

Terminal window
certctl list # trusted certificates
certctl rehash # rebuild /etc/openssl/certs after a change

On an installed system, certctl_init=YES builds the directory on the first boot. The live ISO carries it prebuilt. To trust a local CA, put its certificate in a directory of its own, add a path line for that directory to /etc/openssl/certs.conf and run certctl rehash. certctl untrust distrusts a certificate. See certctl(8).