change roadm app to support EDFA/ROADM/OPS devices, add OPS PowerConfig/LambdaQuery behaviour
Change-Id: Ieb6de727e766fdeb63740c0704f83fd11e44b935
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
index 011c393..a0cace9 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
@@ -25,6 +25,7 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Direction;
@@ -34,6 +35,9 @@
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.net.behaviour.PowerConfig;
+import org.onosproject.net.behaviour.protection.ProtectionConfigBehaviour;
+import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointState;
+import org.onosproject.net.behaviour.protection.TransportEndpointState;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -48,15 +52,21 @@
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.optical.OpticalAnnotations;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -101,94 +111,46 @@
log.info("Stopped");
}
- private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
- Device device = deviceService.getDevice(deviceId);
- if (device != null && device.is(PowerConfig.class)) {
- return device.as(PowerConfig.class);
- }
- log.warn("Unable to load PowerConfig for {}", deviceId);
- return null;
- }
-
- private LambdaQuery getLambdaQuery(DeviceId deviceId) {
- Device device = deviceService.getDevice(deviceId);
- if (device != null && device.is(LambdaQuery.class)) {
- return device.as(LambdaQuery.class);
- }
- return null;
- }
-
- private void initDevices() {
- for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
- initDevice(device.id());
- setAllInitialTargetPortPowers(device.id());
- }
- }
-
- // Initialize RoadmStore for a device to support target power
- private void initDevice(DeviceId deviceId) {
- if (!roadmStore.deviceAvailable(deviceId)) {
- roadmStore.addDevice(deviceId);
- }
- log.info("Initialized device {}", deviceId);
- }
-
- // Sets the target port powers for a port on a device
- // Attempts to read target powers from store. If no value is found then
- // default value is used instead.
- private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
- PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
- if (powerConfig == null) {
- log.warn("Unable to set default initial powers for port {} on device {}",
- portNumber, deviceId);
+ @Override
+ public void setProtectionSwitchWorkingPath(DeviceId deviceId, int index) {
+ checkNotNull(deviceId);
+ ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
+ if (behaviour == null) {
return;
}
-
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
- if (!range.isPresent()) {
- log.warn("No target power range found for port {} on device {}",
- portNumber, deviceId);
+ Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
+ if (map == null) {
+ log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
return;
}
-
- Long power = roadmStore.getTargetPower(deviceId, portNumber);
- if (power == null) {
- // Set default to middle of the range
- power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
- roadmStore.setTargetPower(deviceId, portNumber, power);
+ if (map.isEmpty()) {
+ log.warn("No protected transport endpoint state found in device {}", deviceId);
+ return;
}
- powerConfig.setTargetPower(portNumber, Direction.ALL, power);
+ behaviour.switchWorkingPath(map.keySet().toArray(new ConnectPoint[0])[0], index);
}
- // Sets the target port powers for each each port on a device
- // Attempts to read target powers from store. If no value is found then
- // default value is used instead
- private void setAllInitialTargetPortPowers(DeviceId deviceId) {
- PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
- if (powerConfig == null) {
- log.warn("Unable to set default initial powers for device {}",
- deviceId);
- return;
+ @Override
+ public String getProtectionSwitchPortState(DeviceId deviceId, PortNumber portNumber) {
+ checkNotNull(deviceId);
+ ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
+ if (behaviour == null) {
+ return null;
}
-
- List<Port> ports = deviceService.getPorts(deviceId);
- for (Port port : ports) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
- if (range.isPresent()) {
- Long power = roadmStore.getTargetPower(deviceId, port.number());
- if (power == null) {
- // Set default to middle of the range
- power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
- roadmStore.setTargetPower(deviceId, port.number(), power);
+ Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
+ if (map == null) {
+ log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
+ return null;
+ }
+ for (ProtectedTransportEndpointState state : map.values()) {
+ for (TransportEndpointState element : state.pathStates()) {
+ if (element.description().output().connectPoint().port().equals(portNumber)) {
+ return element.attributes().get(OpticalAnnotations.INPUT_PORT_STATUS);
}
- powerConfig.setTargetPower(port.number(), Direction.ALL, power);
- } else {
- log.warn("No target power range found for port {} on device {}",
- port.number(), deviceId);
}
}
+ log.warn("Unable to get port status, device: {}, port: {}", deviceId, portNumber);
+ return null;
}
@Override
@@ -208,8 +170,7 @@
public Long getTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
checkNotNull(deviceId);
checkNotNull(portNumber);
- // getTargetPortPower is not yet implemented in PowerConfig so we
- // access store instead
+ // getTargetPortPower is not yet implemented in PowerConfig so we access store instead
return roadmStore.getTargetPower(deviceId, portNumber);
}
@@ -229,15 +190,13 @@
}
@Override
- public Long getAttenuation(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Long getAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> attenuation =
- powerConfig.getTargetPower(portNumber, ochSignal);
+ Optional<Long> attenuation = powerConfig.getTargetPower(portNumber, ochSignal);
if (attenuation.isPresent()) {
return attenuation.get();
}
@@ -251,8 +210,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> currentPower =
- powerConfig.currentPower(portNumber, Direction.ALL);
+ Optional<Long> currentPower = powerConfig.currentPower(portNumber, Direction.ALL);
if (currentPower.isPresent()) {
return currentPower.get();
}
@@ -261,15 +219,13 @@
}
@Override
- public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> currentPower =
- powerConfig.currentPower(portNumber, ochSignal);
+ Optional<Long> currentPower = powerConfig.currentPower(portNumber, ochSignal);
if (currentPower.isPresent()) {
return currentPower.get();
}
@@ -290,31 +246,31 @@
@Override
public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
- int timeout, PortNumber inPort, PortNumber outPort,
- OchSignal ochSignal) {
+ int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
- FlowRule.Builder flowBuilder = new DefaultFlowRule.Builder();
- flowBuilder.fromApp(appId);
- flowBuilder.withPriority(priority);
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .add(Criteria.matchInPort(inPort))
+ .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
+ .add(Criteria.matchLambda(ochSignal))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .add(Instructions.createOutput(outPort))
+ .build();
+
+ FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .fromApp(appId)
+ .withPriority(priority)
+ .withSelector(selector)
+ .withTreatment(treatment);
if (isPermanent) {
flowBuilder.makePermanent();
} else {
flowBuilder.makeTemporary(timeout);
}
- flowBuilder.forDevice(deviceId);
-
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- selectorBuilder.add(Criteria.matchInPort(inPort));
- selectorBuilder.add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID));
- selectorBuilder.add(Criteria.matchLambda(ochSignal));
- flowBuilder.withSelector(selectorBuilder.build());
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
- treatmentBuilder.add(Instructions.createOutput(outPort));
- flowBuilder.withTreatment(treatmentBuilder.build());
FlowRule flowRule = flowBuilder.build();
flowRuleService.applyFlowRules(flowRule);
@@ -332,26 +288,11 @@
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
- FlowId flowId = createConnection(deviceId, priority, isPermanent,
- timeout, inPort, outPort, ochSignal);
+ FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
return flowId;
}
- // Delay the call to setTargetPower because the flow may not be in the store yet
- private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
- OchSignal ochSignal, long attenuation) {
- Runnable setAtt = () -> {
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- log.warn("Thread interrupted. Setting attenuation early.");
- }
- setAttenuation(deviceId, outPort, ochSignal, attenuation);
- };
- new Thread(setAtt).start();
- }
-
@Override
public void removeConnection(DeviceId deviceId, FlowId flowId) {
checkNotNull(deviceId);
@@ -371,37 +312,32 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
return range.isPresent();
}
return false;
}
@Override
- public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber,
- long power) {
+ public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
checkNotNull(deviceId);
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
return range.isPresent() && range.get().contains(power);
}
return false;
}
@Override
- public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort,
- long att) {
+ public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
checkNotNull(deviceId);
checkNotNull(outPort);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(outPort, stubOch);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
return range.isPresent() && range.get().contains(att);
}
return false;
@@ -413,8 +349,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getInputPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
return range.isPresent();
}
return false;
@@ -426,10 +361,10 @@
}
@Override
- public boolean validChannel(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
+ checkNotNull(ochSignal);
LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
if (lambdaQuery != null) {
Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
@@ -451,8 +386,7 @@
}
@Override
- public boolean validConnection(DeviceId deviceId, PortNumber inPort,
- PortNumber outPort) {
+ public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
@@ -465,8 +399,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
if (range.isPresent()) {
return range.get();
}
@@ -475,15 +408,13 @@
}
@Override
- public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, ochSignal);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
if (range.isPresent()) {
return range.get();
}
@@ -497,8 +428,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getInputPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
if (range.isPresent()) {
return range.get();
}
@@ -506,6 +436,137 @@
return null;
}
+ private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(PowerConfig.class)) {
+ return device.as(PowerConfig.class);
+ }
+ log.warn("Unable to load PowerConfig for {}", deviceId);
+ return null;
+ }
+
+ private LambdaQuery getLambdaQuery(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(LambdaQuery.class)) {
+ return device.as(LambdaQuery.class);
+ }
+ log.warn("Unable to load LambdaQuery for {}", deviceId);
+ return null;
+ }
+
+ private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(ProtectionConfigBehaviour.class)) {
+ return device.as(ProtectionConfigBehaviour.class);
+ }
+ log.warn("Unable to load ProtectionConfigBehaviour for {}", deviceId);
+ return null;
+ }
+
+ // Initialize all devices
+ private void initDevices() {
+ for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
+ initDevice(device.id());
+ //FIXME
+ // As roadm application is a optional tool for now.
+ // The target power initialization will be enhanced later,
+ // hopefully using an formal optical subsystem.
+ // setAllInitialTargetPortPowers(device.id());
+ }
+ }
+
+ // Initialize RoadmStore for a device to support target power
+ private void initDevice(DeviceId deviceId) {
+ if (!roadmStore.deviceAvailable(deviceId)) {
+ roadmStore.addDevice(deviceId);
+ }
+ log.info("Initialized device {}", deviceId);
+ }
+
+ // Sets the target port powers for a port on a device
+ // Attempts to read target powers from store. If no value is found then
+ // default value is used instead.
+ private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
+ PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
+ if (powerConfig == null) {
+ log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
+ return;
+ }
+
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ if (!range.isPresent()) {
+ log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
+ return;
+ }
+
+ Long power = roadmStore.getTargetPower(deviceId, portNumber);
+ if (power == null) {
+ // Set default to middle of the range
+ power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
+ roadmStore.setTargetPower(deviceId, portNumber, power);
+ }
+ powerConfig.setTargetPower(portNumber, Direction.ALL, power);
+ }
+
+ // Sets the target port powers for each each port on a device
+ // Attempts to read target powers from store. If no value is found then
+ // default value is used instead
+ private void setAllInitialTargetPortPowers(DeviceId deviceId) {
+ PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
+ if (powerConfig == null) {
+ log.warn("Unable to set default initial powers for device {}", deviceId);
+ return;
+ }
+
+ List<Port> ports = deviceService.getPorts(deviceId);
+ for (Port port : ports) {
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
+ if (range.isPresent()) {
+ Long power = roadmStore.getTargetPower(deviceId, port.number());
+ if (power == null) {
+ // Set default to middle of the range
+ power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
+ roadmStore.setTargetPower(deviceId, port.number(), power);
+ }
+ powerConfig.setTargetPower(port.number(), Direction.ALL, power);
+ } else {
+ log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
+ }
+ }
+ }
+
+ // Delay the call to setTargetPower because the flow may not be in the store yet
+ private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
+ OchSignal ochSignal, long attenuation) {
+ Runnable setAtt = () -> {
+ try {
+ TimeUnit.SECONDS.sleep(1);
+ } catch (InterruptedException e) {
+ log.warn("Thread interrupted. Setting attenuation early.");
+ }
+ setAttenuation(deviceId, outPort, ochSignal, attenuation);
+ };
+ new Thread(setAtt).start();
+ }
+
+ // get protection endpoint states
+ private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
+ ProtectionConfigBehaviour behaviour) {
+ CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointState>>
+ states = behaviour.getProtectionEndpointStates();
+ Map<ConnectPoint, ProtectedTransportEndpointState> map;
+ try {
+ map = states.get();
+ } catch (InterruptedException e1) {
+ log.error("Interrupted.", e1);
+ return null;
+ } catch (ExecutionException e1) {
+ log.error("Exception caught.", e1);
+ return null;
+ }
+ return map;
+ }
+
// Listens to device events.
private class InternalDeviceListener implements DeviceListener {
@Override
@@ -519,7 +580,11 @@
break;
case PORT_ADDED:
case PORT_UPDATED:
- setInitialTargetPortPower(device.id(), deviceEvent.port().number());
+ //FIXME
+ // As roadm application is a optional tool for now.
+ // The target power initialization will be enhanced later,
+ // hopefully using an formal optical subsystem.
+ // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
break;
default:
break;