Skip to content

Controller Programming Guide (English)

Byungjoon Lee edited this page Mar 19, 2014 · 2 revisions

This document explains how to program a user-defined controller.

How to create a controller with modules that you want

Before going into the detail, you should understand following concepts first.

  • Controller
  • Module
  • Pipeline

Basically, a controller is a subclass of OFController class. When you define your own controller, you inherit the OFController class, and override some of the methods. Because it's a very easy procedure, you can grasp the basic concept by inspecting the bundled BasicOFController implementation.

package etri.sdn.controller.app.basic;

import java.util.LinkedList;
import java.util.List;

import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;

import etri.sdn.controller.MessageContext;
import etri.sdn.controller.OFController;
import etri.sdn.controller.OFModule;
import etri.sdn.controller.module.devicemanager.OFMDefaultEntityClassifier;
import etri.sdn.controller.module.devicemanager.OFMDeviceManager;
import etri.sdn.controller.module.firewall.OFMFirewall;
import etri.sdn.controller.module.forwarding.Forwarding;
import etri.sdn.controller.module.linkdiscovery.OFMLinkDiscovery;
import etri.sdn.controller.module.netfailover.OFMNetFailover;
import etri.sdn.controller.module.statemanager.OFMStateManager;
import etri.sdn.controller.module.storagemanager.OFMStorageManager;
import etri.sdn.controller.module.topologymanager.OFMTopologyManager;
import etri.sdn.controller.module.ui.OFMUserInterface;
import etri.sdn.controller.protocol.io.Connection;

public class BasicOFController extends OFController {

	private OFMUserInterface m_user_interface = new OFMUserInterface();
	private OFMLinkDiscovery m_link_discovery = new OFMLinkDiscovery();
	private OFMTopologyManager m_topology_manager = new OFMTopologyManager();
	private OFMDefaultEntityClassifier m_entity_classifier = new OFMDefaultEntityClassifier();
	private OFMDeviceManager m_device_manager = new OFMDeviceManager();
	private OFMStateManager m_state_manager = new OFMStateManager();
	private OFMStorageManager m_storage_manager = new OFMStorageManager();	
	private Forwarding m_forwarding = new Forwarding();
	private OFMFirewall m_firewall = new OFMFirewall();
	private OFMNetFailover m_netfailover = new OFMNetFailover();
	
	private OFModule[] packet_in_pipeline = { 
			m_link_discovery, 
			m_topology_manager,
			m_entity_classifier, 
			m_device_manager,
			m_firewall,
			m_forwarding
	};

	public BasicOFController(int num_of_queue, String role) {
		super(num_of_queue, role);
	}
	
	/**
	 * This method is automatically called to do initialization chores.
	 */
	@Override
	public void init() {
		m_link_discovery.init(this);
		m_topology_manager.init(this);
		m_entity_classifier.init(this);
		m_device_manager.init(this);
		m_state_manager.init(this);			// this is not a part of the pipeline.
		m_user_interface.init(this);		// this is not a part of the pipeline.
		m_storage_manager.init(this);		// this is not a part of the pipeline.
		m_firewall.init(this);
		m_forwarding.init(this);
		m_netfailover.init(this);
	}

	@Override
	public boolean handlePacketIn(Connection conn, MessageContext context, OFMessage m) {
		List<OFMessage> out = new LinkedList<OFMessage>();
		for ( int i = 0; i < packet_in_pipeline.length; ++i ) {
			boolean cont = packet_in_pipeline[i].processMessage( conn, context, m, out );
			if ( !conn.write(out) ) {
				return false;
			}
			if ( !cont ) {
				// we process this packet no further.
				break;
			}
			out.clear();
		}
		return true;
	}

	@Override
	public boolean handleGeneric(Connection conn, MessageContext context, OFMessage m) {
		
		OFType t = m.getType();
		
		if ( t == OFType.PORT_STATUS ) {
			List<OFMessage> out = new LinkedList<OFMessage>();

			m_link_discovery.processMessage( conn, context, m, out );
			if ( !conn.write(out) ) {
				// no further processing is possible.
				return true;
			}
		}
		else if ( t == OFType.FEATURES_REPLY ) {
			return m_link_discovery.processHandshakeFinished( conn, context );
		}
		return true;
	}
}

A controller provides entry-points that Openflow messages go into. On accepting an Openflow message, the controller decides how to process the message. As you can easily verify from the above code, Openflow PACKET_IN message goes into a special struct, named 'pipeline' of IRIS modules.

A pipeline is a sequence of IRIS modules. For example, a PACKET_IN message is first passed to the handlePacketIn method, and it delivers the message first into OFMLinkDiscovery module (which is the first module of the pipeline) which discovers links between switches automatically using LLDP packets. Discovered link information is passed to OFMTopologyManager, which builds a topological in-memory database of links and switches. OFMDeviceManager manages switches and devices, and their attachment points (switch ports).

Openflow packets that do not require the pipeline processing (such as PORT_STATUS) are mostly handled by handleGeneric method.

As depicted, you can easily create a controller implementation that suits your needs by using the existing modules. Each module is a set of specific functions targeted to manage a specific part of the network dynamics. Each module is a subclass of OFModule, and its implementation is much more complicated than that of the controller. We will explain further about that in the other wiki page.

Controller installation

After implementing the controller, you should export the source as Jar file under the controllers directory. When you export the file, you should be careful to make its filename include package hierarchy. For example, BasicOFController is in the package etri.sdn.controller.app.basic. That's why the filename is set to etri.sdn.controller.app.basic.BasicOFController.jar. The filename is used by IRIS to load the controller implementation dynamically.

After exporting the jar, you should modify torpedo.properties.

etri.sdn.controller.app.basic.BasicOFController.run = true

The above line is very important in executing your controller correctly. (You should not forget to turn off all the other controller's run flag to false.)

Clone this wiki locally