olt installs default rules on startup and when a port shows up
Change-Id: I0db62db020f94500aeae7191f7681745e1268672
Showing
2 changed files
with
98 additions
and
16 deletions
| ... | @@ -23,12 +23,15 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -23,12 +23,15 @@ import org.apache.felix.scr.annotations.Deactivate; |
| 23 | import org.apache.felix.scr.annotations.Reference; | 23 | import org.apache.felix.scr.annotations.Reference; |
| 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 25 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
| 26 | +import org.onlab.packet.EthType; | ||
| 27 | +import org.onlab.packet.IPv4; | ||
| 26 | import org.onlab.packet.VlanId; | 28 | import org.onlab.packet.VlanId; |
| 27 | import org.onosproject.core.ApplicationId; | 29 | import org.onosproject.core.ApplicationId; |
| 28 | import org.onosproject.core.CoreService; | 30 | import org.onosproject.core.CoreService; |
| 29 | import org.onosproject.event.AbstractListenerManager; | 31 | import org.onosproject.event.AbstractListenerManager; |
| 30 | import org.onosproject.net.ConnectPoint; | 32 | import org.onosproject.net.ConnectPoint; |
| 31 | import org.onosproject.net.DeviceId; | 33 | import org.onosproject.net.DeviceId; |
| 34 | +import org.onosproject.net.Port; | ||
| 32 | import org.onosproject.net.PortNumber; | 35 | import org.onosproject.net.PortNumber; |
| 33 | import org.onosproject.net.config.ConfigFactory; | 36 | import org.onosproject.net.config.ConfigFactory; |
| 34 | import org.onosproject.net.config.NetworkConfigEvent; | 37 | import org.onosproject.net.config.NetworkConfigEvent; |
| ... | @@ -42,7 +45,10 @@ import org.onosproject.net.flow.DefaultTrafficSelector; | ... | @@ -42,7 +45,10 @@ import org.onosproject.net.flow.DefaultTrafficSelector; |
| 42 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 45 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 43 | import org.onosproject.net.flow.TrafficSelector; | 46 | import org.onosproject.net.flow.TrafficSelector; |
| 44 | import org.onosproject.net.flow.TrafficTreatment; | 47 | import org.onosproject.net.flow.TrafficTreatment; |
| 48 | +import org.onosproject.net.flow.criteria.Criteria; | ||
| 49 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
| 45 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; | 50 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; |
| 51 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 46 | import org.onosproject.net.flowobjective.FlowObjectiveService; | 52 | import org.onosproject.net.flowobjective.FlowObjectiveService; |
| 47 | import org.onosproject.net.flowobjective.ForwardingObjective; | 53 | import org.onosproject.net.flowobjective.ForwardingObjective; |
| 48 | import org.onosproject.net.flowobjective.Objective; | 54 | import org.onosproject.net.flowobjective.Objective; |
| ... | @@ -126,6 +132,7 @@ public class Olt | ... | @@ -126,6 +132,7 @@ public class Olt |
| 126 | networkConfig.registerConfigFactory(configFactory); | 132 | networkConfig.registerConfigFactory(configFactory); |
| 127 | networkConfig.addListener(configListener); | 133 | networkConfig.addListener(configListener); |
| 128 | 134 | ||
| 135 | + | ||
| 129 | networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach( | 136 | networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach( |
| 130 | subject -> { | 137 | subject -> { |
| 131 | AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class); | 138 | AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class); |
| ... | @@ -136,6 +143,12 @@ public class Olt | ... | @@ -136,6 +143,12 @@ public class Olt |
| 136 | } | 143 | } |
| 137 | ); | 144 | ); |
| 138 | 145 | ||
| 146 | + oltData.keySet().stream() | ||
| 147 | + .flatMap(did -> deviceService.getPorts(did).stream()) | ||
| 148 | + .filter(p -> oltData.get(p.element().id()).uplink() != p.number()) | ||
| 149 | + .filter(p -> p.isEnabled()) | ||
| 150 | + .forEach(p -> installFilteringObjectives((DeviceId) p.element().id(), p)); | ||
| 151 | + | ||
| 139 | log.info("Started with Application ID {}", appId.id()); | 152 | log.info("Started with Application ID {}", appId.id()); |
| 140 | } | 153 | } |
| 141 | 154 | ||
| ... | @@ -195,17 +208,17 @@ public class Olt | ... | @@ -195,17 +208,17 @@ public class Olt |
| 195 | 208 | ||
| 196 | fwds.stream().forEach( | 209 | fwds.stream().forEach( |
| 197 | fwd -> flowObjectiveService.forward(deviceId, | 210 | fwd -> flowObjectiveService.forward(deviceId, |
| 198 | - fwd.remove(new ObjectiveContext() { | 211 | + fwd.remove(new ObjectiveContext() { |
| 199 | - @Override | 212 | + @Override |
| 200 | - public void onSuccess(Objective objective) { | 213 | + public void onSuccess(Objective objective) { |
| 201 | - upFuture.complete(null); | 214 | + upFuture.complete(null); |
| 202 | - } | 215 | + } |
| 203 | - | 216 | + |
| 204 | - @Override | 217 | + @Override |
| 205 | - public void onError(Objective objective, ObjectiveError error) { | 218 | + public void onError(Objective objective, ObjectiveError error) { |
| 206 | - upFuture.complete(error); | 219 | + upFuture.complete(error); |
| 207 | - } | 220 | + } |
| 208 | - }))); | 221 | + }))); |
| 209 | 222 | ||
| 210 | upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> { | 223 | upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> { |
| 211 | if (upStatus == null && downStatus == null) { | 224 | if (upStatus == null && downStatus == null) { |
| ... | @@ -327,6 +340,57 @@ public class Olt | ... | @@ -327,6 +340,57 @@ public class Olt |
| 327 | 340 | ||
| 328 | } | 341 | } |
| 329 | 342 | ||
| 343 | + private void installFilteringObjectives(DeviceId devId, Port port) { | ||
| 344 | + FilteringObjective eapol = DefaultFilteringObjective.builder() | ||
| 345 | + .permit() | ||
| 346 | + .withKey(Criteria.matchInPort(port.number())) | ||
| 347 | + .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType())) | ||
| 348 | + .withMeta(DefaultTrafficTreatment.builder() | ||
| 349 | + .setOutput(PortNumber.CONTROLLER).build()) | ||
| 350 | + .fromApp(appId) | ||
| 351 | + .withPriority(1000) | ||
| 352 | + .add(new ObjectiveContext() { | ||
| 353 | + @Override | ||
| 354 | + public void onSuccess(Objective objective) { | ||
| 355 | + log.info("Eapol filter for {} on {} installed.", | ||
| 356 | + devId, port); | ||
| 357 | + } | ||
| 358 | + | ||
| 359 | + @Override | ||
| 360 | + public void onError(Objective objective, ObjectiveError error) { | ||
| 361 | + log.info("Eapol filter for {} on {} failed because {}", | ||
| 362 | + devId, port, error); | ||
| 363 | + } | ||
| 364 | + }); | ||
| 365 | + | ||
| 366 | + | ||
| 367 | + FilteringObjective igmp = DefaultFilteringObjective.builder() | ||
| 368 | + .permit() | ||
| 369 | + .withKey(Criteria.matchInPort(port.number())) | ||
| 370 | + .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType())) | ||
| 371 | + .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP)) | ||
| 372 | + .withMeta(DefaultTrafficTreatment.builder() | ||
| 373 | + .setOutput(PortNumber.CONTROLLER).build()) | ||
| 374 | + .fromApp(appId) | ||
| 375 | + .withPriority(1000) | ||
| 376 | + .add(new ObjectiveContext() { | ||
| 377 | + @Override | ||
| 378 | + public void onSuccess(Objective objective) { | ||
| 379 | + log.info("Igmp filter for {} on {} installed.", | ||
| 380 | + devId, port); | ||
| 381 | + } | ||
| 382 | + | ||
| 383 | + @Override | ||
| 384 | + public void onError(Objective objective, ObjectiveError error) { | ||
| 385 | + log.info("Igmp filter for {} on {} failed because {}.", | ||
| 386 | + devId, port, error); | ||
| 387 | + } | ||
| 388 | + }); | ||
| 389 | + | ||
| 390 | + flowObjectiveService.filter(devId, eapol); | ||
| 391 | + flowObjectiveService.filter(devId, igmp); | ||
| 392 | + } | ||
| 393 | + | ||
| 330 | private class InternalDeviceListener implements DeviceListener { | 394 | private class InternalDeviceListener implements DeviceListener { |
| 331 | @Override | 395 | @Override |
| 332 | public void event(DeviceEvent event) { | 396 | public void event(DeviceEvent event) { |
| ... | @@ -336,7 +400,20 @@ public class Olt | ... | @@ -336,7 +400,20 @@ public class Olt |
| 336 | return; | 400 | return; |
| 337 | } | 401 | } |
| 338 | switch (event.type()) { | 402 | switch (event.type()) { |
| 403 | + //TODO: Port handling and bookkeeping should be inproved once | ||
| 404 | + // olt firmware handles correct behaviour. | ||
| 339 | case PORT_ADDED: | 405 | case PORT_ADDED: |
| 406 | + if (event.port().isEnabled()) { | ||
| 407 | + installFilteringObjectives(devId, event.port()); | ||
| 408 | + } | ||
| 409 | + break; | ||
| 410 | + case PORT_REMOVED: | ||
| 411 | + AccessDeviceData olt = oltData.get(devId); | ||
| 412 | + unprovisionSubscriber(devId, olt.uplink(), | ||
| 413 | + event.port().number(), | ||
| 414 | + olt.vlan()); | ||
| 415 | + installFilteringObjectives(devId, event.port()); | ||
| 416 | + break; | ||
| 340 | case PORT_UPDATED: | 417 | case PORT_UPDATED: |
| 341 | break; | 418 | break; |
| 342 | case DEVICE_ADDED: | 419 | case DEVICE_ADDED: |
| ... | @@ -352,7 +429,6 @@ public class Olt | ... | @@ -352,7 +429,6 @@ public class Olt |
| 352 | case DEVICE_UPDATED: | 429 | case DEVICE_UPDATED: |
| 353 | case DEVICE_SUSPENDED: | 430 | case DEVICE_SUSPENDED: |
| 354 | case DEVICE_AVAILABILITY_CHANGED: | 431 | case DEVICE_AVAILABILITY_CHANGED: |
| 355 | - case PORT_REMOVED: | ||
| 356 | case PORT_STATS_UPDATED: | 432 | case PORT_STATS_UPDATED: |
| 357 | default: | 433 | default: |
| 358 | return; | 434 | return; | ... | ... |
| ... | @@ -120,7 +120,8 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -120,7 +120,8 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
| 120 | .limit(1) | 120 | .limit(1) |
| 121 | .findFirst().get(); | 121 | .findFirst().get(); |
| 122 | 122 | ||
| 123 | - if (output != null && !output.port().equals(PortNumber.CONTROLLER)) { | 123 | + if (output == null || !output.port().equals(PortNumber.CONTROLLER)) { |
| 124 | + log.error("OLT can only filter packet to controller"); | ||
| 124 | fail(filter, ObjectiveError.UNSUPPORTED); | 125 | fail(filter, ObjectiveError.UNSUPPORTED); |
| 125 | return; | 126 | return; |
| 126 | } | 127 | } |
| ... | @@ -142,15 +143,19 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -142,15 +143,19 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
| 142 | return; | 143 | return; |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | - if (ethType.ethType().equals(EthType.EtherType.EAPOL)) { | 146 | + if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) { |
| 146 | provisionEapol(filter, ethType, output); | 147 | provisionEapol(filter, ethType, output); |
| 147 | - } else if (ethType.ethType().equals(EthType.EtherType.IPV4)) { | 148 | + } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) { |
| 148 | IPProtocolCriterion ipProto = (IPProtocolCriterion) | 149 | IPProtocolCriterion ipProto = (IPProtocolCriterion) |
| 149 | filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO); | 150 | filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO); |
| 150 | if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) { | 151 | if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) { |
| 151 | provisionIGMP(filter, ethType, ipProto, output); | 152 | provisionIGMP(filter, ethType, ipProto, output); |
| 153 | + } else { | ||
| 154 | + log.error("OLT can only filter igmp"); | ||
| 155 | + fail(filter, ObjectiveError.UNSUPPORTED); | ||
| 152 | } | 156 | } |
| 153 | } else { | 157 | } else { |
| 158 | + log.error("OLT can only filter eapol and igmp"); | ||
| 154 | fail(filter, ObjectiveError.UNSUPPORTED); | 159 | fail(filter, ObjectiveError.UNSUPPORTED); |
| 155 | } | 160 | } |
| 156 | 161 | ||
| ... | @@ -389,6 +394,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -389,6 +394,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
| 389 | .makePermanent() | 394 | .makePermanent() |
| 390 | .withSelector(selector) | 395 | .withSelector(selector) |
| 391 | .withTreatment(treatment) | 396 | .withTreatment(treatment) |
| 397 | + .withPriority(filter.priority()) | ||
| 392 | .build(); | 398 | .build(); |
| 393 | 399 | ||
| 394 | FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder(); | 400 | FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder(); |
| ... | @@ -446,7 +452,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ... | @@ -446,7 +452,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
| 446 | 452 | ||
| 447 | private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) { | 453 | private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) { |
| 448 | return criteria.stream() | 454 | return criteria.stream() |
| 449 | - .filter(c -> c.type().equals(Criterion.Type.ETH_TYPE)) | 455 | + .filter(c -> c.type().equals(type)) |
| 450 | .limit(1) | 456 | .limit(1) |
| 451 | .findFirst().orElse(null); | 457 | .findFirst().orElse(null); |
| 452 | } | 458 | } | ... | ... |
-
Please register or login to post a comment