From 7e62acea5808a0de3254996bc402b92754df0637 Mon Sep 17 00:00:00 2001 From: Ryan Izard <rizard@g.clemson.edu> Date: Thu, 31 Jul 2014 17:53:53 -0700 Subject: [PATCH] Initial OF1.3 handshake and basic Hub module working --- .../core/NullConnection.java | 2 +- .../core/OFConnection.java | 8 +- .../floodlightcontroller/core/OFSwitch.java | 2 + .../core/internal/Controller.java | 129 +- .../core/internal/ControllerCounters.java | 6 +- .../core/internal/OFSwitchManager.java | 1340 ++++++++--------- .../core/web/CounterResource.java | 3 +- .../flowcache/FlowReconcileManager.java | 66 +- .../flowcache/FlowReconcileQuery.java | 39 +- .../loadbalancer/LoadBalancer.java | 327 ++-- .../routing/ForwardingBase.java | 2 +- 11 files changed, 923 insertions(+), 1001 deletions(-) diff --git a/src/main/java/net/floodlightcontroller/core/NullConnection.java b/src/main/java/net/floodlightcontroller/core/NullConnection.java index 8ce0f55de..41a5a1591 100644 --- a/src/main/java/net/floodlightcontroller/core/NullConnection.java +++ b/src/main/java/net/floodlightcontroller/core/NullConnection.java @@ -34,7 +34,7 @@ public class NullConnection implements IOFConnectionBackend, IOFMessageWriter { } private void warn() { - logger.warn("Switch {} not connected -- cannot send message", getDatapathId()); + logger.debug("Switch {} not connected -- cannot send message", getDatapathId()); } @Override diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/OFConnection.java index ff4f529bf..58a6a1f82 100644 --- a/src/main/java/net/floodlightcontroller/core/OFConnection.java +++ b/src/main/java/net/floodlightcontroller/core/OFConnection.java @@ -114,13 +114,14 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ @Override public void write(OFMessage m) { + logger.debug("Got in write() of OFConnection!!!!!"); if (!isConnected()) { if (logger.isDebugEnabled()) logger.debug("{}: not connected - dropping message {}", this, m); return; } - if (logger.isTraceEnabled()) - logger.trace("{}: send {}", this, m); + if (logger.isDebugEnabled()) + logger.debug("{}: send {}", this, m); List<OFMessage> msgBuffer = localMsgBuffer.get(); if (msgBuffer == null) { msgBuffer = new ArrayList<OFMessage>(); @@ -130,8 +131,7 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{ counters.updateWriteStats(m); msgBuffer.add(m); - if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE) - || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) { + if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE) || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) { this.write(msgBuffer); localMsgBuffer.set(null); } diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java index 410b1fea7..332f4725c 100644 --- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java +++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java @@ -705,6 +705,8 @@ public class OFSwitch implements IOFSwitchBackend { @Override public void write(OFMessage m) { + log.debug("Possible OFConnections to write to: {}", connections); + log.debug("Channel info: {} {}", connections.get(OFAuxId.MAIN).getRemoteInetAddress(), connections.get(OFAuxId.MAIN).isConnected()); connections.get(OFAuxId.MAIN).write(m); } diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 7d20f436a..c28a45e1c 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -33,7 +33,6 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; import org.jboss.netty.util.HashedWheelTimer; import org.jboss.netty.util.Timer; @@ -121,6 +120,12 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis protected BlockingQueue<IUpdate> updates; protected ControllerCounters counters; protected Timer timer; + + // Module Loader State + private ModuleLoaderState moduleLoaderState; + public enum ModuleLoaderState { + INIT, STARTUP, COMPLETE + } // Module dependencies private IStorageSourceService storageSourceService; @@ -129,13 +134,11 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis protected IDebugEventService debugEventService; private IRestApiService restApiService; private IPktInProcessingTimeService pktinProcTimeService; - private IThreadPoolService threadPoolService; //TODO @Ryan is this needed here? - private ScheduledExecutorService scheduledExecutorService; //TODO @Ryan is this needed here? + private IThreadPoolService threadPoolService; private ISyncService syncService; private IShutdownService shutdownService; private IStoreClient<DatapathId, SwitchSyncRepresentation> storeClient; - // Configuration options protected int openFlowPort = 6653; // new registered OF port number private String openFlowHostname = null; @@ -143,7 +146,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis // The id for this controller node. Should be unique for each controller // node in a controller cluster. - protected String controllerId = "localhost"; + protected String controllerId = "my-floodlight-controller"; // This controller's current role that modules can use/query to decide // if they should operate in ACTIVE / STANDBY @@ -156,15 +159,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis * based on parameters that are only available in init() */ private RoleManager roleManager; - // private OFSwitchManager switchManager, is implemented as a service now, IOFSwitchService - - private static final int DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS = - 15*1000; // 15s - private int consolidateStoreTimeDelayMs = - DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS; // Storage table names - //TODO @Ryan do we need these anymore? I think we do, since we're using StorageSource protected static final String CONTROLLER_TABLE_NAME = "controller_controller"; protected static final String CONTROLLER_ID = "id"; @@ -198,7 +194,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis // Perf. related configuration protected static final int SEND_BUFFER_SIZE = 128 * 1024; - public static final int BATCH_MAX_SIZE = 100; + public static final int BATCH_MAX_SIZE = 1; //TODO @Ryan this was 100. Causes packet_out messages to stall until 100 accumulated... protected static final boolean ALWAYS_DECODE_ETH = true; // Set of port name prefixes that will be classified as uplink ports, @@ -214,24 +210,16 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis this.uplinkPortPrefixSet = prefixSet; } - // Module Loader State - private ModuleLoaderState moduleLoaderState; //TODO move to top - public enum ModuleLoaderState { - INIT, STARTUP, COMPLETE - } - @Override public ModuleLoaderState getModuleLoaderState(){ return this.moduleLoaderState; } // Load monitor for overload protection - protected final boolean overload_drop = - Boolean.parseBoolean(System.getProperty("overload_drop", "false")); + protected final boolean overload_drop = Boolean.parseBoolean(System.getProperty("overload_drop", "false")); protected final LoadMonitor loadmonitor = new LoadMonitor(log); - private static class NotificationSwitchListener - implements IOFSwitchListener { + private static class NotificationSwitchListener implements IOFSwitchListener { @Override public void switchAdded(DatapathId switchId) { @@ -262,13 +250,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis public void switchChanged(DatapathId switchId) { } } - - //Counters was here. Implemented as ControllerCounters in core.internal.ControllerCounters - - //RoleManager was here. Implemented as RoleManager in core.internal.RoleManager - - //SwitchManager was here. Implemented as OFSwitchManager in core.internal.OFSwitchManager - + /** * Updates handled by the main loop */ @@ -279,13 +261,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis public void dispatch(); } - //ReadyForReconcileUpdate was here. Obsolete? - - //SwitchUpdate was here. Implemented in in core.internal.OFSwitchManager - - //HARoleUpdate was here. Implemented in core.internal.RoleManager + //TODO @Ryan ReadyForReconcileUpdate was here. Obsolete? - //TODO @Ryan HAControllerNodeIPUpdate was here... /** * Update message indicating * IPs of controllers in controller cluster have changed. @@ -486,11 +463,11 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis switch (m.getType()) { case PACKET_IN: + counters.packetIn.increment(); OFPacketIn pi = (OFPacketIn)m; if (pi.getData().length <= 0) { - log.error("Ignoring PacketIn (Xid = " + pi.getXid() + - ") because the data field is empty."); + log.error("Ignoring PacketIn (Xid = " + pi.getXid() + ") because the data field is empty."); return; } @@ -504,8 +481,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis List<IOFMessageListener> listeners = null; if (messageListeners.containsKey(m.getType())) { - listeners = messageListeners.get(m.getType()). - getOrderedListeners(); + listeners = messageListeners.get(m.getType()).getOrderedListeners(); } FloodlightContext bc = null; @@ -551,9 +527,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } } - // switchActivated(IOFSwitch), switchDeactivated(IOFSwitch), switchDisconnected(IOFSwitch) - // removed...Included in OFSwitchManager (I'd guess... //TODO @Ryan)... - // *************** // IFloodlightProvider // *************** @@ -582,8 +555,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } @Override - public synchronized void addOFMessageListener(OFType type, - IOFMessageListener listener) { + public synchronized void addOFMessageListener(OFType type, IOFMessageListener listener) { ListenerDispatcher<OFType, IOFMessageListener> ldd = messageListeners.get(type); if (ldd == null) { @@ -594,8 +566,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } @Override - public synchronized void removeOFMessageListener(OFType type, - IOFMessageListener listener) { + public synchronized void removeOFMessageListener(OFType type, IOFMessageListener listener) { ListenerDispatcher<OFType, IOFMessageListener> ldd = messageListeners.get(type); if (ldd != null) { @@ -604,14 +575,9 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } private void logListeners() { - for (Map.Entry<OFType, - ListenerDispatcher<OFType, - IOFMessageListener>> entry - : messageListeners.entrySet()) { - + for (Map.Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> entry : messageListeners.entrySet()) { OFType type = entry.getKey(); - ListenerDispatcher<OFType, IOFMessageListener> ldd = - entry.getValue(); + ListenerDispatcher<OFType, IOFMessageListener> ldd = entry.getValue(); StringBuilder sb = new StringBuilder(); sb.append("OFListeners for "); @@ -641,8 +607,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis public Map<OFType, List<IOFMessageListener>> getListeners() { Map<OFType, List<IOFMessageListener>> lers = new HashMap<OFType, List<IOFMessageListener>>(); - for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e : - messageListeners.entrySet()) { + for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e : messageListeners.entrySet()) { lers.put(e.getKey(), e.getValue().getOrderedListeners()); } return Collections.unmodifiableMap(lers); @@ -660,8 +625,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis List<IOFMessageListener> listeners = null; if (messageListeners.containsKey(m.getType())) { - listeners = - messageListeners.get(m.getType()).getOrderedListeners(); + listeners = messageListeners.get(m.getType()).getOrderedListeners(); } if (listeners != null) { @@ -741,8 +705,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis recommendation=LogMessageDoc.GENERIC_ACTION) }) public void run() { - //TODO @Ryan, this is quite different from the bootstrap and ChannelPipelineFactory - // stuff that's in the OLD_Controller class... this.moduleLoaderState = ModuleLoaderState.COMPLETE; if (log.isDebugEnabled()) { @@ -769,7 +731,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } } - //TODO @Ryan createServerBootStrap() was here. Implemented how/where??? + //TODO @Ryan createServerBootStrap() was here. Implemented how/where? private void setConfigParams(Map<String, String> configParams) throws FloodlightModuleException { String ofPort = configParams.get("openflowPort"); @@ -788,7 +750,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis this.workerThreads = Integer.parseInt(threads); } log.debug("Number of worker threads set to {}", this.workerThreads); - } /** @@ -800,12 +761,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis // These data structures are initialized here because other // module's startUp() might be called before ours - this.messageListeners = - new ConcurrentHashMap<OFType, - ListenerDispatcher<OFType, - IOFMessageListener>>(); - this.haListeners = - new ListenerDispatcher<HAListenerTypeMarker, IHAListener>(); + this.messageListeners = new ConcurrentHashMap<OFType, ListenerDispatcher<OFType, IOFMessageListener>>(); + this.haListeners = new ListenerDispatcher<HAListenerTypeMarker, IHAListener>(); this.controllerNodeIPsCache = new HashMap<String, String>(); this.updates = new LinkedBlockingQueue<IUpdate>(); this.providerMap = new HashMap<String, List<IInfoProvider>>(); @@ -837,8 +794,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis recommendation="If this message persists, this indicates " + "that the system database has failed to start. " + LogMessageDoc.CHECK_CONTROLLER) - public void startupComponents(FloodlightModuleLoader floodlightModuleLoader) - throws FloodlightModuleException { + public void startupComponents(FloodlightModuleLoader floodlightModuleLoader) throws FloodlightModuleException { this.moduleLoaderState = ModuleLoaderState.STARTUP; @@ -858,25 +814,22 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis // Startup load monitoring if (overload_drop) { - this.loadmonitor.startMonitoring( - this.threadPoolService.getScheduledExecutor()); + this.loadmonitor.startMonitoring(this.threadPoolService.getScheduledExecutor()); } // Add our REST API restApiService.addRestletRoutable(new CoreWebRoutable()); - - this.scheduledExecutorService = threadPoolService.getScheduledExecutor(); - /* try { + try { this.syncService.registerStore(SWITCH_SYNC_STORE_NAME, Scope.LOCAL); - this.storeClient = this.syncService - .getStoreClient(SWITCH_SYNC_STORE_NAME, - DatapathId.class, - SwitchSyncRepresentation.class); - //TODO @Ryan needed? this.storeClient.addStoreListener(this.switchService); + this.storeClient = this.syncService.getStoreClient( + SWITCH_SYNC_STORE_NAME, + DatapathId.class, + SwitchSyncRepresentation.class); + //TODO @Ryan this.storeClient.addStoreListener(this.switchService); } catch (SyncException e) { throw new FloodlightModuleException("Error while setting up sync service", e); - }*/ + } addInfoProvider("summary", this); } @@ -899,20 +852,17 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis String primary_key = (String) row.get(FLOW_COLUMN_PRIMARY_KEY); if (primary_key.equals(FLOW_VALUE_PRIMARY_KEY)) { if (row.containsKey(FLOW_COLUMN_ACCESS_PRIORITY)) { - accessPriority = - Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY)); + accessPriority = Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY)); } if (row.containsKey(FLOW_COLUMN_CORE_PRIORITY)) { - corePriority = - Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY)); + corePriority = Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY)); } } } } } catch (StorageException e) { - log.error("Failed to access storage for forwarding configuration: {}", - e.getMessage()); + log.error("Failed to access storage for forwarding configuration: {}", e.getMessage()); } catch (NumberFormatException e) { // log error, no stack-trace @@ -935,7 +885,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis log.debug("Provider type {} doesn't exist.", type); return; } - providerMap.get(type).remove(provider); } @@ -947,7 +896,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis for (IInfoProvider provider : providerMap.get(type)) { result.putAll(provider.getInfo(type)); } - return result; } @@ -1051,8 +999,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) { log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP); } - - } @Override @@ -1125,7 +1071,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis */ void resetModuleState() { this.moduleLoaderState = ModuleLoaderState.INIT; - } /** diff --git a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java index c511a09ee..de5b99255 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java +++ b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java @@ -13,12 +13,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class ControllerCounters { public final String prefix = ControllerCounters.class.getSimpleName(); - public final String statsPrefix = IOFSwitchBackend.class.getPackage() - .getName(); + public final String statsPrefix = IOFSwitchBackend.class.getPackage().getName(); public final IDebugCounter packetParsingError; public final IDebugCounter dispatchMessageWhileStandby; public final IDebugCounter dispatchMessage; + public final IDebugCounter packetIn; public ControllerCounters(IDebugCounterService debugCounters) { debugCounters.registerModule(prefix); @@ -44,5 +44,7 @@ public class ControllerCounters { "Number of times the packet parsing " + "encountered an error", MetaData.ERROR); + + packetIn = debugCounters.registerCounter(prefix, "packet-in", "Number of packet_in's seen"); } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java index 6e46b1cca..46d90645c 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java @@ -74,680 +74,672 @@ import com.google.common.collect.ImmutableSet; * */ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListener, IHAListener, IFloodlightModule, IOFSwitchService { - private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class); - - private volatile OFControllerRole role; - private SwitchManagerCounters counters; - - private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers; - private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches; - - private ISwitchDriverRegistry driverRegistry; - - private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>(); - private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>(); - private int numRequiredConnections = -1; - // Event IDs for debug events - protected IEventCategory<SwitchEvent> evSwitch; - - // ISwitchService - protected Set<IOFSwitchListener> switchListeners; - - // Module Dependencies - IFloodlightProviderService floodlightProvider; - IDebugEventService debugEventService; - IDebugCounterService debugCounterService; - - /** IHAListener Implementation **/ - @Override - public void transitionToActive() { - this.role = HARole.ACTIVE.getOFRole(); - } - - @Override - public void transitionToStandby() { - this.role = HARole.STANDBY.getOFRole(); - } - - /** IOFSwitchManager Implementation **/ - - @Override public SwitchManagerCounters getCounters() { - return this.counters; - } - - private void addUpdateToQueue(IUpdate iUpdate) { - floodlightProvider.addUpdateToQueue(iUpdate); - } - - @Override - public synchronized void switchAdded(IOFSwitchBackend sw) { - DatapathId dpid = sw.getId(); - IOFSwitchBackend oldSw = this.switches.put(dpid, sw); - // Update event history - evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected")); - - if (oldSw == sw) { - // Note == for object equality, not .equals for value - counters.errorActivatedSwitchNotPresent.increment(); - log.error("Switch {} added twice?", sw); - return; - } else if (oldSw != null) { - // This happens either when we have switches with duplicate - // DPIDs or when a switch reconnects before we saw the - // disconnect - counters.switchWithSameDpidActivated.increment(); - log.warn("New switch added {} for already-added switch {}", sw, oldSw); - // We need to disconnect and remove the old switch - // TODO: we notify switch listeners that the switch has been - // removed and then we notify them that the new one has been - // added. One could argue that a switchChanged notification - // might be more appropriate in this case.... - oldSw.cancelAllPendingRequests(); - addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); - oldSw.disconnect(); - } - - } - - @LogMessageDocs({ - @LogMessageDoc(level="ERROR", - message="Switch {switch} activated but was already active", - explanation="A switch that was already activated was " + - "activated again. This should not happen.", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG - ), - @LogMessageDoc(level="WARN", - message="New switch added {switch} for already-added switch {switch}", - explanation="A switch with the same DPID as another switch " + - "connected to the controller. This can be caused by " + - "multiple switches configured with the same DPID, or " + - "by a switch reconnected very quickly after " + - "disconnecting.", - recommendation="If this happens repeatedly, it is likely there " + - "are switches with duplicate DPIDs on the network. " + - "Reconfigure the appropriate switches. If it happens " + - "very rarely, then it is likely this is a transient " + - "network problem that can be ignored." - ) - }) - @Override - public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) { - DatapathId dpid = sw.getId(); - IOFSwitchBackend presentSw = this.switches.get(dpid); - - if (presentSw != sw) { - // Note == for object equality, not .equals for value - counters.errorActivatedSwitchNotPresent - .increment(); - log.debug("Switch {} status change but not present in sync manager", sw); - return; - } - evSwitch.newEventWithFlush(new SwitchEvent(dpid, - String.format("%s -> %s", - oldStatus, - newStatus))); - - if(newStatus == SwitchStatus.MASTER && role != OFControllerRole.ROLE_MASTER) { - counters.invalidSwitchActivatedWhileSlave.increment(); - log.error("Switch {} activated but controller not MASTER", sw); - sw.disconnect(); - return; // only react to switch connections when master - } - - if(!oldStatus.isVisible() && newStatus.isVisible()) { - // the switch has just become visible. Send 'add' notification to our - // listeners - addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED)); - } else if((oldStatus.isVisible() && !newStatus.isVisible())) { - addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); - } - - // note: no else if - both may be true - if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) { - counters.switchActivated.increment(); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ACTIVATED)); - } else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) { - counters.switchDeactivated.increment(); - addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED)); - } - } - - @Override - public synchronized void switchDisconnected(IOFSwitchBackend sw) { - DatapathId dpid = sw.getId(); - IOFSwitchBackend presentSw = this.switches.get(dpid); - - if (presentSw != sw) { - // Note == for object equality, not .equals for value - counters.errorActivatedSwitchNotPresent - .increment(); - log.warn("Switch {} disconnect but not present in sync manager", sw); - return; - } - - counters.switchDisconnected.increment(); - this.switches.remove(dpid); - } - - @Override public void handshakeDisconnected(DatapathId dpid) { - this.switchHandlers.remove(dpid); - } - - public Iterable<IOFSwitch> getActiveSwitches() { - ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder(); - for(IOFSwitch sw: switches.values()) { - if(sw.getStatus().isControllable()) - builder.add(sw); - } - return builder.build(); - } - - public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) { - if(showInvisible) { - return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches); - } else { - ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder(); - for(IOFSwitch sw: switches.values()) { - if(sw.getStatus().isVisible()) - builder.put(sw.getId(), sw); - } - return builder.build(); - } - } - - @Override - public Map<DatapathId, IOFSwitch> getAllSwitchMap() { - return getAllSwitchMap(true); - } - - @Override - public Set<DatapathId> getAllSwitchDpids() { - return getAllSwitchMap().keySet(); - } - - public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) { - return getAllSwitchMap(showInvisible).keySet(); - } - - @Override - public IOFSwitch getSwitch(DatapathId dpid) { - return this.switches.get(dpid); - } - - @Override - public IOFSwitch getActiveSwitch(DatapathId dpid) { - IOFSwitchBackend sw = this.switches.get(dpid); - if(sw != null && sw.getStatus().isVisible()) - return sw; - else - return null; - } - - enum SwitchUpdateType { - ADDED, - REMOVED, - ACTIVATED, - DEACTIVATED, - PORTCHANGED, - OTHERCHANGE - } - - /** - * Update message indicating a switch was added or removed - */ - class SwitchUpdate implements IUpdate { - private final DatapathId swId; - private final SwitchUpdateType switchUpdateType; - private final OFPortDesc port; - private final PortChangeType changeType; - - public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) { - this(swId, switchUpdateType, null, null); - } - - public SwitchUpdate(DatapathId swId, - SwitchUpdateType switchUpdateType, - OFPortDesc port, - PortChangeType changeType) { - if (switchUpdateType == SwitchUpdateType.PORTCHANGED) { - if (port == null) { - throw new NullPointerException("Port must not be null " + - "for PORTCHANGED updates"); - } - if (changeType == null) { - throw new NullPointerException("ChangeType must not be " + - "null for PORTCHANGED updates"); - } - } else { - if (port != null || changeType != null) { - throw new IllegalArgumentException("port and changeType " + - "must be null for " + switchUpdateType + - " updates"); - } - } - this.swId = swId; - this.switchUpdateType = switchUpdateType; - this.port = port; - this.changeType = changeType; - } - - @Override - public void dispatch() { - if (log.isTraceEnabled()) { - log.trace("Dispatching switch update {} {}", swId, switchUpdateType); - } - if (switchListeners != null) { - for (IOFSwitchListener listener : switchListeners) { - switch(switchUpdateType) { - case ADDED: - // don't count here. We have more specific - // counters before the update is created - listener.switchAdded(swId); - break; - case REMOVED: - // don't count here. We have more specific - // counters before the update is created - listener.switchRemoved(swId); - break; - case PORTCHANGED: - counters.switchPortChanged - .increment(); - listener.switchPortChanged(swId, port, changeType); - break; - case ACTIVATED: - // don't count here. We have more specific - // counters before the update is created - listener.switchActivated(swId); - break; - case DEACTIVATED: - // ignore - break; - case OTHERCHANGE: - counters.switchOtherChange - .increment(); - listener.switchChanged(swId); - break; - } - } - } - } - } - - /** - * Handles a new OF Connection - * @param IOFConnectionBackend connection an opened OF Connection - * @param OFFeaturesReply featuresReply the features reply received for the opened connection. - * It is needed for the rest of the switch handshake. - */ - @Override - public void connectionOpened(IOFConnectionBackend connection, - OFFeaturesReply featuresReply) { - DatapathId dpid = connection.getDatapathId(); - OFAuxId auxId = connection.getAuxId(); - - log.debug("{} opened", connection); - - if(auxId.equals(OFAuxId.MAIN)) { - - // Create a new switch handshake handler - OFSwitchHandshakeHandler handler = - new OFSwitchHandshakeHandler(connection, featuresReply, this, - floodlightProvider.getRoleManager(), floodlightProvider.getTimer()); - - OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler); - - // Disconnect all the handler's connections - if(oldHandler != null){ - log.debug("{} is a new main connection, killing old handler connections", connection); - oldHandler.cleanup(); - } - - handler.beginHandshake(); - - } else { - OFSwitchHandshakeHandler handler = switchHandlers.get(dpid); - - if(handler != null) { - handler.auxConnectionOpened(connection); - } - // Connections have arrived before the switchhandler is ready - else { - log.warn("{} arrived before main connection, closing connection", connection); - connection.disconnect(); - } - } - } - - @Override - public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) { - if (flushNow) - evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason)); - else - evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason)); - } - - @Override - public synchronized void notifyPortChanged(IOFSwitchBackend sw, - OFPortDesc port, - PortChangeType changeType) { - Preconditions.checkNotNull(sw, "switch must not be null"); - Preconditions.checkNotNull(port, "port must not be null"); - Preconditions.checkNotNull(changeType, "changeType must not be null"); - - if (role != OFControllerRole.ROLE_MASTER) { - counters.invalidPortsChanged.increment(); - return; - } - if (!this.switches.containsKey(sw.getId())) { - counters.invalidPortsChanged.increment(); - return; - } - - if(sw.getStatus().isVisible()) { - // no need to count here. SwitchUpdate.dispatch will count - // the portchanged - SwitchUpdate update = new SwitchUpdate(sw.getId(), - SwitchUpdateType.PORTCHANGED, - port, changeType); - addUpdateToQueue(update); - } - } - - @Override - public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, - SwitchDescription description, - OFFactory factory, DatapathId datapathId) { - return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); - } - - @Override - public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) { - floodlightProvider.handleMessage(sw, m, bContext); - } - - @Override - public void addOFSwitchDriver(String manufacturerDescriptionPrefix, - IOFSwitchDriver driver) { - this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver); - } - - @Override - public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() { - return ImmutableList.copyOf(this.switchHandlers.values()); - } - - @Override - public int getNumRequiredConnections() { - Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated"); - return numRequiredConnections; - } - - public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() { - return logicalOFMessageCategories; - } - - private int calcNumRequiredConnections() { - if(!this.logicalOFMessageCategories.isEmpty()){ - // We use tree set here to maintain ordering - TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>(); - - for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){ - auxConnections.add(category.getAuxId()); - } - - OFAuxId first = auxConnections.first(); - OFAuxId last = auxConnections.last(); - - // Check for contiguous set (1....size()) - if(first.equals(OFAuxId.MAIN)) { - if(last.getValue() != auxConnections.size() - 1){ - throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)"); - } - return auxConnections.size() - 1; - } else if(first.equals(OFAuxId.of(1))) { - if(last.getValue() != auxConnections.size()){ - throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)"); - } - return auxConnections.size(); - } else { - throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1"); - } - } else { - return 0; - } - } - - /** ISwitchService Implementation **/ - @Override - public void addOFSwitchListener(IOFSwitchListener listener) { - this.switchListeners.add(listener); - } - - @Override - public void removeOFSwitchListener(IOFSwitchListener listener) { - this.switchListeners.remove(listener); - } - - @Override - public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) { - logicalOFMessageCategories.add(category); - } - - @Override - public boolean isCategoryRegistered(LogicalOFMessageCategory category) { - return logicalOFMessageCategories.contains(category); - } - - @Override - public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) { - IOFSwitch sw = this.switches.get(dpid); - OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid); - - if(sw != null && handler != null) { - return new SwitchRepresentation(sw, handler); - } - return null; - } - - @Override - public List<SwitchRepresentation> getSwitchRepresentations() { - - List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>(); - - for(DatapathId dpid : this.switches.keySet()) { - SwitchRepresentation representation = getSwitchRepresentation(dpid); - if(representation != null) { - representations.add(representation); - } - } - return representations; - } - - @Override - public void registerHandshakePlugin(IAppHandshakePluginFactory factory) { - Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT, - "handshakeplugins can only be registered when the module loader is in state INIT!"); - handshakePlugins.add(factory); - } - - @Override - public List<IAppHandshakePluginFactory> getHandshakePlugins() { - return handshakePlugins; - } - - /* IFloodlightModule Implementation */ - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleServices() { - Collection<Class<? extends IFloodlightService>> l = - new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IOFSwitchService.class); - return l; - } - - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> - getServiceImpls() { - Map<Class<? extends IFloodlightService>, IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); - m.put(IOFSwitchService.class, this); - return m; - } - - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleDependencies() { - Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); - - l.add(IFloodlightProviderService.class); - l.add(IDebugEventService.class); - l.add(IDebugCounterService.class); - - return l; - } - - @Override - public void init(FloodlightModuleContext context) throws FloodlightModuleException { - // Module dependencies - floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); - debugEventService = context.getServiceImpl(IDebugEventService.class); - debugCounterService = context.getServiceImpl(IDebugCounterService.class); - - // Module variables - switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>(); - switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>(); - floodlightProvider.getTimer(); - counters = new SwitchManagerCounters(debugCounterService); - driverRegistry = new NaiveSwitchDriverRegistry(this); - - this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); - - this.counters = new SwitchManagerCounters(debugCounterService); - - } - - @Override - public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { - startUpBase(context); - bootstrapNetty(); - } - - /** - * Startup method that includes everything besides the netty boostrap. - * This has been isolated for testing. - * @param context floodlight module context - * @throws FloodlightModuleException - */ - public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException { - // Initial Role - role = floodlightProvider.getRole().getOFRole(); - - // IRoleListener - floodlightProvider.addHAListener(this); - - loadLogicalCategories(); - - registerDebugEvents(); - } - - /** - * Bootstraps netty, the server that handles all openflow connections - */ - public void bootstrapNetty() { - try { - final ServerBootstrap bootstrap = createServerBootStrap(); - - bootstrap.setOption("reuseAddr", true); - bootstrap.setOption("child.keepAlive", true); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - - ChannelPipelineFactory pfact = - new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService); - bootstrap.setPipelineFactory(pfact); - InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort()); - final ChannelGroup cg = new DefaultChannelGroup(); - cg.add(bootstrap.bind(sa)); - - log.info("Listening for switch connections on {}", sa); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Helper that bootstrapNetty. - * @return - */ - private ServerBootstrap createServerBootStrap() { - if (floodlightProvider.getWorkerThreads() == 0) { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool())); - } else { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads())); - } - } - - /** - * Performs startup related actions for logical OF message categories. - * Setting the categories list to immutable ensures that unsupported operation - * exceptions will be activated if modifications are attempted. - */ - public void loadLogicalCategories() { - logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories); - numRequiredConnections = calcNumRequiredConnections(); - } - - /** - * Registers an event handler with the debug event service - * for switch events. - * @throws FloodlightModuleException - */ - private void registerDebugEvents() throws FloodlightModuleException { - if (debugEventService == null) { - debugEventService = new MockDebugEventService(); - } - evSwitch = debugEventService.buildEvent(SwitchEvent.class) - .setModuleName(this.counters.getPrefix()) - .setEventName("switch-event") - .setEventDescription("Switch connected, disconnected or port changed") - .setEventType(EventType.ALWAYS_LOG) - .setBufferCapacity(100) - .register(); - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type, - String name) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type, - String name) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void controllerNodeIPsChanged( - Map<String, String> curControllerNodeIPs, + private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class); + + private volatile OFControllerRole role; + private SwitchManagerCounters counters; + + private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers; + private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches; + + private ISwitchDriverRegistry driverRegistry; + + private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>(); + private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>(); + private int numRequiredConnections = -1; + // Event IDs for debug events + protected IEventCategory<SwitchEvent> evSwitch; + + // ISwitchService + protected Set<IOFSwitchListener> switchListeners; + + // Module Dependencies + IFloodlightProviderService floodlightProvider; + IDebugEventService debugEventService; + IDebugCounterService debugCounterService; + + /** IHAListener Implementation **/ + @Override + public void transitionToActive() { + this.role = HARole.ACTIVE.getOFRole(); + } + + @Override + public void transitionToStandby() { + this.role = HARole.STANDBY.getOFRole(); + } + + /** IOFSwitchManager Implementation **/ + + @Override public SwitchManagerCounters getCounters() { + return this.counters; + } + + private void addUpdateToQueue(IUpdate iUpdate) { + floodlightProvider.addUpdateToQueue(iUpdate); + } + + @Override + public synchronized void switchAdded(IOFSwitchBackend sw) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend oldSw = this.switches.put(dpid, sw); + // Update event history + evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected")); + + if (oldSw == sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent.increment(); + log.error("Switch {} added twice?", sw); + return; + } else if (oldSw != null) { + // This happens either when we have switches with duplicate + // DPIDs or when a switch reconnects before we saw the + // disconnect + counters.switchWithSameDpidActivated.increment(); + log.warn("New switch added {} for already-added switch {}", sw, oldSw); + // We need to disconnect and remove the old switch + // TODO: we notify switch listeners that the switch has been + // removed and then we notify them that the new one has been + // added. One could argue that a switchChanged notification + // might be more appropriate in this case.... + oldSw.cancelAllPendingRequests(); + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); + oldSw.disconnect(); + } + + } + + @LogMessageDocs({ + @LogMessageDoc(level="ERROR", + message="Switch {switch} activated but was already active", + explanation="A switch that was already activated was " + + "activated again. This should not happen.", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG + ), + @LogMessageDoc(level="WARN", + message="New switch added {switch} for already-added switch {switch}", + explanation="A switch with the same DPID as another switch " + + "connected to the controller. This can be caused by " + + "multiple switches configured with the same DPID, or " + + "by a switch reconnected very quickly after " + + "disconnecting.", + recommendation="If this happens repeatedly, it is likely there " + + "are switches with duplicate DPIDs on the network. " + + "Reconfigure the appropriate switches. If it happens " + + "very rarely, then it is likely this is a transient " + + "network problem that can be ignored." + ) + }) + @Override + public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend presentSw = this.switches.get(dpid); + + if (presentSw != sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent + .increment(); + log.debug("Switch {} status change but not present in sync manager", sw); + return; + } + evSwitch.newEventWithFlush(new SwitchEvent(dpid, + String.format("%s -> %s", + oldStatus, + newStatus))); + + if(newStatus == SwitchStatus.MASTER && role != OFControllerRole.ROLE_MASTER) { + counters.invalidSwitchActivatedWhileSlave.increment(); + log.error("Switch {} activated but controller not MASTER", sw); + sw.disconnect(); + return; // only react to switch connections when master + } + + if(!oldStatus.isVisible() && newStatus.isVisible()) { + // the switch has just become visible. Send 'add' notification to our + // listeners + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED)); + } else if((oldStatus.isVisible() && !newStatus.isVisible())) { + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); + } + + // note: no else if - both may be true + if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) { + counters.switchActivated.increment(); + addUpdateToQueue(new SwitchUpdate(dpid, + SwitchUpdateType.ACTIVATED)); + } else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) { + counters.switchDeactivated.increment(); + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED)); + } + } + + @Override + public synchronized void switchDisconnected(IOFSwitchBackend sw) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend presentSw = this.switches.get(dpid); + + if (presentSw != sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent + .increment(); + log.warn("Switch {} disconnect but not present in sync manager", sw); + return; + } + + counters.switchDisconnected.increment(); + this.switches.remove(dpid); + } + + @Override public void handshakeDisconnected(DatapathId dpid) { + this.switchHandlers.remove(dpid); + } + + public Iterable<IOFSwitch> getActiveSwitches() { + ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder(); + for(IOFSwitch sw: switches.values()) { + if(sw.getStatus().isControllable()) + builder.add(sw); + } + return builder.build(); + } + + public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) { + if(showInvisible) { + return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches); + } else { + ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder(); + for(IOFSwitch sw: switches.values()) { + if(sw.getStatus().isVisible()) + builder.put(sw.getId(), sw); + } + return builder.build(); + } + } + + @Override + public Map<DatapathId, IOFSwitch> getAllSwitchMap() { + return getAllSwitchMap(true); + } + + @Override + public Set<DatapathId> getAllSwitchDpids() { + return getAllSwitchMap().keySet(); + } + + public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) { + return getAllSwitchMap(showInvisible).keySet(); + } + + @Override + public IOFSwitch getSwitch(DatapathId dpid) { + return this.switches.get(dpid); + } + + @Override + public IOFSwitch getActiveSwitch(DatapathId dpid) { + IOFSwitchBackend sw = this.switches.get(dpid); + if(sw != null && sw.getStatus().isVisible()) + return sw; + else + return null; + } + + enum SwitchUpdateType { + ADDED, + REMOVED, + ACTIVATED, + DEACTIVATED, + PORTCHANGED, + OTHERCHANGE + } + + /** + * Update message indicating a switch was added or removed + */ + class SwitchUpdate implements IUpdate { + private final DatapathId swId; + private final SwitchUpdateType switchUpdateType; + private final OFPortDesc port; + private final PortChangeType changeType; + + public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) { + this(swId, switchUpdateType, null, null); + } + + public SwitchUpdate(DatapathId swId, + SwitchUpdateType switchUpdateType, + OFPortDesc port, + PortChangeType changeType) { + if (switchUpdateType == SwitchUpdateType.PORTCHANGED) { + if (port == null) { + throw new NullPointerException("Port must not be null " + + "for PORTCHANGED updates"); + } + if (changeType == null) { + throw new NullPointerException("ChangeType must not be " + + "null for PORTCHANGED updates"); + } + } else { + if (port != null || changeType != null) { + throw new IllegalArgumentException("port and changeType " + + "must be null for " + switchUpdateType + + " updates"); + } + } + this.swId = swId; + this.switchUpdateType = switchUpdateType; + this.port = port; + this.changeType = changeType; + } + + @Override + public void dispatch() { + if (log.isTraceEnabled()) { + log.trace("Dispatching switch update {} {}", swId, switchUpdateType); + } + if (switchListeners != null) { + for (IOFSwitchListener listener : switchListeners) { + switch(switchUpdateType) { + case ADDED: + // don't count here. We have more specific + // counters before the update is created + listener.switchAdded(swId); + break; + case REMOVED: + // don't count here. We have more specific + // counters before the update is created + listener.switchRemoved(swId); + break; + case PORTCHANGED: + counters.switchPortChanged + .increment(); + listener.switchPortChanged(swId, port, changeType); + break; + case ACTIVATED: + // don't count here. We have more specific + // counters before the update is created + listener.switchActivated(swId); + break; + case DEACTIVATED: + // ignore + break; + case OTHERCHANGE: + counters.switchOtherChange + .increment(); + listener.switchChanged(swId); + break; + } + } + } + } + } + + /** + * Handles a new OF Connection + * @param IOFConnectionBackend connection an opened OF Connection + * @param OFFeaturesReply featuresReply the features reply received for the opened connection. + * It is needed for the rest of the switch handshake. + */ + @Override + public void connectionOpened(IOFConnectionBackend connection, + OFFeaturesReply featuresReply) { + DatapathId dpid = connection.getDatapathId(); + OFAuxId auxId = connection.getAuxId(); + + log.debug("{} opened", connection); + + if(auxId.equals(OFAuxId.MAIN)) { + + // Create a new switch handshake handler + OFSwitchHandshakeHandler handler = + new OFSwitchHandshakeHandler(connection, featuresReply, this, + floodlightProvider.getRoleManager(), floodlightProvider.getTimer()); + + OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler); + + // Disconnect all the handler's connections + if(oldHandler != null){ + log.debug("{} is a new main connection, killing old handler connections", connection); + oldHandler.cleanup(); + } + + handler.beginHandshake(); + + } else { + OFSwitchHandshakeHandler handler = switchHandlers.get(dpid); + + if(handler != null) { + handler.auxConnectionOpened(connection); + } + // Connections have arrived before the switchhandler is ready + else { + log.warn("{} arrived before main connection, closing connection", connection); + connection.disconnect(); + } + } + } + + @Override + public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) { + if (flushNow) + evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason)); + else + evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason)); + } + + @Override + public synchronized void notifyPortChanged(IOFSwitchBackend sw, + OFPortDesc port, + PortChangeType changeType) { + Preconditions.checkNotNull(sw, "switch must not be null"); + Preconditions.checkNotNull(port, "port must not be null"); + Preconditions.checkNotNull(changeType, "changeType must not be null"); + + if (role != OFControllerRole.ROLE_MASTER) { + counters.invalidPortsChanged.increment(); + return; + } + if (!this.switches.containsKey(sw.getId())) { + counters.invalidPortsChanged.increment(); + return; + } + + if(sw.getStatus().isVisible()) { + // no need to count here. SwitchUpdate.dispatch will count + // the portchanged + SwitchUpdate update = new SwitchUpdate(sw.getId(), + SwitchUpdateType.PORTCHANGED, + port, changeType); + addUpdateToQueue(update); + } + } + + @Override + public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, + SwitchDescription description, + OFFactory factory, DatapathId datapathId) { + return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); + } + + @Override + public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) { + floodlightProvider.handleMessage(sw, m, bContext); + } + + @Override + public void addOFSwitchDriver(String manufacturerDescriptionPrefix, + IOFSwitchDriver driver) { + this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver); + } + + @Override + public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() { + return ImmutableList.copyOf(this.switchHandlers.values()); + } + + @Override + public int getNumRequiredConnections() { + Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated"); + return numRequiredConnections; + } + + public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() { + return logicalOFMessageCategories; + } + + private int calcNumRequiredConnections() { + if(!this.logicalOFMessageCategories.isEmpty()){ + // We use tree set here to maintain ordering + TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>(); + + for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){ + auxConnections.add(category.getAuxId()); + } + + OFAuxId first = auxConnections.first(); + OFAuxId last = auxConnections.last(); + + // Check for contiguous set (1....size()) + if(first.equals(OFAuxId.MAIN)) { + if(last.getValue() != auxConnections.size() - 1){ + throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)"); + } + return auxConnections.size() - 1; + } else if(first.equals(OFAuxId.of(1))) { + if(last.getValue() != auxConnections.size()){ + throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)"); + } + return auxConnections.size(); + } else { + throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1"); + } + } else { + return 0; + } + } + + /** ISwitchService Implementation **/ + @Override + public void addOFSwitchListener(IOFSwitchListener listener) { + this.switchListeners.add(listener); + } + + @Override + public void removeOFSwitchListener(IOFSwitchListener listener) { + this.switchListeners.remove(listener); + } + + @Override + public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) { + logicalOFMessageCategories.add(category); + } + + @Override + public boolean isCategoryRegistered(LogicalOFMessageCategory category) { + return logicalOFMessageCategories.contains(category); + } + + @Override + public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) { + IOFSwitch sw = this.switches.get(dpid); + OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid); + + if(sw != null && handler != null) { + return new SwitchRepresentation(sw, handler); + } + return null; + } + + @Override + public List<SwitchRepresentation> getSwitchRepresentations() { + + List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>(); + + for(DatapathId dpid : this.switches.keySet()) { + SwitchRepresentation representation = getSwitchRepresentation(dpid); + if(representation != null) { + representations.add(representation); + } + } + return representations; + } + + @Override + public void registerHandshakePlugin(IAppHandshakePluginFactory factory) { + Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT, + "handshakeplugins can only be registered when the module loader is in state INIT!"); + handshakePlugins.add(factory); + } + + @Override + public List<IAppHandshakePluginFactory> getHandshakePlugins() { + return handshakePlugins; + } + + /* IFloodlightModule Implementation */ + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IOFSwitchService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IOFSwitchService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); + + l.add(IFloodlightProviderService.class); + l.add(IDebugEventService.class); + l.add(IDebugCounterService.class); + + return l; + } + + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + // Module dependencies + floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + debugEventService = context.getServiceImpl(IDebugEventService.class); + debugCounterService = context.getServiceImpl(IDebugCounterService.class); + + // Module variables + switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>(); + switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>(); + floodlightProvider.getTimer(); + counters = new SwitchManagerCounters(debugCounterService); + driverRegistry = new NaiveSwitchDriverRegistry(this); + + this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); + + this.counters = new SwitchManagerCounters(debugCounterService); + + } + + @Override + public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { + startUpBase(context); + bootstrapNetty(); + } + + /** + * Startup method that includes everything besides the netty boostrap. + * This has been isolated for testing. + * @param context floodlight module context + * @throws FloodlightModuleException + */ + public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException { + // Initial Role + role = floodlightProvider.getRole().getOFRole(); + + // IRoleListener + floodlightProvider.addHAListener(this); + + loadLogicalCategories(); + + registerDebugEvents(); + } + + /** + * Bootstraps netty, the server that handles all openflow connections + */ + public void bootstrapNetty() { + try { + final ServerBootstrap bootstrap = createServerBootStrap(); + + bootstrap.setOption("reuseAddr", true); + bootstrap.setOption("child.keepAlive", true); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); + + ChannelPipelineFactory pfact = + new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService); + bootstrap.setPipelineFactory(pfact); + InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort()); + final ChannelGroup cg = new DefaultChannelGroup(); + cg.add(bootstrap.bind(sa)); + + log.info("Listening for switch connections on {}", sa); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Helper that bootstrapNetty. + * @return + */ + private ServerBootstrap createServerBootStrap() { + if (floodlightProvider.getWorkerThreads() == 0) { + return new ServerBootstrap( + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool())); + } else { + return new ServerBootstrap( + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads())); + } + } + + /** + * Performs startup related actions for logical OF message categories. + * Setting the categories list to immutable ensures that unsupported operation + * exceptions will be activated if modifications are attempted. + */ + public void loadLogicalCategories() { + logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories); + numRequiredConnections = calcNumRequiredConnections(); + } + + /** + * Registers an event handler with the debug event service + * for switch events. + * @throws FloodlightModuleException + */ + private void registerDebugEvents() throws FloodlightModuleException { + if (debugEventService == null) { + debugEventService = new MockDebugEventService(); + } + evSwitch = debugEventService.buildEvent(SwitchEvent.class) + .setModuleName(this.counters.getPrefix()) + .setEventName("switch-event") + .setEventDescription("Switch connected, disconnected or port changed") + .setEventType(EventType.ALWAYS_LOG) + .setBufferCapacity(100) + .register(); + } + + @Override + public String getName() { + return null; + } + + @Override + public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type, String name) { + return false; + } + + @Override + public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type, String name) { + return false; + } + + @Override + public void controllerNodeIPsChanged(Map<String, String> curControllerNodeIPs, Map<String, String> addedControllerNodeIPs, - Map<String, String> removedControllerNodeIPs) { - // TODO Auto-generated method stub - + Map<String, String> removedControllerNodeIPs) { } } diff --git a/src/main/java/net/floodlightcontroller/core/web/CounterResource.java b/src/main/java/net/floodlightcontroller/core/web/CounterResource.java index 35c771c2c..14fa1b1e3 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CounterResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/CounterResource.java @@ -47,7 +47,8 @@ public class CounterResource extends CounterResourceBase { } } } else { - List<DebugCounterResource> counter = this.debugCounterService.getCounterHierarchy(moduleName, counterTitle); + List<DebugCounterResource> counter = this.debugCounterService.getCounterHierarchy(???, counterTitle)); + long v = 0; if (counter != null) { v = counter.getCounterValue(); } else { diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java index 4c517a25b..f5fedabdf 100644 --- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java +++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java @@ -26,12 +26,14 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import net.floodlightcontroller.core.IFloodlightProviderService; 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.core.util.ListenerDispatcher; import net.floodlightcontroller.core.util.SingletonTask; +import net.floodlightcontroller.debugcounter.DebugCounterResource; import net.floodlightcontroller.debugcounter.IDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.flowcache.FlowReconcileQuery.FlowReconcileQueryDebugEvent; @@ -44,24 +46,24 @@ import org.projectfloodlight.openflow.protocol.OFType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class FlowReconcileManager - implements IFloodlightModule, IFlowReconcileService { +import com.sun.j3d.utils.scenegraph.io.retained.Controller; +public class FlowReconcileManager implements IFloodlightModule, IFlowReconcileService { /** The logger. */ - private static Logger logger = - LoggerFactory.getLogger(FlowReconcileManager.class); + private static Logger logger = LoggerFactory.getLogger(FlowReconcileManager.class); /** Reference to dependent modules */ - protected IThreadPoolService threadPool; + protected IThreadPoolService threadPoolService; protected IDebugCounterService debugCounterService; + protected IFloodlightProviderService floodlightProviderService; + /** * The list of flow reconcile listeners that have registered to get * flow reconcile callbacks. Such callbacks are invoked, for example, when * a switch with existing flow-mods joins this controller and those flows * need to be reconciled with the current configuration of the controller. */ - protected ListenerDispatcher<OFType, IFlowReconcileListener> - flowReconcileListeners; + protected ListenerDispatcher<OFType, IFlowReconcileListener> flowReconcileListeners; /** A FIFO queue to keep all outstanding flows for reconciliation */ PriorityPendingQueue <OFMatchReconcile> flowQueue; @@ -69,7 +71,7 @@ public class FlowReconcileManager /** Asynchronous task to feed the flowReconcile pipeline */ protected SingletonTask flowReconcileTask; - String controllerPktInCounterName; + protected DebugCounterResource ctrControllerPktIn; protected IDebugCounter lastPacketInCounter; protected final static int MAX_SYSTEM_LOAD_PER_SECOND = 10000; @@ -91,6 +93,7 @@ public class FlowReconcileManager private IDebugCounter ctrFlowReconcileRequest; private IDebugCounter ctrReconciledFlows; protected boolean flowReconcileEnabled; + private DebugCounterResource ctrPacketInRsrc = null; public AtomicInteger flowReconcileThreadRunCount; @@ -191,11 +194,11 @@ public class FlowReconcileManager @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { - threadPool = context.getServiceImpl(IThreadPoolService.class); + floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class); + threadPoolService = context.getServiceImpl(IThreadPoolService.class); debugCounterService = context.getServiceImpl(IDebugCounterService.class); flowQueue = new PriorityPendingQueue<OFMatchReconcile>(); - flowReconcileListeners = - new ListenerDispatcher<OFType, IFlowReconcileListener>(); + flowReconcileListeners = new ListenerDispatcher<OFType, IFlowReconcileListener>(); Map<String, String> configParam = context.getConfigParams(this); String enableValue = configParam.get(EnableConfigKey); @@ -216,6 +219,7 @@ public class FlowReconcileManager logger.error("Debug Counter Service not found."); } try { + debugCounterService.registerModule(PACKAGE); ctrFlowReconcileRequest = debugCounterService.registerCounter(PACKAGE, "flow-reconcile-request", "All flow reconcile request received by this module"); ctrReconciledFlows = debugCounterService.registerCounter(PACKAGE, "reconciled-flows", @@ -229,7 +233,7 @@ public class FlowReconcileManager @Override public void startUp(FloodlightModuleContext context) { // thread to do flow reconcile - ScheduledExecutorService ses = threadPool.getScheduledExecutor(); + ScheduledExecutorService ses = threadPoolService.getScheduledExecutor(); flowReconcileTask = new SingletonTask(ses, new Runnable() { @Override public void run() { @@ -247,11 +251,6 @@ public class FlowReconcileManager String packetInName = OFType.PACKET_IN.getClass().getName(); packetInName = packetInName.substring(packetInName.lastIndexOf('.')+1); - - // Construct controller counter for the packet_in - /*controllerPktInCounterName = debugCounterService. CounterStore.createCounterName(ICounterStoreService.CONTROLLER_NAME, - -1, - packetInName); */ } protected void updateFlush() { @@ -319,7 +318,7 @@ public class FlowReconcileManager for (OFMatchReconcile ofmRc : ofmRcList) { if (ofmRc.origReconcileQueryEvent != null) { ofmRc.origReconcileQueryEvent.evType.getDebugEvent() - .updateEventWithFlush(new FlowReconcileQueryDebugEvent( + .newEventWithFlush(new FlowReconcileQueryDebugEvent( ofmRc.origReconcileQueryEvent, "Flow Reconciliation Complete", ofmRc)); @@ -363,26 +362,25 @@ public class FlowReconcileManager * @return */ protected int getCurrentCapacity() { - IDebugCounter pktInCounter = - counterStore.getCounter(controllerPktInCounterName); - int minFlows = MIN_FLOW_RECONCILE_PER_SECOND * - FLOW_RECONCILE_DELAY_MILLISEC / 1000; - + int minFlows = MIN_FLOW_RECONCILE_PER_SECOND * FLOW_RECONCILE_DELAY_MILLISEC / 1000; + + List<DebugCounterResource> contCtrRsrcList = debugCounterService.getModuleCounterValues(Controller.class.getName()); + for (DebugCounterResource dcr : contCtrRsrcList) { + if (dcr.getCounterHierarchy().equals("packet-in")) { + ctrPacketInRsrc = dcr; + break; + } + } + // If no packetInCounter, then there shouldn't be any flow. - if (pktInCounter == null || - pktInCounter.getCounterDate() == null || - pktInCounter.getCounterValue() == null) { - logger.debug("counter {} doesn't exist", - controllerPktInCounterName); + if (ctrPacketInRsrc == null || ctrPacketInRsrc.getCounterValue() == null || ctrPacketInRsrc.getCounterValue() == 0) { + logger.debug("counter {} doesn't exist", ctrPacketInRsrc); return minFlows; } - // Haven't get any counter yet. - if (lastPacketInCounter == null) { - logger.debug("First time get the count for {}", - controllerPktInCounterName); - lastPacketInCounter = (SimpleCounter) - SimpleCounter.createCounter(pktInCounter); + // We're the first packet_in + if (lastPacketInCounter.getCounterValue() == 0) { + logger.debug("First time get the count for {}", lastPacketInCounter); return minFlows; } diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java index 68a433ef7..538e01d87 100644 --- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java +++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java @@ -21,8 +21,9 @@ import java.lang.ref.SoftReference; import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType; import net.floodlightcontroller.debugevent.IDebugEventService.EventType; +import net.floodlightcontroller.debugevent.IEventCategory; import net.floodlightcontroller.debugevent.IDebugEventService; -import net.floodlightcontroller.debugevent.IEventUpdater; +import net.floodlightcontroller.debugevent.MockDebugEventService; import net.floodlightcontroller.flowcache.PriorityPendingQueue.EventPriority; /** @@ -92,33 +93,37 @@ public class FlowReconcileQuery { private String description; private EventPriority priority; - private IEventUpdater<FlowReconcileQueryDebugEvent> - evReconcileQueryDebugEvent; + private IEventCategory<FlowReconcileQueryDebugEvent> eventCategory; + private IDebugEventService debugEventService; - private ReconcileQueryEvType(EventPriority priority, - String description) { + private ReconcileQueryEvType(EventPriority priority, String description) { this.priority = priority; this.description = description; } + public EventPriority getPriority() { return this.priority; } + public String getDescription() { return description; } - public void registerDebugEvent(String packageName, - IDebugEventService debugEvents) - evReconcileQueryDebugEvent = - debugEvents.registerEvent( - packageName, - this.toString().toLowerCase().replace("_", "-"), - this.getDescription(), - EventType.ALWAYS_LOG, - FlowReconcileQueryDebugEvent.class, - 500); + + public void registerDebugEvent(String packageName, IDebugEventService debugEvents) { + if (debugEventService == null) { + debugEventService = new MockDebugEventService(); + } + eventCategory = debugEventService.buildEvent(FlowReconcileQueryDebugEvent.class) + .setModuleName(packageName) + .setEventName(this.toString().toLowerCase().replace("_", "-")) + .setEventDescription(this.getDescription()) + .setEventType(EventType.ALWAYS_LOG) + .setBufferCapacity(500) + .register(); } - public IEventUpdater<FlowReconcileQueryDebugEvent> getDebugEvent() { - return evReconcileQueryDebugEvent; + + public IEventCategory<FlowReconcileQueryDebugEvent> getDebugEvent() { + return eventCategory; } } public FlowReconcileQuery(ReconcileQueryEvType evType) { diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java index 36212b889..64c835ace 100644 --- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java +++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java @@ -32,11 +32,12 @@ import java.util.regex.Pattern; import org.projectfloodlight.openflow.protocol.OFFlowMod; import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketOut; -import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.protocol.action.OFAction; import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc; import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst; @@ -50,14 +51,17 @@ import org.projectfloodlight.openflow.protocol.action.OFActionSetTpSrc; import org.projectfloodlight.openflow.protocol.action.OFActionSetTpDst; import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid; import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp; // PCP = Priority Code Point -import org.projectfloodlight.openflow.util.HexString; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IpProtocol; +import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U16; +import org.projectfloodlight.openflow.types.U64; +import org.projectfloodlight.openflow.types.VlanPcp; +import org.projectfloodlight.openflow.types.VlanVid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,6 +69,7 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; @@ -87,6 +92,7 @@ import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService; import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.NodePortTuple; import net.floodlightcontroller.util.MACAddress; +import net.floodlightcontroller.util.MatchString; import net.floodlightcontroller.util.OFMessageDamper; /** @@ -108,15 +114,16 @@ public class LoadBalancer implements IFloodlightModule, protected static Logger log = LoggerFactory.getLogger(LoadBalancer.class); // Our dependencies - protected IFloodlightProviderService floodlightProvider; - protected IRestApiService restApi; + protected IFloodlightProviderService floodlightProviderService; + protected IRestApiService restApiService; protected IDebugCounterService debugCounterService; protected OFMessageDamper messageDamper; - protected IDeviceService deviceManager; - protected IRoutingService routingEngine; - protected ITopologyService topology; - protected IStaticFlowEntryPusherService sfp; + protected IDeviceService deviceManagerService; + protected IRoutingService routingEngineService; + protected ITopologyService topologyService; + protected IStaticFlowEntryPusherService sfpService; + protected IOFSwitchService switchService; protected HashMap<String, LBVip> vips; protected HashMap<String, LBPool> pools; @@ -138,9 +145,9 @@ public class LoadBalancer implements IFloodlightModule, @Override public int compare(SwitchPort d1, SwitchPort d2) { DatapathId d1ClusterId = - topology.getL2DomainId(d1.getSwitchDPID()); + topologyService.getL2DomainId(d1.getSwitchDPID()); DatapathId d2ClusterId = - topology.getL2DomainId(d2.getSwitchDPID()); + topologyService.getL2DomainId(d2.getSwitchDPID()); return d1ClusterId.compareTo(d2ClusterId); } }; @@ -191,12 +198,9 @@ public class LoadBalancer implements IFloodlightModule, return Command.CONTINUE; } - private net.floodlightcontroller.core.IListener.Command - processPacketIn(IOFSwitch sw, OFPacketIn pi, - FloodlightContext cntx) { + private net.floodlightcontroller.core.IListener.Command processPacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { - Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD); + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); IPacket pkt = eth.getPayload(); if (eth.isBroadcast() || eth.isMulticast()) { @@ -325,9 +329,9 @@ public class LoadBalancer implements IFloodlightModule, */ public void pushPacket(IPacket packet, IOFSwitch sw, - int bufferId, - short inPort, - short outPort, + OFBufferId bufferId, + OFPort inPort, + OFPort outPort, FloodlightContext cntx, boolean flush) { if (log.isTraceEnabled()) { @@ -335,25 +339,20 @@ public class LoadBalancer implements IFloodlightModule, new Object[] {sw, inPort, outPort}); } - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.PACKET_OUT); + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); // set actions List<OFAction> actions = new ArrayList<OFAction>(); - actions.add(new OFActionOutput(outPort, (short) 0xffff)); - - po.setActions(actions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); - short poLength = - (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); + actions.add(sw.getOFFactory().actions().buildOutput().setPort(outPort).build()); + pob.setActions(actions); + // set buffer_id, in_port - po.setBufferId(bufferId); - po.setInPort(inPort); + pob.setBufferId(bufferId); + pob.setInPort(inPort); // set data - only if buffer_id == -1 - if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { + if (pob.getBufferId() == OFBufferId.NO_BUFFER) { if (packet == null) { log.error("BufferId is not set and packet data is null. " + "Cannot send packetOut. " + @@ -362,15 +361,12 @@ public class LoadBalancer implements IFloodlightModule, return; } byte[] packetData = packet.serialize(); - poLength += packetData.length; - po.setPacketData(packetData); + pob.setData(packetData); } - po.setLength(poLength); - try { - counterStore.updatePktOutFMCounterStoreLocal(sw, po); - messageDamper.write(sw, po, cntx, flush); + //TODO @Ryan debugCounterService.updatePktOutFMCounterStoreLocal(sw, pob.build()); + messageDamper.write(sw, pob.build(), cntx, flush); } catch (IOException e) { log.error("Failure writing packet out", e); } @@ -392,8 +388,7 @@ public class LoadBalancer implements IFloodlightModule, IDevice dstDevice = null; // retrieve all known devices - Collection<? extends IDevice> allDevices = deviceManager - .getAllDevices(); + Collection<? extends IDevice> allDevices = deviceManagerService.getAllDevices(); for (IDevice d : allDevices) { for (int j = 0; j < d.getIPv4Addresses().length; j++) { @@ -411,7 +406,7 @@ public class LoadBalancer implements IFloodlightModule, // srcDevice and/or dstDevice is null, no route can be pushed if (srcDevice == null || dstDevice == null) return; - DatapathId srcIsland = topology.getL2DomainId(sw.getId()); + DatapathId srcIsland = topologyService.getL2DomainId(sw.getId()); if (srcIsland == null) { log.debug("No openflow island found for source {}/{}", @@ -425,7 +420,7 @@ public class LoadBalancer implements IFloodlightModule, boolean on_same_if = false; for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) { DatapathId dstSwDpid = dstDap.getSwitchDPID(); - DatapathId dstIsland = topology.getL2DomainId(dstSwDpid); + DatapathId dstIsland = topologyService.getL2DomainId(dstSwDpid); if ((dstIsland != null) && dstIsland.equals(srcIsland)) { on_same_island = true; if ((sw.getId() == dstSwDpid) && @@ -470,9 +465,9 @@ public class LoadBalancer implements IFloodlightModule, SwitchPort srcDap = srcDaps[iSrcDaps]; SwitchPort dstDap = dstDaps[iDstDaps]; DatapathId srcCluster = - topology.getL2DomainId(srcDap.getSwitchDPID()); + topologyService.getL2DomainId(srcDap.getSwitchDPID()); DatapathId dstCluster = - topology.getL2DomainId(dstDap.getSwitchDPID()); + topologyService.getL2DomainId(dstDap.getSwitchDPID()); int srcVsDest = srcCluster.compareTo(dstCluster); if (srcVsDest == 0) { @@ -480,12 +475,12 @@ public class LoadBalancer implements IFloodlightModule, (srcCluster != null) && (dstCluster != null)) { Route routeIn = - routingEngine.getRoute(srcDap.getSwitchDPID(), + routingEngineService.getRoute(srcDap.getSwitchDPID(), srcDap.getPort(), dstDap.getSwitchDPID(), dstDap.getPort(), 0); Route routeOut = - routingEngine.getRoute(dstDap.getSwitchDPID(), + routingEngineService.getRoute(dstDap.getSwitchDPID(), dstDap.getPort(), srcDap.getSwitchDPID(), srcDap.getPort(), 0); @@ -533,17 +528,14 @@ public class LoadBalancer implements IFloodlightModule, String matchString = null; String actionString = null; - OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD); - - fm.setIdleTimeout((short) 0); // infinite - fm.setHardTimeout((short) 0); // infinite - fm.setBufferId(OFPacketOut.BUFFER_ID_NONE); - fm.setCommand((short) 0); - fm.setFlags((short) 0); - fm.setOutPort(OFPort.OFPP_NONE.getValue()); - fm.setCookie((long) 0); - fm.setPriority(Short.MAX_VALUE); + OFFlowMod.Builder fmb = switchService.getSwitch(pinSwitch).getOFFactory().buildFlowModify(); + + fmb.setIdleTimeout((short) 0); // infinite + fmb.setHardTimeout((short) 0); // infinite + fmb.setBufferId(OFBufferId.NO_BUFFER); + fmb.setOutPort(OFPort.ANY); //TODO @Ryan is this the same as OFPort.NONE in the old openflowj? + fmb.setCookie(U64.of(0)); + fmb.setPriority(Short.MAX_VALUE); if (inBound) { entryName = "inbound-vip-"+ member.vipId+"-client-"+client.ipAddress+"-port-"+client.targetPort @@ -581,20 +573,19 @@ public class LoadBalancer implements IFloodlightModule, } - parseActionString(fm, actionString, log); + parseActionString(fmb.build(), actionString, log); - fm.setPriority(U16.t(LB_PRIORITY)); + fmb.setPriority(U16.t(LB_PRIORITY)); - OFMatch ofMatch = new OFMatch(); + Match match = null; try { - ofMatch.fromString(matchString); + match = MatchString.fromString(matchString, switchService.getSwitch(sw).getOFFactory().getVersion()); } catch (IllegalArgumentException e) { - log.debug("ignoring flow entry {} on switch {} with illegal OFMatch() key: " - + matchString, entryName, swString); + log.debug("ignoring flow entry {} on switch {} with illegal OFMatch() key: " + matchString, entryName, swString); } - fm.setMatch(ofMatch); - sfp.addFlow(entryName, fm, swString); + fmb.setMatch(match); + sfpService.addFlow(entryName, fmb.build(), swString); } } @@ -809,8 +800,9 @@ public class LoadBalancer implements IFloodlightModule, new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); l.add(IRestApiService.class); - l.add(ICounterStoreService.class); + l.add(IOFSwitchService.class); l.add(IDeviceService.class); + l.add(IDebugCounterService.class); l.add(ITopologyService.class); l.add(IRoutingService.class); l.add(IStaticFlowEntryPusherService.class); @@ -821,13 +813,14 @@ public class LoadBalancer implements IFloodlightModule, @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { - floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); - restApi = context.getServiceImpl(IRestApiService.class); - counterStore = context.getServiceImpl(ICounterStoreService.class); - deviceManager = context.getServiceImpl(IDeviceService.class); - routingEngine = context.getServiceImpl(IRoutingService.class); - topology = context.getServiceImpl(ITopologyService.class); - sfp = context.getServiceImpl(IStaticFlowEntryPusherService.class); + floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class); + restApiService = context.getServiceImpl(IRestApiService.class); + debugCounterService = context.getServiceImpl(IDebugCounterService.class); + deviceManagerService = context.getServiceImpl(IDeviceService.class); + routingEngineService = context.getServiceImpl(IRoutingService.class); + topologyService = context.getServiceImpl(ITopologyService.class); + sfpService = context.getServiceImpl(IStaticFlowEntryPusherService.class); + switchService = context.getServiceImpl(IOFSwitchService.class); messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY, EnumSet.of(OFType.FLOW_MOD), @@ -843,15 +836,14 @@ public class LoadBalancer implements IFloodlightModule, @Override public void startUp(FloodlightModuleContext context) { - floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); - restApi.addRestletRoutable(new LoadBalancerWebRoutable()); + floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this); + restApiService.addRestletRoutable(new LoadBalancerWebRoutable()); } // Utilities borrowed from StaticFlowEntries private static class SubActionStruct { OFAction action; - int len; } /** @@ -862,7 +854,7 @@ public class LoadBalancer implements IFloodlightModule, */ public static void parseActionString(OFFlowMod flowMod, String actionstr, Logger log) { List<OFAction> actions = new LinkedList<OFAction>(); - int actionsLength = 0; + OFVersion version = flowMod.getVersion(); if (actionstr != null) { actionstr = actionstr.toLowerCase(); for (String subaction : actionstr.split(",")) { @@ -870,40 +862,40 @@ public class LoadBalancer implements IFloodlightModule, SubActionStruct subaction_struct = null; if (action.equals("output")) { - subaction_struct = decode_output(subaction, log); + subaction_struct = decode_output(subaction, version, log); } else if (action.equals("enqueue")) { - subaction_struct = decode_enqueue(subaction, log); + subaction_struct = decode_enqueue(subaction, version, log); } else if (action.equals("strip-vlan")) { - subaction_struct = decode_strip_vlan(subaction, log); + subaction_struct = decode_strip_vlan(subaction, version, log); } else if (action.equals("set-vlan-id")) { - subaction_struct = decode_set_vlan_id(subaction, log); + subaction_struct = decode_set_vlan_id(subaction, version, log); } else if (action.equals("set-vlan-priority")) { - subaction_struct = decode_set_vlan_priority(subaction, log); + subaction_struct = decode_set_vlan_priority(subaction, version, log); } else if (action.equals("set-src-mac")) { - subaction_struct = decode_set_src_mac(subaction, log); + subaction_struct = decode_set_src_mac(subaction, version, log); } else if (action.equals("set-dst-mac")) { - subaction_struct = decode_set_dst_mac(subaction, log); + subaction_struct = decode_set_dst_mac(subaction, version, log); } else if (action.equals("set-tos-bits")) { - subaction_struct = decode_set_tos_bits(subaction, log); + subaction_struct = decode_set_tos_bits(subaction, version, log); } else if (action.equals("set-src-ip")) { - subaction_struct = decode_set_src_ip(subaction, log); + subaction_struct = decode_set_src_ip(subaction, version, log); } else if (action.equals("set-dst-ip")) { - subaction_struct = decode_set_dst_ip(subaction, log); + subaction_struct = decode_set_dst_ip(subaction, version, log); } else if (action.equals("set-src-port")) { - subaction_struct = decode_set_src_port(subaction, log); + subaction_struct = decode_set_src_port(subaction, version, log); } else if (action.equals("set-dst-port")) { - subaction_struct = decode_set_dst_port(subaction, log); + subaction_struct = decode_set_dst_port(subaction, version, log); } else { log.error("Unexpected action '{}', '{}'", action, subaction); @@ -911,28 +903,25 @@ public class LoadBalancer implements IFloodlightModule, if (subaction_struct != null) { actions.add(subaction_struct.action); - actionsLength += subaction_struct.len; } } } log.debug("action {}", actions); - flowMod.setActions(actions); - flowMod.setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLength); + flowMod = flowMod.createBuilder().setActions(actions).build(); } - private static SubActionStruct decode_output(String subaction, Logger log) { + private static SubActionStruct decode_output(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n; n = Pattern.compile("output=(?:((?:0x)?\\d+)|(all)|(controller)|(local)|(ingress-port)|(normal)|(flood))").matcher(subaction); if (n.matches()) { - OFActionOutput action = new OFActionOutput(); - action.setMaxLength(Short.MAX_VALUE); - short port = OFPort.OFPP_NONE.getValue(); + OFActionOutput.Builder ab = OFFactories.getFactory(version).actions().buildOutput(); + OFPort port = OFPort.ANY; //TODO @Ryan is ANY == NONE? if (n.group(1) != null) { try { - port = get_short(n.group(1)); + port = OFPort.of(get_short(n.group(1))); } catch (NumberFormatException e) { log.debug("Invalid port in: '{}' (error ignored)", subaction); @@ -940,23 +929,22 @@ public class LoadBalancer implements IFloodlightModule, } } else if (n.group(2) != null) - port = OFPort.OFPP_ALL.getValue(); + port = OFPort.ALL; else if (n.group(3) != null) - port = OFPort.OFPP_CONTROLLER.getValue(); + port = OFPort.CONTROLLER; else if (n.group(4) != null) - port = OFPort.OFPP_LOCAL.getValue(); + port = OFPort.LOCAL; else if (n.group(5) != null) - port = OFPort.OFPP_IN_PORT.getValue(); + port = OFPort.IN_PORT; else if (n.group(6) != null) - port = OFPort.OFPP_NORMAL.getValue(); + port = OFPort.NORMAL; else if (n.group(7) != null) - port = OFPort.OFPP_FLOOD.getValue(); - action.setPort(port); - log.debug("action {}", action); + port = OFPort.FLOOD; + ab.setPort(port); + log.debug("action {}", ab.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionOutput.MINIMUM_LENGTH; + sa.action = ab.build(); } else { log.error("Invalid subaction: '{}'", subaction); @@ -966,16 +954,16 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_enqueue(String subaction, Logger log) { + private static SubActionStruct decode_enqueue(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n; n = Pattern.compile("enqueue=(?:((?:0x)?\\d+)\\:((?:0x)?\\d+))").matcher(subaction); if (n.matches()) { - short portnum = 0; + OFPort portnum = OFPort.of(0); if (n.group(1) != null) { try { - portnum = get_short(n.group(1)); + portnum = OFPort.of(get_short(n.group(1))); } catch (NumberFormatException e) { log.debug("Invalid port-num in: '{}' (error ignored)", subaction); @@ -994,14 +982,13 @@ public class LoadBalancer implements IFloodlightModule, } } - OFActionEnqueue action = new OFActionEnqueue(); - action.setPort(portnum); - action.setQueueId(queueid); - log.debug("action {}", action); + OFActionEnqueue.Builder aeb = OFFactories.getFactory(version).actions().buildEnqueue(); + aeb.setPort(portnum); + aeb.setQueueId(queueid); + log.debug("action {}", aeb.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionEnqueue.MINIMUM_LENGTH; + sa.action = aeb.build(); } else { log.debug("Invalid action: '{}'", subaction); @@ -1011,17 +998,16 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_strip_vlan(String subaction, Logger log) { + private static SubActionStruct decode_strip_vlan(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("strip-vlan").matcher(subaction); if (n.matches()) { - OFActionStripVirtualLan action = new OFActionStripVirtualLan(); - log.debug("action {}", action); + OFActionStripVlan asvl = OFFactories.getFactory(version).actions().stripVlan(); + log.debug("action {}", asvl); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionStripVirtualLan.MINIMUM_LENGTH; + sa.action = asvl; } else { log.debug("Invalid action: '{}'", subaction); @@ -1031,7 +1017,7 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_vlan_id(String subaction, Logger log) { + private static SubActionStruct decode_set_vlan_id(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-vlan-id=((?:0x)?\\d+)").matcher(subaction); @@ -1039,13 +1025,12 @@ public class LoadBalancer implements IFloodlightModule, if (n.group(1) != null) { try { short vlanid = get_short(n.group(1)); - OFActionVirtualLanIdentifier action = new OFActionVirtualLanIdentifier(); - action.setVirtualLanIdentifier(vlanid); - log.debug(" action {}", action); + OFActionSetVlanVid.Builder avvid = OFFactories.getFactory(version).actions().buildSetVlanVid(); + avvid.setVlanVid(VlanVid.ofVlan(vlanid)); + log.debug(" action {}", avvid.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionVirtualLanIdentifier.MINIMUM_LENGTH; + sa.action = avvid.build(); } catch (NumberFormatException e) { log.debug("Invalid VLAN in: {} (error ignored)", subaction); @@ -1061,7 +1046,7 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_vlan_priority(String subaction, Logger log) { + private static SubActionStruct decode_set_vlan_priority(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-vlan-priority=((?:0x)?\\d+)").matcher(subaction); @@ -1069,13 +1054,12 @@ public class LoadBalancer implements IFloodlightModule, if (n.group(1) != null) { try { byte prior = get_byte(n.group(1)); - OFActionVirtualLanPriorityCodePoint action = new OFActionVirtualLanPriorityCodePoint(); - action.setVirtualLanPriorityCodePoint(prior); - log.debug(" action {}", action); + OFActionSetVlanPcp.Builder avpcp = OFFactories.getFactory(version).actions().buildSetVlanPcp(); + avpcp.setVlanPcp(VlanPcp.of(prior)); + log.debug(" action {}", avpcp.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH; + sa.action = avpcp.build(); } catch (NumberFormatException e) { log.debug("Invalid VLAN priority in: {} (error ignored)", subaction); @@ -1091,20 +1075,19 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_src_mac(String subaction, Logger log) { + private static SubActionStruct decode_set_src_mac(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-src-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction); if (n.matches()) { byte[] macaddr = get_mac_addr(n, subaction, log); if (macaddr != null) { - OFActionDataLayerSource action = new OFActionDataLayerSource(); - action.setDataLayerAddress(macaddr); - log.debug("action {}", action); + OFActionSetDlSrc.Builder asdls = OFFactories.getFactory(version).actions().buildSetDlSrc(); + asdls.setDlAddr(MacAddress.of(macaddr)); + log.debug("action {}", asdls.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionDataLayerSource.MINIMUM_LENGTH; + sa.action = asdls.build(); } } else { @@ -1115,20 +1098,19 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_dst_mac(String subaction, Logger log) { + private static SubActionStruct decode_set_dst_mac(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-dst-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction); if (n.matches()) { byte[] macaddr = get_mac_addr(n, subaction, log); if (macaddr != null) { - OFActionDataLayerDestination action = new OFActionDataLayerDestination(); - action.setDataLayerAddress(macaddr); - log.debug(" action {}", action); + OFActionSetDlDst.Builder asdld = OFFactories.getFactory(version).actions().buildSetDlDst(); + asdld.setDlAddr(MacAddress.of(macaddr)); + log.debug(" action {}", asdld.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionDataLayerDestination.MINIMUM_LENGTH; + sa.action = asdld.build(); } } else { @@ -1139,7 +1121,7 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_tos_bits(String subaction, Logger log) { + private static SubActionStruct decode_set_tos_bits(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-tos-bits=((?:0x)?\\d+)").matcher(subaction); @@ -1147,13 +1129,12 @@ public class LoadBalancer implements IFloodlightModule, if (n.group(1) != null) { try { byte tosbits = get_byte(n.group(1)); - OFActionNetworkTypeOfService action = new OFActionNetworkTypeOfService(); - action.setNetworkTypeOfService(tosbits); - log.debug(" action {}", action); + OFActionSetNwTos.Builder snwtos = OFFactories.getFactory(version).actions().buildSetNwTos(); + snwtos.setNwTos(tosbits); + log.debug(" action {}", snwtos.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionNetworkTypeOfService.MINIMUM_LENGTH; + sa.action = snwtos.build(); } catch (NumberFormatException e) { log.debug("Invalid dst-port in: {} (error ignored)", subaction); @@ -1169,19 +1150,18 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_src_ip(String subaction, Logger log) { + private static SubActionStruct decode_set_src_ip(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-src-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction); if (n.matches()) { int ipaddr = get_ip_addr(n, subaction, log); - OFActionNetworkLayerSource action = new OFActionNetworkLayerSource(); - action.setNetworkAddress(ipaddr); - log.debug(" action {}", action); + OFActionSetNwSrc.Builder snws = OFFactories.getFactory(version).actions().buildSetNwSrc(); + snws.setNwAddr(IPv4Address.of(ipaddr)); + log.debug(" action {}", snws.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionNetworkLayerSource.MINIMUM_LENGTH; + sa.action = snws.build(); } else { log.debug("Invalid action: '{}'", subaction); @@ -1191,19 +1171,18 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_dst_ip(String subaction, Logger log) { + private static SubActionStruct decode_set_dst_ip(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-dst-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction); if (n.matches()) { int ipaddr = get_ip_addr(n, subaction, log); - OFActionNetworkLayerDestination action = new OFActionNetworkLayerDestination(); - action.setNetworkAddress(ipaddr); - log.debug("action {}", action); + OFActionSetNwDst.Builder snwd = OFFactories.getFactory(version).actions().buildSetNwDst(); + snwd.setNwAddr(IPv4Address.of(ipaddr)); + log.debug("action {}", snwd.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionNetworkLayerDestination.MINIMUM_LENGTH; + sa.action = snwd.build(); } else { log.debug("Invalid action: '{}'", subaction); @@ -1213,21 +1192,20 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_src_port(String subaction, Logger log) { + private static SubActionStruct decode_set_src_port(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-src-port=((?:0x)?\\d+)").matcher(subaction); if (n.matches()) { if (n.group(1) != null) { try { - short portnum = get_short(n.group(1)); - OFActionTransportLayerSource action = new OFActionTransportLayerSource(); - action.setTransportPort(portnum); - log.debug("action {}", action); + TransportPort portnum = TransportPort.of(get_short(n.group(1))); + OFActionSetTpSrc.Builder stps = OFFactories.getFactory(version).actions().buildSetTpSrc(); + stps.setTpPort(portnum); + log.debug("action {}", stps.build()); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionTransportLayerSource.MINIMUM_LENGTH;; + sa.action = stps.build(); } catch (NumberFormatException e) { log.debug("Invalid src-port in: {} (error ignored)", subaction); @@ -1243,21 +1221,20 @@ public class LoadBalancer implements IFloodlightModule, return sa; } - private static SubActionStruct decode_set_dst_port(String subaction, Logger log) { + private static SubActionStruct decode_set_dst_port(String subaction, OFVersion version, Logger log) { SubActionStruct sa = null; Matcher n = Pattern.compile("set-dst-port=((?:0x)?\\d+)").matcher(subaction); if (n.matches()) { if (n.group(1) != null) { try { - short portnum = get_short(n.group(1)); - OFActionTransportLayerDestination action = new OFActionTransportLayerDestination(); - action.setTransportPort(portnum); - log.debug("action {}", action); + TransportPort portnum = TransportPort.of(get_short(n.group(1))); + OFActionSetTpDst.Builder stpd = OFFactories.getFactory(version).actions().buildSetTpDst(); + stpd.setTpPort(portnum); + log.debug("action {}", stpd); sa = new SubActionStruct(); - sa.action = action; - sa.len = OFActionTransportLayerDestination.MINIMUM_LENGTH;; + sa.action = stpd.build(); } catch (NumberFormatException e) { log.debug("Invalid dst-port in: {} (error ignored)", subaction); diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index 1c273f826..abd7e8bf1 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -113,7 +113,7 @@ public abstract class ForwardingBase static { AppCookie.registerApp(FORWARDING_APP_ID, "Forwarding"); } - public static final long appCookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); + public static final U64 appCookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); // Comparator for sorting by SwitchCluster public Comparator<SwitchPort> clusterIdComparator = -- GitLab