OpenFlow is a Layer 2 communications protocol that gives access to the forwarding plane of a network switch or router over the network… … In simpler terms, OpenFlow allows the path of network packets through the network of switches to be determined by software running on multiple routers (minimum two of them — primary and secondary — has a role of observers). This separation of the control from the forwarding allows for more sophisticated traffic management than is feasible using access control lists (ACLs) and routing protocols. Its inventors consider OpenFlow an enabler of software-defined networking (SDN) - Wikipedia.
This Document explores the differences between traditional networking infrastructure and SDN with OpenFlow.
OpenFlow enables networks to evolve, by giving a remote controller the power to modify the behavior of network devices, through a well-defined “forwarding instruction set”.
- http://www.openflow.org/
While servers and storage have evolved in cost, flexibility, speed of development, and performance, networking has not kept pace. The networking world today is still mostly a closed platform dominated by traditional networking vendors.
Closed Platform:
This is about to change drastically with software defined networking. The key idea is to move to a Open Platform with:
With a open platform innovative ways of networking a possible. Open standards and well understood hardware e.g. allow for separating the control from the data plane. The Spanning tree is a great example: Traditionally features like Spanning Tree must be implemented as a fully distributed algorithm in every closed stack at the protocol level. Some features like Spanning Tree get obsolete with this separation. You gain an outside view of the world.
The same is true with adding new features to network components. Traditionally each network component has to provide a feature. You can not simply add a feature from a 3rd party.
By separating the control from the data plane, features can be implemented as applications utilizing controllers which control each network component.
OpenFlow is one example for this new software defined networking world. OpenFlow provides:
OpenFlow introduces an OpenFlow Controller and the OpenFlow Protocol to talk to OpenFlow client enabled networking components.
The OpenFlow Controller allows for so called applications which implement the desired behavior and configure the Flow Table of an OpenFlow Client enabled component. Examples applications are: Hub, Switch, Traffic Monitor, Loadbalancer, ect.
Flow Table entries consist of a Rule, an Action and Stats
Some example flow table entries are shown here:
With OpenFlow Flow-Based and aggregated processing is possible.
Flow-Based:
Aggregated:
OpenFlow allows for a centralized or distributed controller model.
Reactive:
Proactive:
The main building blocks of OpenFlow are shown in the following figure:
NOX - Created by Nicira, supporting C++.
No quantum plugin.
Not to be confused with “NOX classic” an older implementation supporting both C++/Python.
An example hub implementation:
#include <boost/bind.hpp> #include <boost/shared_array.hpp> #include "assert.hh" #include "component.hh" #include "flow.hh" #include "packet-in.hh" #include "vlog.hh" #include "netinet++/ethernet.hh" namespace { using namespace vigil; using namespace vigil::container; Vlog_module lg("hub"); class Hub : public Component { public: Hub(const Context* c, const json_object*) : Component(c) { } void configure(const Configuration*) { } Disposition handler(const Event& e) { const Packet_in_event& pi = assert_cast<const Packet_in_event&>(e); uint32_t buffer_id = pi.buffer_id; Flow flow(pi.in_port, *(pi.get_buffer())); if (flow.dl_type == ethernet::LLDP){ return CONTINUE; } ofp_flow_mod* ofm; size_t size = sizeof *ofm + sizeof(ofp_action_output); boost::shared_array<char> raw_of(new char[size]); ofm = (ofp_flow_mod*) raw_of.get(); ofm->header.version = OFP_VERSION; ofm->header.type = OFPT_FLOW_MOD; ofm->header.length = htons(size); ofm->match.wildcards = htonl(0); ofm->match.in_port = htons(flow.in_port); ofm->match.dl_vlan = flow.dl_vlan; ofm->match.dl_vlan_pcp = flow.dl_vlan_pcp; memcpy(ofm->match.dl_src, flow.dl_src.octet, sizeof ofm->match.dl_src); memcpy(ofm->match.dl_dst, flow.dl_dst.octet, sizeof ofm->match.dl_dst); ofm->match.dl_type = flow.dl_type; ofm->match.nw_src = flow.nw_src; ofm->match.nw_dst = flow.nw_dst; ofm->match.nw_proto = flow.nw_proto; ofm->match.tp_src = flow.tp_src; ofm->match.tp_dst = flow.tp_dst; ofm->cookie = htonl(0); ofm->command = htons(OFPFC_ADD); ofm->buffer_id = htonl(buffer_id); ofm->idle_timeout = htons(5); ofm->hard_timeout = htons(5); ofm->priority = htons(OFP_DEFAULT_PRIORITY); ofm->flags = htons(0); ofp_action_output& action = *((ofp_action_output*)ofm->actions); memset(&action, 0, sizeof(ofp_action_output)); action.type = htons(OFPAT_OUTPUT); action.len = htons(sizeof(ofp_action_output)); action.port = htons(OFPP_FLOOD); action.max_len = htons(0); send_openflow_command(pi.datapath_id, &ofm->header, true); free(ofm); if (buffer_id == UINT32_MAX) { size_t data_len = pi.get_buffer()->size(); size_t total_len = pi.total_len; if (total_len == data_len) { send_openflow_packet(pi.datapath_id, *pi.get_buffer(), OFPP_FLOOD, pi.in_port, true); } } return CONTINUE; } void install() { register_handler<Packet_in_event>(boost::bind(&Hub::handler, this, _1)); } }; REGISTER_COMPONENT(container::Simple_component_factory<Hub>, Hub); }
POX - Same as NOX, but younger of the two projects and supports Python.
No quantum plugin.
An example hub implementation:
from pox.core import core import pox.openflow.libopenflow_01 as of class RepeaterHub (object): def __init__ (self, connection): self.connection = connection connection.addListeners(self) def send_packet (self, buffer_id, raw_data, out_port, in_port): msg = of.ofp_packet_out() msg.in_port = in_port if buffer_id != -1 and buffer_id is not None: msg.buffer_id = buffer_id else: if raw_data is None: return msg.data = raw_data action = of.ofp_action_output(port = out_port) msg.actions.append(action) self.connection.send(msg) def act_like_hub (self, packet, packet_in): self.send_packet(packet_in.buffer_id, packet_in.data, of.OFPP_FLOOD, packet_in.in_port) def _handle_PacketIn (self, event): packet = event.parsed if not packet.parsed: return packet_in = event.ofp self.act_like_hub(packet, packet_in) def launch (): def start_switch (event): RepeaterHub(event.connection) core.openflow.addListenerByName("ConnectionUp", start_switch)
Beacon - Research project written in Java by David Erickson, a PhD candidate at Stanford.
No quantum plugin.
Floodlight - Written in Java and recently opensourced by Big Switch Networks as “the foundation of a commercial controller product”.
In terms of Quantum plugins, Big Switch Networks stated on the project mailing list that it wasn’t in their roadmap, but encouraged the community to do it, e.g.: “…Big Switch also has a quantum plugin but its based on functionality not present in Floodlight on this point.”
An example hub implementation:
package net.floodlightcontroller.hub; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Map; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFPacketOut; import org.openflow.protocol.OFPort; import org.openflow.protocol.OFType; import org.openflow.protocol.action.OFAction; import org.openflow.protocol.action.OFActionOutput; import org.openflow.util.U16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Hub implements IFloodlightModule, IOFMessageListener { protected static Logger log = LoggerFactory.getLogger(Hub.class); protected IFloodlightProviderService floodlightProvider; public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; } @Override public String getName() { return Hub.class.getPackage().getName(); } public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { OFPacketIn pi = (OFPacketIn) msg; OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory() .getMessage(OFType.PACKET_OUT); po.setBufferId(pi.getBufferId()) .setInPort(pi.getInPort()); OFActionOutput action = new OFActionOutput() .setPort((short) OFPort.OFPP_FLOOD.getValue()); po.setActions(Collections.singletonList((OFAction)action)); po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); if (pi.getBufferId() == 0xffffffff) { byte[] packetData = pi.getPacketData(); po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length)); po.setPacketData(packetData); } else { po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength())); } try { sw.write(po, cntx); } catch (IOException e) { log.error("Failure writing PacketOut", e); } return Command.CONTINUE; } @Override public boolean isCallbackOrderingPrereq(OFType type, String name) { return false; } @Override public boolean isCallbackOrderingPostreq(OFType type, String name) { return false; } @Override public Collection<Class<? extends IFloodlightService>> getModuleServices() { return null; } @Override public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { return null; } @Override public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); return l; } @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); } @Override public void startUp(FloodlightModuleContext context) { floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); } }
Trema - Supports Ruby and C. Developed out of Japan according to their twitter feed.
NEC has created a Quantum plugin that works with Trema, as well as their commercial OpenFlow controller.
An example hub implementation:
class RepeaterHub < Controller def packet_in datapath_id, message send_flow_mod_add( datapath_id, :match => ExactMatch.from( message ), :actions => ActionOutput.new( OFPP_FLOOD ) ) send_packet_out( datapath_id, :packet_in => message, :actions => ActionOutput.new( OFPP_FLOOD ) ) end end
RYU - Written in Python by NTT, who have also directly contributed a Quantum plugin.
Quantum is an OpenStack project to provide “networking as a service” between interface devices (e.g., vNICs) managed by other Openstack services (e.g., nova).
Give cloud tenants an API to build rich networking topologies, and configure advanced network policies in the cloud.
Enable innovation plugins (open and closed source) that introduce advanced network capabilities
Let anyone build advanced network services (open and closed source) that plug into Openstack tenant networks.
Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag).
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