yjimmyy
Committed by Gerrit Code Review

Implement PowerConfig for Oplink Devices

Change-Id: I939126580f8d3cdcdbcd9a46f6ee5cacbd25051d
......@@ -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 final class AnnotationKeys {
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";
......
/*
* 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.List;
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.OFCircuitPortsReply;
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 @@ import org.projectfloodlight.openflow.protocol.OFStatsType;
* 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 @@ public class OplinkRoadmHandshaker extends AbstractOpenFlowSwitch implements Ope
@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 @@ public class OplinkRoadmHandshaker extends AbstractOpenFlowSwitch implements Ope
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;
}
}
......
/*
* 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");
}
}
}
/*
* 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;
......@@ -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>
......
......@@ -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 @@ public interface OpenFlowOpticalSwitch extends OpenFlowSwitch, WithTypedPorts {
@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();
}
}
......
......@@ -833,6 +833,16 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
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:
......