Oplink EDFA driver
Change-Id: I7fafa66bf7a5290f2d7ea2e07046fa8dabdb20de
diff --git a/core/api/src/main/java/org/onosproject/net/Device.java b/core/api/src/main/java/org/onosproject/net/Device.java
index 58b60c6..c8966fb 100644
--- a/core/api/src/main/java/org/onosproject/net/Device.java
+++ b/core/api/src/main/java/org/onosproject/net/Device.java
@@ -27,7 +27,7 @@
*/
enum Type {
SWITCH, ROUTER, ROADM, OTN, ROADM_OTN, FIREWALL, BALANCER, IPS, IDS, CONTROLLER,
- VIRTUAL, FIBER_SWITCH, MICROWAVE, OLT, ONU, OTHER
+ VIRTUAL, FIBER_SWITCH, MICROWAVE, OLT, ONU, OPTICAL_AMPLIFIER, OTHER
}
/**
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkEdfaHandshaker.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkEdfaHandshaker.java
new file mode 100644
index 0000000..34ad613
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkEdfaHandshaker.java
@@ -0,0 +1,210 @@
+/*
+ * 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.handshaker;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.onosproject.net.Device;
+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;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
+import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
+import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
+import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
+import org.projectfloodlight.openflow.protocol.OFExpPortAdjacencyReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFObject;
+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.OFOplinkPortPowerReply;
+
+import static org.onosproject.net.Device.Type;
+
+/**
+ * Oplink open flow EDFA handshaker - for Open Flow 1.3.
+ * Driver for Oplink EDFA openflow device.
+ * Driver implements custom handshaker and supports Optical Port based on OpenFlow OTN extension.
+ */
+public class OplinkEdfaHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+
+ private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
+ private List<OFPortOptical> opticalPorts = new ArrayList<>();
+ private OplinkHandshakerUtil oplinkUtil = new OplinkHandshakerUtil(this);
+
+ @Override
+ public List<? extends OFObject> getPortsOf(PortDescPropertyType type) {
+ // Expected type is OPTICAL_TRANSPORT
+ if (type == PortDescPropertyType.OPTICAL_TRANSPORT) {
+ return ImmutableList.copyOf(opticalPorts);
+ }
+ // Any other type, return empty
+ log.warn("Unexpected port description property type: {}", type);
+ return ImmutableList.of();
+ }
+
+ /**
+ * Returns a list of standard (Ethernet) ports.
+ *
+ * @return List of ports
+ */
+ @Override
+ public List<OFPortDesc> getPorts() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public Set<PortDescPropertyType> getPortTypes() {
+ return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
+ }
+
+ @Override
+ public Boolean supportNxRole() {
+ return false;
+ }
+
+ @Override
+ public void startDriverHandshake() {
+ log.info("Starting driver handshake for sw {}", getStringId());
+ if (startDriverHandshakeCalled) {
+ throw new SwitchDriverSubHandshakeAlreadyStarted();
+ }
+ startDriverHandshakeCalled = true;
+ try {
+ sendHandshakeOFExperimenterPortDescRequest();
+ } catch (IOException e) {
+ log.error("OPLK EDFA exception while sending experimenter port desc:", e);
+ }
+ }
+
+ @Override
+ public boolean isDriverHandshakeComplete() {
+ return driverHandshakeComplete.get();
+ }
+
+ @Override
+ public void processDriverHandshakeMessage(OFMessage m) {
+
+ if (!startDriverHandshakeCalled) {
+ throw new SwitchDriverSubHandshakeNotStarted();
+ }
+
+ if (driverHandshakeComplete.get()) {
+ throw new SwitchDriverSubHandshakeCompleted(m);
+ }
+
+ switch (m.getType()) {
+ case BARRIER_REPLY:
+ log.debug("OPLK EDFA Received barrier response");
+ break;
+ case ERROR:
+ log.error("Switch {} Error {}", getStringId(), m);
+ break;
+ case PORT_STATUS:
+ processOFPortStatus((OFCircuitPortStatus) m);
+ break;
+ case STATS_REPLY:
+ OFStatsReply stats = (OFStatsReply) m;
+ if (stats.getStatsType() == OFStatsType.EXPERIMENTER) {
+ log.debug("OPLK EDFA : Received multipart (port desc) reply message {}", m);
+ //OTN Optical extension 1.0 port-desc
+ createOpticalPortList((OFCircuitPortsReply) m);
+ driverHandshakeComplete.set(true);
+ }
+ break;
+ default:
+ log.warn("Received message {} during switch-driver " +
+ "subhandshake from switch {} ... " +
+ "Ignoring message", m, getStringId());
+ }
+ }
+
+ @Override
+ public Device.Type deviceType() {
+ return Type.OPTICAL_AMPLIFIER;
+ }
+
+ @Override
+ public final void sendMsg(OFMessage m) {
+ List<OFMessage> messages = new ArrayList<>();
+ messages.add(m);
+
+ if (m.getType() == OFType.STATS_REQUEST) {
+ OFStatsRequest sr = (OFStatsRequest) m;
+ log.debug("OPLK EDFA rebuilding stats request type {}", sr.getStatsType());
+ switch (sr.getStatsType()) {
+ case PORT:
+ // add Oplink experiment message to get the port's current power
+ messages.add(oplinkUtil.buildPortPowerRequest());
+ // add experiment message to get adjacent ports
+ messages.add(oplinkUtil.buildPortAdjacencyRequest());
+ break;
+ default:
+ break;
+ }
+ } else {
+ log.debug("OPLK EDFA sends msg:{}, as is", m.getType());
+ }
+
+ super.sendMsg(messages);
+ }
+
+ @Override
+ public List<PortDescription> processExpPortStats(OFMessage msg) {
+ if (msg instanceof OFOplinkPortPowerReply) {
+ return oplinkUtil.buildPortPowerDescriptions(((OFOplinkPortPowerReply) msg).getEntries());
+ } else if (msg instanceof OFExpPortAdjacencyReply) {
+ return oplinkUtil.buildPortAdjacencyDescriptions(((OFExpPortAdjacencyReply) msg).getEntries());
+ }
+ return Collections.emptyList();
+ }
+
+ private void processOFPortStatus(OFCircuitPortStatus ps) {
+ log.debug("OPLK EDFA ..OF Port Status :", ps);
+ }
+
+ private void sendHandshakeOFExperimenterPortDescRequest() throws IOException {
+ // Send multipart message for port description for optical switches
+ OFCircuitPortsRequest circuitPortsRequest = oplinkUtil.buildCircuitPortsRequest();
+ log.debug("OPLK EDFA : Sending experimented port description message {}", circuitPortsRequest);
+ sendHandshakeMessage(circuitPortsRequest);
+ }
+
+ /**
+ * Builds list of OFPortOptical ports based on the multi-part circuit ports reply.
+ * Ensure the optical transport port's signal type is configured correctly.
+ *
+ * @param wPorts OF reply with circuit ports
+ */
+ private void createOpticalPortList(OFCircuitPortsReply wPorts) {
+ opticalPorts.addAll(wPorts.getEntries());
+ }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkHandshakerUtil.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkHandshakerUtil.java
new file mode 100644
index 0000000..298f65f
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/handshaker/OplinkHandshakerUtil.java
@@ -0,0 +1,251 @@
+/*
+ * 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.handshaker;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.onosproject.drivers.optical.OpticalAdjacencyLinkService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+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.net.link.DefaultLinkDescription;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.optical.OpticalAnnotations;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
+import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
+import org.projectfloodlight.openflow.protocol.OFExpExtAdId;
+import org.projectfloodlight.openflow.protocol.OFExpPortAdidOtn;
+import org.projectfloodlight.openflow.protocol.OFExpPortAdjacency;
+import org.projectfloodlight.openflow.protocol.OFExpPortAdjacencyId;
+import org.projectfloodlight.openflow.protocol.OFExpPortAdjacencyRequest;
+import org.projectfloodlight.openflow.protocol.OFOplinkPortPower;
+import org.projectfloodlight.openflow.protocol.OFOplinkPortPowerRequest;
+
+/**
+ * Oplink handshaker utility.
+ */
+public class OplinkHandshakerUtil {
+
+ // Parent driver instance
+ private OpenFlowSwitchDriver driver;
+ // Total count of opspec in OFExpPortAdidOtn
+ private static final int OPSPEC_BYTES = 32;
+ // Bit count of id in opspec
+ private static final int OPSPEC_ID_BITS = 4;
+ // Start byte position of mac info
+ private static final int OPSPEC_MAC_POS = 18;
+ // Bit offset for mac
+ private static final int OPSPEC_MAC_BIT_OFF = 16;
+ // Start byte position of port info
+ private static final int OPSPEC_PORT_POS = 24;
+ // Right bit offset for mac
+ private static final int OPSPEC_PORT_BIT_OFF = 32;
+
+ /**
+ * Create a new OplinkHandshakerUtil.
+ * @param driver parent driver instance
+ */
+ public OplinkHandshakerUtil(OpenFlowSwitchDriver driver) {
+ this.driver = driver;
+ }
+
+ /**
+ * Creates an oplink port power request OF message.
+ *
+ * @return OF message of oplink port power request
+ */
+ public OFOplinkPortPowerRequest buildPortPowerRequest() {
+ OFOplinkPortPowerRequest request = driver.factory().buildOplinkPortPowerRequest()
+ .setXid(driver.getNextTransactionId())
+ .build();
+ return request;
+ }
+
+ /**
+ * Creates port adjacency request OF message.
+ *
+ * @return OF message of oplink port adjacency request
+ */
+ public OFExpPortAdjacencyRequest buildPortAdjacencyRequest() {
+ OFExpPortAdjacencyRequest request = driver.factory().buildExpPortAdjacencyRequest()
+ .setXid(driver.getNextTransactionId())
+ .build();
+ return request;
+ }
+
+ /**
+ * Creates an oplink port description request OF message.
+ *
+ * @return OF message of oplink port description request
+ */
+ public OFCircuitPortsRequest buildCircuitPortsRequest() {
+ OFCircuitPortsRequest request = driver.factory().buildCircuitPortsRequest()
+ .setXid(driver.getNextTransactionId())
+ .build();
+ return request;
+ }
+
+ /**
+ * Creates port descriptions with current power.
+ *
+ * @param portPowers current power
+ * @return port descriptions
+ */
+ public List<PortDescription> buildPortPowerDescriptions(List<OFOplinkPortPower> portPowers) {
+ DeviceService deviceService = driver.handler().get(DeviceService.class);
+ List<Port> ports = deviceService.getPorts(driver.data().deviceId());
+ HashMap<Long, OFOplinkPortPower> powerMap = new HashMap<>(portPowers.size());
+ // Get each port power value
+ portPowers.forEach(power -> powerMap.put((long) power.getPort(), power));
+ final List<PortDescription> portDescs = new ArrayList<>();
+ for (Port port : ports) {
+ DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+ builder.putAll(port.annotations());
+ OFOplinkPortPower power = powerMap.get(port.number().toLong());
+ if (power != null) {
+ // power value is actually signed-short value, down casting to recover sign bit.
+ builder.set(OpticalAnnotations.CURRENT_POWER, Short.toString((short) power.getPowerValue()));
+ }
+ portDescs.add(new DefaultPortDescription(port.number(), port.isEnabled(),
+ port.type(), port.portSpeed(), builder.build()));
+ }
+ return portDescs;
+ }
+
+ /**
+ * Creates port descriptions with adjacency.
+ *
+ * @param portAds adjacency information
+ * @return port descriptions
+ */
+ public List<PortDescription> buildPortAdjacencyDescriptions(List<OFExpPortAdjacency> portAds) {
+ DeviceService deviceService = driver.handler().get(DeviceService.class);
+ List<Port> ports = deviceService.getPorts(driver.data().deviceId());
+ // Map port's number with port's adjacency
+ HashMap<Long, OFExpPortAdjacency> adMap = new HashMap<>(portAds.size());
+ portAds.forEach(ad -> adMap.put((long) ad.getPortNo().getPortNumber(), ad));
+ List<PortDescription> portDescs = new ArrayList<>();
+ for (Port port : ports) {
+ DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+ Annotations oldAnnotations = port.annotations();
+ builder.putAll(oldAnnotations);
+ OFExpPortAdjacency ad = adMap.get(port.number().toLong());
+ OplinkPortAdjacency neighbor = getNeighbor(ad);
+ if (neighbor == null) {
+ // no neighbors found
+ builder.remove(OpticalAnnotations.NEIGHBOR_ID);
+ builder.remove(OpticalAnnotations.NEIGHBOR_PORT);
+ removeLink(port.number());
+ } else {
+ // neighbor discovered, add to port descriptions
+ String newId = neighbor.getDeviceId().toString();
+ String newPort = neighbor.getPort().toString();
+ // Check if annotation already exists
+ if (!newId.equals(oldAnnotations.value(OpticalAnnotations.NEIGHBOR_ID)) ||
+ !newPort.equals(oldAnnotations.value(OpticalAnnotations.NEIGHBOR_PORT))) {
+ builder.set(OpticalAnnotations.NEIGHBOR_ID, newId);
+ builder.set(OpticalAnnotations.NEIGHBOR_PORT, newPort);
+ }
+ addLink(port.number(), neighbor);
+ }
+ portDescs.add(new DefaultPortDescription(port.number(), port.isEnabled(),
+ port.type(), port.portSpeed(), builder.build()));
+ }
+ return portDescs;
+ }
+
+ private OplinkPortAdjacency getNeighbor(OFExpPortAdjacency ad) {
+ // Check input parameter
+ if (ad == null) {
+ return null;
+ }
+ // Get adjacency properties
+ for (OFExpPortAdjacencyId adid : ad.getProperties()) {
+ List<OFExpExtAdId> otns = adid.getAdId();
+ if (otns != null && otns.size() > 0) {
+ OFExpPortAdidOtn otn = (OFExpPortAdidOtn) otns.get(0);
+ // ITU-T G.7714 ETH MAC Format (in second 16 bytes of the following)
+ // |---------------------------------------------------------------------------|
+ // | Other format (16 bytes) |
+ // |---------------------------------------------------------------------------|
+ // | Header (2 bytes) | ID (4 BITS) | MAC (6 bytes) | Port (4 bytes) | Unused |
+ // |---------------------------------------------------------------------------|
+ ChannelBuffer buffer = ChannelBuffers.buffer(OPSPEC_BYTES);
+ otn.getOpspec().write32Bytes(buffer);
+ long mac = buffer.getLong(OPSPEC_MAC_POS) << OPSPEC_ID_BITS >>> OPSPEC_MAC_BIT_OFF;
+ int port = (int) (buffer.getLong(OPSPEC_PORT_POS) << OPSPEC_ID_BITS >>> OPSPEC_PORT_BIT_OFF);
+ // Oplink does not use the 4 most significant bytes of Dpid so Dpid can be
+ // constructed from MAC address
+ return new OplinkPortAdjacency(DeviceId.deviceId(Dpid.uri(new Dpid(mac))),
+ PortNumber.portNumber(port));
+ }
+ }
+ // Returns null if no properties found
+ return null;
+ }
+
+ // Add incoming link with port
+ private void addLink(PortNumber portNumber, OplinkPortAdjacency neighbor) {
+ ConnectPoint dst = new ConnectPoint(driver.handler().data().deviceId(), portNumber);
+ ConnectPoint src = new ConnectPoint(neighbor.getDeviceId(), neighbor.getPort());
+ OpticalAdjacencyLinkService adService = driver.handler().get(OpticalAdjacencyLinkService.class);
+ adService.linkDetected(new DefaultLinkDescription(src, dst, Link.Type.OPTICAL));
+ }
+
+ // Remove incoming link with port if there are any.
+ private void removeLink(PortNumber portNumber) {
+ ConnectPoint dst = new ConnectPoint(driver.handler().data().deviceId(), portNumber);
+ // Check so only incoming links are removed
+ Set<Link> links = driver.handler().get(LinkService.class).getIngressLinks(dst);
+ if (links.isEmpty()) {
+ return;
+ }
+ // If link exists, remove it
+ OpticalAdjacencyLinkService adService = driver.handler().get(OpticalAdjacencyLinkService.class);
+ adService.linksVanished(dst);
+ }
+
+ private class OplinkPortAdjacency {
+ private DeviceId deviceId;
+ private PortNumber portNumber;
+
+ public OplinkPortAdjacency(DeviceId deviceId, PortNumber portNumber) {
+ this.deviceId = deviceId;
+ this.portNumber = portNumber;
+ }
+
+ public DeviceId getDeviceId() {
+ return deviceId;
+ }
+
+ public PortNumber getPort() {
+ return portNumber;
+ }
+ }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkEdfaPowerConfig.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkEdfaPowerConfig.java
new file mode 100644
index 0000000..554df14
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/power/OplinkEdfaPowerConfig.java
@@ -0,0 +1,190 @@
+/*
+ * 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.concurrent.atomic.AtomicInteger;
+import java.util.Optional;
+
+import com.google.common.collect.Range;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+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.net.optical.OpticalAnnotations;
+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 EDFA device.
+ *
+ * An Oplink EDFA port exposes Direction resources.
+ * Set gain(attenuation) at AGC mode or set output level at APC mode.
+ *
+ */
+
+public class OplinkEdfaPowerConfig extends AbstractHandlerBehaviour
+ implements PowerConfig<Object> {
+
+ /**
+ * Input and ouput port number
+ * Note:
+ * These port number configurations are just in use for a short time.
+ * In the future, the port number and direction type would be obtained from physical device.
+ */
+ private static final int LINE_IN_WEST = 1;
+ private static final int LINE_OUT_WEST = 2;
+ private static final int LINE_IN_EAST = 3;
+ private static final int LINE_OUT_EAST = 4;
+
+ /**
+ * Power threshold of each port, magnified 100 times
+ * Note:
+ * These threshold configurations are just in use for a short time.
+ * In the future, the power threshold would be obtained from physical device.
+ */
+ private static final long POWER_IN_WEST_LOW_THRES = -1900L;
+ private static final long POWER_IN_WEST_HIGH_THRES = 0L;
+ private static final long POWER_IN_EAST_LOW_THRES = -3100L;
+ private static final long POWER_IN_EAST_HIGH_THRES = 700L;
+ private static final long POWER_OUT_LOW_THRES = 0L;
+ private static final long POWER_OUT_HIGH_THRES = 1900L;
+
+ // Transaction id to use.
+ private final AtomicInteger xidCounter = new AtomicInteger(0);
+ // Log
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public Optional<Long> getTargetPower(PortNumber portNum, Object component) {
+ Long returnVal = getTargetPortPower(portNum);
+ return Optional.ofNullable(returnVal);
+ }
+
+ @Override
+ public Optional<Long> currentPower(PortNumber portNum, Object component) {
+ Long returnVal = getCurrentPortPower(portNum);
+ return Optional.ofNullable(returnVal);
+ }
+
+ @Override
+ public void setTargetPower(PortNumber portNum, Object component, long power) {
+ setTargetPortPower(portNum, power);
+ }
+
+ @Override
+ public Optional<Range<Long>> getTargetPowerRange(PortNumber port, Object component) {
+ Range<Long> range = getTargetPortPowerRange(port);
+ return Optional.ofNullable(range);
+ }
+
+ @Override
+ public Optional<Range<Long>> getInputPowerRange(PortNumber port, Object component) {
+ Range<Long> range = getInputPortPowerRange(port);
+ return Optional.ofNullable(range);
+ }
+
+ private OpenFlowSwitch getOpenFlowDevice() {
+ final OpenFlowController controller = handler().get(OpenFlowController.class);
+ final Dpid dpid = Dpid.dpid(data().deviceId().uri());
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null || !sw.isConnected()) {
+ log.warn("OpenFlow handshaker driver not found or device is not connected");
+ return null;
+ }
+ return sw;
+ }
+
+ private Long getPowerFromPort(PortNumber portNum, String annotation) {
+ // Check if switch is connected, otherwise do not return value in store, which is obsolete.
+ if (getOpenFlowDevice() == null) {
+ // Warning already exists in method getOpenFlowDevice()
+ return null;
+ }
+ DeviceService deviceService = handler().get(DeviceService.class);
+ Port port = deviceService.getPort(data().deviceId(), portNum);
+ if (port == null) {
+ log.warn("Unexpected port: {}", portNum);
+ return null;
+ }
+ String power = port.annotations().value(annotation);
+ if (power == null) {
+ log.warn("Cannot get {} from port {}.", annotation, portNum);
+ return null;
+ }
+ return Long.valueOf(power);
+ }
+
+ private Long getTargetPortPower(PortNumber portNum) {
+ return getPowerFromPort(portNum, OpticalAnnotations.TARGET_POWER);
+ }
+
+ private Long getCurrentPortPower(PortNumber portNum) {
+ return getPowerFromPort(portNum, OpticalAnnotations.CURRENT_POWER);
+ }
+
+ private void setTargetPortPower(PortNumber portNum, long power) {
+ OpenFlowSwitch device = getOpenFlowDevice();
+ // Check if switch is connected, otherwise do not return value in store, which is obsolete.
+ if (device == null) {
+ // Warning already exists in method getOpenFlowDevice()
+ return;
+ }
+ device.sendMsg(device.factory().buildOplinkPortPowerSet()
+ .setXid(xidCounter.getAndIncrement())
+ .setPort((int) portNum.toLong())
+ .setPowerValue((int) power)
+ .build());
+ }
+
+ // Returns the acceptable target range for an output Port, null otherwise
+ private Range<Long> getTargetPortPowerRange(PortNumber port) {
+ long portNum = port.toLong();
+ // FIXME
+ // Short time hard code, we will use port direction type instead in the future.
+ // And more, the power range will be also obtained from device configuration.
+ switch ((int) portNum) {
+ case LINE_OUT_EAST:
+ case LINE_OUT_WEST:
+ return Range.closed(POWER_OUT_LOW_THRES, POWER_OUT_HIGH_THRES);
+ default:
+ // Unexpected port. Do not need warning here for port polling.
+ return null;
+ }
+ }
+
+ // Returns the working input power range for an input port, null if the port
+ // is not an input port.
+ private Range<Long> getInputPortPowerRange(PortNumber port) {
+ long portNum = port.toLong();
+ // FIXME
+ // Short time hard code, we will use port direction type instead in the future.
+ // And more, the power range will be also obtained from device configuration.
+ switch ((int) portNum) {
+ case LINE_IN_EAST:
+ return Range.closed(POWER_IN_EAST_LOW_THRES, POWER_IN_EAST_HIGH_THRES);
+ case LINE_IN_WEST:
+ return Range.closed(POWER_IN_WEST_LOW_THRES, POWER_IN_WEST_HIGH_THRES);
+ default:
+ // Unexpected port. Do not need warning here for port polling.
+ return null;
+ }
+ }
+}
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
new file mode 100644
index 0000000..b37dfbf
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/OplinkEdfaLambdaQuery.java
@@ -0,0 +1,48 @@
+/*
+ * 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 java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+
+/**
+ * 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.
+ */
+
+public class OplinkEdfaLambdaQuery extends AbstractHandlerBehaviour implements LambdaQuery {
+
+ private static final int MIN_CHANNEL = -28;
+ private static final int MAX_CHANNEL = 59;
+
+ @Override
+ public Set<OchSignal> queryLambdas(PortNumber port) {
+ return IntStream.rangeClosed(MIN_CHANNEL, MAX_CHANNEL)
+ .mapToObj(x -> OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, x))
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/drivers/optical/src/main/resources/optical-drivers.xml b/drivers/optical/src/main/resources/optical-drivers.xml
index 96dad6c..65ed00f 100644
--- a/drivers/optical/src/main/resources/optical-drivers.xml
+++ b/drivers/optical/src/main/resources/optical-drivers.xml
@@ -70,5 +70,14 @@
impl="org.onosproject.driver.optical.handshaker.OplinkSwitchHandshaker"/>
</driver>
+ <driver name="oplk-edfa" extends="default"
+ manufacturer="Oplink a Molex company" hwVersion="edfa" swVersion="of-agent-1.0">
+ <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
+ impl="org.onosproject.driver.optical.handshaker.OplinkEdfaHandshaker"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.optical.query.OplinkEdfaLambdaQuery"/>
+ <behaviour api="org.onosproject.net.behaviour.PowerConfig"
+ impl="org.onosproject.driver.optical.power.OplinkEdfaPowerConfig"/>
+ </driver>
</drivers>
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 3012722..6119a1f 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
@@ -489,7 +489,8 @@
private List<PortDescription> buildPortDescriptions(OpenFlowSwitch sw) {
final List<PortDescription> portDescs = new ArrayList<>(sw.getPorts().size());
if (!((Device.Type.ROADM.equals(sw.deviceType())) ||
- (Device.Type.OTN.equals(sw.deviceType())))) {
+ (Device.Type.OTN.equals(sw.deviceType())) ||
+ (Device.Type.OPTICAL_AMPLIFIER.equals(sw.deviceType())))) {
sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port)));
}
@@ -497,6 +498,7 @@
switch (sw.deviceType()) {
case ROADM:
case OTN:
+ case OPTICAL_AMPLIFIER:
opsw = (OpenFlowOpticalSwitch) sw;
List<OFPortDesc> ports = opsw.getPorts();
LOG.debug("SW ID {} , ETH- ODU CLT Ports {}", opsw.getId(), ports);