In this exercise, you'll make a static layer-3 forwarder/switch. It's not exactly a router, because it won't decrement the IP TTL and recompute the checksum at each hop (so traceroute won't work). Actions to do TTL and checksum modification are expected in the upcoming OpenFlow version 1.1. However, it will match on masked IP prefix ranges, just like a real router.
From http://www.faqs.org/rfcs/rfc1812.html#ixzz0oPra4P9C:
An IP router can be distinguished from other sorts of packet switching devices in that a router examines the IP protocol header as part of the switching process. It generally removes the Link Layer header a message was received with, modifies the IP header, and replaces the Link Layer header for retransmission.
To simplify the exercise, your "router" will be completely static. With no BGP or OSPF, you'll have no need to send or receive route table updates.
Each network node will have a configured subnet. If a packet is destined for a host within that subnet, the node acts as a switch and forwards the packet with no changes, to a known port or broadcast, just like in the previous exercise. If a packet is destined for some IP address for which the router knows the next hop, it should modify the layer-2 destination and forward the packet to the correct port.
Our hope is that this exercise will show that with an OpenFlow-enabled forwarding device, the network is effectively layerless; you can mix switch, router, and higher-layer functionality.
Please note that this is an advanced exercise, and given that most implementation details are up to you, will be harder.
You'll need a slightly different topology, something like this:
… which will need to be described in a way that Mininet will understand.
There's an example custom topology at:
~/mininet/custom/topo-2sw-2host.py
First, copy the example to a new file:
$ cp ~/mininet/custom/topo-2sw-2host.py mytopo.py
To run a custom topology, pass Mininet the custom file and pass in the custom topology:
$ sudo mn --custom mytopo.py --topo mytopo --mac
Then, in the Mininet console, run:
mininet> pingall
Now, modify your topology file to match the picture and verify full host connectivity with pingall in the Mininet console.
Set up IP configuration on each virtual host to force each one to send to the gateway for destination IPs that are outside of their configured subnet.
You'll need to configure each host with a subnet, IP, gateway, and netmask.
It may seem obvious, but we will warn you anyway: do not attempt to assign IP addresses to the interfaces belonging to switches s1 and s2. If you need to handle traffic "to" or "from" a switch, do so using OpenFlow.
There are several ways that this can be done:
- Unix commands via Mininet CLI
mininet> h2 ifconfig h2-eth0 10.0.1.2/24 mininet> h2 route add default gw 10.0.1.1 mininet> h2 route -n
- Regular Unix commands via an xterm
mininet> xterm h2
and then to type into that xterm window to configure the host:
# ifconfig h2-eth0 10.0.1.2/24
- Running a configuration script
mininet> h2 config_script
If you write such a script, you can either have it automatically know what to do (e.g. based on MAC address, which you can assign based on node number with --mac ) or pass in additional parameters as desired.
- CLI scripting
mininet> source my_cli_script
or
# mn --pre my_cli_script
A sample CLI script might look like:
py "Configuring network" h3 ifconfig h3-eth0 10.0.1.2/24 h4 ifconfig h4-eth0 10.0.1.3/24 h5 ifconfig h5-eth0 10.0.2.2/24 h3 route add default gw 10.0.1.1 h4 route add default gw 10.0.1.1 h5 route add default gw 10.0.2.1 py "Current network:" net dump
CLI scripting is designed to save typing rather than to be a full programming environment (although you can evaluate Python expressions from the CLI, as shown above using the 'py' command!) For advanced tasks, the Mininet API provides flexible access to all Mininet capabilities.
- Mininet API
- Changing the node IDs in the topology
The node ID in a topology is the default IP address in base 256. For example, setting node ID 258 will result in a default IP address of 10.0.1.2.
The default IP prefix length may be changed with the command-line option --prefixlen. For example,
# mn --prefixlen 24
will use /24 as the default prefix length (i.e. netmask of 255.255.255.0).
For the this tutorial, you may find that using CLI scripting or changing the node IDs (and setting the prefix length to 24) may be most convenient.
Once you have your new topology configured and connected to your pytutorial controller, you should be able to ping between hosts on the same subnet, but not between hosts on different subnets. Your job is to create a new (or revised) controller that installs rules to forward packets between the two subnets!
A router generally has to respond to ARP requests. You will see ethernet broadcasts which will (initially at least) be forwarded to the controller.
Your controller should probably construct ARP replies and forward them out the appropriate ports.
It may be possible to avoid dealing with ARP (at least initially) by adding static ARP entries in each host for all of the nodes on its subnet.
Once ARP has been handled, you will need to handle routing for the static configuration. Since we know what is connected to each port, we can match on IP address (or prefix, in the case of the remote subnet) and forward out the appropriate port.
In the case of the left switch, for example, we will want to forward packets destined for an attached host to the appropriate port, while packets destined for the remote subnet should be forwarded to the right switch.
Additionally, your controller may receive ICMP echo (ping) requests for each switch, which it should respond to.
Lastly, packets for unreachable subnets should be responded to with ICMP network unreachable messages.
If the router works properly:
- attempts to send from 10.0.1.2 to an unknown address range like 10.99.0.1 should yield an http://en.wikipedia.org/wiki/ICMP_Destination_Unreachable message.
- packets sent to hosts on the same subnet should be treated like before.
- packets sent to hosts on a known address range should have their MAC dst field changed to that of the next-hop router.
- the router should be pingable, and should generate an ICMP echo reply in response to an ICMP echo request.
Let the instructor know when you get stuck or when you complete the exercise. This one is more open, and you'll need different actions (MAC dst modify) and matching (IP dst/prefix combinations), for which NOX core.py should help.