L3Routing.java

package edu.wisc.cs.sdn.apps.l3routing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.wisc.cs.sdn.apps.util.Host;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
import net.floodlightcontroller.core.IOFSwitchListener;
import net.floodlightcontroller.core.ImmutablePort;
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 net.floodlightcontroller.devicemanager.IDevice;
import net.floodlightcontroller.devicemanager.IDeviceListener;
import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
import net.floodlightcontroller.routing.Link;

public class L3Routing implements IFloodlightModule, IOFSwitchListener,
ILinkDiscoveryListener, IDeviceListener, IL3Routing
public static final String MODULE_NAME = L3Routing.class.getSimpleName();

// Interface to the logging system
private static Logger log = LoggerFactory.getLogger(MODULE_NAME);

// Interface to Floodlight core for interacting with connected switches
private IFloodlightProviderService floodlightProv;

// Interface to link discovery service
private ILinkDiscoveryService linkDiscProv;

// Interface to device manager service
private IDeviceService deviceProv;

// Switch table in which rules should be installed
private byte table;

// Map of hosts to devices
private Map knownHosts;

* Loads dependencies and initializes data structures.
public void init(FloodlightModuleContext context)
throws FloodlightModuleException
log.info(String.format(“Initializing %s…”, MODULE_NAME));
Map config = context.getConfigParams(this);
this.table = Byte.parseByte(config.get(“table”));

this.floodlightProv = context.getServiceImpl(
IFloodlightProviderService.class);
this.linkDiscProv = context.getServiceImpl(ILinkDiscoveryService.class);
this.deviceProv = context.getServiceImpl(IDeviceService.class);

this.knownHosts = new ConcurrentHashMap();

/*********************************************************************/
/* TODO: Initialize other class variables, if necessary */

/*********************************************************************/

* Subscribes to events and performs other startup tasks.
public void startUp(FloodlightModuleContext context)
throws FloodlightModuleException
log.info(String.format(“Starting %s…”, MODULE_NAME));
this.floodlightProv.addOFSwitchListener(this);
this.linkDiscProv.addListener(this);
this.deviceProv.addListener(this);

/*********************************************************************/
/* TODO: Perform other tasks, if necessary */

/*********************************************************************/

* Get the table in which this application installs rules.
public byte getTable()
{ return this.table; }

* Get a list of all known hosts in the network.
private Collection getHosts()
{ return this.knownHosts.values(); }

* Get a map of all active switches in the network. Switch DPID is used as
* the key.
private Map getSwitches()
{ return floodlightProv.getAllSwitchMap(); }

* Get a list of all active links in the network.
private Collection getLinks()
{ return linkDiscProv.getLinks().keySet(); }

* Event handler called when a host joins the network.
* @param device information about the host
public void deviceAdded(IDevice device)
Host host = new Host(device, this.floodlightProv);
// We only care about a new host if we know its IP
if (host.getIPv4Address() != null)
log.info(String.format(“Host %s added”, host.getName()));
this.knownHosts.put(device, host);

/*****************************************************************/
/* TODO: Update routing: add rules to route to new host */

/*****************************************************************/

* Event handler called when a host is no longer attached to a switch.
* @param device information about the host
public void deviceRemoved(IDevice device)
Host host = this.knownHosts.get(device);
if (null == host)
host = new Host(device, this.floodlightProv);
this.knownHosts.put(device, host);

log.info(String.format(“Host %s is no longer attached to a switch”,
host.getName()));

/*********************************************************************/
/* TODO: Update routing: remove rules to route to host */

/*********************************************************************/

* Event handler called when a host moves within the network.
* @param device information about the host
public void deviceMoved(IDevice device)
Host host = this.knownHosts.get(device);
if (null == host)
host = new Host(device, this.floodlightProv);
this.knownHosts.put(device, host);

if (!host.isAttachedToSwitch())
this.deviceRemoved(device);
log.info(String.format(“Host %s moved to s%d:%d”, host.getName(),
host.getSwitch().getId(), host.getPort()));

/*********************************************************************/
/* TODO: Update routing: change rules to route to host */

/*********************************************************************/

* Event handler called when a switch joins the network.
* @param DPID for the switch
public void switchAdded(long switchId)
IOFSwitch sw = this.floodlightProv.getSwitch(switchId);
log.info(String.format(“Switch s%d added”, switchId));

/*********************************************************************/
/* TODO: Update routing: change routing rules for all hosts */

/*********************************************************************/

* Event handler called when a switch leaves the network.
* @param DPID for the switch
public void switchRemoved(long switchId)
IOFSwitch sw = this.floodlightProv.getSwitch(switchId);
log.info(String.format(“Switch s%d removed”, switchId));

/*********************************************************************/
/* TODO: Update routing: change routing rules for all hosts */

/*********************************************************************/

* Event handler called when multiple links go up or down.
* @param updateList information about the change in each link’s state
public void linkDiscoveryUpdate(List updateList)
for (LDUpdate update : updateList)
// If we only know the switch & port for one end of the link, then
// the link must be from a switch to a host
if (0 == update.getDst())
log.info(String.format(“Link s%s:%d -> host updated”,
update.getSrc(), update.getSrcPort()));
// Otherwise, the link is between two switches
log.info(String.format(“Link s%s:%d -> %s:%d updated”,
update.getSrc(), update.getSrcPort(),
update.getDst(), update.getDstPort()));

/*********************************************************************/
/* TODO: Update routing: change routing rules for all hosts */

/*********************************************************************/

* Event handler called when link goes up or down.
* @param update information about the change in link state
public void linkDiscoveryUpdate(LDUpdate update)
{ this.linkDiscoveryUpdate(Arrays.asList(update)); }

* Event handler called when the IP address of a host changes.
* @param device information about the host
public void deviceIPV4AddrChanged(IDevice device)
{ this.deviceAdded(device); }

* Event handler called when the VLAN of a host changes.
* @param device information about the host
public void deviceVlanChanged(IDevice device)
{ /* Nothing we need to do, since we’re not using VLANs */ }

* Event handler called when the controller becomes the master for a switch.
* @param DPID for the switch
public void switchActivated(long switchId)
{ /* Nothing we need to do, since we’re not switching controller roles */ }

* Event handler called when some attribute of a switch changes.
* @param DPID for the switch
public void switchChanged(long switchId)
{ /* Nothing we need to do */ }

* Event handler called when a port on a switch goes up or down, or is
* added or removed.
* @param DPID for the switch
* @param port the port on the switch whose status changed
* @param type the type of status change (up, down, add, remove)
public void switchPortChanged(long switchId, ImmutablePort port,
PortChangeType type)
{ /* Nothing we need to do, since we’ll get a linkDiscoveryUpdate event */ }

* Gets a name for this module.
* @return name for this module
public String getName()
{ return this.MODULE_NAME; }

* Check if events must be passed to another module before this module is
* notified of the event.
public boolean isCallbackOrderingPrereq(String type, String name)
{ return false; }

* Check if events must be passed to another module after this module has
* been notified of the event.
public boolean isCallbackOrderingPostreq(String type, String name)
{ return false; }

* Tell the module system which services we provide.
public Collection> getModuleServices()
Collection> services =
new ArrayList>();
services.add(IL3Routing.class);
return services;

* Tell the module system which services we implement.
public Map, IFloodlightService>
getServiceImpls()
Map, IFloodlightService> services =
new HashMap,
IFloodlightService>();
// We are the class that implements the service
services.put(IL3Routing.class, this);
return services;

* Tell the module system which modules we depend on.
public Collection>
getModuleDependencies()
Collection> modules =
new ArrayList>();
modules.add(IFloodlightProviderService.class);
modules.add(ILinkDiscoveryService.class);
modules.add(IDeviceService.class);
return modules;