alshabib

olt installs default rules on startup and when a port shows up

Change-Id: I0db62db020f94500aeae7191f7681745e1268672
......@@ -23,12 +23,15 @@ import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.EthType;
import org.onlab.packet.IPv4;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
......@@ -42,7 +45,10 @@ import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
......@@ -126,6 +132,7 @@ public class Olt
networkConfig.registerConfigFactory(configFactory);
networkConfig.addListener(configListener);
networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
subject -> {
AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
......@@ -136,6 +143,12 @@ public class Olt
}
);
oltData.keySet().stream()
.flatMap(did -> deviceService.getPorts(did).stream())
.filter(p -> oltData.get(p.element().id()).uplink() != p.number())
.filter(p -> p.isEnabled())
.forEach(p -> installFilteringObjectives((DeviceId) p.element().id(), p));
log.info("Started with Application ID {}", appId.id());
}
......@@ -195,17 +208,17 @@ public class Olt
fwds.stream().forEach(
fwd -> flowObjectiveService.forward(deviceId,
fwd.remove(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
upFuture.complete(null);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
upFuture.complete(error);
}
})));
fwd.remove(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
upFuture.complete(null);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
upFuture.complete(error);
}
})));
upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
if (upStatus == null && downStatus == null) {
......@@ -327,6 +340,57 @@ public class Olt
}
private void installFilteringObjectives(DeviceId devId, Port port) {
FilteringObjective eapol = DefaultFilteringObjective.builder()
.permit()
.withKey(Criteria.matchInPort(port.number()))
.addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
.withMeta(DefaultTrafficTreatment.builder()
.setOutput(PortNumber.CONTROLLER).build())
.fromApp(appId)
.withPriority(1000)
.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
log.info("Eapol filter for {} on {} installed.",
devId, port);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.info("Eapol filter for {} on {} failed because {}",
devId, port, error);
}
});
FilteringObjective igmp = DefaultFilteringObjective.builder()
.permit()
.withKey(Criteria.matchInPort(port.number()))
.addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
.addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
.withMeta(DefaultTrafficTreatment.builder()
.setOutput(PortNumber.CONTROLLER).build())
.fromApp(appId)
.withPriority(1000)
.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
log.info("Igmp filter for {} on {} installed.",
devId, port);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.info("Igmp filter for {} on {} failed because {}.",
devId, port, error);
}
});
flowObjectiveService.filter(devId, eapol);
flowObjectiveService.filter(devId, igmp);
}
private class InternalDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
......@@ -336,7 +400,20 @@ public class Olt
return;
}
switch (event.type()) {
//TODO: Port handling and bookkeeping should be inproved once
// olt firmware handles correct behaviour.
case PORT_ADDED:
if (event.port().isEnabled()) {
installFilteringObjectives(devId, event.port());
}
break;
case PORT_REMOVED:
AccessDeviceData olt = oltData.get(devId);
unprovisionSubscriber(devId, olt.uplink(),
event.port().number(),
olt.vlan());
installFilteringObjectives(devId, event.port());
break;
case PORT_UPDATED:
break;
case DEVICE_ADDED:
......@@ -352,7 +429,6 @@ public class Olt
case DEVICE_UPDATED:
case DEVICE_SUSPENDED:
case DEVICE_AVAILABILITY_CHANGED:
case PORT_REMOVED:
case PORT_STATS_UPDATED:
default:
return;
......
......@@ -120,7 +120,8 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
.limit(1)
.findFirst().get();
if (output != null && !output.port().equals(PortNumber.CONTROLLER)) {
if (output == null || !output.port().equals(PortNumber.CONTROLLER)) {
log.error("OLT can only filter packet to controller");
fail(filter, ObjectiveError.UNSUPPORTED);
return;
}
......@@ -142,15 +143,19 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
return;
}
if (ethType.ethType().equals(EthType.EtherType.EAPOL)) {
if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) {
provisionEapol(filter, ethType, output);
} else if (ethType.ethType().equals(EthType.EtherType.IPV4)) {
} else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) {
IPProtocolCriterion ipProto = (IPProtocolCriterion)
filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) {
provisionIGMP(filter, ethType, ipProto, output);
} else {
log.error("OLT can only filter igmp");
fail(filter, ObjectiveError.UNSUPPORTED);
}
} else {
log.error("OLT can only filter eapol and igmp");
fail(filter, ObjectiveError.UNSUPPORTED);
}
......@@ -389,6 +394,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
.makePermanent()
.withSelector(selector)
.withTreatment(treatment)
.withPriority(filter.priority())
.build();
FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
......@@ -446,7 +452,7 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
return criteria.stream()
.filter(c -> c.type().equals(Criterion.Type.ETH_TYPE))
.filter(c -> c.type().equals(type))
.limit(1)
.findFirst().orElse(null);
}
......