Copy myswitch.py to the directory pox/pox/misc, before you start, and edit only the latter.
To run this, you will need two root-login windows. In the first window, invoke mininet as follows:
Then, start up pox in the second window as follows, from /root/pox; this will run myswitch.py (note the .py extension is not entered here). Using log.level --WARNING gets rid of a lot of annoying messages; the default log.level is INFO.
./pox.py log.level --WARNING misc.myswitch
At any time you can halt Pox (with CNTL-C) and restart it, without restarting mininet. Stopping and restarting Pox will leave the openflow tables in the switches alone, also, at least for a while.
Since you're running pox in its own window, print statements will appear right there, and you won't need the logging facility.
Handy Mininet commands are:
h1 ping -c 1 h2 # single ping
pingall # should install all hosts into all switch forwarding tables
Information about Pox objects can be found, along with examples, in openflow.stanford.edu/display/ONL/POX+Wiki. Find misc.of_tutorial in the index and follow the link; that leads to a very detailed page on the exercise.The program, as it stands now, keeps for each switch a Python dictionary mac_to_port that maps an Ethernet address to the switch port by which it is reached. The line in act_like_switch() implements the source learning:
There are really two approaches here. Approach one should be sufficient, but once you get that working, approach two is cool:
Approach one: use self.resend_packet(packet_in, port) to have the controller tell the switch to resend the packet out the given port. This means that the controller will look in the switch's mac_to_port dictionary to see if the appropriate port (next_hop) is known. If it is, use self.resend_packet() to send packet_in to that port. If It is not, then send packet_in to of.OFPP_FLOOD (or ALL).
Approach two: use msg = of.ofp_flow_mod() / msg.match.dl_dst = ... / msg.actions.append(...) to install a new forwarding rule in the switch (so packets with the matching destination can be handled by the switch with no further interaction with the controller).
If working on approach two, remember that you can use the command ovs-ofctl dump-tables s1 to
examine the forwarding table of a switch (here s1). Approach two will
require matching on both dst and src, much like in the
For either approach, you need to complete the code in act_like_switch(). Once it's reasonable (that is, once you think it might compile), change _handle_PacketIn() according to this:
Comment out the following line and uncomment the one after
# when starting the exercise.
For act_like_switch() itself, the Pox website has more on what's in the parameters packet and packet_in. However, I've set the important values:
pdst = packet.dst
inport = packet_in.in_port
# outport defined below
# switch is self.switchnum
The basic idea is that you will replace act_like_hub()'s
by changing of.OFPP_ALL to the specific next_hop port number.
1. What if the controller keeps a mac_to_port table for each switch, and, once it knows how to reach both ha and hb, installs destination-based forwarding routes for ha and hb:
of.ofp_flow_mod() # pld: always start here
msg.match.dl_dst = ha
msg.actions.append(of.ofp_action_output(port = self.mac_to_port[ha]))
self.connection.send(msg) # send flow message to switch via connection
And the same for hb. (This was the approach outlined in the July 27 class.) What happens? This works for 1 switch. This works for two switches.
But for three or more switches in the switchline.py configuration, after a single pingall the last switch is unknown to the earlier switches. Packets from the earlier switches to the last one have to be flooded; this is not correct. Suppose N=3. Then after h1 pings h2, s1 and s2 both have forwarding entries for h1 and h2. When h1 pings h3, s1 and s2 flood the packet. When h3 replies, s1 and s2 simply forward the packet, as they have destination entries for h1, and never report the packet to the controller. So the controller never installs a forwarding entry for h3, even though the controller knows where h3 is.
Hint: wait until the controller knows about both entries, and then add two pair-style forwarding entries, where the match is on both the destination address and the source address.
2. What if the controller uses this (not working)
if (srcaddr is NOT in the forwarding table)
add flow rule: reach srcaddr via srcport
This is what happens with 5 linear switches and a pingall:
The core problem is that it's new source addresses that switches must inform the controller about, but the flows above match only on the destination address. So, if a packet arrives at a switch S with a destination known to S, then S will not contact the controller even if the source is new.