Mininet is an open-source network emulator that creates a realistic virtual network — hosts, switches, routers, links — on a single Linux machine in seconds. Each host runs in a lightweight Linux network namespace with its own interfaces, routing table, and process space. Switches are real Open vSwitch (OVS) or Linux bridge instances. Links are virtual Ethernet pairs with configurable bandwidth, delay, loss, and queue limits.
The result is a network that behaves like real hardware — you can run actual network applications (ping, iperf, curl, web servers, routing daemons) on Mininet hosts and get realistic results — without buying a single physical device.
Mininet is the standard platform for SDN (Software-Defined Networking) research, protocol prototyping, teaching, and OpenFlow controller development.
Why Mininet?
| Use Case |
What Mininet Provides |
| SDN development |
Test OpenFlow controllers against realistic topologies |
| Protocol research |
Experiment with routing, QoS, multipath without hardware |
| Teaching |
Students build and break networks safely |
| Performance testing |
Benchmark link utilisation, latency, throughput |
| Regression testing |
Automated network behaviour verification in CI/CD |
| Rapid prototyping |
Spin up a 100-node topology in under 10 seconds |
Architecture
Mininet uses Linux network namespaces to create isolated network stacks for each host, and virtual Ethernet (veth) pairs as links between them:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
┌─────────────────────────────────────────────────────────┐
│ Mininet Process │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Host h1 │ │ Host h2 │ │ Controller │ │
│ │ netns:h1 │ │ netns:h2 │ │ (POX/Ryu/etc) │ │
│ │ eth0 │ │ eth0 │ └────────┬─────────┘ │
│ └────┬─────┘ └────┬─────┘ │ OpenFlow │
│ │ veth │ veth │ │
│ ┌────▼───────────────▼──────────────┐ │ │
│ │ Open vSwitch (s1) │◄───┘ │
│ │ OpenFlow datapath │ │
│ └───────────────────────────────────┘ │
│ Linux Kernel │
└─────────────────────────────────────────────────────────┘
|
Key components:
-
Host — a Linux network namespace with one or more virtual interfaces, an independent routing table, and its own process space
-
Switch — an OVS or Linux bridge instance operating as an OpenFlow switch
-
Controller — an external (or built-in) OpenFlow controller managing switch flow tables
-
Link — a veth pair connecting a host port to a switch port, with optional
tc (traffic control) parameters
-
Mininet API — a Python library for building and controlling topologies programmatically
Installation
Option 1: Pre-built VM (Recommended for Beginners)
Download the official Mininet VM from mininet.org/download:
1
2
|
# Import the OVF into VirtualBox or VMware
# Default credentials: mininet / mininet
|
Option 2: Install on Ubuntu / Debian
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# Ubuntu 20.04 / 22.04
sudo apt update
sudo apt install -y mininet
# Verify
sudo mn --version
# mininet 2.3.x
# Install additional tools
sudo apt install -y openvswitch-switch \
python3-pip \
iperf iperf3 \
wireshark tshark \
xterm
# Install Python dependencies for custom topologies
pip3 install mininet
|
Option 3: Install from Source (Latest Features)
1
2
3
4
5
6
7
|
git clone https://github.com/mininet/mininet
cd mininet
sudo util/install.sh -a # Install everything (OVS, OF tools, POX)
# or selectively:
sudo util/install.sh -nfv # Mininet + OVS + OpenFlow reference switch
sudo util/install.sh -p # POX controller
sudo util/install.sh -r # Ryu controller
|
Verify Installation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
sudo mn --test pingall
# *** Creating network
# *** Adding controller
# *** Adding hosts:
# h1 h2
# *** Adding switches:
# s1
# *** Adding links:
# (h1, s1) (h2, s1)
# *** Configuring hosts
# h1 h2
# *** Starting controller
# *** Starting switches
# *** Waiting for switches to connect
# *** Ping: testing ping reachability
# h1 -> h2
# h2 -> h1
# *** Results: 0% dropped (2/2 received)
# *** Stopping network
|
The Mininet CLI
Start a basic two-host, one-switch topology:
This creates the default topology: 2 hosts (h1, h2) connected to 1 switch (s1) with a built-in OpenFlow controller (c0).
Essential CLI Commands
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
# Inside the Mininet CLI (mininet>)
help # List all available commands
nodes # Show all nodes (hosts, switches, controllers)
net # Show network connections
dump # Show node details (PID, interface, IP)
links # Show link status
ports # Show switch port assignments
# Run a command on a specific host
h1 ifconfig # Show h1's network interfaces
h1 ping -c 3 h2 # Ping from h1 to h2
h1 ip route # Show h1's routing table
h1 arp -n # Show h1's ARP table
# Connectivity tests
ping h1 h2 # Ping between two specific hosts
pingall # Ping between all host pairs
pingpair # Ping between first pair of hosts
# Open a terminal for a host (requires X11 or xterm)
xterm h1 # Open xterm for h1
xterm h1 h2 # Open xterms for h1 and h2
# Bandwidth test
iperf h1 h2 # TCP bandwidth test between h1 and h2
iperfudp h1 h2 # UDP bandwidth test
# Switch and controller interaction
sh ovs-vsctl show # Show OVS configuration
sh ovs-ofctl dump-flows s1 # Show OpenFlow flows on s1
sh ovs-ofctl dump-ports s1 # Show port statistics on s1
# Topology modification at runtime
py net.addHost('h3') # Add a host dynamically
py net.stop() # Stop the network
# Exit
exit
quit
|
Built-in Topologies
Mininet ships with several ready-made topologies, selectable with the --topo flag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# Minimal: 1 switch, 2 hosts (default)
sudo mn --topo minimal
# Single switch with N hosts
sudo mn --topo single,4 # 1 switch, 4 hosts
# Linear: N switches in a chain, 1 host per switch
sudo mn --topo linear,5 # s1-s2-s3-s4-s5, each with one host
# Tree: depth D, fanout F
sudo mn --topo tree,depth=3,fanout=2 # 3-level tree, 2 branches each
# Reversed linear
sudo mn --topo reversed,4
|
Topology with Custom Link Parameters
1
2
3
4
|
# Set link bandwidth (10 Mbps), delay (10ms), loss (1%)
sudo mn --topo single,3 \
--link tc,bw=10,delay=10ms,loss=1 \
--test pingall
|
Custom Topologies in Python
The real power of Mininet is the Python API. You can define any topology, set per-link parameters, assign custom IPs, and automate tests entirely in code.
Basic Custom Topology
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#!/usr/bin/env python3
"""
Simple custom topology: two switches, three hosts
"""
from mininet.net import Mininet
from mininet.node import Controller, OVSKernelSwitch
from mininet.link import TCLink
from mininet.topo import Topo
from mininet.log import setLogLevel
from mininet.cli import CLI
class MyTopo(Topo):
"""
Topology:
h1 ─── s1 ─── s2 ─── h3
\\ /
h2 ────
"""
def build(self):
# Add switches
s1 = self.addSwitch('s1')
s2 = self.addSwitch('s2')
# Add hosts with explicit IPs
h1 = self.addHost('h1', ip='10.0.1.1/24')
h2 = self.addHost('h2', ip='10.0.1.2/24')
h3 = self.addHost('h3', ip='10.0.1.3/24')
# Add links with bandwidth and delay parameters
self.addLink(h1, s1, bw=100, delay='1ms')
self.addLink(h2, s1, bw=100, delay='1ms')
self.addLink(s1, s2, bw=1000, delay='5ms')
self.addLink(h3, s2, bw=100, delay='1ms')
def run():
setLogLevel('info')
topo = MyTopo()
net = Mininet(
topo=topo,
switch=OVSKernelSwitch,
link=TCLink,
controller=Controller,
autoSetMacs=True
)
net.start()
print("\n--- Network Info ---")
print("Nodes:", [node.name for node in net.values()])
net.pingAll()
CLI(net) # Drop into interactive CLI
net.stop()
if __name__ == '__main__':
run()
|
1
|
sudo python3 my_topo.py
|
Fat-Tree Data Centre Topology
A fat-tree is the standard topology for multi-path data centre networks — k=4 gives 16 hosts, k=8 gives 128 hosts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#!/usr/bin/env python3
"""
k-ary Fat-Tree topology
k=4: 4 core, 8 aggregation, 8 edge switches, 16 hosts
"""
from mininet.topo import Topo
class FatTree(Topo):
def build(self, k=4):
num_pods = k
num_core = (k // 2) ** 2
num_agg = k * (k // 2)
num_edge = k * (k // 2)
num_host = k * (k // 2) ** 2
# Core switches
core = [self.addSwitch(f'c{i+1}') for i in range(num_core)]
pod_switches = []
for pod in range(num_pods):
# Aggregation switches for this pod
agg = [self.addSwitch(f'a{pod+1}_{j+1}') for j in range(k // 2)]
# Edge switches for this pod
edge = [self.addSwitch(f'e{pod+1}_{j+1}') for j in range(k // 2)]
pod_switches.append((agg, edge))
# Connect edge to aggregation (full mesh within pod)
for e in edge:
for a in agg:
self.addLink(e, a, bw=1000)
# Add hosts
for e_idx, e in enumerate(edge):
for h in range(k // 2):
host_id = pod * (k // 2) ** 2 + e_idx * (k // 2) + h + 1
host = self.addHost(
f'h{host_id}',
ip=f'10.{pod+1}.{e_idx+1}.{h+2}/24'
)
self.addLink(host, e, bw=1000)
# Connect aggregation to core (each agg connects to k/2 core switches)
core_idx = 0
for pod, (agg, edge) in enumerate(pod_switches):
for a_idx, a in enumerate(agg):
for j in range(k // 2):
c = core[a_idx * (k // 2) + j]
self.addLink(a, c, bw=10000)
if __name__ == '__main__':
from mininet.net import Mininet
from mininet.node import Controller, OVSKernelSwitch
from mininet.link import TCLink
from mininet.log import setLogLevel
from mininet.cli import CLI
setLogLevel('info')
topo = FatTree(k=4)
net = Mininet(topo=topo, switch=OVSKernelSwitch,
link=TCLink, controller=Controller)
net.start()
net.pingAll()
CLI(net)
net.stop()
|
Link Parameters and Traffic Control
Mininet’s TCLink applies Linux tc (traffic control) to each link, enabling realistic WAN simulation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
from mininet.link import TCLink
from mininet.topo import Topo
class WanSimTopo(Topo):
"""Simulate a WAN link between two sites."""
def build(self):
# Site A
h1 = self.addHost('h1', ip='10.1.0.1/24')
s1 = self.addSwitch('s1')
# Site B
h2 = self.addHost('h2', ip='10.2.0.1/24')
s2 = self.addSwitch('s2')
# Local LAN links — high bandwidth, low delay
self.addLink(h1, s1, bw=1000, delay='0.1ms')
self.addLink(h2, s2, bw=1000, delay='0.1ms')
# WAN link — limited bandwidth, 50ms RTT, 0.1% packet loss
self.addLink(
s1, s2,
cls=TCLink,
bw=10, # 10 Mbps
delay='25ms', # 25ms each way = 50ms RTT
loss=0.1, # 0.1% packet loss
max_queue_size=100
)
|
Link Parameter Reference
| Parameter |
Type |
Description |
bw |
float (Mbps) |
Maximum bandwidth |
delay |
string ('10ms', '1us') |
One-way propagation delay |
loss |
float (%) |
Random packet loss percentage |
max_queue_size |
int (packets) |
Queue size (affects bufferbloat) |
jitter |
string ('5ms') |
Random delay variation |
use_tbf |
bool |
Use token bucket filter (better rate control) |
Integrating with OpenFlow Controllers
Mininet switches speak OpenFlow — you can connect them to any external controller for SDN experiments.
Built-in Reference Controller
1
2
|
# Uses Mininet's default Python OpenFlow reference controller
sudo mn --controller default
|
Remote External Controller
1
2
3
4
5
|
# Point all switches at an external controller
sudo mn --controller remote,ip=192.168.1.100,port=6633
# Multiple switches, all connecting to the same remote controller
sudo mn --topo tree,3,2 --controller remote,ip=127.0.0.1,port=6653
|
Ryu Controller Integration
Ryu is a Python-based SDN framework — the most common choice for custom controller development:
1
2
3
4
5
6
|
# Terminal 1: Start a Ryu application
ryu-manager ryu.app.simple_switch_13 # Learning switch
# Terminal 2: Start Mininet pointing at Ryu
sudo mn --controller remote,ip=127.0.0.1,port=6633 \
--switch ovsk,protocols=OpenFlow13
|
Custom Controller in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#!/usr/bin/env python3
"""
Mininet with a custom inline controller.
The controller installs a simple learning switch behaviour.
"""
from mininet.net import Mininet
from mininet.node import Controller
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel
from mininet.cli import CLI
class LearningController(Controller):
"""Minimal OpenFlow learning switch controller."""
def start(self):
self.cmd('ovs-ofctl add-flow', self.name,
'priority=0,actions=CONTROLLER:65535')
def run():
setLogLevel('info')
topo = SingleSwitchTopo(4)
net = Mininet(topo=topo, controller=LearningController)
net.start()
net.pingAll()
CLI(net)
net.stop()
if __name__ == '__main__':
run()
|
POX Controller Example
POX is a Python OpenFlow controller framework included in Mininet installations:
1
2
3
4
5
6
|
# Start POX with the L2 learning switch component
cd ~/pox
python3 pox.py forwarding.l2_learning
# In a new terminal, connect Mininet
sudo mn --controller remote,port=6633 --topo single,4
|
Programmatic Network Control
Beyond topology creation, the Python API lets you control the network programmatically during a simulation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#!/usr/bin/env python3
"""
Automated test: build topology, run tests, collect results.
"""
from mininet.net import Mininet
from mininet.topo import LinearTopo
from mininet.node import OVSKernelSwitch, Controller
from mininet.link import TCLink
from mininet.log import setLogLevel
import time
def bandwidth_test(net):
"""Run iperf between all host pairs and return results."""
hosts = net.hosts
results = {}
for i, src in enumerate(hosts):
for dst in hosts[i+1:]:
print(f"\n--- iperf {src.name} → {dst.name} ---")
# Start iperf server on dst
dst.cmd('iperf3 -s -D')
time.sleep(0.5)
# Run iperf client on src (5-second test)
output = src.cmd(f'iperf3 -c {dst.IP()} -t 5 --json')
results[f'{src.name}→{dst.name}'] = output
# Stop iperf server
dst.cmd('kill %iperf3')
return results
def latency_test(net):
"""Measure round-trip latency between all pairs."""
hosts = net.hosts
print("\n=== Latency Matrix ===")
print(f"{'':8}", end='')
for h in hosts:
print(f"{h.name:>8}", end='')
print()
for src in hosts:
print(f"{src.name:8}", end='')
for dst in hosts:
if src == dst:
print(f"{'0':>8}", end='')
else:
result = src.cmd(
f'ping -c 5 -q {dst.IP()} 2>/dev/null '
f'| tail -1 | awk -F/ "{{print $5}}"'
)
print(f"{result.strip():>8}", end='')
print()
def run():
setLogLevel('warning')
# Linear topology: 4 switches, 4 hosts, 10Mbps links with 5ms delay
topo = LinearTopo(4)
net = Mininet(
topo=topo,
switch=OVSKernelSwitch,
link=TCLink,
controller=Controller,
autoSetMacs=True,
waitConnected=True
)
net.start()
print("=== Connectivity Test ===")
packet_loss = net.pingAll(timeout=1)
print(f"Packet loss: {packet_loss:.1f}%")
latency_test(net)
bandwidth_test(net)
net.stop()
print("\nTests complete.")
if __name__ == '__main__':
run()
|
Working with Open vSwitch Directly
Because Mininet switches are real OVS instances, you can inspect and manipulate them with standard ovs-vsctl and ovs-ofctl commands:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# Inside Mininet CLI or from the host shell:
# Show OVS configuration
sh ovs-vsctl show
# Show flow tables on switch s1
sh ovs-ofctl dump-flows s1
# Add a manual OpenFlow flow: forward all traffic from port 1 to port 2
sh ovs-ofctl add-flow s1 "priority=100,in_port=1,actions=output:2"
# Add a flow matching on IP destination
sh ovs-ofctl add-flow s1 \
"priority=200,ip,nw_dst=10.0.0.2,actions=output:2"
# Delete all flows on s1
sh ovs-ofctl del-flows s1
# Show port statistics
sh ovs-ofctl dump-ports s1
# Monitor flow events in real time
sh ovs-ofctl monitor s1
|
Packet Capture Inside Mininet
1
2
3
4
5
6
7
8
|
# Capture traffic on h1's interface from within h1
mininet> h1 tcpdump -i h1-eth0 -w /tmp/h1.pcap &
# Capture on a switch port
mininet> sh tcpdump -i s1-eth1 -n &
# View capture with tshark
mininet> h1 tshark -r /tmp/h1.pcap
|
iperf3 Throughput Tests
1
2
3
4
5
6
7
8
9
10
11
|
# Start server on h2
mininet> h2 iperf3 -s &
# Run 10-second TCP test from h1
mininet> h1 iperf3 -c 10.0.0.2 -t 10
# UDP bandwidth test at 5 Mbps
mininet> h1 iperf3 -c 10.0.0.2 -u -b 5M -t 10
# Parallel streams (simulate multiple flows)
mininet> h1 iperf3 -c 10.0.0.2 -P 4 -t 10
|
Latency Measurement
1
2
3
4
5
6
7
8
|
# Basic round-trip time
mininet> h1 ping -c 100 h2
# High-resolution latency with hping3
mininet> h1 hping3 -c 100 -S -p 80 10.0.0.2
# Traceroute through the topology
mininet> h1 traceroute -n 10.0.0.3
|
Built-in Mininet Benchmarks
1
2
3
4
5
6
7
8
|
# Test CLI startup time and pingall
sudo mn --test pingall
# Test switch datapath performance
sudo mn --test iperf
# All tests
sudo mn --test all
|
Advanced: Custom Node Types
Host with Custom Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
from mininet.node import Host
class RouterHost(Host):
"""A host configured as an IP router."""
def config(self, **params):
super().config(**params)
# Enable IP forwarding
self.cmd('sysctl -w net.ipv4.ip_forward=1')
# Disable reverse path filtering
self.cmd('sysctl -w net.ipv4.conf.all.rp_filter=0')
def terminate(self):
self.cmd('sysctl -w net.ipv4.ip_forward=0')
super().terminate()
class NATHost(Host):
"""A host that performs NAT on outbound traffic."""
def config(self, wan_intf='eth0', **params):
super().config(**params)
self.cmd('sysctl -w net.ipv4.ip_forward=1')
self.cmd(f'iptables -t nat -A POSTROUTING -o {wan_intf} -j MASQUERADE')
|
Switch with Custom OpenFlow Version
1
2
3
4
5
6
7
8
9
10
|
from mininet.node import OVSSwitch
class OVS13Switch(OVSSwitch):
"""OVS switch forced to OpenFlow 1.3."""
def __init__(self, name, **params):
OVSSwitch.__init__(self, name,
failMode='secure',
protocols='OpenFlow13',
**params)
|
Mininet-WiFi (Wireless Extension)
Mininet-WiFi extends Mininet with IEEE 802.11 wireless station and access point emulation:
1
2
3
4
5
6
7
|
# Install
git clone https://github.com/intrig-unicamp/mininet-wifi
cd mininet-wifi
sudo util/install.sh -Wlnfv
# Run a basic wireless topology
sudo python3 examples/simple.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from mn_wifi.net import Mininet_wifi
from mn_wifi.node import Station, OVSKernelAP
net = Mininet_wifi()
sta1 = net.addStation('sta1', ip='10.0.0.1/8')
sta2 = net.addStation('sta2', ip='10.0.0.2/8')
ap1 = net.addAccessPoint('ap1', ssid='mininet-wifi',
mode='g', channel='1',
position='50,50,0')
net.configureWifiNodes()
net.addLink(sta1, ap1)
net.addLink(sta2, ap1)
net.build()
net.start()
sta1.cmd('ping -c 3 10.0.0.2')
net.stop()
|
Common Issues and Solutions
| Problem |
Cause |
Solution |
mn: command not found |
Mininet not installed |
sudo apt install mininet or install from source |
RTNETLINK: File exists on startup |
Previous topology not cleaned up |
sudo mn -c to clean up |
| Hosts cannot ping each other |
No controller / no flows installed |
Start a controller first or use --controller default
|
ovs-vsctl: unix:... connection failed |
OVS not running |
sudo systemctl start openvswitch-switch |
| High latency on veth links |
Kernel bridge overhead |
Use TCLink and set explicit delay parameters |
xterm not opening |
No X11 / display |
Set DISPLAY=:0 or use --xterms flag with SSH X11 forwarding |
iperf shows 0 bandwidth |
Firewall blocking or no flows |
Check ovs-ofctl dump-flows and firewall rules |
| Python script permission denied |
Not running as root |
Prefix with sudo
|
| Controller not connecting |
Wrong IP/port |
Verify controller is listening: ss -tlnp \| grep 6653
|
Cleanup After a Crash
1
2
|
sudo mn -c
# Cleans up namespaces, OVS bridges, veth pairs, and processes
|
Integration with Real Networks
Mininet can bridge its virtual network to a real physical interface, enabling communication between emulated hosts and real machines:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from mininet.net import Mininet
from mininet.node import Controller, OVSKernelSwitch
from mininet.link import Link
from mininet.topo import SingleSwitchTopo
net = Mininet(topo=SingleSwitchTopo(2),
switch=OVSKernelSwitch,
controller=Controller)
# Add a NAT interface (connects Mininet to the real network)
net.addNAT().configDefault()
net.start()
# Mininet hosts can now reach the internet through the host's real NIC
net.hosts[0].cmd('ping -c 3 8.8.8.8')
from mininet.cli import CLI
CLI(net)
net.stop()
|
Quick Reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# Start / stop
sudo mn # Default minimal topology
sudo mn --topo single,4 # 1 switch, 4 hosts
sudo mn --topo linear,5 # Linear chain of 5 switches
sudo mn --topo tree,depth=3,fanout=2 # 3-level tree
sudo mn --controller remote,ip=127.0.0.1,port=6653
sudo mn --link tc,bw=10,delay=10ms
sudo mn --test pingall # Run and auto-test
sudo mn -c # Clean up after crash
# CLI commands
nodes / net / dump / links
h1 ping -c 3 h2
h1 iperf3 -c 10.0.0.2 -t 5
pingall / pingpair
xterm h1
sh ovs-vsctl show
sh ovs-ofctl dump-flows s1
sh ovs-ofctl add-flow s1 "priority=100,in_port=1,actions=output:2"
# Python API essentials
from mininet.net import Mininet
from mininet.topo import Topo
from mininet.node import Controller, OVSKernelSwitch
from mininet.link import TCLink
from mininet.log import setLogLevel
from mininet.cli import CLI
topo = MyTopo()
net = Mininet(topo=topo, switch=OVSKernelSwitch,
link=TCLink, controller=Controller)
net.start()
net.pingAll()
CLI(net)
net.stop()
|
Conclusion
Mininet compresses an entire network lab into a single Linux process. The combination of real Linux network namespaces, actual OVS dataplane, and a clean Python API makes it simultaneously a teaching tool, a research platform, and a CI/CD testing framework. You can prototype a new SDN controller application in the morning, validate it against a 100-node fat-tree topology at lunchtime, and have regression tests running in a pipeline by end of day — all on a laptop.
The natural progression from Mininet is Containernet (Mininet with Docker containers as hosts, enabling realistic application stacks), GNS3 (graphical network simulator that can embed Mininet topologies), and physical SDN testbeds where the same OpenFlow controller code developed in Mininet is deployed against real hardware switches.
Additional Resources