| /* |
| * Copyright 2017-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.drivers.microsemi; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.onlab.packet.EthType.EtherType; |
| import org.onlab.packet.IpPrefix; |
| import org.onlab.packet.VlanId; |
| import org.onosproject.core.ApplicationId; |
| import org.onosproject.core.DefaultApplicationId; |
| import org.onosproject.net.PortNumber; |
| import org.onosproject.net.flow.DefaultFlowEntry; |
| import org.onosproject.net.flow.DefaultFlowRule; |
| import org.onosproject.net.flow.DefaultTrafficSelector; |
| import org.onosproject.net.flow.DefaultTrafficTreatment; |
| import org.onosproject.net.flow.FlowEntry; |
| import org.onosproject.net.flow.FlowEntry.FlowEntryState; |
| 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.criteria.Criterion; |
| import org.onosproject.net.flow.criteria.Criterion.Type; |
| import org.onosproject.net.flow.criteria.IPCriterion; |
| import org.onosproject.net.flow.criteria.PortCriterion; |
| import org.onosproject.net.flow.criteria.VlanIdCriterion; |
| import org.onosproject.net.flow.instructions.Instruction; |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| |
| public class EA1000FlowRuleProgrammableTest { |
| EA1000FlowRuleProgrammable frProgramable; |
| |
| @Before |
| public void setUp() throws Exception { |
| frProgramable = new EA1000FlowRuleProgrammable(); |
| frProgramable.setHandler(new MockEa1000DriverHandler()); |
| assertNotNull(frProgramable.handler().data().deviceId()); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| } |
| |
| @Test |
| public void testGetFlowEntries() { |
| //From MockNetconfSession sample of MseaSaFiltering |
| Collection<FlowEntry> flowEntries = frProgramable.getFlowEntries(); |
| |
| assertNotNull(flowEntries); |
| //There will be 12 flow entries |
| // 2 for IP Src Address filtering |
| // 2 for EVC 7 - one each port |
| // 8 for EVC 8 - one for host port, 7 on optics port because of ceVlanMap 12:14,20:22,25 |
| assertEquals(12, flowEntries.size()); |
| |
| //Test the first Flow Entry |
| Iterator<FlowEntry> feIter = flowEntries.iterator(); |
| while (feIter.hasNext()) { |
| FlowEntry fe = feIter.next(); |
| assertTrue(fe.isPermanent()); |
| assertEquals(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT, fe.priority()); |
| |
| Set<Criterion> criteria = fe.selector().criteria(); |
| IPCriterion ipCr = null; |
| PortNumber port = null; |
| for (Criterion cr:criteria.toArray(new Criterion[criteria.size()])) { |
| if (cr.type() == Criterion.Type.IPV4_SRC) { |
| ipCr = (IPCriterion) cr; |
| } else if (cr.type() == Criterion.Type.IN_PORT) { |
| port = ((PortCriterion) cr).port(); |
| } else if (cr.type() == Criterion.Type.VLAN_VID) { |
| VlanId vid = ((VlanIdCriterion) cr).vlanId(); |
| } else { |
| fail("Unexpected Criterion type: " + cr.type().toString()); |
| } |
| } |
| if (ipCr != null && (port == null || port.toLong() != 0L)) { |
| fail("Port number not equal 0 when IP Src Address filter is present"); |
| } |
| |
| List<Instruction> instructions = fe.treatment().allInstructions(); |
| |
| if (fe.tableId() == 1) { |
| //Note that in MockNetconf session 10.10.10.10/16 was entered |
| //but it has been corrected to the following by the OF implementation |
| assertEquals("10.10.0.0/16", ipCr.ip().toString()); |
| assertEquals(FlowEntryState.ADDED, fe.state()); |
| } else if (fe.tableId() == 2) { |
| //Likewise 20.30.40.50 has been truncated because of the 18 bit mask |
| assertEquals("20.30.0.0/18", ipCr.ip().toString()); |
| assertEquals(FlowEntryState.ADDED, fe.state()); |
| } else if (fe.tableId() == 7 || fe.tableId() == 8) { |
| // 7 and 8 are EVC entries - 2 elements - IN_PORT and VLAN_ID |
| assertEquals(2, fe.selector().criteria().size()); |
| //In MockNetconfSession we're rigged it so that the last two chars of the |
| //flow id is the same as the VlanId |
| short vlanId = ((VlanIdCriterion) fe.selector().getCriterion(Type.VLAN_VID)).vlanId().toShort(); |
| long flowId = fe.id().id(); |
| String flowIdStr = String.valueOf(flowId).substring(String.valueOf(flowId).length() - 2); |
| assertEquals(flowIdStr, String.valueOf(vlanId)); |
| if (((PortCriterion) fe.selector().getCriterion(Type.IN_PORT)).port().toLong() == 1L) { |
| assertEquals(Instruction.Type.L2MODIFICATION, instructions.get(0).type()); |
| } |
| } else { |
| fail("Unexpected Flow Entry Rule " + fe.tableId()); |
| } |
| } |
| } |
| |
| @Test |
| public void testSetFlowEntries() { |
| Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0)); |
| |
| TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder().drop().build(); |
| |
| Collection<FlowRule> frAddedList = new HashSet<FlowRule>(); |
| |
| FlowRule fr4 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(4) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchIPSrc(IpPrefix.valueOf("192.168.60.0/22")) |
| .add(matchInPort).build()) |
| .withTreatment(treatmentDrop) |
| .fromApp(new DefaultApplicationId(4, "Filter4")) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(fr4); |
| |
| FlowRule fr5 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(5) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchIPSrc(IpPrefix.valueOf("192.168.50.0/23")) |
| .add(matchInPort).build()) |
| .withTreatment(treatmentDrop) |
| .withCookie(Long.valueOf("5e0000abaa2772", 16)) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(fr5); |
| |
| //Add in some EVCs - especially with complex ceVlanMaps |
| FlowRule frEvc1Vid19P0 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(1) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchInPort(PortNumber.portNumber(0L)) |
| .matchVlanId(VlanId.vlanId((short) 19)) |
| .build()) |
| .withTreatment(DefaultTrafficTreatment.builder() |
| .popVlan() |
| .build()) |
| .withCookie(Long.valueOf("1e0000abaa0019", 16)) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(frEvc1Vid19P0); |
| |
| FlowRule frEvc1Vid20P0 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(1) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchInPort(PortNumber.portNumber(0L)) |
| .matchVlanId(VlanId.vlanId((short) 20)) |
| .build()) |
| .withTreatment(DefaultTrafficTreatment.builder() |
| .popVlan() |
| .build()) |
| .withCookie(Long.valueOf("1e0000abaa0020", 16)) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(frEvc1Vid20P0); |
| |
| FlowRule frEvc1Vid21P1 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(1) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchInPort(PortNumber.portNumber(1L)) |
| .matchVlanId(VlanId.vlanId((short) 21)) |
| .build()) |
| .withTreatment(DefaultTrafficTreatment.builder() |
| .setVlanId(VlanId.vlanId((short) 250)) |
| .pushVlan(EtherType.QINQ.ethType()) |
| .build()) |
| .withCookie(Long.valueOf("1e0000abaa0121", 16)) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(frEvc1Vid21P1); |
| |
| FlowRule frEvc1Vid22P1 = new DefaultFlowRule.Builder() |
| .forDevice(frProgramable.handler().data().deviceId()) |
| .forTable(1) |
| .withSelector(DefaultTrafficSelector.builder() |
| .matchInPort(PortNumber.portNumber(1L)) |
| .matchVlanId(VlanId.vlanId((short) 22)) |
| .build()) |
| .withTreatment(DefaultTrafficTreatment.builder() |
| .setVlanId(VlanId.vlanId((short) 250)) |
| .pushVlan(EtherType.QINQ.ethType()) |
| .build()) |
| .withCookie(Long.valueOf("1e0000abaa0122", 16)) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frAddedList.add(frEvc1Vid22P1); |
| |
| Collection<FlowRule> returnedFrList = frProgramable.applyFlowRules(frAddedList); |
| |
| assertNotNull(returnedFrList); |
| assertEquals(6, returnedFrList.size()); |
| |
| //Test the scenario like in FlowRuleManager$InternalFlowRuleProviderService.pushFlowMetricsInternal() |
| Map<FlowEntry, FlowEntry> storedRules = Maps.newHashMap(); |
| frAddedList.forEach(f -> storedRules.put(new DefaultFlowEntry(f), new DefaultFlowEntry(f))); |
| List<FlowEntry> feList = Lists.newArrayList(); |
| returnedFrList.forEach(f -> feList.add(new DefaultFlowEntry(f))); |
| |
| for (FlowEntry rule : feList) { |
| FlowEntry fer = storedRules.remove(rule); |
| assertNotNull(fer); |
| assertTrue(fer.exactMatch(rule)); |
| } |
| |
| for (FlowRule fr:returnedFrList.toArray(new FlowRule[2])) { |
| if (fr.tableId() == 4) { |
| assertEquals("IPV4_SRC:192.168.60.0/22", |
| ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString()); |
| } else if (fr.tableId() == 5) { |
| assertEquals("IPV4_SRC:192.168.50.0/23", |
| ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString()); |
| assertEquals(Long.valueOf("5e0000abaa2772", 16), fr.id().id()); |
| } else if (fr.tableId() == 1) { |
| //TODO add in tests |
| } else { |
| fail("Unexpected flow rule " + fr.tableId() + " in test"); |
| } |
| } |
| } |
| |
| @Test |
| public void testRemoveFlowEntries() { |
| TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder(); |
| Criterion matchInPort0 = Criteria.matchInPort(PortNumber.portNumber(0)); |
| Criterion matchInPort1 = Criteria.matchInPort(PortNumber.portNumber(1)); |
| |
| TrafficTreatment.Builder trDropBuilder = DefaultTrafficTreatment.builder(); |
| TrafficTreatment treatmentDrop = trDropBuilder.drop().build(); |
| |
| Collection<FlowRule> frRemoveList = new HashSet<FlowRule>(); |
| ApplicationId app = new DefaultApplicationId(1, "org.onosproject.rest"); |
| |
| Criterion matchIpSrc1 = Criteria.matchIPSrc(IpPrefix.valueOf("10.10.10.10/16")); |
| TrafficSelector selector1 = tsBuilder.add(matchIpSrc1).add(matchInPort0).build(); |
| FlowRule.Builder frBuilder1 = new DefaultFlowRule.Builder(); |
| frBuilder1.forDevice(frProgramable.handler().data().deviceId()) |
| .withSelector(selector1) |
| .withTreatment(treatmentDrop) |
| .forTable(2) |
| .fromApp(app) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT); |
| frRemoveList.add(frBuilder1.build()); |
| |
| Criterion matchIpSrc2 = Criteria.matchIPSrc(IpPrefix.valueOf("10.30.10.10/16")); |
| TrafficSelector selector2 = tsBuilder.add(matchIpSrc2).add(matchInPort0).build(); |
| FlowRule.Builder frBuilder2 = new DefaultFlowRule.Builder(); |
| frBuilder2.forDevice(frProgramable.handler().data().deviceId()) |
| .withSelector(selector2) |
| .withTreatment(treatmentDrop) |
| .forTable(3) |
| .fromApp(app) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frRemoveList.add(frBuilder2.build()); |
| |
| |
| TrafficTreatment.Builder trVlanPopBuilder = DefaultTrafficTreatment.builder(); |
| TrafficTreatment treatmentVlanPop = trVlanPopBuilder.popVlan().build(); |
| |
| |
| Criterion matchVlan710 = Criteria.matchVlanId(VlanId.vlanId((short) 710)); |
| TrafficSelector selector3 = DefaultTrafficSelector.builder().add(matchVlan710).add(matchInPort1).build(); |
| FlowRule.Builder frBuilder3 = new DefaultFlowRule.Builder(); |
| frBuilder3.forDevice(frProgramable.handler().data().deviceId()) |
| .withSelector(selector3) |
| .withTreatment(treatmentVlanPop) |
| .forTable(7) |
| .fromApp(app) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frRemoveList.add(frBuilder3.build()); |
| |
| |
| Criterion matchVlan101 = Criteria.matchVlanId(VlanId.vlanId((short) 101)); |
| TrafficSelector selector4 = DefaultTrafficSelector.builder().add(matchVlan101).add(matchInPort1).build(); |
| FlowRule.Builder frBuilder4 = new DefaultFlowRule.Builder(); |
| frBuilder4.forDevice(frProgramable.handler().data().deviceId()) |
| .withSelector(selector4) |
| .withTreatment(treatmentVlanPop) |
| .forTable(1) |
| .fromApp(app) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frRemoveList.add(frBuilder4.build()); |
| |
| Criterion matchVlan102 = Criteria.matchVlanId(VlanId.vlanId((short) 102)); |
| TrafficSelector selector5 = DefaultTrafficSelector.builder().add(matchVlan102).add(matchInPort0).build(); |
| FlowRule.Builder frBuilder5 = new DefaultFlowRule.Builder(); |
| frBuilder5.forDevice(frProgramable.handler().data().deviceId()) |
| .withSelector(selector5) |
| .withTreatment(treatmentVlanPop) |
| .forTable(1) |
| .fromApp(app) |
| .makePermanent() |
| .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| .build(); |
| frRemoveList.add(frBuilder5.build()); |
| |
| Collection<FlowRule> removedFrList = frProgramable.removeFlowRules(frRemoveList); |
| assertNotNull(removedFrList); |
| assertEquals(5, removedFrList.size()); |
| |
| for (FlowRule frRemoved:removedFrList) { |
| assertNotNull(frRemoved); |
| } |
| } |
| } |