The MirageOS Blogon building functional operating systems


Connected Cloud Control: OpenFlow in MirageOS

By Richard Mortier

Due to continuing development, some of the details in this blog post are now out-of-date. It is archived here.

Something we've been working on for a little while now that we're pretty excited about is an OpenFlow implementation for MirageOS. For those who're not networking types, in short, OpenFlow is a protocol and framework for devolving network control to software running on platforms other than the network elements themselves. It consists of three main parts:

  • a controller, responsible for exercising control over the network;
  • switches, consisting of switching hardware, with flow tables that apply forwarding behaviours to matching packets; and
  • the protocol, by which controllers and switches communicate.

For more -- and far clearer! -- explanations, see any of the many online OpenFlow resources such as OpenFlowHub.

Within MirageOS we have an OpenFlow implementation in two parts: individual libraries that provide controller and switch functionality. Linking the switch library enables your application to become a software-based OpenFlow switch. Linking in the controller library enables your application to exercise direct control over OpenFlow network elements.

The controller is modelled after the NOX open-source controller and currently provides only relatively low-level access to the OpenFlow primitives: a very cool thing to build on top of it would be a higher-level abstraction such as that provided by Nettle or Frenetic.

The switch is primarily intended as an experimental platform -- it is hopefully easier to extend than some of the existing software switches while still being sufficiently high performance to be interesting!

By way of a sample of how it fits together, here's a skeleton for a simple controller application:

type mac_switch = {
  addr: OP.eaddr; 
  switch: OP.datapath_id;

type switch_state = {
  mutable mac_cache: 
        (mac_switch, OP.Port.t) Hashtbl.t;
  mutable dpid: OP.datapath_id list

let switch_data = {
  mac_cache = Hashtbl.create 7; 
  dpid = [];

let join_cb controller dpid evt =
  let dp = match evt with
      | OE.Datapath_join c -> c
      | _ -> invalid_arg "bogus datapath_join"
  switch_data.dpid <- switch_data.dpid @ [dp]

let packet_in_cb controller dpid evt =
  (* algorithm details omitted for space *)

let init ctrl = 
  OC.register_cb ctrl OE.DATAPATH_JOIN join_cb;
  OC.register_cb ctrl OE.PACKET_IN packet_in_cb

let main () =
  Net.Manager.create (fun mgr interface id ->
    let port = 6633 in 
    OC.listen mgr (None, port) init

We've written up some of the gory details of the design, implementation and performance in a short paper to the ICC Software Defined Networking workshop. Thanks to some sterling work by Haris and Balraj, the headline numbers are pretty good though: the unoptimised Mirage controller implementation is only 30--40% lower performance than the highly optimised NOX destiny-fast branch, which drops most of the programmability and flexibility of NOX; but is about six times higher performance than the fully flexible current NOX release. The switch's performance running as a domU virtual machine is indistinguishable from the current Open vSwitch release.

For more details see the paper or contact Mort, Haris or Anil. Please do get in touch if you've any comments or questions, or you do anything interesting with it!