Pavlin Radoslavov

Added a mechanism to configure the following timeout values.

Those are needed for the Internet2 deployment.

 * FlowRuleManager Timeout per Flow Operation (default to 500ms)
   This can be set in the following configuration file and variable:

   tools/package/etc/org.onosproject.net.flow.impl.FlowRuleManager.cfg
   timeoutPerFlowOpMsec = 500

 * IntentManager Timeout per Intent Operation (default to 500ms)
   This can be set in the following configuration file and variable:

   tools/package/etc/org.onosproject.net.intent.impl.IntentManager.cfg
   timeoutPerIntentOpMsec = 500

   For the Intentet2 deployment the above two parameters should be
   configured to 15000 (i.e., 15 seconds).
   The reason is because of recent modifications to the Internet2 firewall:
   it could take up to 10s for the reported FlowStats to reflect added
   FlowMods.

   Also, sometimes a single FlowAdd FLOW_MOD operation
   with the Internet2 firewall in the middle could take close to 1s to
   complete.

 * Added sample configuration files:
   tools/package/etc/samples/org.onosproject.*.cfg

   Those sample configuration files should be copied to the following
   directory so they can be used:

   tools/package/etc/

Change-Id: I699d93d4210fd7033234fd71be9b64c1f1d86117
......@@ -25,6 +25,8 @@ import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
......@@ -53,8 +55,10 @@ import org.onosproject.net.flow.FlowRuleStore;
import org.onosproject.net.flow.FlowRuleStoreDelegate;
import org.onosproject.net.provider.AbstractProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
......@@ -68,6 +72,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
......@@ -82,6 +87,8 @@ public class FlowRuleManager
enum BatchState { STARTED, FINISHED, CANCELLED };
private static final int DEFAULT_TIMEOUT_PER_FLOW_OP_MSEC = 500; // ms
public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
private final Logger log = getLogger(getClass());
......@@ -101,8 +108,16 @@ public class FlowRuleManager
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Property(name = "timeoutPerFlowOpMsec", intValue = DEFAULT_TIMEOUT_PER_FLOW_OP_MSEC,
label = "Configure Timeout per Flow Operation; " +
"default is 500 msec")
private int timeoutPerFlowOpMsec = DEFAULT_TIMEOUT_PER_FLOW_OP_MSEC;
@Activate
public void activate() {
public void activate(ComponentContext context) {
readComponentConfiguration(context);
futureService =
Executors.newFixedThreadPool(32, namedThreads("provider-future-listeners-%d"));
store.setDelegate(delegate);
......@@ -119,6 +134,54 @@ public class FlowRuleManager
log.info("Stopped");
}
@Modified
public void modified(ComponentContext context) {
readComponentConfiguration(context);
}
/**
* Extracts properties from the component configuration context.
*
* @param context the component context
*/
private void readComponentConfiguration(ComponentContext context) {
if (context == null) {
return; // Nothing to do
}
Dictionary<?, ?> properties = context.getProperties();
Integer timeoutPerFlowOpMsecConfigured =
getIntegerProperty(properties, "timeoutPerFlowOpMsec");
if (timeoutPerFlowOpMsecConfigured == null) {
log.info("Timeout per Flow Operation is not configured, " +
"using current value of {} ms", timeoutPerFlowOpMsec);
} else {
timeoutPerFlowOpMsec = timeoutPerFlowOpMsecConfigured;
log.info("Configured. Timeout per Flow Operation is " +
"configured to {} ms", timeoutPerFlowOpMsec);
}
}
/**
* Get Integer property from the propertyName
* Return null if propertyName is not found.
*
* @param properties properties to be looked up
* @param propertyName the name of the property to look up
* @return value when the propertyName is defined or return null
*/
private static Integer getIntegerProperty(Dictionary<?, ?> properties,
String propertyName) {
Integer value = null;
try {
String s = (String) properties.get(propertyName);
value = isNullOrEmpty(s) ? null : Integer.parseInt(s.trim());
} catch (NumberFormatException | ClassCastException e) {
value = null;
}
return value;
}
@Override
public int getFlowRuleCount() {
return store.getFlowRuleCount();
......@@ -378,9 +441,6 @@ public class FlowRuleManager
// Store delegate to re-post events emitted from the store.
private class InternalStoreDelegate implements FlowRuleStoreDelegate {
// FIXME set appropriate default and make it configurable
private static final int TIMEOUT_PER_OP = 500; // ms
// TODO: Right now we only dispatch events at individual flowEntry level.
// It may be more efficient for also dispatch events as a batch.
@Override
......@@ -408,7 +468,8 @@ public class FlowRuleManager
public void run() {
CompletedBatchOperation res;
try {
res = result.get(TIMEOUT_PER_OP * batchOperation.size(), TimeUnit.MILLISECONDS);
res = result.get(timeoutPerFlowOpMsec * batchOperation.size(),
TimeUnit.MILLISECONDS);
store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res));
} catch (TimeoutException | InterruptedException | ExecutionException e) {
log.warn("Something went wrong with the batch operation {}",
......
......@@ -22,6 +22,8 @@ import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
......@@ -50,10 +52,12 @@ import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentStore;
import org.onosproject.net.intent.BatchWrite;
import org.onosproject.net.intent.IntentStoreDelegate;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
......@@ -67,6 +71,7 @@ import java.util.concurrent.TimeoutException;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.onosproject.net.intent.IntentState.*;
import static org.onlab.util.Tools.namedThreads;
......@@ -79,6 +84,9 @@ import static org.slf4j.LoggerFactory.getLogger;
@Service
public class IntentManager
implements IntentService, IntentExtensionService {
private static final int DEFAULT_TIMEOUT_PER_INTENT_OP_MSEC = 500; // ms
private static final Logger log = getLogger(IntentManager.class);
public static final String INTENT_NULL = "Intent cannot be null";
......@@ -119,6 +127,10 @@ public class IntentManager
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleService flowRuleService;
@Property(name = "timeoutPerIntentOpMsec", intValue = DEFAULT_TIMEOUT_PER_INTENT_OP_MSEC,
label = "Configure Timeout per Intent Operation; " +
"default is 500 msec")
private int timeoutPerIntentOpMsec = DEFAULT_TIMEOUT_PER_INTENT_OP_MSEC;
private ExecutorService executor;
......@@ -128,7 +140,9 @@ public class IntentManager
private IdGenerator idGenerator;
@Activate
public void activate() {
public void activate(ComponentContext context) {
readComponentConfiguration(context);
store.setDelegate(delegate);
trackerService.setDelegate(topoDelegate);
batchService.setDelegate(batchDelegate);
......@@ -150,6 +164,54 @@ public class IntentManager
log.info("Stopped");
}
@Modified
public void modified(ComponentContext context) {
readComponentConfiguration(context);
}
/**
* Extracts properties from the component configuration context.
*
* @param context the component context
*/
private void readComponentConfiguration(ComponentContext context) {
if (context == null) {
return; // Nothing to do
}
Dictionary<?, ?> properties = context.getProperties();
Integer timeoutPerIntentOpMsecConfigured =
getIntegerProperty(properties, "timeoutPerIntentOpMsec");
if (timeoutPerIntentOpMsecConfigured == null) {
log.info("Timeout per Intent Operation is not configured, " +
"using current value of {} ms", timeoutPerIntentOpMsec);
} else {
timeoutPerIntentOpMsec = timeoutPerIntentOpMsecConfigured;
log.info("Configured. Timeout per Intent Operation is " +
"configured to {} ms", timeoutPerIntentOpMsec);
}
}
/**
* Get Integer property from the propertyName
* Return null if propertyName is not found.
*
* @param properties properties to be looked up
* @param propertyName the name of the property to look up
* @return value when the propertyName is defined or return null
*/
private static Integer getIntegerProperty(Dictionary<?, ?> properties,
String propertyName) {
Integer value = null;
try {
String s = (String) properties.get(propertyName);
value = isNullOrEmpty(s) ? null : Integer.parseInt(s.trim());
} catch (NumberFormatException | ClassCastException e) {
value = null;
}
return value;
}
@Override
public void submit(Intent intent) {
checkNotNull(intent, INTENT_NULL);
......@@ -744,7 +806,6 @@ public class IntentManager
private class IntentInstallMonitor implements Runnable {
// TODO make this configurable
private static final int TIMEOUT_PER_OP = 500; // ms
private static final int MAX_ATTEMPTS = 3;
private final IntentOperations ops;
......@@ -764,7 +825,7 @@ public class IntentManager
private void resetTimeoutLimit() {
// FIXME compute reasonable timeouts
this.endTime = System.currentTimeMillis()
+ ops.operations().size() * TIMEOUT_PER_OP;
+ ops.operations().size() * timeoutPerIntentOpMsec;
}
private void buildIntentUpdates() {
......
......@@ -106,7 +106,7 @@ public class FlowRuleManagerTest {
service = mgr;
registry = mgr;
mgr.activate();
mgr.activate(null);
mgr.addListener(listener);
provider = new TestProvider(PID);
providerService = registry.register(provider);
......
......@@ -285,7 +285,7 @@ public class IntentManagerTest {
service = manager;
extensionService = manager;
manager.activate();
manager.activate(null);
service.addListener(listener);
extensionService.registerCompiler(MockIntent.class, compiler);
extensionService.registerInstaller(MockInstallableIntent.class, installer);
......
#
# Sample configuration for the ONOS FlowRuleManager.
#
#
# Timeout per Flow Operation (in milliseconds).
# Default is 500 msec
#
# timeoutPerFlowOpMsec = 500
#
# Sample configuration for the ONOS IntentManager.
#
#
# Timeout per Intent Operation (in milliseconds).
# Default is 500 msec
#
# timeoutPerIntentOpMsec = 500