OpenFlow Tutorial
Based on:
def there_is_something_like_this(): return True if there_is_something_like_this(): print('It is a code. Paste it to the respective file.')
You can use either VirtualBox, VMWare, KDM, or Qemu.
Username: openflow, Password: openflowMininet is a tool that emulates an arbitrary openflow network on your machine.
How to run mininet:
Note: The default topology is a line with two hosts (h2 and h3) and a switch (s1).
By default, mininet boots its default controller and connects to the controller at localhost:6633.
To specify the controller's address, run:
sudo mn --controller remote --ip 127.0.0.1 --port 6633
Now, ping h3 from h2: mininet> h2 ping h3
Why do the pings fail?
By default, mininet boots its default controller and connects to the controller at localhost:6633.
To specify the controller's address, run:
sudo mn --controller remote --ip 127.0.0.1 --port 6633
Now, ping h3 from h2: mininet> h2 ping h3
Why do the pings fail?
Because there is no flow entry in s1, packets are forwarded to the controller.
But, you don't have any controller running on your machine.
So, packets are simply dropped!
There are a handful of controllers available:
In this tutorial, we use NOX Classic.
Open a new terminal.
Run: cd ~/noxcore/build/src/
Then, run: ./nox_core -v -v -i ptcp: pytutorial
Now, in your mininet terminal, rerun mininet.
Your NOX controller is running:
~/noxcore/src/nox/coreapps/examples/tutorial/pytutorial.py
Now let's see what this code does.
pytutorial.py
class pytutorial(Component): def __init__(self, ctxt): ... def learn_and_forward(self, dpid, inport, packet, buf, bufid): ... self.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport) ... def packet_in_callback(self, dpid, inport, reason, len, bufid, packet): if not packet.parsed: log.debug('Ignoring incomplete packet') else: self.learn_and_forward(dpid, inport, packet, packet.arr, bufid) return CONTINUE def install(self): self.register_for_packet_in(self.packet_in_callback)
def send_openflow(self, dp_id, buffer_id, packet, actions, inport=openflow.OFPP_CONTROLLER): """\brief Send an openflow packet to a datapath. This function is a convenient wrapper for send_openflow_packet and send_openflow_buffer for situations where it is unknown in advance whether the packet to be sent is buffered. If 'buffer_id' is -1, it sends 'packet'; otherwise, it sends the buffer represented by 'buffer_id'. @param dp_id datapath to send packet to @param buffer_id id of buffer to send out @param packet data to put in openflow packet @param actions list of actions or dp port to send out of @param inport dp port to mark as source (defaults to Controller port) """
Let's implement a control app that drops half of the packet.
How to implement it?
Let's implement a control app that drops half of the packet.
How to implement it?
from random import random ... if random() <= 0.5: self.send_openflow(...)
If you know which mac address is on which port, you can packets directly to their destination.
You can extract src and dst address using:
packet.src packet.dst
Now, log src and dst in the demo app.
Hint: src and dst are byte strings. You can covert them to string using mac_to_str.
Done? Ping your virtual machine.
If you know which mac address is on which port, you can packets directly to their destination.
You can extract src and dst address using:
packet.src packet.dst
Now, log src and dst in the demo app.
Hint: src and dst are byte strings. You can covert them to string using mac_to_str.
Done? Ping your virtual machine.
print(mac_to_str(packet.src), "-->", mac_to_str(packet.dst))
Now, build a dictionary of mac addresses to ports, and log its content.
To get the input port use:
msg.in_port
Done? Ping your virtual machine.
We are almost there...
Now, try to use your dictionary instead of using OFPP_FLOOD.
Done? Ping your virtual machine.
Pings are too slow!
Why?
What can we do?
We need to install flow-entries on the switch.
flow entry (matched action rules) = attributes + actions
def install_datapath_flow(self, dp_id, attrs, idle_timeout, hard_timeout, actions, buffer_id=None, priority=openflow.OFP_DEFAULT_PRIORITY, inport=None, packet=None): """\brief Add a flow entry to datapath. @param dp_id datapath to add the entry to @param attrs the flow as a dictionary (described above) @param idle_timeout # idle seconds before flow is removed from dp @param hard_timeout # of seconds before flow is removed from dp @param actions a list where each entry is a two-element list representing an action. Elem 0 of an action list should be an ofp_action_type and elem 1 should be the action argument (if needed). For OFPAT_OUTPUT, this should be another two-element list with max_len as the first elem, and port_no as the second """
# Attributes. attrs = {} attrs[core.IN_PORT] = inport attrs[core.DL_DST] = packet.dst # Actions. actions = [[openflow.OFPAT_OUTPUT, [0, outport]]] # Installs flow entries. self.install_datapath_flow(dpid, attrs, 0, 0, actions)
Done? ping your VMS! Faster, eh?
Any questions?
/
#