OLT ability to remove a subscriber

Change-Id: I5fee9dd8189ae374bf39b0a74da5bd33304a3346
This commit is contained in:
alshabib 2016-01-14 17:27:11 -08:00 committed by Gerrit Code Review
parent 98c0a39e92
commit 02cbe6aefa

View File

@ -15,6 +15,8 @@
*/ */
package org.onosproject.olt; package org.onosproject.olt;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Deactivate;
@ -52,6 +54,7 @@ import org.slf4j.Logger;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -89,11 +92,16 @@ public class Olt
private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0); private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0);
private ExecutorService oltInstallers = Executors.newFixedThreadPool(4, private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
groupedThreads("onos/olt-service", groupedThreads("onos/olt-service",
"olt-installer-%d")); "olt-installer-%d"));
private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>(); private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
private Map<ConnectPoint, Set<ForwardingObjective.Builder>> objectives =
Maps.newConcurrentMap();
private Map<ConnectPoint, VlanId> subscribers = Maps.newConcurrentMap();
private InternalNetworkConfigListener configListener = private InternalNetworkConfigListener configListener =
new InternalNetworkConfigListener(); new InternalNetworkConfigListener();
private static final Class<AccessDeviceConfig> CONFIG_CLASS = private static final Class<AccessDeviceConfig> CONFIG_CLASS =
@ -102,11 +110,12 @@ public class Olt
private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory = private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
new ConfigFactory<DeviceId, AccessDeviceConfig>( new ConfigFactory<DeviceId, AccessDeviceConfig>(
SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") { SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
@Override @Override
public AccessDeviceConfig createConfig() { public AccessDeviceConfig createConfig() {
return new AccessDeviceConfig(); return new AccessDeviceConfig();
} }
}; };
@Activate @Activate
public void activate() { public void activate() {
@ -152,7 +161,68 @@ public class Olt
@Override @Override
public void removeSubscriber(ConnectPoint port) { public void removeSubscriber(ConnectPoint port) {
throw new UnsupportedOperationException(); AccessDeviceData olt = oltData.get(port.deviceId());
if (olt == null) {
log.warn("No data found for OLT device {}", port.deviceId());
return;
}
unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), olt.vlan());
}
private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
PortNumber subscriberPort, VlanId deviceVlan) {
//FIXME: This method is slightly ugly but it'll do until we have a better
// way to remove flows from the flow store.
CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
VlanId subscriberVlan = subscribers.remove(cp);
Set<ForwardingObjective.Builder> fwds = objectives.remove(cp);
if (fwds == null || fwds.size() != 2) {
log.warn("Unknown or incomplete subscriber at {}", cp);
return;
}
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);
}
})));
upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
if (upStatus == null && downStatus == null) {
post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
deviceId,
deviceVlan,
subscriberVlan));
} else if (downStatus != null) {
log.error("Subscriber with vlan {} on device {} " +
"on port {} failed downstream uninstallation: {}",
subscriberVlan, deviceId, subscriberPort, downStatus);
} else if (upStatus != null) {
log.error("Subscriber with vlan {} on device {} " +
"on port {} failed upstream uninstallation: {}",
subscriberVlan, deviceId, subscriberPort, upStatus);
}
}, oltInstallers);
} }
@ -190,46 +260,53 @@ public class Olt
.build(); .build();
ForwardingObjective upFwd = DefaultForwardingObjective.builder() ForwardingObjective.Builder upFwd = DefaultForwardingObjective.builder()
.withFlag(ForwardingObjective.Flag.VERSATILE) .withFlag(ForwardingObjective.Flag.VERSATILE)
.withPriority(1000) .withPriority(1000)
.makePermanent() .makePermanent()
.withSelector(upstream) .withSelector(upstream)
.fromApp(appId) .fromApp(appId)
.withTreatment(upstreamTreatment) .withTreatment(upstreamTreatment);
.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
upFuture.complete(null);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
upFuture.complete(error);
}
});
ForwardingObjective downFwd = DefaultForwardingObjective.builder() ForwardingObjective.Builder downFwd = DefaultForwardingObjective.builder()
.withFlag(ForwardingObjective.Flag.VERSATILE) .withFlag(ForwardingObjective.Flag.VERSATILE)
.withPriority(1000) .withPriority(1000)
.makePermanent() .makePermanent()
.withSelector(downstream) .withSelector(downstream)
.fromApp(appId) .fromApp(appId)
.withTreatment(downstreamTreatment) .withTreatment(downstreamTreatment);
.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
downFuture.complete(null);
}
@Override ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
public void onError(Objective objective, ObjectiveError error) {
downFuture.complete(error);
}
});
flowObjectiveService.forward(deviceId, upFwd); subscribers.put(cp, subscriberVlan);
flowObjectiveService.forward(deviceId, downFwd); objectives.put(cp, Sets.newHashSet(upFwd, downFwd));
flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
upFuture.complete(null);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
upFuture.complete(error);
}
}));
flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
downFuture.complete(null);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
downFuture.complete(error);
}
}));
upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> { upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
if (upStatus == null && downStatus == null) { if (upStatus == null && downStatus == null) {
@ -288,20 +365,20 @@ public class Olt
public void event(NetworkConfigEvent event) { public void event(NetworkConfigEvent event) {
switch (event.type()) { switch (event.type()) {
case CONFIG_ADDED: case CONFIG_ADDED:
case CONFIG_UPDATED: case CONFIG_UPDATED:
if (event.configClass().equals(CONFIG_CLASS)) { if (event.configClass().equals(CONFIG_CLASS)) {
AccessDeviceConfig config = AccessDeviceConfig config =
networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS); networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
if (config != null) { if (config != null) {
oltData.put(config.getOlt().deviceId(), config.getOlt()); oltData.put(config.getOlt().deviceId(), config.getOlt());
}
} }
} break;
break; case CONFIG_UNREGISTERED:
case CONFIG_UNREGISTERED: case CONFIG_REMOVED:
case CONFIG_REMOVED: default:
default: break;
break;
} }
} }
} }