| /* |
| * Copyright 2016-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.net.optical.intent.impl.compiler; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Sets; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.onlab.packet.ChassisId; |
| import org.onosproject.TestApplicationId; |
| import org.onosproject.core.ApplicationId; |
| import org.onosproject.core.CoreService; |
| import org.onosproject.net.AbstractProjectableModel; |
| import org.onosproject.net.Annotations; |
| import org.onosproject.net.CltSignalType; |
| import org.onosproject.net.ConnectPoint; |
| import org.onosproject.net.DefaultAnnotations; |
| import org.onosproject.net.DefaultDevice; |
| import org.onosproject.net.DefaultLink; |
| import org.onosproject.net.DefaultPath; |
| import org.onosproject.net.DefaultPort; |
| import org.onosproject.net.Device; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.Link; |
| import org.onosproject.net.OduSignalId; |
| import org.onosproject.net.OduSignalType; |
| import org.onosproject.net.OduSignalUtils; |
| import org.onosproject.net.OtuSignalType; |
| import org.onosproject.net.Path; |
| import org.onosproject.net.Port; |
| import org.onosproject.net.PortNumber; |
| import org.onosproject.net.TributarySlot; |
| import org.onosproject.net.device.DeviceServiceAdapter; |
| import org.onosproject.net.driver.DriverService; |
| import org.onosproject.net.driver.DriverServiceAdapter; |
| import org.onosproject.net.flow.DefaultTrafficSelector; |
| import org.onosproject.net.flow.DefaultTrafficTreatment; |
| import org.onosproject.net.flow.FlowRule; |
| import org.onosproject.net.flow.TrafficSelector; |
| import org.onosproject.net.flow.TrafficTreatment; |
| import org.onosproject.net.flow.criteria.Criteria; |
| import org.onosproject.net.flow.instructions.Instructions; |
| import org.onosproject.net.intent.AbstractIntentTest; |
| import org.onosproject.net.intent.FlowRuleIntent; |
| import org.onosproject.net.intent.Intent; |
| import org.onosproject.net.intent.IntentExtensionService; |
| import org.onosproject.net.intent.Key; |
| import org.onosproject.net.intent.OpticalOduIntent; |
| import org.onosproject.net.optical.OduCltPort; |
| import org.onosproject.net.optical.OtuPort; |
| import org.onosproject.net.optical.impl.DefaultOduCltPort; |
| import org.onosproject.net.optical.impl.DefaultOtuPort; |
| import org.onosproject.net.provider.ProviderId; |
| import org.onosproject.net.resource.MockResourceService; |
| import org.onosproject.net.topology.LinkWeight; |
| import org.onosproject.net.topology.Topology; |
| import org.onosproject.net.topology.TopologyServiceAdapter; |
| |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| |
| import static org.easymock.EasyMock.*; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.hamcrest.Matchers.*; |
| import static org.junit.Assert.assertEquals; |
| import static org.onosproject.net.AnnotationKeys.PORT_NAME; |
| import static org.onosproject.net.AnnotationKeys.STATIC_PORT; |
| import static org.onosproject.net.Device.Type.OTN; |
| import static org.onosproject.net.DeviceId.deviceId; |
| import static org.onosproject.net.Link.Type.OPTICAL; |
| import static org.onosproject.net.NetTestTools.APP_ID; |
| import static org.onosproject.net.NetTestTools.PID; |
| |
| public class OpticalOduIntentCompilerTest extends AbstractIntentTest { |
| |
| private static final String DEV1 = "of:1"; |
| private static final String DEV2 = "of:2"; |
| private static final String DEV3 = "of:3"; |
| |
| static final Key KEY1 = Key.of(5L, APP_ID); |
| |
| private static final String STATIC_TRUE = "true"; |
| private static final String PNAME = "p2"; |
| |
| private CoreService coreService; |
| private IntentExtensionService intentExtensionService; |
| private OpticalOduIntentCompiler sut; |
| |
| private final ApplicationId appId = new TestApplicationId("test"); |
| private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), OTN, |
| "m", "h", "s", "n", new ChassisId(0L)); |
| private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), OTN, |
| "m", "h", "s", "n", new ChassisId(1L)); |
| private static Device device3 = new DefaultDevice(ProviderId.NONE, deviceId(DEV3), OTN, |
| "m", "h", "s", "n", new ChassisId(2L)); |
| |
| private static Annotations annotations1 = DefaultAnnotations.builder().set(STATIC_PORT, STATIC_TRUE).build(); |
| private static Annotations annotations2 = DefaultAnnotations.builder().set(PORT_NAME, PNAME).build(); |
| |
| // OduClt ports with signalType=1GBE |
| private static final OduCltPort D1P1 = |
| new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(1), true, annotations1), |
| CltSignalType.CLT_1GBE); |
| private static final OduCltPort D3P2 = |
| new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(2), true, annotations1), |
| CltSignalType.CLT_1GBE); |
| |
| // Otu ports with signalType=ODU2 |
| private static final OtuPort D1P2 = |
| new DefaultOtuPort(new DefaultPort(device1, PortNumber.portNumber(2), true, annotations2), |
| OtuSignalType.OTU2); |
| private static final OtuPort D2P1 = |
| new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(1), true, annotations2), |
| OtuSignalType.OTU2); |
| private static final OtuPort D2P2 = |
| new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(2), true, annotations2), |
| OtuSignalType.OTU2); |
| private static final OtuPort D3P1 = |
| new DefaultOtuPort(new DefaultPort(device3, PortNumber.portNumber(1), true, annotations2), |
| OtuSignalType.OTU2); |
| |
| // OduClt ports with signalType=10GBE |
| private static final OduCltPort D1P3 = |
| new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(3), true, annotations1), |
| CltSignalType.CLT_10GBE); |
| private static final OduCltPort D3P3 = |
| new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(3), true, annotations1), |
| CltSignalType.CLT_10GBE); |
| |
| // OduCltPort ConnectPoints |
| private final ConnectPoint d1p1 = new ConnectPoint(device1.id(), D1P1.number()); |
| private final ConnectPoint d1p3 = new ConnectPoint(device1.id(), D1P3.number()); |
| private final ConnectPoint d3p2 = new ConnectPoint(device3.id(), D3P2.number()); |
| private final ConnectPoint d3p3 = new ConnectPoint(device3.id(), D3P3.number()); |
| |
| // OtuPort ConnectPoints |
| private final ConnectPoint d1p2 = new ConnectPoint(device1.id(), D1P2.number()); |
| private final ConnectPoint d2p1 = new ConnectPoint(device2.id(), D2P1.number()); |
| private final ConnectPoint d2p2 = new ConnectPoint(device2.id(), D2P2.number()); |
| private final ConnectPoint d3p1 = new ConnectPoint(device3.id(), D3P1.number()); |
| |
| private final List<Link> links = Arrays.asList( |
| DefaultLink.builder().providerId(PID).src(d1p2).dst(d2p1).type(OPTICAL).build(), |
| DefaultLink.builder().providerId(PID).src(d2p2).dst(d3p1).type(OPTICAL).build() |
| ); |
| private final Path path = new DefaultPath(PID, links, 3); |
| |
| private OpticalOduIntent intent; |
| |
| /** |
| * Mocks the topology service to give paths in the test. |
| */ |
| private class MockTopologyService extends TopologyServiceAdapter { |
| Set<Path> paths = Sets.newHashSet(path); |
| |
| @Override |
| public Topology currentTopology() { |
| return null; |
| } |
| |
| @Override |
| public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) { |
| return paths; |
| } |
| } |
| |
| /** |
| * Mocks the device service so that devices and ports appear available in the test. |
| */ |
| private static class MockDeviceService extends DeviceServiceAdapter { |
| @Override |
| public boolean isAvailable(DeviceId deviceId) { |
| return true; |
| } |
| |
| @Override |
| public List<Port> getPorts(DeviceId deviceId) { |
| if (deviceId.equals(deviceId(DEV1))) { |
| return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3); |
| } |
| |
| if (deviceId.equals(deviceId(DEV2))) { |
| return ImmutableList.of((Port) D2P1, (Port) D2P2); |
| } |
| |
| if (deviceId.equals(deviceId(DEV3))) { |
| return ImmutableList.of((Port) D3P1, (Port) D3P2, (Port) D3P3); |
| } |
| |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public Port getPort(DeviceId deviceId, PortNumber portNumber) { |
| if (deviceId.equals(deviceId(DEV1))) { |
| switch (portNumber.toString()) { |
| case "1": |
| return D1P1; |
| case "2": |
| return D1P2; |
| case "3": |
| return D1P3; |
| default: |
| return null; |
| } |
| } |
| if (deviceId.equals(deviceId(DEV2))) { |
| switch (portNumber.toString()) { |
| case "1": |
| return D2P1; |
| case "2": |
| return D2P2; |
| default: |
| return null; |
| } |
| } |
| if (deviceId.equals(deviceId(DEV3))) { |
| switch (portNumber.toString()) { |
| case "1": |
| return D3P1; |
| case "2": |
| return D3P2; |
| case "3": |
| return D3P3; |
| default: |
| return null; |
| } |
| } |
| return null; |
| } |
| } |
| |
| private static class MockDriverService extends DriverServiceAdapter |
| implements DriverService { |
| // TODO override to return appropriate driver, |
| // with DefaultOpticalDevice support, etc. |
| } |
| |
| @Before |
| public void setUp() { |
| AbstractProjectableModel.setDriverService(null, new MockDriverService()); |
| sut = new OpticalOduIntentCompiler(); |
| coreService = createMock(CoreService.class); |
| expect(coreService.registerApplication("org.onosproject.net.intent")) |
| .andReturn(appId); |
| sut.coreService = coreService; |
| sut.deviceService = new MockDeviceService(); |
| sut.resourceService = new MockResourceService(); |
| sut.topologyService = new MockTopologyService(); |
| |
| super.setUp(); |
| |
| intentExtensionService = createMock(IntentExtensionService.class); |
| intentExtensionService.registerCompiler(OpticalOduIntent.class, sut); |
| intentExtensionService.unregisterCompiler(OpticalOduIntent.class); |
| sut.intentManager = intentExtensionService; |
| |
| replay(coreService, intentExtensionService); |
| } |
| |
| /** |
| * Tests compile of OpticalOduIntent with allocation of TributarySlots. |
| * Compile two ODUCLT ports (with CLT_1GBE), over OTU ports (with OTU2): |
| * - only one TributarySlot is used |
| */ |
| @Test |
| public void test1GbeMultiplexOverOdu2() { |
| |
| intent = OpticalOduIntent.builder() |
| .appId(APP_ID) |
| .key(KEY1) |
| .src(d1p1) |
| .dst(d3p2) |
| .signalType(D1P1.signalType()) |
| .bidirectional(false) |
| .build(); |
| |
| sut.activate(); |
| |
| List<Intent> compiled = sut.compile(intent, Collections.emptyList()); |
| assertThat(compiled, hasSize(1)); |
| |
| assertThat("key is inherited", |
| compiled.stream().map(Intent::key).collect(Collectors.toList()), |
| everyItem(is(intent.key()))); |
| |
| Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules(); |
| |
| // 1st Device |
| FlowRule rule1 = rules.stream() |
| .filter(x -> x.deviceId().equals(device1.id())) |
| .findFirst() |
| .get(); |
| // validate SRC selector |
| TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder(); |
| selectorBuilder1.matchInPort(d1p1.port()); |
| selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0)); |
| assertThat(rule1.selector(), is(selectorBuilder1.build())); |
| |
| // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used) |
| TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder(); |
| Set<TributarySlot> slots = new HashSet<>(); |
| slots.add(TributarySlot.of(1)); |
| OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(OduSignalType.ODU2, slots); |
| treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId)); |
| treatmentBuilder1.setOutput(d1p2.port()); |
| assertThat(rule1.treatment(), is(treatmentBuilder1.build())); |
| |
| // 2nd Device |
| FlowRule rule2 = rules.stream() |
| .filter(x -> x.deviceId().equals(device2.id())) |
| .findFirst() |
| .get(); |
| // validate SRC selector |
| TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder(); |
| selectorBuilder2.matchInPort(d2p1.port()); |
| selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0)); |
| selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId)); |
| assertThat(rule2.selector(), is(selectorBuilder2.build())); |
| |
| // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used) |
| TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder(); |
| treatmentBuilder2.add(Instructions.modL1OduSignalId(oduSignalId)); |
| treatmentBuilder2.setOutput(d2p2.port()); |
| assertThat(rule2.treatment(), is(treatmentBuilder2.build())); |
| |
| |
| // 3rd Device |
| FlowRule rule3 = rules.stream() |
| .filter(x -> x.deviceId().equals(device3.id())) |
| .findFirst() |
| .get(); |
| // validate DST selector (with OduSignalId, where the same TributarySlot is used) |
| TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder(); |
| selectorBuilder3.matchInPort(d3p1.port()); |
| selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU0)); |
| selectorBuilder3.add(Criteria.matchOduSignalId(oduSignalId)); |
| assertThat(rule3.selector(), is(selectorBuilder3.build())); |
| |
| // validate DST treatment |
| assertThat(rule3.treatment(), is( |
| DefaultTrafficTreatment.builder().setOutput(d3p2.port()).build() |
| )); |
| |
| rules.forEach(rule -> assertEquals("FlowRule priority is incorrect", |
| intent.priority(), rule.priority())); |
| |
| sut.deactivate(); |
| } |
| |
| /** |
| * Tests compile of OpticalOduIntent with allocation of TributarySlots. |
| * Compile two ODUCLT ports (with CLT_10GBE), over OTU ports (with OTU2): |
| * - All TributarySlots are used |
| */ |
| @Test |
| public void test10GbeMultiplexOverOdu2() { |
| |
| intent = OpticalOduIntent.builder() |
| .appId(APP_ID) |
| .key(KEY1) |
| .src(d1p3) |
| .dst(d3p3) |
| .signalType(D1P3.signalType()) |
| .bidirectional(false) |
| .build(); |
| |
| sut.activate(); |
| |
| List<Intent> compiled = sut.compile(intent, Collections.emptyList()); |
| assertThat(compiled, hasSize(1)); |
| |
| assertThat("key is inherited", |
| compiled.stream().map(Intent::key).collect(Collectors.toList()), |
| everyItem(is(intent.key()))); |
| |
| Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules(); |
| |
| // 1st Device |
| FlowRule rule1 = rules.stream() |
| .filter(x -> x.deviceId().equals(device1.id())) |
| .findFirst() |
| .get(); |
| // validate SRC selector |
| TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder(); |
| selectorBuilder1.matchInPort(d1p3.port()); |
| selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2)); |
| assertThat(rule1.selector(), is(selectorBuilder1.build())); |
| |
| // validate SRC treatment (without OduSignalId - all TributarySlots are used) |
| TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder(); |
| treatmentBuilder1.setOutput(d1p2.port()); |
| assertThat(rule1.treatment(), is(treatmentBuilder1.build())); |
| |
| // 2nd Device |
| FlowRule rule2 = rules.stream() |
| .filter(x -> x.deviceId().equals(device2.id())) |
| .findFirst() |
| .get(); |
| // validate SRC selector |
| TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder(); |
| selectorBuilder2.matchInPort(d2p1.port()); |
| selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2)); |
| assertThat(rule2.selector(), is(selectorBuilder2.build())); |
| |
| // validate SRC treatment (without OduSignalId - all TributarySlots are used) |
| TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder(); |
| treatmentBuilder2.setOutput(d2p2.port()); |
| assertThat(rule2.treatment(), is(treatmentBuilder2.build())); |
| |
| |
| // 3rd Device |
| FlowRule rule3 = rules.stream() |
| .filter(x -> x.deviceId().equals(device3.id())) |
| .findFirst() |
| .get(); |
| // validate DST selector (without OduSignalId - all TributarySlots are used) |
| TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder(); |
| selectorBuilder3.matchInPort(d3p1.port()); |
| selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU2)); |
| assertThat(rule3.selector(), is(selectorBuilder3.build())); |
| |
| // validate DST treatment |
| assertThat(rule3.treatment(), is( |
| DefaultTrafficTreatment.builder().setOutput(d3p3.port()).build() |
| )); |
| |
| rules.forEach(rule -> assertEquals("FlowRule priority is incorrect", |
| intent.priority(), rule.priority())); |
| |
| sut.deactivate(); |
| } |
| |
| } |