ONOS-6059 Favor FlowRuleProgrammable
Enable Driver to override flow programming implementation,
even for full feature southbound implementation, such as OpenFlow.
Change-Id: I3df74d3df741afe9a3900bc6a8e26a26a1ed1ec0
diff --git a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
index cd244ff..2bd6ca2 100644
--- a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
@@ -52,6 +52,7 @@
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperation;
import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderRegistry;
import org.onosproject.net.flow.FlowRuleProviderService;
@@ -61,6 +62,7 @@
import org.onosproject.net.flow.TableStatisticsEntry;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
+import org.onosproject.net.provider.ProviderId;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
@@ -69,6 +71,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
@@ -118,7 +121,7 @@
private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
private final DeviceListener deviceListener = new InternalDeviceListener();
- private final FlowRuleDriverProvider defaultProvider = new FlowRuleDriverProvider();
+ private final FlowRuleDriverProvider driverProvider = new FlowRuleDriverProvider();
protected ExecutorService deviceInstallers =
Executors.newFixedThreadPool(32, groupedThreads("onos/flowservice", "device-installer-%d", log));
@@ -172,13 +175,13 @@
if (context != null) {
readComponentConfiguration(context);
}
- defaultProvider.init(new InternalFlowRuleProviderService(defaultProvider),
+ driverProvider.init(new InternalFlowRuleProviderService(driverProvider),
deviceService, mastershipService, fallbackFlowPollFrequency);
}
@Override
protected FlowRuleProvider defaultProvider() {
- return defaultProvider;
+ return driverProvider;
}
/**
@@ -323,6 +326,26 @@
return new InternalFlowRuleProviderService(provider);
}
+ @Override
+ protected synchronized FlowRuleProvider getProvider(ProviderId pid) {
+ log.warn("should not be calling getProvider(ProviderId)");
+ return super.getProvider(pid);
+ }
+
+ /**
+ * {@inheritDoc}
+ * if the Device does not support {@link FlowRuleProgrammable}.
+ */
+ @Override
+ protected synchronized FlowRuleProvider getProvider(DeviceId deviceId) {
+ // if device supports FlowRuleProgrammable,
+ // use FlowRuleProgrammable via FlowRuleDriverProvider
+ return Optional.ofNullable(deviceService.getDevice(deviceId))
+ .filter(dev -> dev.is(FlowRuleProgrammable.class))
+ .<FlowRuleProvider>map(x -> driverProvider)
+ .orElseGet(() -> super.getProvider(deviceId));
+ }
+
private class InternalFlowRuleProviderService
extends AbstractProviderService<FlowRuleProvider>
implements FlowRuleProviderService {
@@ -349,8 +372,7 @@
if (flowEntry.reason() == FlowEntry.FlowRemoveReason.HARD_TIMEOUT) {
((DefaultFlowEntry) stored).setState(FlowEntry.FlowEntryState.REMOVED);
}
- Device device = deviceService.getDevice(flowEntry.deviceId());
- FlowRuleProvider frp = getProvider(device.providerId());
+ FlowRuleProvider frp = getProvider(flowEntry.deviceId());
FlowRuleEvent event = null;
switch (stored.state()) {
case ADDED:
@@ -375,8 +397,7 @@
private void flowMissing(FlowEntry flowRule) {
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
- Device device = deviceService.getDevice(flowRule.deviceId());
- FlowRuleProvider frp = getProvider(device.providerId());
+ FlowRuleProvider frp = getProvider(flowRule.deviceId());
FlowRuleEvent event = null;
switch (flowRule.state()) {
case PENDING_REMOVE:
@@ -409,6 +430,7 @@
private void extraneousFlow(FlowRule flowRule) {
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
+ // getProvider is customized to favor driverProvider
FlowRuleProvider frp = getProvider(flowRule.deviceId());
frp.removeFlowRule(flowRule);
log.debug("Flow {} is on switch but not in store.", flowRule);
@@ -573,6 +595,7 @@
DeviceId deviceId = event.deviceId();
FlowRuleBatchOperation batchOperation = request.asBatchOperation(deviceId);
+ // getProvider is customized to favor driverProvider
FlowRuleProvider flowRuleProvider = getProvider(deviceId);
if (flowRuleProvider != null) {
flowRuleProvider.executeBatch(batchOperation);