Implement PowerConfig for Oplink Devices
Change-Id: I939126580f8d3cdcdbcd9a46f6ee5cacbd25051d
diff --git a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
index 00efb4a..4235ed1 100644
--- a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
+++ b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.net;
+import com.google.common.annotations.Beta;
+
/**
* Collection of keys for annotation.
* <p>
@@ -110,6 +112,18 @@
public static final String STATIC_LAMBDA = "staticLambda";
/**
+ * Annotation key for optical port's target power.
+ */
+ @Beta
+ public static final String TARGET_POWER = "targetPower";
+
+ /**
+ * Annotation key for optical port's current power.
+ */
+ @Beta
+ public static final String CURRENT_POWER = "currentPower";
+
+ /**
* Annotation key for the static port.
*/
public static final String STATIC_PORT = "staticPort";
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkRoadmHandshaker.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkRoadmHandshaker.java
index 13c238b..cf1a179 100644
--- a/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkRoadmHandshaker.java
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkRoadmHandshaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2016 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.
@@ -25,7 +25,14 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortDescription;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
@@ -37,10 +44,16 @@
import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFObject;
+import org.projectfloodlight.openflow.protocol.OFOplinkPortPower;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortOptical;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFOplinkPortPowerRequest;
+import org.projectfloodlight.openflow.protocol.OFOplinkPortPowerReply;
+
/**
* Driver for Oplink single WSS 8D ROADM.
@@ -49,6 +62,7 @@
* The device consists of Och ports, and performances wavelength cross-connect among the ports.
*/
public class OplinkRoadmHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private List<OFPortOptical> opticalPorts;
@@ -159,7 +173,26 @@
@Override
public final void sendMsg(OFMessage m) {
OFMessage newMsg = m;
- //Stub for later enhancement.
+
+ if (m.getType() == OFType.STATS_REQUEST) {
+ OFStatsRequest sr = (OFStatsRequest) m;
+ log.debug("OPLK ROADM rebuilding stats request type {}", sr.getStatsType());
+ switch (sr.getStatsType()) {
+ case PORT:
+ //replace with Oplink experiment stats message to get the port current power
+ OFOplinkPortPowerRequest pRequest = this.factory().buildOplinkPortPowerRequest()
+ .setXid(sr.getXid())
+ .setFlags(sr.getFlags())
+ .build();
+ newMsg = pRequest;
+ break;
+ default:
+ break;
+ }
+ } else {
+ log.debug("OPLK ROADM sends msg:{}, as is", m.getType());
+ }
+
super.sendMsg(newMsg);
}
@@ -185,4 +218,38 @@
opticalPorts = new ArrayList<>();
opticalPorts.addAll(wPorts.getEntries());
}
+
+ @Override
+ public List<PortDescription> processExpPortStats(OFMessage msg) {
+ if (msg instanceof OFOplinkPortPowerReply) {
+ return buildPortPowerDescriptions(((OFOplinkPortPowerReply) msg).getEntries());
+ }
+ return Collections.emptyList();
+ }
+
+ private OFOplinkPortPower getPortPower(List<OFOplinkPortPower> portPowers, PortNumber portNum) {
+ for (OFOplinkPortPower power : portPowers) {
+ if (power.getPort() == portNum.toLong()) {
+ return power;
+ }
+ }
+ return null;
+ }
+
+ private List<PortDescription> buildPortPowerDescriptions(List<OFOplinkPortPower> portPowers) {
+ DeviceService deviceService = this.handler().get(DeviceService.class);
+ List<Port> ports = deviceService.getPorts(this.data().deviceId());
+ final List<PortDescription> portDescs = new ArrayList<>();
+ for (Port port : ports) {
+ DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+ builder.putAll(port.annotations());
+ OFOplinkPortPower power = getPortPower(portPowers, port.number());
+ if (power != null) {
+ builder.set(AnnotationKeys.CURRENT_POWER, Long.toString(power.getPowerValue()));
+ }
+ portDescs.add(new DefaultPortDescription(port.number(), port.isEnabled(),
+ port.type(), port.portSpeed(), builder.build()));
+ }
+ return portDescs;
+ }
}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkRoadmPowerConfig.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkRoadmPowerConfig.java
new file mode 100644
index 0000000..47a699d
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkRoadmPowerConfig.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 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 org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.Direction;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.PowerConfig;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowController;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Port Power (Gain and attenuation) implementation for Oplink ROADM.
+ *
+ * An Oplink ROADM port exposes OchSignal resources.
+ * Optical Power can be set at port level or channel/wavelength level (attenuation).
+ *
+ */
+
+public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour
+ implements PowerConfig<Direction> {
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ private OpenFlowSwitch getOpenFlowDevice() {
+ final OpenFlowController controller = this.handler().get(OpenFlowController.class);
+ final Dpid dpid = Dpid.dpid(this.data().deviceId().uri());
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null || !sw.isConnected()) {
+ return null;
+ } else {
+ return sw;
+ }
+ }
+
+ @Override
+ public Optional<Long> getTargetPower(PortNumber portNum, Direction component) {
+ // Will be implemented in the future.
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<Long> currentPower(PortNumber portNum, Direction component) {
+ Long returnVal = null;
+ // Check if switch is connected, otherwise do not return value in store,
+ // which is obsolete.
+ if (getOpenFlowDevice() != null) {
+ DeviceService deviceService = this.handler().get(DeviceService.class);
+ Port port = deviceService.getPort(this.data().deviceId(), portNum);
+ if (port != null) {
+ String currentPower = port.annotations().value(AnnotationKeys.CURRENT_POWER);
+ if (currentPower != null) {
+ returnVal = Long.valueOf(currentPower);
+ }
+ }
+ }
+ return Optional.ofNullable(returnVal);
+ }
+
+ @Override
+ public void setTargetPower(PortNumber portNum, Direction component, long power) {
+ OpenFlowSwitch device = getOpenFlowDevice();
+ if (device != null) {
+ device.sendMsg(device.factory().buildOplinkPortPowerSet()
+ .setXid(0)
+ .setPort((int) portNum.toLong())
+ .setPowerValue((int) power)
+ .build());
+ } else {
+ log.warn("OpenFlow handshaker driver not found or device is not connected");
+ }
+ }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/package-info.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/package-info.java
new file mode 100644
index 0000000..db6378ef
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementations of the power config behaviours for optical devices.
+ */
+package org.onosproject.driver.optical.power;
diff --git a/drivers/optical/src/main/resources/optical-drivers.xml b/drivers/optical/src/main/resources/optical-drivers.xml
index c87a8cd..505db69 100644
--- a/drivers/optical/src/main/resources/optical-drivers.xml
+++ b/drivers/optical/src/main/resources/optical-drivers.xml
@@ -56,6 +56,8 @@
impl="org.onosproject.driver.optical.query.OplinkRoadmLambdaQuery"/>
<behaviour api="org.onosproject.net.optical.OpticalDevice"
impl="org.onosproject.net.optical.DefaultOpticalDevice"/>
+ <behaviour api="org.onosproject.net.behaviour.PowerConfig"
+ impl="org.onosproject.driver.optical.power.OplinkRoadmPowerConfig"/>
</driver>
</drivers>
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
index 34d4f88..42f8638 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
@@ -15,8 +15,11 @@
*/
package org.onosproject.openflow.controller;
+import java.util.Collections;
import java.util.List;
+import org.onosproject.net.device.PortDescription;
+import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import com.google.common.annotations.Beta;
@@ -38,4 +41,15 @@
@Beta
@Override
abstract List<OFPortDesc> getPorts();
+
+ /**
+ * Returns updated PortDescriptions built from experimenter message
+ * received from device.
+ *
+ * @param msg OpenFlow message from device.
+ * @return List of updated PortDescriptions.
+ */
+ default List<PortDescription> processExpPortStats(OFMessage msg) {
+ return Collections.emptyList();
+ }
}
diff --git a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
index 1f6a888..177cf1a 100644
--- a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -547,7 +547,7 @@
private PortDescription buildPortDescription(PortDescPropertyType ptype, OFObject port,
OpenFlowOpticalSwitch opsw) {
- if (port instanceof OFPortOptical) {
+ if (port instanceof OFPortOptical) {
return buildPortDescription(ptype, (OFPortOptical) port, opsw);
}
return buildPortDescription(ptype, (OFExpPort) port);
@@ -833,6 +833,16 @@
statsEntries.clear();
}
}
+ } else if (((OFStatsReply) msg).getStatsType() == OFStatsType.EXPERIMENTER) {
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw instanceof OpenFlowOpticalSwitch) {
+ // Optical switch uses experimenter stats message to update power
+ List<PortDescription> portDescs =
+ ((OpenFlowOpticalSwitch) sw).processExpPortStats(msg);
+ if (!portDescs.isEmpty()) {
+ providerService.updatePorts(DeviceId.deviceId(Dpid.uri(dpid)), portDescs);
+ }
+ }
}
break;
case ERROR: