The last blog entry I demonstrated how to configure a Juniper EX9200 switch to communicate with an Openflow controller (POX). The flow entry logic was very basic. It turned all the ports on the Openflow switch into a dumb hub. Flood out all ports except for the source.
In this post I'll demonstrate how to create a more unique flow entry. This is based on the 10-tuple OpenFlow v1.0 header fields which are:
Ingress Port, Ethec Src, Ether Dst, Ether Type, Vlan ID, IP Dst, IP Src, TCP Dst, TCP Src, and IP Proto
First we need to figure out what a host does on a layer 2 network. If Host A wants to talk to Host B, it will first send out an ARP packet asking what is the mac address of Host B based on the IP address. After recieving a reply, Host A will send a unicast frame with the destnation Mac of Host B. Host B in turn will send unicast packets back to Host A. This means we need to program three types of flows. One for ARP and two for unicast packets for each direction.
Below is the output in action:
jnpr@EX9200-RE0> show openflow flows detail
jnpr@EX9200-RE0>
Next I startup the openflow controller:
jnpr@ubuntu:~/OPENFLOW-CONTROLLER$ ./pox.py misc.static
POX 0.2.0 (carp) / Copyright 2011-2013 James McCauley, et al.
INFO:core:POX 0.2.0 (carp) is up.
INFO:openflow.of_01:[3c-8a-b0-0d-c7-c0 1] connected
INFO:misc.static:sending to DPID ARP flow creation
INFO:misc.static:sending to DPID flow creation->
INFO:misc.static:sending to DPID flow creation<-
On the EX switch:
jnpr@EX9200-RE0> show openflow flows detail
Flow name: flow-16842752
Table ID: 1 Flow ID: 16842752
Priority: 32768 Idle timeout(in sec):0 Hard timeout(in sec): 0
Match: Input port: 1
Ethernet src addr: wildcard
Ethernet dst addr: wildcard
Input vlan id: 100 Input VLAN priority: wildcard
Ether type: 0x800
IP ToS: wildcard IP protocol: wildcard
IP src addr: wildcard IP dst addr: 10.1.1.3/32
Source port: 0 Destination port: 0
Action: Output port 2,
Flow name: flow-33619968
Table ID: 1 Flow ID: 33619968
Priority: 32768 Idle timeout(in sec):0 Hard timeout(in sec): 0
Match: Input port: 2
Ethernet src addr: wildcard
Ethernet dst addr: wildcard
Input vlan id: 100 Input VLAN priority: wildcard
Ether type: 0x800
IP ToS: wildcard IP protocol: wildcard
IP src addr: wildcard IP dst addr: 10.1.1.2/32
Source port: 0 Destination port: 0
Action: Output port 1,
Flow name: flow-83951616
Table ID: 1 Flow ID: 83951616
Priority: 32768 Idle timeout(in sec):0 Hard timeout(in sec): 0
Match: Input port: wildcard
Ethernet src addr: wildcard
Ethernet dst addr: wildcard
Input vlan id: wildcard Input VLAN priority: wildcard
Ether type: 0x806
IP ToS: 0x0 IP protocol: wildcard
IP src addr: wildcard IP dst addr: wildcard
Source port: 0 Destination port: 0
Action: Output port 65531,
jnpr@EX9200-RE0> show openflow flows
Switch Flow Number of packets Priority Number of Number of
Name ID match action
oftest-92k 16842752 248 32768 6 1
oftest-92k 33619968 248 32768 6 1
oftest-92k 83951616 4 32768 4 1
Python code for POX
jnpr@ubuntu:~/OPENFLOW-CONTROLLER/pox/misc$ cat static.py
---------------------
from pox.core import core
from pox.lib.packet.ipv4 import ipv4
from pox.lib.packet.arp import arp
import pox.lib.packet as pkt
import pox.openflow.libopenflow_01 as of
import re
log = core.getLogger()
class Sdn (object):
def __init__ (self, connection):
self.connection = connection
connection.addListeners(self)
# FIRST OPENFLOW RULE - ARP
#create an Openflow using flow table modification
arp = of.ofp_flow_mod()
#Define a match structure for your flow rules to follow
#if ether type is 0x0806 or Arp
arp.match.dl_type = 0x0806
# Add an action to send to flood out all ports except the source
arp.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
# program flow on switch
self.connection.send(arp)
#Send debug message for controller
log.info("sending to DPID ARP flow creation " )
# FIRST OPENFLOW RULE
#create an Openflow using flow table modification
msg = of.ofp_flow_mod()
#Define a match structure for your flow rules to follow
msg.match.in_port = 1
msg.match.dl_vlan = 100
msg.match.dl_type = 0x0800
msg.match.nw_dst = "10.1.1.3/32"
# Add an action to send to the specified port
msg.actions.append(of.ofp_action_output(port = 2))
# Send message to switch
self.connection.send(msg)
#Debug message for controller
log.info("sending to DPID flow creation->" )
# SECOND OPENFLOW RULE
#create an Openflow using flow table modification
msg2 = of.ofp_flow_mod()
#Define a match structure for your flow rule
msg2.match.in_port = 2
msg2.match.dl_vlan = 100
msg2.match.dl_type = 0x0800
msg2.match.nw_dst = "10.1.1.2/32"
# Add an action to send to the specified port
msg2.actions.append(of.ofp_action_output(port = 1))
# Send message to switch
self.connection.send(msg2)
#Debug message for controller
log.info("sending to DPID flow creation<-" )
def launch ():
"""
Starts the component
"""
def start_switch (event):
log.debug("Controlling DPID %s" % (event.connection,))
Sdn(event.connection)
core.openflow.addListenerByName("ConnectionUp", start_switch)
No comments:
Post a Comment