package net.floodlightcontroller.core.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import org.openflow.protocol.statistics.OFDescriptionStatistics;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitchDriver;
/**
* This implementation of ISwitchDriverRegistry uses a naiive algorithm to
* perform longest prefix matching on the manufacturere description prefixes
*
* We maintain a map that maps prefixes to the drivers as well as a sorted
* set that contains the prefixes sorted by their length. We exploit the fact
* that lexicographical order defines that shorter strings are always less
* than longer strings with the same prefix). Thus we can use reverse order for
* our purposes.
* To perform a lookup we iterate through the sorted set until we find a prefix
* that matches the manufacturer description. Since the set is sorted this
* will be the longest matching prefix.
*
* @author gregor
*/
class NaiiveSwitchDriverRegistry implements ISwitchDriverRegistry {
private final SortedSet<String> switchDescSorted;
private final Map<String,IOFSwitchDriver> switchBindingMap;
public NaiiveSwitchDriverRegistry() {
switchBindingMap = new HashMap<String, IOFSwitchDriver>();
switchDescSorted = new TreeSet<String>(Collections.reverseOrder());
}
@Override
public synchronized void addSwitchDriver(String manufacturerDescPrefix,
IOFSwitchDriver driver) {
if (manufacturerDescPrefix == null) {
throw new NullPointerException("manufacturerDescrptionPrefix" +
" must not be null");
}
if (driver == null) {
throw new NullPointerException("driver must not be null");
}
IOFSwitchDriver existingDriver = switchBindingMap.get(manufacturerDescPrefix);
if (existingDriver != null ) {
throw new IllegalStateException("Failed to add OFSwitch driver for "
+ manufacturerDescPrefix + "already registered");
}
switchBindingMap.put(manufacturerDescPrefix, driver);
switchDescSorted.add(manufacturerDescPrefix);
}
@Override
// TODO: instead of synchronized we could actually use a r/w lock
// but it's probably not worth it.
public synchronized IOFSwitch
getOFSwitchInstance(OFDescriptionStatistics description) {
if (description == null)
throw new NullPointerException("description must not be null");
if (description.getHardwareDescription() == null) {
throw new NullPointerException(
"hardware description must not be null");
}
if (description.getManufacturerDescription() == null) {
throw new NullPointerException(
"manufacturer description must not be null");
}
if (description.getSerialNumber() == null) {
throw new NullPointerException(
"serial number must not be null");
}
if (description.getDatapathDescription() == null) {
throw new NullPointerException(
"datapath description must not be null");
}
if (description.getSoftwareDescription() == null) {
throw new NullPointerException(
"software description must not be null");
}
// Find the appropriate driver
for (String descPrefix: switchDescSorted) {
if (description.getManufacturerDescription()
.startsWith(descPrefix)) {
IOFSwitchDriver driver = switchBindingMap.get(descPrefix);
IOFSwitch sw = driver.getOFSwitchImpl(description);
if (sw != null) {
sw.setSwitchProperties(description);
return sw;
}
}
}
// no switch found
IOFSwitch sw = new OFSwitchImpl();
sw.setSwitchProperties(description);
return sw;
}
}