Summary

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.

Introduction

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:

  • Specialized Hardware
  • Closed proprietary stack
  • Slow innovation

closed-open.png

This is about to change drastically with software defined networking. The key idea is to move to a Open Platform with:

  • Standard, well understood hardware
  • Open standards and a vibrant 3rd party ecosystem
  • Very fast innovation

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.

control-data-plane-separation.png

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:

  • Separation of the control and the data plane
  • Clean abstractions and an easy programming model for networking
  • Faster innovation, lower costs, and more

OpenFlow introduces an OpenFlow Controller and the OpenFlow Protocol to talk to OpenFlow client enabled networking components.

openflow-layers.png

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.

example-network.png

Flow Table entries consist of a Rule, an Action and Stats

basic-table.png

Some example flow table entries are shown here:

flow-table.png

With OpenFlow Flow-Based and aggregated processing is possible.

Flow-Based:

  • Every flow is individually set up by controller
  • Exact-match flow entries
  • Flow table contains one entry per flow
  • Good for fine grain control, e.g. campus networks

Aggregated:

  • One flow entry covers large groups of flows
  • Wildcard flow entries
  • Flow table contains one entry per category of flows
  • Good for large number of flows, e.g. backbone

OpenFlow allows for a centralized or distributed controller model.

centralized-distributed-control.png

Reactive:

  • First packet of flow triggers controller to insert flow entries
  • Efficient use of flow table
  • Every flow incurs small additional flow setup time
  • If control connection lost, switch has limited utility

Proactive:

  • Controller pre-populates flow table in switch
  • Zero additional flow setup time
  • Loss of control connection does not disrupt traffic
  • Essentially requires aggregated (wildcard) rules

The main building blocks of OpenFlow are shown in the following figure:

building-blocks.png

OpenFow Controllers

NOX

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

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

Beacon - Research project written in Java by David Erickson, a PhD candidate at Stanford.

No quantum plugin.

Floodlight

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

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

RYU - Written in Python by NTT, who have also directly contributed a Quantum plugin.

Quantum and OpenFlow

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.

  • Example: create multi-tier web application topology

Enable innovation plugins (open and closed source) that introduce advanced network capabilities

  • Example: use L2-in-L3 tunneling to avoid VLAN limits, provide end-to-end QoS guarantees, used monitoring protocols like NetFlow.

Let anyone build advanced network services (open and closed source) that plug into Openstack tenant networks.

  • Examples: LB-aaS, VPN-aaS, firewall-aaS, IDS-aaS, data-center-interconnect-aaS.

quantum.png quantum-trema.png

Open vSwitch

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).

References

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
Blog Tags