In this topic, we’ll discuss about how to simulate a network environment using only your Linux system’s kernel and some management tools. There’s a well-consolidated tool that makes this a piece of cake, but what if we wanted to do the same with our own hands?
The Mininet Network Simulator
The Mininet is a tool developed in Python and widely used in teaching and researching network technologies accross the globe. In my time we used Cisco’s Packet Tracer to do this sort of testing and teaching, but when you want to teach SDN concepts, then the Packet Tracer isn’t actually the best tool for this scenario. Mininet allows you to create a whole topology in your machine with just a single command.
The idea behind Mininet is: you choose the way you want your topology built, or use some of the presets, it will start the kernel structures and processes necessary to you and even show you a CLI so you can interact directly with the objects of your topology (hosts, links, switches and controller) and let you run some common commands like ping to test out the connectivity in the topology.
Mininet is originally based in the Open vSwitch (OvS) for switching and a Stanford Reference Controller for controlling those, but you can customize even the bin you’ll be using for switch and controller and also passing parameters to those. You can also customize the links your switches and hosts will be communicating, like specifying the Throughput Rate or the Jitter of those.
Mininet was also extended to other use-cases: there’s Mininet-Wifi, developed and maintained by Dr. Ramon Fontes and Dr. Christian Rothenberg, that’s capable of simulating the behavior of a Wi-Fi wireless network even considering distance, obstacles and propagation patterns, enabling the test of scenarios like Handover between stations and Seemless Roaming. Other use-case is the Mininet-Optical, that uses the GN-Model of optical transmission for link behavior simulation, and also adds several optical network components like transceivers, ROADMs and other.
You can install Mininet following the instructions at mininet.org and can make some tests in an emulated environment using the “mn” command. If you just run “mn”, it will instantiate a minimum topology with 2 hosts, 1 switch and 1 controller. You can specify different topos using the “–topo” option and can customize the topology if you have enough knowledge of Python by using it’s available API through the classes available in the code.
The main idea here is not to focus on Mininet, but actually on some of the structures that’s hidden behind the magic it simulator does.
Two basic structures: vETHs and NetNS
For it’s internal working, Mininet uses 2 kernel structures: one of the are the Virtual Interfaces, or vETHs (virtual Ethernets) that’s part of the iproute2 suite of tooling. The other structure are the Network Namespaces, that allows you to divide the kernel network resources in groups and hide their content one from another, like the expected behavior of a set of hosts in a network. All the commands in this section must be runned as Root or using Sudo to have higher-priviledges.
vETHs are always created in pairs, that means that if you create one point of your link, you must also already create the other, and they will be as configurable as a physical interface would be in your system: you can define the MAC Address, IP Address, MTU, state (UP/DOWN) and some other resources. For creating a vETH, you’ll need to use the command “ip link add type veth <veth1 name> peer name <veth2 name>“. For example, let’s suppose I want to connect an virtual interface that will represent Host1’s first interface in my topology with the vETH that will represent the Host2’s first interface in the same topology. I could use the following command: “ip link add type veth h1-eth0 peer name h2-eth0“. With that, all traffic sent through h1-eth0 will reach h2-eth0 and vice-versa.
Now, one Host should only be able to see it’s own interfaces, not others, and have the same restrictions you’d have in forwarding a package in a network (for example, Host1 shouldn’t be able to send a packet from Host2’s interface, it’s not possible in a real scenario), so we need to separate then in their own “namespace”, so they can’t have access to each other’s resources. For this, we use Network Namespaces (NetNS), a kernel structure for dividing those resources. We can use the command “ip netns add <netns name>“. For example, we can create the NetNS for each host using the “ip netns add h1” and “ip netns add h2” commands.
Since we created our interfaces outside the NetNS we created later, we can move each host’s interface to their respective NetNS using the command “ip link set <interface> netns <netns name>“, for example: “ip link set h1-eth0 netns h1“. Doing that for both interfaces, then each other won’t be able to see the other interfaces, not even the kernel interfaces. For us to validate that, we need to run a command inside the NetNS. It’s possible using the iproute2 tooling with the following command: “ip netns exec <netns name> <command and arguments>“. So, for us to see the interfaces available in each NetNS, we can use the command “ip netns exec h1 ip link” and “ip netns exec h2 ip link“, it will show us the links available from each NetNS.
Now, we can define ip addresses for each interface and try a ping between them. Since the interfaces are inside the NetNS, we’ll need to use the “ip netns exec” command to add the ip addresses. Let’s consider h1-eth0 as “10.10.10.1/24” and h2-eth0 as “10.10.10.2/24“, then our commands will be: “ip netns exec h1 ip address add 10.10.10.1/24 dev h1-eth0” and “ip netns exec h2 ip address add 10.10.10.2/24 dev h2-eth0“. Now that we have the addresses set in each interface, we need to set then “UP” so we can use then and each host’s routing tables be populated with each interface’s routes. For that, we’ll need to execute the “ip link set up dev <interface>” in each NetNS for the referred interface. So: “ip netns exec h1 ip link set up dev h1-eth0” and “ip netns exec h2 ip link set up dev h2-eth0“. After running both commands, we can start a ping from Host1 to Host2 to test our connection: “ip netns exec h1 ping 10.10.10.2“. You’ll see the ping is working!
To clean up everything, you just need to remove both NetNS: “ip netns del h1” and “ip netns del h2“. To make more complex topologies, you’ll need software capable of forwarding packets from one NetNS to other through the interfaces, or use other software switches that runs outside the NetNS but are connected to the vETH in the other end. You can also connect your physical interfaces in the vETHs using a structure called MacVLAN, but that’s for other post!
That’s all for now, folks!
If you enjoyed this post, please leave a comment and share it if your friends who are interested in Computer Networks =) In a later post I’ll try covering the Software Switches like OVS and BMv2, maybe even use python to show a simple switching software using the Scapy library.