--- /dev/null
+= README
+
+linux-network-namespace-labs is a small program to create networking lab
+setups based on Linux network namespaces in a simple manner. It provides a
+quick way to setup labs using a text file describing the architecture
+(networks, nodes, links, commands). This is much simpler than running each
+node in a separate virtual machine. It is licensed under GPLv3+.
+
+
+== Requirements
+
+- Linux compiled with `CONFIG_NET_NS` (available on most modern systems)
+- iproute2 (`ip`)
+- Go, no external dependencies
+
+
+== Build
+
+ $ go build
+
+Then copy the binary `linux-network-namespace-labs` to somewhere in your
+`$PATH`.
+
+
+== Usage
+
+The following configuration from `examples/readme/` setups a lab with three
+nodes (routers) and configures static routes.
+
+----
+# Network range for loopback addresses of the nodes
+net loops 192.0.2.0/24 3fff::/20
+# Network range for interfaces between nodes
+net addrs 198.51.100.0/24 2001:db8::/32
+
+# Setup three nodes (routers) and assign IPv4 and IPv6 loopback addresses
+node r1 loops
+node r2 loops
+node r3 loops
+
+# Links between routers: /31 or /127 is used for each interface
+link r1 r2 addrs
+link r2 r3 addrs
+
+# Commands to run on each node; $1 is the node name (= name of network
+# namespace). Here it's used to setup static routes but can also be used to
+# start routing daemons like bird.
+cmd ./setup.sh $1
+----
+
+Then setup the lab by running (as root):
+
+ # cd examples/readme
+ # linux-network-namespace-labs up lab.conf
+ [...]
+
+Now you can enter the network namespace of each router and test a simple
+traceroute:
+
+ # ip netns exec r1 sh
+ # ip -br a
+ lo UNKNOWN 127.0.0.1/8 ::1/128
+ lo2 UNKNOWN 192.0.2.0/32 3fff::/128 fe80::438:67ff:fe0a:4e58/64
+ r2@if287 UP 198.51.100.0/31 2001:db8::/127 fe80::a896:cdff:fe58:5c23/64
+ # traceroute 192.0.2.2
+ traceroute to 192.0.2.2 (192.0.2.2), 30 hops max, 60 byte packets
+ 1 r2 (198.51.100.1) 0.937 ms 0.818 ms 0.768 ms
+ 2 r3-loop (192.0.2.2) 0.722 ms 0.650 ms 0.603 ms
+
+Use `exit` to leave the network namespace.
+
+`/etc/hosts` of each node (via `/etc/netns/<ns>/hosts`) is automatically
+filled with all known addresses so you can use hostnames as well:
+
+ # ping -c1 r3-loop
+ PING r3-loop(r3-loop (3fff::2)) 56 data bytes
+ 64 bytes from r3-loop (3fff::2): icmp_seq=1 ttl=63 time=0.266 ms
+ --- r3-loop ping statistics ---
+ 1 packets transmitted, 1 received, 0% packet loss, time 0ms
+ rtt min/avg/max/mdev = 0.266/0.266/0.266/0.000 ms
+
+When you change the configuration you can simply rerun "up" and it will remove
+the lab (and killing all processes inside it) before starting it up again:
+
+ # linux-network-namespace-labs up lab.conf
+ [...]
+
+When you're done you can remove the lab with:
+
+ # linux-network-namespace-labs down lab.conf
+ [...]
+
+To get an overview of the network you can create a
+https://en.wikipedia.org/wiki/DOT_(graph_description_language)[DOT] file:
+
+ $ linux-network-namespace-labs dot lab.conf lab.dot
+ $ dot -Tpng lab.dot > lab.png
+
+image::examples/readme/lab.png[DOT style diagram of network nodes and links]
+
+
+== Examples
+
+Have a look at `examples/` for a few small examples which also include running
+https://bird.network.cz/[Bird] on each node and spawning a Podman container
+inside the created nodes running https://frrouting.org/[FRR].
+
+
+== Syntax of configuration file
+
+One option per line, empty lines are permitted as well as comments at the
+beginning of the line with `#`.
+
+The config files is parsed from top to bottom and the options "net", "node",
+"link" must be given in this order. "cmd" can be put anywhere (but is only
+executed at the end).
+
+=== Option "net"
+
+ "net" <name> <prefix>...
+
+"net" creates a new prefix which is used to allocate addresses for loopback
+and link interfaces. Multiple IPv4 and IPv6 prefixes can be specified. When
+the network is used one address of each prefix is assigned to the interface.
+
+=== Option "node"
+
+ "node" <name> [<loopback-net-name>...]
+
+"node" creates a new node (router) and (if specified) assigns loopback
+addresses from the given networks. The loopback addresses are assigned to a
+new interface "lo2".
+
+=== Option "link"
+
+ "link" <node> <node> <net-name>
+
+"link" creates (veth-)links between nodes. The IP addresses are taken from the
+given network name. /31 is used for IPv4- and /127 for IPv6-prefixes. The MAC
+address is not static and allocated by the kernel. The link is named after the
+node "on the other side". Multiple links can be created between two nodes. In
+this case "_2", "_3", etc. is appended to the interface name.
+
+=== Option "cmd"
+
+ "cmd" <string-passed-to-sh-c>
+
+"cmd" runs the given command (by passing it as is to `sh -c`) on each node.
+The first argument is the name of the node (which is also the name of the
+network namespace). This can be used to run setup commands or routing daemons
+on the nodes.
+
+If "cmd" is not flexible enough you can simply use `ip netns exec` to manually
+run commands on specific nodes.
+
+
+== Authors
+
+Written by Simon Ruderich <simon@ruderich.org>.
+
+Please report bugs, feature requests and patches via email.
+
+
+== License
+
+This program is licensed under GPL version 3 or later.
+
+Copyright (C) 2024 Simon Ruderich
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.