OpenFlow is a technology for implementing software defined networking (SDN). This Document guides you through a hands-on example on how to create a learning switch with Trema a full stack SDN development environment.
To demonstrate OpenFlow and its usage we use a switch that “learns” the hosts on its network. The network consists of one switch and two hosts:
Trema uses a build in OpenVswitch for the switching. This can be seen in the process list:
vagrant@vagrant:~$ ps -ef|grep switch vagrant 18248 2891 0 01:05 pts/2 00:00:00 /usr/bin/ruby1.8 /usr/local/bin/trema run learning_switch.rb -c learning-switch.conf vagrant 18254 1 0 01:05 ? 00:00:00 /var/lib/gems/1.8/gems/trema-0.2.5/objects/switch_manager/switch_manager --daemonize --port=6633 -- port_status::LearningSwitch packet_in::LearningSwitch state_notify::LearningSwitch vendor::LearningSwitch root 18325 1 0 01:05 ? 00:00:08 /var/lib/gems/1.8/gems/trema-0.2.5/objects/openvswitch/bin/ovs-openflowd --detach --out-of-band --fail=closed --inactivity-probe=180 --rate-limit=40000 --burst-limit=20000 --pidfile=/var/lib/gems/1.8/gems/trema-0.2.5/tmp/pid/open_vswitch.0xabc.pid --verbose=ANY:file:dbg --verbose=ANY:console:err --log-file=/var/lib/gems/1.8/gems/trema-0.2.5/tmp/log/openflowd.0xabc.log --datapath-id=0000000000000abc --unixctl=/var/lib/gems/1.8/gems/trema-0.2.5/tmp/sock/ovs-openflowd.0xabc.ctl --ports=trema0-0,trema1-0 netdev@vsw_0xabc tcp:127.0.0.1:6633 vagrant 18329 1 0 01:05 ? 00:00:00 switch.127.0.0.1:49381 --name=switch.127.0.0.1:49381 --socket=3 --daemonize state_notify::switch_manager port_status::LearningSwitch packet_in::LearningSwitch state_notify::LearningSwitch vendor::LearningSwitch
The Trema network configuration for this switch is:
vswitch { dpid "0xabc" } vhost ("host1") { ip "192.168.0.1" netmask "255.255.0.0" mac "00:00:00:01:00:01" } vhost ("host2") { ip "192.168.0.2" netmask "255.255.0.0" mac "00:00:00:01:00:02" } link "0xabc", "host1" link "0xabc", "host2"
The purpose of the learning switch is to memorize which host is connected to which port of the switch and send packages to the known hosts.
So first we need something to store and retrieve this kind of information in the controller. What we want to do is have a mac address and get a port id or put a port id to a mac adress. This is simply a Hash:
class FDB def initialize @db = {} end def lookup mac @db[ mac ] end def learn mac, port_no @db[ mac ] = port_no end end
Another thing to take away from this is that the controller knows about the configuration. We simply could store this somewhere remote in a service application and connect to it later on (e.g. to initialize a switch)
If we receive a message we learn the mac address of the host connected to the port and lookup the destination of the message. If we already have seen a message from the source mac address we get a port_no from the lookup and will send the message to this port. If not we simply flood the message.
class LearningSwitch < Controller ... def packet_in dpid, message @fdb.learn message.macsa, message.in_port port_no = @fdb.lookup( message.macda ) if port_no flow_mod dpid, message, port_no packet_out dpid, message, port_no else flood dpid, message end end ... end
So how does the switch know what to do with a message? We have to update the flow table of the switch. This is done with the flow_mod
method.
def flow_mod dpid, message, port_no send_flow_mod_add( dpid, :match => ExactMatch.from( message ), :actions => ActionOutput.new( port_no ) ) end
Simply put this means: If you ever see a message like this one send it the port port_no
. This does update the flow table to actually send the message during this flow-table update process we additionally have to send it. This is done with the packet_out
method:
def packet_out dpid, message, port_no send_packet_out( dpid, :packet_in => message, :actions => ActionOutput.new( port_no ) ) end
The only thing missing is what to do with a message we do not have neither a flow table entry nor a controller lookup result? We flood it to all ports with the flood
method:
def flood dpid, message packet_out dpid, message, OFPP_FLOOD end
There is a vagrant Virtualbox with Trema already installed and the learning switch example ready to use at: https://github.com/ehaselwanter/virtualbox-sdn
Terminal 1:
trema run learning_switch.rb -c learning-switch.conf
Terminal 2:
vagrant@vagrant:~$ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4): vagrant@vagrant:~$ trema show_stats host2 Sent packets: Received packets: vagrant@vagrant:~$ watch trema show_stats host2
Terminal 3:
trema send_packet --source host1 --dest host2 trema send_packet --source host1 --dest host2 trema send_packet --source host2 --dest host1 trema send_packet --source host2 --dest host1 vagrant@vagrant:~$ trema show_stats host2 Sent packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.1,1,192.168.0.2,1,2,100 Received packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.2,1,192.168.0.1,1,2,100 vagrant@vagrant:~$ trema show_stats host1 Sent packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.2,1,192.168.0.1,1,2,100 Received packets: ip_dst,tp_dst,ip_src,tp_src,n_pkts,n_octets 192.168.0.1,1,192.168.0.2,1,2,100 vagrant@vagrant:~$ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4): cookie=0x1, duration=180.465s, table=0, n_packets=1, n_bytes=64, priority=65535,udp,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:01:00:02,dl_dst=00:00:00:01:00:01,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,tp_src=1,tp_dst=1 actions=output:2 trema send_packet --source host1 --dest host2 trema send_packet --source host1 --dest host2 trema send_packet --source host2 --dest host1 trema send_packet --source host2 --dest host1 vagrant@vagrant:~$ trema dump_flows 0xabc NXST_FLOW reply (xid=0x4): cookie=0x1, duration=310.596s, table=0, n_packets=3, n_bytes=192, priority=65535,udp,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:01:00:02,dl_dst=00:00:00:01:00:01,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,tp_src=1,tp_dst=1 actions=output:2 cookie=0x2, duration=54.63s, table=0, n_packets=1, n_bytes=64, priority=65535,udp,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:01:00:01,dl_dst=00:00:00:01:00:02,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,tp_src=1,tp_dst=1 actions=output:1
Interested in Cloud or Chef Trainings? Have a look at our Commandemy Trainings page. Need help migrating to the cloud? Check out Infralovers.
comments powered by Disqus