It's useful when experimenting with network to have a lot of machines for testing — the development machine; a system under test; a machine running a packet capture. But that leads to a lot of machines. Another approach is to buy a USB hub and a handful of USB/ethernet dongles. Usually we're much more interested in mere connectivity rather than performance, so the shared USB bus back to the computer doesn't worry us.
Let's say a dongle appears as eth1. We can configure that separately from the main set of routing tables by using network namespaces. Users of networking platforms might know this as VRF — virtual routing and forwarding — but Linux's namespace approach applies more widely throughout the operating system than merely the networking components.
Begin by creating the network namespace:
$ sudo ip netns add TEST $ ip netns show TEST
[Aside: For descriptive clarity I am using a network namespace name which is all upper case. In the real world we will use lower case.]
Now move the eth1 interface into that namespace:
$ ip link show dev eth1 2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff $ ip link set dev eth1 netns TEST $ ip link show dev eth1 Device "eth1" does not exist.
The magic arrives when we can execute commands within that namespace, in this case ip link show dev eth1 to display the ethernet-layer details of eth1:
$ sudo ip netns exec TEST ip link show dev eth1 2: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff
The link is down. Let's bring it up:
$ sudo ip netns exec TEST ip link set dev eth1 up $ sudo ip netns exec TEST ip link show dev eth1 2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
Let's apply an IP address.
$ sudo ip netns exec TEST ip addr add 192.168.255.1/24 dev eth1
Note carefully that every namespace has its own routing table. Sometimes merely being connected to the subnet is enough to do what we need to do. But if we do need a default route then it can be added manually:
$ sudo ip netns exec TEST ip route add 0.0.0.0/0 via 192.168.255.254 dev eth1 $ sudo ip netns exec TEST ip route show default via 192.168.255.254 dev eth1 192.168.255.0/24 dev eth1 proto kernel scope link src 192.168.255.1 $ sudo ip netns exec TEST ping www.fsf.org 64 bytes from www.fsf.org (18.104.22.168): icmp_seq=1 ttl=43 time=266 ms
If we are connecting to a production network then DHCP works too:
$ sudo ip netns exec TEST dhclient -v eth1 Listening on LPF/eth1/11:22:33:44:55:66 Sending on LPF/eth1/11:22:33:44:55:66 Sending on Socket/fallback DHCPREQUEST on eth1 to 255.255.255.255 port 67 DHCPACK from 192.168.255.254 bound to 192.168.255.96 -- renewal in 10000 seconds.
You'll recall that the concept of "namespaces" is broader than the concept of "VRFs". Although the "dhclient" program appears in ps's process list, the program is executing within the TEST network namespace. It is best to manipulate the program from within that network namespace by using the command ip netns exec …. We can see what network namespace a process is in with:
$ sudo ip netns pids TEST 12345 $ sudo ip netns identify 12345 TEST
As is usual, IPv6 just works. If there is subnet connectivity then the interface has a link local address. If there is global connectivity then the interface also has a global address. You can use IPv6 and mDNS (via Linux's "Avahi" package) to use symbolic names for systems under test.
We needn't be limited to just one namespace. Let's say we're testing a new SDN switch. We could put interface eth1 into a PORT1 namespace and cable it to Port 1 of the switch. We could put interface eth2 into a PORT2 namespace can cable it to Port 2 of the switch. By using namespaces we can be sure that a ping attempt from eth1 to eth2 isn't using the Linux machine's usual routing table, but is using the namespaces' routing tables. That routing can send the packets across the eth1, and — if the switch is working — through switch ports Port 1 and Port 2, before appearing at eth2.
When we are done we can list all the process IDs in the namespace, kill them all, then delete the namespace with:
$ sudo ip netns delete TEST
If we just want to move the interface out of the TEST namespace and into the default namespace that's made tricky by the default namespace having no name. Here's how to give that namespace a name and move the interface:
$ sudo touch /run/netns/default $ sudo mount --bind /proc/1/ns/net /run/netns/default $ sudo ip netns exec TEST ip link set dev eth1 down $ sudo ip netns exec TEST ip link set dev eth1 netns default $ sudo umount /run/netns/default $ sudo rm /run/netns/default
We set the interface to "down" to forestall the interface from conflicting with the addressing of another running interface in the destination namespace.