Add a configuration option to remove or use Flow Path from database during ONOS cluster restart (ONOS-857)
The new configuration option inside conf/onos.properties or
conf/onos-embedded.properties is:
net.onrc.onos.ofcontroller.flowmanager.FlowManager.reuseDatabaseFlowPath = false
If the configuration option is not listed, the default value is "false",
i.e., the leftover FlowPath state in the database will be deleted.
If it is set to true, the FlowPath state (i.e., the result Flow Entries)
will be pushed into the switches.
Conflicts:
conf/onos.properties
conf/onos-embedded.properties
src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
NOTE: The above three conflicts have been resolved by hand.
Change-Id: Ie39bb7f00e617a3765530d7112fccfa95bbafa71
diff --git a/conf/onos-embedded.properties b/conf/onos-embedded.properties
index d47b0d1..ec7a78f 100644
--- a/conf/onos-embedded.properties
+++ b/conf/onos-embedded.properties
@@ -12,6 +12,6 @@
net.floodlightcontroller.core.FloodlightProvider.workerthreads = 48
net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
+net.onrc.onos.ofcontroller.flowmanager.FlowManager.reuseDatabaseFlowPath = false
#net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = conf/titan-embedded.properties
net.onrc.onos.datagrid.HazelcastDatagrid.datagridConfig = conf/hazelcast.xml
-
diff --git a/conf/onos.properties b/conf/onos.properties
index 508ffef..ee2c9c9 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -14,6 +14,7 @@
net.floodlightcontroller.core.FloodlightProvider.workerthreads = 16
net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
+net.onrc.onos.ofcontroller.flowmanager.FlowManager.reuseDatabaseFlowPath = false
#net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/cassandra.titan
net.onrc.onos.datagrid.HazelcastDatagrid.datagridConfig = conf/hazelcast.xml
#net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/ramcloud.conf
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index f4664cc..108d945 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -39,6 +39,7 @@
import net.onrc.onos.ofcontroller.util.FlowPathUserState;
import net.onrc.onos.ofcontroller.util.Pair;
import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
import com.thinkaurelius.titan.core.TitanException;
import com.esotericsoftware.kryo.Kryo;
@@ -62,8 +63,9 @@
protected FloodlightModuleContext context;
protected FlowEventHandler flowEventHandler;
- protected IFlowPusherService pusher;
+ protected IFlowPusherService pusherService;
protected IForwardingService forwardingService;
+ protected IControllerRegistryService registryService;
private KryoFactory kryoFactory = new KryoFactory();
@@ -153,6 +155,7 @@
l.add(IDatagridService.class);
l.add(IRestApiService.class);
l.add(IFlowPusherService.class);
+ l.add(IControllerRegistryService.class);
//
// TODO: Comment-out the dependency on the IForwardingService,
// because it is an optional module. Apparently, adding the dependency
@@ -174,8 +177,9 @@
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
datagridService = context.getServiceImpl(IDatagridService.class);
restApi = context.getServiceImpl(IRestApiService.class);
- pusher = context.getServiceImpl(IFlowPusherService.class);
+ pusherService = context.getServiceImpl(IFlowPusherService.class);
forwardingService = context.getServiceImpl(IForwardingService.class);
+ registryService = context.getServiceImpl(IControllerRegistryService.class);
this.init("","");
}
@@ -233,6 +237,49 @@
floodlightProvider.addOFSwitchListener(flowEventHandler);
datagridService.registerFlowEventHandlerService(flowEventHandler);
flowEventHandler.start();
+
+ //
+ // FlowManager cleanup if cluster leader
+ //
+ if (registryService.isClusterLeader()) {
+ boolean reuseDatabaseFlowPath = false;
+
+ //
+ // Deal with leftover Flow state in the database: cleanup
+ // or push it into the switches.
+ //
+ do {
+ Map<String, String> configMap = context.getConfigParams(this);
+ if (configMap == null)
+ break;
+ String operation = configMap.get("reuseDatabaseFlowPath");
+ if (operation == null)
+ break;
+ if (operation.equals("true"))
+ reuseDatabaseFlowPath = true;
+ } while (false);
+
+ if (reuseDatabaseFlowPath) {
+ // Push all flows from the database into the switches
+ log.debug("Startup Cluster Leader FlowManager: push Flow Paths to Switches");
+ //
+ // NOTE: For simplicity, we explicitly re-add all flows
+ // from the database, even if this means we are re-adding
+ // them to the database.
+ // One of the reasons is because addFlow() contains a
+ // number of sanity checks and cleanups which we don't
+ // want to repeat here; e.g., truncating Shortest Path
+ // Flow Entries which might be obsoleted.
+ //
+ ArrayList<FlowPath> flowPaths = getAllFlows();
+ for (FlowPath flowPath : flowPaths)
+ addFlow(flowPath);
+ } else {
+ // Delete all flows in the database
+ log.debug("Startup Cluster Leader FlowManager: cleanup Flow Paths in database");
+ deleteAllFlows();
+ }
+ }
}
/**
@@ -635,7 +682,7 @@
entries.add(new Pair<IOFSwitch, FlowEntry>(mySwitch, flowEntry));
}
- pusher.pushFlowEntries(entries);
+ pusherService.pushFlowEntries(entries);
}
/**