Sean Condon | fae8e66 | 2016-12-15 10:25:13 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017-present Open Networking Laboratory |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | package org.onosproject.drivers.microsemi; |
| 17 | |
| 18 | import static org.junit.Assert.assertEquals; |
| 19 | import static org.junit.Assert.assertNotNull; |
| 20 | import static org.junit.Assert.assertTrue; |
| 21 | import static org.junit.Assert.fail; |
| 22 | |
| 23 | import java.util.Collection; |
| 24 | import java.util.HashSet; |
| 25 | import java.util.Iterator; |
| 26 | import java.util.List; |
| 27 | import java.util.Map; |
| 28 | import java.util.Set; |
| 29 | |
| 30 | import org.junit.After; |
| 31 | import org.junit.Before; |
| 32 | import org.junit.Test; |
| 33 | import org.onlab.packet.EthType.EtherType; |
| 34 | import org.onlab.packet.IpPrefix; |
| 35 | import org.onlab.packet.VlanId; |
| 36 | import org.onosproject.core.ApplicationId; |
| 37 | import org.onosproject.core.DefaultApplicationId; |
| 38 | import org.onosproject.net.PortNumber; |
| 39 | import org.onosproject.net.flow.DefaultFlowEntry; |
| 40 | import org.onosproject.net.flow.DefaultFlowRule; |
| 41 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 42 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 43 | import org.onosproject.net.flow.FlowEntry; |
| 44 | import org.onosproject.net.flow.FlowEntry.FlowEntryState; |
| 45 | import org.onosproject.net.flow.FlowRule; |
| 46 | import org.onosproject.net.flow.TrafficSelector; |
| 47 | import org.onosproject.net.flow.TrafficTreatment; |
| 48 | import org.onosproject.net.flow.criteria.Criteria; |
| 49 | import org.onosproject.net.flow.criteria.Criterion; |
| 50 | import org.onosproject.net.flow.criteria.Criterion.Type; |
| 51 | import org.onosproject.net.flow.criteria.IPCriterion; |
| 52 | import org.onosproject.net.flow.criteria.PortCriterion; |
| 53 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
| 54 | import org.onosproject.net.flow.instructions.Instruction; |
| 55 | |
| 56 | import com.google.common.collect.Lists; |
| 57 | import com.google.common.collect.Maps; |
| 58 | |
| 59 | public class EA1000FlowRuleProgrammableTest { |
| 60 | EA1000FlowRuleProgrammable frProgramable; |
| 61 | |
| 62 | @Before |
| 63 | public void setUp() throws Exception { |
| 64 | frProgramable = new EA1000FlowRuleProgrammable(); |
| 65 | frProgramable.setHandler(new MockEa1000DriverHandler()); |
| 66 | assertNotNull(frProgramable.handler().data().deviceId()); |
| 67 | } |
| 68 | |
| 69 | @After |
| 70 | public void tearDown() throws Exception { |
| 71 | } |
| 72 | |
| 73 | @Test |
| 74 | public void testGetFlowEntries() { |
| 75 | //From MockNetconfSession sample of MseaSaFiltering |
| 76 | Collection<FlowEntry> flowEntries = frProgramable.getFlowEntries(); |
| 77 | |
| 78 | assertNotNull(flowEntries); |
| 79 | //There will be 12 flow entries |
| 80 | // 2 for IP Src Address filtering |
| 81 | // 2 for EVC 7 - one each port |
| 82 | // 8 for EVC 8 - one for host port, 7 on optics port because of ceVlanMap 12:14,20:22,25 |
| 83 | assertEquals(12, flowEntries.size()); |
| 84 | |
| 85 | //Test the first Flow Entry |
| 86 | Iterator<FlowEntry> feIter = flowEntries.iterator(); |
| 87 | while (feIter.hasNext()) { |
| 88 | FlowEntry fe = feIter.next(); |
| 89 | assertTrue(fe.isPermanent()); |
| 90 | assertEquals(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT, fe.priority()); |
| 91 | |
| 92 | Set<Criterion> criteria = fe.selector().criteria(); |
| 93 | IPCriterion ipCr = null; |
| 94 | PortNumber port = null; |
| 95 | for (Criterion cr:criteria.toArray(new Criterion[criteria.size()])) { |
| 96 | if (cr.type() == Criterion.Type.IPV4_SRC) { |
| 97 | ipCr = (IPCriterion) cr; |
| 98 | } else if (cr.type() == Criterion.Type.IN_PORT) { |
| 99 | port = ((PortCriterion) cr).port(); |
| 100 | } else if (cr.type() == Criterion.Type.VLAN_VID) { |
| 101 | VlanId vid = ((VlanIdCriterion) cr).vlanId(); |
| 102 | } else { |
| 103 | fail("Unexpected Criterion type: " + cr.type().toString()); |
| 104 | } |
| 105 | } |
| 106 | if (ipCr != null && (port == null || port.toLong() != 0L)) { |
| 107 | fail("Port number not equal 0 when IP Src Address filter is present"); |
| 108 | } |
| 109 | |
| 110 | List<Instruction> instructions = fe.treatment().allInstructions(); |
| 111 | |
| 112 | if (fe.tableId() == 1) { |
| 113 | //Note that in MockNetconf session 10.10.10.10/16 was entered |
| 114 | //but it has been corrected to the following by the OF implementation |
| 115 | assertEquals("10.10.0.0/16", ipCr.ip().toString()); |
| 116 | assertEquals(FlowEntryState.ADDED, fe.state()); |
| 117 | } else if (fe.tableId() == 2) { |
| 118 | //Likewise 20.30.40.50 has been truncated because of the 18 bit mask |
| 119 | assertEquals("20.30.0.0/18", ipCr.ip().toString()); |
| 120 | assertEquals(FlowEntryState.ADDED, fe.state()); |
| 121 | } else if (fe.tableId() == 7 || fe.tableId() == 8) { |
| 122 | // 7 and 8 are EVC entries - 2 elements - IN_PORT and VLAN_ID |
| 123 | assertEquals(2, fe.selector().criteria().size()); |
| 124 | //In MockNetconfSession we're rigged it so that the last two chars of the |
| 125 | //flow id is the same as the VlanId |
| 126 | short vlanId = ((VlanIdCriterion) fe.selector().getCriterion(Type.VLAN_VID)).vlanId().toShort(); |
| 127 | long flowId = fe.id().id(); |
| 128 | String flowIdStr = String.valueOf(flowId).substring(String.valueOf(flowId).length() - 2); |
| 129 | assertEquals(flowIdStr, String.valueOf(vlanId)); |
| 130 | if (((PortCriterion) fe.selector().getCriterion(Type.IN_PORT)).port().toLong() == 1L) { |
| 131 | assertEquals(Instruction.Type.L2MODIFICATION, instructions.get(0).type()); |
| 132 | } |
| 133 | } else { |
| 134 | fail("Unexpected Flow Entry Rule " + fe.tableId()); |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | @Test |
| 140 | public void testSetFlowEntries() { |
| 141 | Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0)); |
| 142 | |
| 143 | TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder().drop().build(); |
| 144 | |
| 145 | Collection<FlowRule> frAddedList = new HashSet<FlowRule>(); |
| 146 | |
| 147 | FlowRule fr4 = new DefaultFlowRule.Builder() |
| 148 | .forDevice(frProgramable.handler().data().deviceId()) |
| 149 | .forTable(4) |
| 150 | .withSelector(DefaultTrafficSelector.builder() |
| 151 | .matchIPSrc(IpPrefix.valueOf("192.168.60.0/22")) |
| 152 | .add(matchInPort).build()) |
| 153 | .withTreatment(treatmentDrop) |
| 154 | .fromApp(new DefaultApplicationId(4, "Filter4")) |
| 155 | .makePermanent() |
| 156 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 157 | .build(); |
| 158 | frAddedList.add(fr4); |
| 159 | |
| 160 | FlowRule fr5 = new DefaultFlowRule.Builder() |
| 161 | .forDevice(frProgramable.handler().data().deviceId()) |
| 162 | .forTable(5) |
| 163 | .withSelector(DefaultTrafficSelector.builder() |
| 164 | .matchIPSrc(IpPrefix.valueOf("192.168.50.0/23")) |
| 165 | .add(matchInPort).build()) |
| 166 | .withTreatment(treatmentDrop) |
| 167 | .withCookie(Long.valueOf("5e0000abaa2772", 16)) |
| 168 | .makePermanent() |
| 169 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 170 | .build(); |
| 171 | frAddedList.add(fr5); |
| 172 | |
| 173 | //Add in some EVCs - especially with complex ceVlanMaps |
| 174 | FlowRule frEvc1Vid19P0 = new DefaultFlowRule.Builder() |
| 175 | .forDevice(frProgramable.handler().data().deviceId()) |
| 176 | .forTable(1) |
| 177 | .withSelector(DefaultTrafficSelector.builder() |
| 178 | .matchInPort(PortNumber.portNumber(0L)) |
| 179 | .matchVlanId(VlanId.vlanId((short) 19)) |
| 180 | .build()) |
| 181 | .withTreatment(DefaultTrafficTreatment.builder() |
| 182 | .popVlan() |
| 183 | .build()) |
| 184 | .withCookie(Long.valueOf("1e0000abaa0019", 16)) |
| 185 | .makePermanent() |
| 186 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 187 | .build(); |
| 188 | frAddedList.add(frEvc1Vid19P0); |
| 189 | |
| 190 | FlowRule frEvc1Vid20P0 = new DefaultFlowRule.Builder() |
| 191 | .forDevice(frProgramable.handler().data().deviceId()) |
| 192 | .forTable(1) |
| 193 | .withSelector(DefaultTrafficSelector.builder() |
| 194 | .matchInPort(PortNumber.portNumber(0L)) |
| 195 | .matchVlanId(VlanId.vlanId((short) 20)) |
| 196 | .build()) |
| 197 | .withTreatment(DefaultTrafficTreatment.builder() |
| 198 | .popVlan() |
| 199 | .build()) |
| 200 | .withCookie(Long.valueOf("1e0000abaa0020", 16)) |
| 201 | .makePermanent() |
| 202 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 203 | .build(); |
| 204 | frAddedList.add(frEvc1Vid20P0); |
| 205 | |
| 206 | FlowRule frEvc1Vid21P1 = new DefaultFlowRule.Builder() |
| 207 | .forDevice(frProgramable.handler().data().deviceId()) |
| 208 | .forTable(1) |
| 209 | .withSelector(DefaultTrafficSelector.builder() |
| 210 | .matchInPort(PortNumber.portNumber(1L)) |
| 211 | .matchVlanId(VlanId.vlanId((short) 21)) |
| 212 | .build()) |
| 213 | .withTreatment(DefaultTrafficTreatment.builder() |
| 214 | .setVlanId(VlanId.vlanId((short) 250)) |
| 215 | .pushVlan(EtherType.QINQ.ethType()) |
| 216 | .build()) |
| 217 | .withCookie(Long.valueOf("1e0000abaa0121", 16)) |
| 218 | .makePermanent() |
| 219 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 220 | .build(); |
| 221 | frAddedList.add(frEvc1Vid21P1); |
| 222 | |
| 223 | FlowRule frEvc1Vid22P1 = new DefaultFlowRule.Builder() |
| 224 | .forDevice(frProgramable.handler().data().deviceId()) |
| 225 | .forTable(1) |
| 226 | .withSelector(DefaultTrafficSelector.builder() |
| 227 | .matchInPort(PortNumber.portNumber(1L)) |
| 228 | .matchVlanId(VlanId.vlanId((short) 22)) |
| 229 | .build()) |
| 230 | .withTreatment(DefaultTrafficTreatment.builder() |
| 231 | .setVlanId(VlanId.vlanId((short) 250)) |
| 232 | .pushVlan(EtherType.QINQ.ethType()) |
| 233 | .build()) |
| 234 | .withCookie(Long.valueOf("1e0000abaa0122", 16)) |
| 235 | .makePermanent() |
| 236 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 237 | .build(); |
| 238 | frAddedList.add(frEvc1Vid22P1); |
| 239 | |
| 240 | Collection<FlowRule> returnedFrList = frProgramable.applyFlowRules(frAddedList); |
| 241 | |
| 242 | assertNotNull(returnedFrList); |
| 243 | assertEquals(6, returnedFrList.size()); |
| 244 | |
| 245 | //Test the scenario like in FlowRuleManager$InternalFlowRuleProviderService.pushFlowMetricsInternal() |
| 246 | Map<FlowEntry, FlowEntry> storedRules = Maps.newHashMap(); |
| 247 | frAddedList.forEach(f -> storedRules.put(new DefaultFlowEntry(f), new DefaultFlowEntry(f))); |
| 248 | List<FlowEntry> feList = Lists.newArrayList(); |
| 249 | returnedFrList.forEach(f -> feList.add(new DefaultFlowEntry(f))); |
| 250 | |
| 251 | for (FlowEntry rule : feList) { |
| 252 | FlowEntry fer = storedRules.remove(rule); |
| 253 | assertNotNull(fer); |
| 254 | assertTrue(fer.exactMatch(rule)); |
| 255 | } |
| 256 | |
| 257 | for (FlowRule fr:returnedFrList.toArray(new FlowRule[2])) { |
| 258 | if (fr.tableId() == 4) { |
| 259 | assertEquals("IPV4_SRC:192.168.60.0/22", |
| 260 | ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString()); |
| 261 | } else if (fr.tableId() == 5) { |
| 262 | assertEquals("IPV4_SRC:192.168.50.0/23", |
| 263 | ((IPCriterion) fr.selector().getCriterion(Type.IPV4_SRC)).toString()); |
| 264 | assertEquals(Long.valueOf("5e0000abaa2772", 16), fr.id().id()); |
| 265 | } else if (fr.tableId() == 1) { |
| 266 | //TODO add in tests |
| 267 | } else { |
| 268 | fail("Unexpected flow rule " + fr.tableId() + " in test"); |
| 269 | } |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | @Test |
| 274 | public void testRemoveFlowEntries() { |
| 275 | TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder(); |
| 276 | Criterion matchInPort0 = Criteria.matchInPort(PortNumber.portNumber(0)); |
| 277 | Criterion matchInPort1 = Criteria.matchInPort(PortNumber.portNumber(1)); |
| 278 | |
| 279 | TrafficTreatment.Builder trDropBuilder = DefaultTrafficTreatment.builder(); |
| 280 | TrafficTreatment treatmentDrop = trDropBuilder.drop().build(); |
| 281 | |
| 282 | Collection<FlowRule> frRemoveList = new HashSet<FlowRule>(); |
| 283 | ApplicationId app = new DefaultApplicationId(1, "org.onosproject.rest"); |
| 284 | |
| 285 | Criterion matchIpSrc1 = Criteria.matchIPSrc(IpPrefix.valueOf("10.10.10.10/16")); |
| 286 | TrafficSelector selector1 = tsBuilder.add(matchIpSrc1).add(matchInPort0).build(); |
| 287 | FlowRule.Builder frBuilder1 = new DefaultFlowRule.Builder(); |
| 288 | frBuilder1.forDevice(frProgramable.handler().data().deviceId()) |
| 289 | .withSelector(selector1) |
| 290 | .withTreatment(treatmentDrop) |
| 291 | .forTable(2) |
| 292 | .fromApp(app) |
| 293 | .makePermanent() |
| 294 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT); |
| 295 | frRemoveList.add(frBuilder1.build()); |
| 296 | |
| 297 | Criterion matchIpSrc2 = Criteria.matchIPSrc(IpPrefix.valueOf("10.30.10.10/16")); |
| 298 | TrafficSelector selector2 = tsBuilder.add(matchIpSrc2).add(matchInPort0).build(); |
| 299 | FlowRule.Builder frBuilder2 = new DefaultFlowRule.Builder(); |
| 300 | frBuilder2.forDevice(frProgramable.handler().data().deviceId()) |
| 301 | .withSelector(selector2) |
| 302 | .withTreatment(treatmentDrop) |
| 303 | .forTable(3) |
| 304 | .fromApp(app) |
| 305 | .makePermanent() |
| 306 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 307 | .build(); |
| 308 | frRemoveList.add(frBuilder2.build()); |
| 309 | |
| 310 | |
| 311 | TrafficTreatment.Builder trVlanPopBuilder = DefaultTrafficTreatment.builder(); |
| 312 | TrafficTreatment treatmentVlanPop = trVlanPopBuilder.popVlan().build(); |
| 313 | |
| 314 | |
| 315 | Criterion matchVlan710 = Criteria.matchVlanId(VlanId.vlanId((short) 710)); |
| 316 | TrafficSelector selector3 = DefaultTrafficSelector.builder().add(matchVlan710).add(matchInPort1).build(); |
| 317 | FlowRule.Builder frBuilder3 = new DefaultFlowRule.Builder(); |
| 318 | frBuilder3.forDevice(frProgramable.handler().data().deviceId()) |
| 319 | .withSelector(selector3) |
| 320 | .withTreatment(treatmentVlanPop) |
| 321 | .forTable(7) |
| 322 | .fromApp(app) |
| 323 | .makePermanent() |
| 324 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 325 | .build(); |
| 326 | frRemoveList.add(frBuilder3.build()); |
| 327 | |
| 328 | |
| 329 | Criterion matchVlan101 = Criteria.matchVlanId(VlanId.vlanId((short) 101)); |
| 330 | TrafficSelector selector4 = DefaultTrafficSelector.builder().add(matchVlan101).add(matchInPort1).build(); |
| 331 | FlowRule.Builder frBuilder4 = new DefaultFlowRule.Builder(); |
| 332 | frBuilder4.forDevice(frProgramable.handler().data().deviceId()) |
| 333 | .withSelector(selector4) |
| 334 | .withTreatment(treatmentVlanPop) |
| 335 | .forTable(1) |
| 336 | .fromApp(app) |
| 337 | .makePermanent() |
| 338 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 339 | .build(); |
| 340 | frRemoveList.add(frBuilder4.build()); |
| 341 | |
| 342 | Criterion matchVlan102 = Criteria.matchVlanId(VlanId.vlanId((short) 102)); |
| 343 | TrafficSelector selector5 = DefaultTrafficSelector.builder().add(matchVlan102).add(matchInPort0).build(); |
| 344 | FlowRule.Builder frBuilder5 = new DefaultFlowRule.Builder(); |
| 345 | frBuilder5.forDevice(frProgramable.handler().data().deviceId()) |
| 346 | .withSelector(selector5) |
| 347 | .withTreatment(treatmentVlanPop) |
| 348 | .forTable(1) |
| 349 | .fromApp(app) |
| 350 | .makePermanent() |
| 351 | .withPriority(EA1000FlowRuleProgrammable.PRIORITY_DEFAULT) |
| 352 | .build(); |
| 353 | frRemoveList.add(frBuilder5.build()); |
| 354 | |
| 355 | Collection<FlowRule> removedFrList = frProgramable.removeFlowRules(frRemoveList); |
| 356 | assertNotNull(removedFrList); |
| 357 | assertEquals(5, removedFrList.size()); |
| 358 | |
| 359 | for (FlowRule frRemoved:removedFrList) { |
| 360 | assertNotNull(frRemoved); |
| 361 | } |
| 362 | } |
| 363 | } |