change roadm app to support EDFA/ROADM/OPS devices, add OPS PowerConfig/LambdaQuery behaviour
Change-Id: Ieb6de727e766fdeb63740c0704f83fd11e44b935
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkPowerConfigUtil.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkPowerConfigUtil.java
index a24df09..45e2c58 100644
--- a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkPowerConfigUtil.java
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkPowerConfigUtil.java
@@ -114,6 +114,9 @@
private static final long ROADM_POWER_OTHER_OUT_HIGH_THRES = 1500L;
private static final long ROADM_MIN_ATTENUATION = 0L;
private static final long ROADM_MAX_ATTENUATION = 2500L;
+ // SWITCH
+ private static final long SWITCH_POWER_LOW_THRES = -6000L;
+ private static final long SWITCH_POWER_HIGH_THRES = 6000L;
/**
* Create a new OplinkPowerConfigUtil.
@@ -296,6 +299,8 @@
return Range.closed(ROADM_POWER_OTHER_OUT_LOW_THRES, ROADM_POWER_OTHER_OUT_HIGH_THRES);
}
break;
+ case FIBER_SWITCH:
+ return Range.closed(SWITCH_POWER_LOW_THRES, SWITCH_POWER_HIGH_THRES);
default:
log.warn("Unexpected device type: {}", devType);
break;
@@ -335,6 +340,8 @@
return Range.closed(ROADM_POWER_OTHER_IN_LOW_THRES, ROADM_POWER_OTHER_IN_HIGH_THRES);
}
break;
+ case FIBER_SWITCH:
+ return Range.closed(SWITCH_POWER_LOW_THRES, SWITCH_POWER_HIGH_THRES);
default:
log.warn("Unexpected device type: {}", devType);
break;
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkSwitchPowerConfig.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkSwitchPowerConfig.java
new file mode 100644
index 0000000..5be34a4
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkSwitchPowerConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.driver.optical.power;
+
+import java.util.Optional;
+
+import com.google.common.collect.Range;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.PowerConfig;
+
+/**
+ * Port Power implementation for Oplink protection switch device.
+ *
+ * Intruduction:
+ * _____
+ * _____________________ | | 0 VIRTUAL
+ * | | | 1 |
+ * CLIENT | |---|-----|--- PRIMARY
+ * -----------| OPS | | | NETWORK
+ * 3 | |---|-----|--- SECONDARY
+ * |_____________________| | 2 |
+ * |_____|
+ * Uses flow to set switch path.
+ * network port = 0, client port = 3, AUTO mode.
+ * network port = 1 or 2, client port = 3, MANUAL mode.
+ *
+ */
+
+public class OplinkSwitchPowerConfig extends AbstractHandlerBehaviour
+ implements PowerConfig<Object> {
+
+ // oplink power config utility
+ private OplinkPowerConfigUtil oplinkUtil = new OplinkPowerConfigUtil(this);
+
+ @Override
+ public Optional<Long> getTargetPower(PortNumber port, Object component) {
+ return Optional.ofNullable(null);
+ }
+
+ @Override
+ public Optional<Long> currentPower(PortNumber port, Object component) {
+ return Optional.ofNullable(oplinkUtil.getCurrentPower(port, component));
+ }
+
+ @Override
+ public void setTargetPower(PortNumber port, Object component, long power) {
+ return;
+ }
+
+ @Override
+ public Optional<Range<Long>> getTargetPowerRange(PortNumber port, Object component) {
+ return Optional.ofNullable(oplinkUtil.getTargetPowerRange(port, component));
+ }
+
+ @Override
+ public Optional<Range<Long>> getInputPowerRange(PortNumber port, Object component) {
+ return Optional.ofNullable(oplinkUtil.getInputPowerRange(port, component));
+ }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/protection/OplinkSwitchProtection.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/protection/OplinkSwitchProtection.java
index f512b9c..16009f7 100644
--- a/drivers/optical/src/main/java/org/onosproject/driver/optical/protection/OplinkSwitchProtection.java
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/protection/OplinkSwitchProtection.java
@@ -16,6 +16,7 @@
package org.onosproject.driver.optical.protection;
+import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.FilteredConnectPoint;
@@ -73,16 +74,14 @@
private static final int PRIMARY_PORT = 1;
private static final int SECONDARY_PORT = 2;
private static final int CLIENT_PORT = 3;
+ private static final int FLOWRULE_PRIORITY = 88;
private static final String PRIMARY_ID = "primary_port";
private static final String SECONDARY_ID = "secondary_port";
private static final String OPLINK_FINGERPRINT = "OplinkOPS";
+ private static final String APP_ID = "org.onosproject.drivers.optical";
protected final Logger log = LoggerFactory.getLogger(getClass());
- private FlowRuleService flowRuleService = this.handler().get(FlowRuleService.class);
- private DeviceService deviceService = this.handler().get(DeviceService.class);
- private NetworkConfigService netCfgService = this.handler().get(NetworkConfigService.class);
-
@Override
public CompletableFuture<ConnectPoint> createProtectionEndpoint(
ProtectedTransportEndpointDescription configuration) {
@@ -96,7 +95,7 @@
//add a virtual link bewteen two virtual ports of this device and peer
addLinkToPeer(configuration.peer());
- result.complete(new ConnectPoint(this.data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT)));
+ result.complete(new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT)));
return result;
}
@@ -108,7 +107,7 @@
log.warn("Update protection configuration is not supported by this device");
CompletableFuture result = new CompletableFuture<ConnectPoint>();
- result.complete(new ConnectPoint(this.data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT)));
+ result.complete(new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT)));
return result;
}
@@ -132,7 +131,7 @@
@Override
public CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointDescription>> getProtectionEndpointConfigs() {
- ConnectPoint cp = new ConnectPoint(this.data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
+ ConnectPoint cp = new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
Map<ConnectPoint, ProtectedTransportEndpointDescription> protectedGroups = new HashMap<>();
CompletableFuture result = new CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointDescription>>();
@@ -145,7 +144,7 @@
@Override
public CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointState>> getProtectionEndpointStates() {
- ConnectPoint cp = new ConnectPoint(this.data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
+ ConnectPoint cp = new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
Map<ConnectPoint, ProtectedTransportEndpointState> protectedGroups = new HashMap<>();
CompletableFuture result = new CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointState>>();
@@ -193,9 +192,7 @@
teds.add(tedPrimary);
teds.add(tedSecondary);
- return ProtectedTransportEndpointDescription.of(teds,
- getPeerId(),
- OPLINK_FINGERPRINT);
+ return ProtectedTransportEndpointDescription.of(teds, getPeerId(), OPLINK_FINGERPRINT);
}
/*
@@ -205,7 +202,7 @@
Map<String, String> attributes = new HashMap<>();
//get status form port annotations, the status is update by hand shaker driver periodically
- Port port = deviceService.getPort(this.data().deviceId(), portNumber);
+ Port port = handler().get(DeviceService.class).getPort(data().deviceId(), portNumber);
if (port != null) {
String portStatus = port.annotations().value(OpticalAnnotations.INPUT_PORT_STATUS);
attributes.put(OpticalAnnotations.INPUT_PORT_STATUS, portStatus);
@@ -214,7 +211,8 @@
}
private int getActiveIndex() {
- Port port = deviceService.getPort(this.data().deviceId(), PortNumber.portNumber(PRIMARY_PORT));
+ Port port = handler().get(DeviceService.class)
+ .getPort(data().deviceId(), PortNumber.portNumber(PRIMARY_PORT));
if (port != null) {
if (port.annotations().value(OpticalAnnotations.INPUT_PORT_STATUS)
.equals(OpticalAnnotations.STATUS_IN_SERVICE)) {
@@ -229,10 +227,12 @@
*/
private ProtectedTransportEndpointState getProtectedTransportEndpointState() {
List<TransportEndpointState> tess = new ArrayList<>();
+ PortNumber portPrimary = PortNumber.portNumber(PRIMARY_PORT);
+ PortNumber portSecondary = PortNumber.portNumber(SECONDARY_PORT);
FilteredConnectPoint fcpPrimary = new FilteredConnectPoint(
- new ConnectPoint(data().deviceId(), PortNumber.portNumber(PRIMARY_PORT)));
+ new ConnectPoint(data().deviceId(), portPrimary));
FilteredConnectPoint fcpSecondary = new FilteredConnectPoint(
- new ConnectPoint(data().deviceId(), PortNumber.portNumber(SECONDARY_PORT)));
+ new ConnectPoint(data().deviceId(), portSecondary));
TransportEndpointDescription tedPrimary = TransportEndpointDescription.builder()
.withOutput(fcpPrimary).build();
TransportEndpointDescription tedSecondary = TransportEndpointDescription.builder()
@@ -241,12 +241,12 @@
TransportEndpointState tesPrimary = TransportEndpointState.builder()
.withDescription(tedPrimary)
.withId(TransportEndpointId.of(PRIMARY_ID))
- .addAttributes(getProtectionStateAttributes(PortNumber.portNumber(PRIMARY_PORT)))
+ .addAttributes(getProtectionStateAttributes(portPrimary))
.build();
TransportEndpointState tesSecondary = TransportEndpointState.builder()
.withDescription(tedSecondary)
.withId(TransportEndpointId.of(SECONDARY_ID))
- .addAttributes(getProtectionStateAttributes((PortNumber.portNumber(SECONDARY_PORT))))
+ .addAttributes(getProtectionStateAttributes((portSecondary)))
.build();
tess.add(tesPrimary);
@@ -266,30 +266,32 @@
* - A flow from secondary port to client port indicates the device is manually switched to secondary
*/
private void addFlow(PortNumber workingPort) {
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- FlowRule.Builder flowRule = DefaultFlowRule.builder();
-
- //set working port as flow's input port
- selectorBuilder.matchInPort(workingPort);
-
- //the flow's output port is always the clinet port
- treatment.setOutput(PortNumber.portNumber(CLIENT_PORT));
-
- flowRule.forDevice(this.data().deviceId())
- .withSelector(selectorBuilder.build())
- .withTreatment(treatment.build())
- .makePermanent();
+ // set working port as flow's input port
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(workingPort)
+ .build();
+ // the flow's output port is always the clinet port
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(CLIENT_PORT))
+ .build();
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(data().deviceId())
+ .fromApp(handler().get(CoreService.class).getAppId(APP_ID))
+ .withPriority(FLOWRULE_PRIORITY)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .makePermanent()
+ .build();
// install flow rule
- flowRuleService.applyFlowRules(flowRule.build());
+ handler().get(FlowRuleService.class).applyFlowRules(flowRule);
}
/*
Delete all the flows to put device in default mode.
*/
private void deleteFlow() {
// remove all the flows.
- flowRuleService.purgeFlowRules(this.data().deviceId());
+ handler().get(FlowRuleService.class).purgeFlowRules(data().deviceId());
}
private void addLinkToPeer(DeviceId peerId) {
@@ -301,7 +303,8 @@
ConnectPoint dstCp = new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
ConnectPoint srcCp = new ConnectPoint(peerId, PortNumber.portNumber(VIRTUAL_PORT));
LinkKey link = linkKey(srcCp, dstCp);
- BasicLinkConfig cfg = netCfgService.addConfig(link, BasicLinkConfig.class);
+ BasicLinkConfig cfg = handler().get(NetworkConfigService.class)
+ .addConfig(link, BasicLinkConfig.class);
cfg.type(Link.Type.VIRTUAL);
cfg.apply();
}
@@ -314,12 +317,12 @@
ConnectPoint dstCp = new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
ConnectPoint srcCp = new ConnectPoint(peerId, PortNumber.portNumber(VIRTUAL_PORT));
LinkKey link = linkKey(srcCp, dstCp);
- netCfgService.removeConfig(link, BasicLinkConfig.class);
+ handler().get(NetworkConfigService.class).removeConfig(link, BasicLinkConfig.class);
}
private DeviceId getPeerId() {
ConnectPoint dstCp = new ConnectPoint(data().deviceId(), PortNumber.portNumber(VIRTUAL_PORT));
- Set<Link> links = this.handler().get(LinkService.class).getIngressLinks(dstCp);
+ Set<Link> links = handler().get(LinkService.class).getIngressLinks(dstCp);
for (Link l : links) {
if (l.type() == Link.Type.VIRTUAL) {
@@ -328,6 +331,6 @@
}
}
- return null;
+ return data().deviceId();
}
}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkEdfaLambdaQuery.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkEdfaLambdaQuery.java
index b37dfbf..c8bf529 100644
--- a/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkEdfaLambdaQuery.java
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkEdfaLambdaQuery.java
@@ -19,7 +19,9 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import org.onlab.util.Spectrum;
import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.LambdaQuery;
@@ -28,21 +30,22 @@
/**
* Lambda query implementation for Oplink EDFA.
*
- * An Oplink EDFA port exposes OMSn resources: 88 lambdas with 50GHz width (fixed grid).
- *
- * Channel id: Nominal central frequency = 193.1 THz + spacingMultiplier * channelSpacing).
- * Channel (-28 to 59): starting from 191.7 THz to 196.05 THz, Increment by 50GHz.
+ * An Oplink EDFA port supports min bandwidth 6.25Hz (flex grid).
+ * Usable optical spectrum range is C band, see {@link Spectrum} for spectrum definitions.
*/
public class OplinkEdfaLambdaQuery extends AbstractHandlerBehaviour implements LambdaQuery {
- private static final int MIN_CHANNEL = -28;
- private static final int MAX_CHANNEL = 59;
+ // Wavelength range: 1528 - 1567 nm
+ private long startSpacingMultiplier = Spectrum.C_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_6P25GHZ.frequency().asHz();
+ private long stopSpacingMultiplier = Spectrum.C_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_6P25GHZ.frequency().asHz();
@Override
public Set<OchSignal> queryLambdas(PortNumber port) {
- return IntStream.rangeClosed(MIN_CHANNEL, MAX_CHANNEL)
- .mapToObj(x -> OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, x))
+ return IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
+ .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, x, 1))
.collect(Collectors.toSet());
}
}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkSwitchLambdaQuery.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkSwitchLambdaQuery.java
new file mode 100644
index 0000000..21c41bf
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkSwitchLambdaQuery.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.optical.query;
+
+import org.onlab.util.Spectrum;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * Lambda query implementation for Oplink optical protection switch.
+ *
+ * An Oplink optical protection switch supports min bandwidth 6.25Hz (flex grid).
+ * Usable optical spectrum range is U to O band, see {@link Spectrum} for spectrum definitions.
+ */
+public class OplinkSwitchLambdaQuery extends AbstractHandlerBehaviour implements LambdaQuery {
+
+ @Override
+ public Set<OchSignal> queryLambdas(PortNumber port) {
+ // Wavelength range: 1260 - 1675 nm
+ long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_6P25GHZ.frequency().asHz();
+ long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_6P25GHZ.frequency().asHz();
+
+ // Only consider odd values for the multiplier (for easy mapping to fixed grid)
+ return IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
+ .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, x, 1))
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/drivers/optical/src/main/resources/optical-drivers.xml b/drivers/optical/src/main/resources/optical-drivers.xml
index 21829a1..4d01858 100644
--- a/drivers/optical/src/main/resources/optical-drivers.xml
+++ b/drivers/optical/src/main/resources/optical-drivers.xml
@@ -68,9 +68,12 @@
manufacturer="Oplink a Molex company" hwVersion="protection-switch" swVersion="of-agent-1.0">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.optical.handshaker.OplinkSwitchHandshaker"/>
-
<behaviour api="org.onosproject.net.behaviour.protection.ProtectionConfigBehaviour"
impl="org.onosproject.driver.optical.protection.OplinkSwitchProtection"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.optical.query.OplinkSwitchLambdaQuery"/>
+ <behaviour api="org.onosproject.net.behaviour.PowerConfig"
+ impl="org.onosproject.driver.optical.power.OplinkSwitchPowerConfig"/>
</driver>
<driver name="oplk-edfa" extends="default"