ONOS-6613 Non-disruptive intent reallocation
Change-Id: I5d051c20402a226ad540b8bc08695b602ff75273
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java
index f979f27..fdef627 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java
@@ -18,11 +18,14 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.VlanId;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -40,13 +43,17 @@
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.PathIntent;
import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.store.trivial.SimpleIntentStore;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.mock;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
* Tests for flow rule Intent installer.
@@ -54,17 +61,21 @@
public class FlowRuleIntentInstallerTest extends AbstractIntentInstallerTest {
private TestFlowRuleService flowRuleService;
+ private TestFlowRuleServiceNonDisruptive flowRuleServiceNonDisruptive;
private FlowRuleIntentInstaller installer;
@Before
public void setup() {
super.setup();
flowRuleService = new TestFlowRuleService();
+ flowRuleServiceNonDisruptive = new TestFlowRuleServiceNonDisruptive();
installer = new FlowRuleIntentInstaller();
installer.flowRuleService = flowRuleService;
+ installer.store = new SimpleIntentStore();
installer.intentExtensionService = intentExtensionService;
installer.intentInstallCoordinator = intentInstallCoordinator;
installer.trackerService = trackerService;
+ installer.configService = mock(ComponentConfigService.class);
installer.activate();
}
@@ -328,6 +339,109 @@
}
/**
+ * Testing the non-disruptive reallocation.
+ */
+ @Test
+ public void testUninstallAndInstallNonDisruptive() throws InterruptedException {
+
+ installer.flowRuleService = flowRuleServiceNonDisruptive;
+
+ List<Intent> intentsToInstall = createAnotherFlowRuleIntentsNonDisruptive();
+ List<Intent> intentsToUninstall = createFlowRuleIntentsNonDisruptive();
+
+ IntentData toInstall = new IntentData(createP2PIntentNonDisruptive(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentData toUninstall = new IntentData(createP2PIntentNonDisruptive(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ //A single FlowRule is evaluated for every non-disruptive stage
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(CP1.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP3.port())
+ .build();
+
+ FlowRule firstStageInstalledRule = DefaultFlowRule.builder()
+ .forDevice(CP1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY - 1)
+ .makePermanent()
+ .build();
+
+ assertTrue(flowRuleServiceNonDisruptive.flowRulesAdd.contains(firstStageInstalledRule));
+
+ selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(CP4_2.port())
+ .build();
+ treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP4_1.port())
+ .build();
+
+ FlowRule secondStageUninstalledRule = DefaultFlowRule.builder()
+ .forDevice(CP4_1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+
+ assertTrue(flowRuleServiceNonDisruptive.flowRulesRemove.contains(secondStageUninstalledRule));
+
+ selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(CP4_3.port())
+ .build();
+ treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP4_1.port())
+ .build();
+
+ FlowRule thirdStageInstalledRule = DefaultFlowRule.builder()
+ .forDevice(CP4_1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+
+ assertTrue(flowRuleServiceNonDisruptive.flowRulesAdd.contains(thirdStageInstalledRule));
+
+ selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(CP2_1.port())
+ .build();
+ treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP2_2.port())
+ .build();
+
+ FlowRule lastStageUninstalledRule = DefaultFlowRule.builder()
+ .forDevice(CP2_1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+
+ assertTrue(flowRuleServiceNonDisruptive.flowRulesRemove.contains(lastStageUninstalledRule));
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
* Generates FlowRuleIntents for test.
*
* @return the FlowRuleIntents for test
@@ -442,6 +556,107 @@
}
/**
+ * Generates FlowRuleIntents for testing non-disruptive reallocation.
+ *
+ * @return the FlowRuleIntents for test
+ */
+ public List<Intent> createFlowRuleIntentsNonDisruptive() {
+
+ Map<ConnectPoint, ConnectPoint> portsAssociation = Maps.newHashMap();
+ portsAssociation.put(CP1, CP2);
+ portsAssociation.put(CP2_1, CP2_2);
+ portsAssociation.put(CP4_2, CP4_1);
+
+ List<FlowRule> flowRules = Lists.newArrayList();
+
+ for (ConnectPoint srcPoint : portsAssociation.keySet()) {
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(srcPoint.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(portsAssociation.get(srcPoint).port())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(srcPoint.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+ flowRules.add(flowRule);
+ }
+
+
+
+ List<NetworkResource> resources = ImmutableList.of(S1_S2, S2_S4);
+
+ FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
+ KEY1,
+ flowRules,
+ resources,
+ PathIntent.ProtectionType.PRIMARY,
+ RG1);
+
+ List<Intent> flowRuleIntents = Lists.newArrayList();
+ flowRuleIntents.add(intent);
+
+ return flowRuleIntents;
+ }
+
+ /**
+ * Generates another FlowRuleIntent, going through a different path, for testing non-disruptive reallocation.
+ *
+ * @return the FlowRuleIntents for test
+ */
+ public List<Intent> createAnotherFlowRuleIntentsNonDisruptive() {
+ Map<ConnectPoint, ConnectPoint> portsAssociation = Maps.newHashMap();
+ portsAssociation.put(CP1, CP3);
+ portsAssociation.put(CP3_1, CP3_2);
+ portsAssociation.put(CP4_3, CP4_1);
+
+ List<FlowRule> flowRules = Lists.newArrayList();
+
+ for (ConnectPoint srcPoint : portsAssociation.keySet()) {
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(srcPoint.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(portsAssociation.get(srcPoint).port())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(srcPoint.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+ flowRules.add(flowRule);
+ }
+
+
+
+ List<NetworkResource> resources = ImmutableList.of(S1_S3, S3_S4);
+
+ FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
+ KEY1,
+ flowRules,
+ resources,
+ PathIntent.ProtectionType.PRIMARY,
+ RG1);
+
+ List<Intent> flowRuleIntents = Lists.newArrayList();
+ flowRuleIntents.add(intent);
+
+ return flowRuleIntents;
+ }
+
+ /**
* The FlowRuleService for test; always success for any flow rule operations.
*/
class TestFlowRuleService extends FlowRuleServiceAdapter {
@@ -489,4 +704,37 @@
}
}
+ /**
+ * The FlowRuleService for testing non-disruptive reallocation.
+ * It keeps all the FlowRules installed/uninstalled.
+ */
+ class TestFlowRuleServiceNonDisruptive extends FlowRuleServiceAdapter {
+
+ Set<FlowRule> flowRulesAdd = Sets.newHashSet();
+ Set<FlowRule> flowRulesRemove = Sets.newHashSet();
+
+ public void record(FlowRuleOperations ops) {
+ ops.stages().forEach(stage -> {
+ stage.forEach(op -> {
+ switch (op.type()) {
+ case ADD:
+ flowRulesAdd.add(op.rule());
+ break;
+ case REMOVE:
+ flowRulesRemove.add(op.rule());
+ break;
+ default:
+ break;
+ }
+ });
+ });
+ }
+
+ @Override
+ public void apply(FlowRuleOperations ops) {
+ record(ops);
+ ops.callback().onSuccess(ops);
+ }
+ }
+
}