Add driver for oplink netconf device.
Change-Id: I3c8a2e5ba3f79df48a2212b25664821891b6d2ae
diff --git a/drivers/oplink/BUCK b/drivers/oplink/BUCK
new file mode 100755
index 0000000..bc52ab2
--- /dev/null
+++ b/drivers/oplink/BUCK
@@ -0,0 +1,36 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//drivers/default:onos-drivers-default',
+ '//drivers/utilities:onos-drivers-utilities',
+ '//protocols/netconf/api:onos-protocols-netconf-api',
+ '//apps/optical-model:onos-apps-optical-model',
+]
+
+TEST_DEPS = [
+ '//lib:TEST_ADAPTERS',
+ '//core/api:onos-api-tests',
+]
+
+BUNDLES = [
+ ':onos-drivers-oplink',
+ '//drivers/utilities:onos-drivers-utilities',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
+ resources_root = 'src/main/resources',
+ resources = glob(['src/main/resources/**']),
+)
+
+onos_app(
+ app_name = 'org.onosproject.drivers.oplink',
+ title = 'Oplink Device Drivers',
+ category = 'Drivers',
+ url = 'http://onosproject.org',
+ description = 'ONOS Oplink Device Drivers application.',
+ included_bundles = BUNDLES,
+ required_apps = [
+ 'org.onosproject.netconf', 'org.onosproject.optical-model'
+ ],
+)
\ No newline at end of file
diff --git a/drivers/oplink/features.xml b/drivers/oplink/features.xml
new file mode 100755
index 0000000..ed1f431
--- /dev/null
+++ b/drivers/oplink/features.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<!--
+ ~ 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.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+
+ <bundle>mvn:${project.groupId}/onos-drivers-utilities/${project.version}</bundle>
+
+ <bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/drivers/oplink/pom.xml b/drivers/oplink/pom.xml
new file mode 100755
index 0000000..71bd788
--- /dev/null
+++ b/drivers/oplink/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>onos-drivers-general</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.10.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <description>Oplink device drivers</description>
+
+ <artifactId>onos-drivers-oplink</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <onos.app.name>org.onosproject.drivers.oplink</onos.app.name>
+ <onos.app.origin>Oplink</onos.app.origin>
+ <onos.app.category>Drivers</onos.app.category>
+ <onos.app.title>Oplink Device Drivers</onos.app.title>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.requires>
+ org.onosproject.drivers,
+ org.onosproject.netconf,
+ org.onosproject.optical-model
+ </onos.app.requires>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-optical-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-netconf-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-drivers-utilities</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-drivers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkCrossConnect.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkCrossConnect.java
new file mode 100644
index 0000000..1ffc5e1
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkCrossConnect.java
@@ -0,0 +1,89 @@
+/*
+ * 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.drivers.oplink;
+
+import org.onosproject.net.PortNumber;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Oplink cross connect data unit.
+ * The requirement members are input port, output port, wavelength channel and channel attenuation.
+ */
+public class OplinkCrossConnect {
+
+ private final PortNumber inPort;
+ private final PortNumber outPort;
+ private final int channel;
+ private final int attenuation;
+
+ /**
+ * OplinkConnection structure.
+ * @param inPort the input port
+ * @param outPort the output port
+ * @param channel the channel
+ * @param attenuation the attenuation
+ */
+ public OplinkCrossConnect(PortNumber inPort, PortNumber outPort, int channel, int attenuation) {
+ this.inPort = inPort;
+ this.outPort = outPort;
+ this.channel = channel;
+ this.attenuation = attenuation;
+ }
+
+ /**
+ * Returns the input port of the cross connect.
+ * @return input port
+ */
+ public PortNumber getInPort() {
+ return inPort;
+ }
+
+ /**
+ * Returns the output port of the cross connect.
+ * @return output port
+ */
+ public PortNumber getOutPort() {
+ return outPort;
+ }
+
+ /**
+ * Returns the channel number of the cross connect.
+ * @return channel number
+ */
+ public int getChannel() {
+ return channel;
+ }
+
+ /**
+ * Returns the channel attenuation of the cross connect.
+ * @return attenuation
+ */
+ public int getAttenuation() {
+ return attenuation;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("inPort", inPort)
+ .add("outPort", outPort)
+ .add("channel", channel)
+ .add("attenuation", attenuation)
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkDriversLoader.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkDriversLoader.java
new file mode 100755
index 0000000..cf56174
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkDriversLoader.java
@@ -0,0 +1,36 @@
+/*
+ * 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.drivers.oplink;
+
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+import org.onosproject.net.optical.OpticalDevice;
+
+/**
+ * Loader for Oplink device drivers.
+ */
+@Component(immediate = true)
+public class OplinkDriversLoader extends AbstractDriverLoader {
+
+ // OSGI: help bundle plugin discover runtime package dependency.
+ @SuppressWarnings("unused")
+ private OpticalDevice optical;
+
+ public OplinkDriversLoader() {
+ super("/oplink-drivers.xml");
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkNetconfUtility.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkNetconfUtility.java
new file mode 100644
index 0000000..f474a5c
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkNetconfUtility.java
@@ -0,0 +1,154 @@
+/*
+ * 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.drivers.oplink;
+
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+
+import java.io.IOException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Netconf utility for oplink netconf drivers.
+ */
+public final class OplinkNetconfUtility {
+
+ // public used nodes
+ public static final String CFG_TAR_RUNNING = "running";
+ public static final String CFG_MODE_MERGE = "merge";
+ public static final String CFG_MODE_REMOVE = "remove";
+ public static final String KEY_XMLNS = "xmlns=\"http://com/att/device\"";
+ public static final String KEY_DATA = "data";
+ public static final String KEY_OPENOPTICALDEV = "open-optical-device";
+ public static final String KEY_CONNS = "connections";
+ public static final String KEY_CONNID = "connection-id";
+ public static final String KEY_PORTS = "ports";
+ public static final String KEY_PORTID = "port-id";
+ public static final String KEY_PORT = "port";
+ public static final String KEY_PORTDIRECT = "port-direction";
+ public static final String KEY_CHATT = "attenuation";
+ public static final String KEY_DATA_CONNS = String.format("%s.%s.%s", KEY_DATA, KEY_OPENOPTICALDEV, KEY_CONNS);
+ public static final String KEY_DATA_PORTS = String.format("%s.%s.%s", KEY_DATA, KEY_OPENOPTICALDEV, KEY_PORTS);
+ public static final String KEY_OPENOPTICALDEV_XMLNS = String.format("%s %s", KEY_OPENOPTICALDEV, KEY_XMLNS);
+
+ private OplinkNetconfUtility() {
+ }
+
+ /**
+ * Retrieves session reply information for get config operation.
+ *
+ * @param handler parent driver handler
+ * @param filter the filter string of xml content
+ * @return the reply string
+ */
+ public static String netconfGetConfig(DriverHandler handler, String filter) {
+ NetconfController controller = checkNotNull(handler.get(NetconfController.class));
+ NetconfSession session = controller.getNetconfDevice(handler.data().deviceId()).getSession();
+ String reply;
+ try {
+ reply = session.getConfig(CFG_TAR_RUNNING, filter);
+ } catch (IOException e) {
+ throw new RuntimeException(new NetconfException("Failed to retrieve configuration.", e));
+ }
+ return reply;
+ }
+
+ /**
+ * Retrieves session reply information for edit config operation.
+ *
+ * @param handler parent driver handler
+ * @param mode selected mode to change the configuration
+ * @param cfg the new configuration to be set
+ * @return the reply string
+ */
+ public static boolean netconfEditConfig(DriverHandler handler, String mode, String cfg) {
+ NetconfController controller = checkNotNull(handler.get(NetconfController.class));
+ NetconfSession session = controller.getNetconfDevice(handler.data().deviceId()).getSession();
+ boolean reply = false;
+ try {
+ reply = session.editConfig(CFG_TAR_RUNNING, mode, cfg);
+ } catch (IOException e) {
+ throw new RuntimeException(new NetconfException("Failed to edit configuration.", e));
+ }
+ return reply;
+ }
+
+ /**
+ * Retrieves specified node hierarchical configuration from the xml information.
+ *
+ * @param content the xml information
+ * @param key the configuration key node
+ * @return the hierarchical configuration
+ */
+ public static HierarchicalConfiguration configAt(String content, String key) {
+ HierarchicalConfiguration cfg = XmlConfigParser.loadXmlString(content);
+ HierarchicalConfiguration info;
+ try {
+ info = cfg.configurationAt(key);
+ } catch (Exception e) {
+ // Accept null for information polling
+ return null;
+ }
+ return info;
+ }
+
+ /**
+ * Makes a xml format sentence.
+ *
+ * @param node the node name
+ * @param content the node content
+ * @return the xml format sentence
+ */
+ public static String xml(String node, String content) {
+ return String.format("<%s>%s</%s>", node, content, node);
+ }
+
+ /**
+ * Makes a xml format open tag.
+ *
+ * @param node the node name
+ * @return the xml head format string
+ */
+ public static String xmlOpen(String node) {
+ return String.format("<%s>", node);
+ }
+
+ /**
+ * Makes a xml format close tag.
+ *
+ * @param node the node name
+ * @return the xml end format string
+ */
+ public static String xmlClose(String node) {
+ return String.format("</%s>", node);
+ }
+
+ /**
+ * Makes a xml format empty tag.
+ *
+ * @param node the node name
+ * @return the xml format of empty tag
+ */
+ public static String xmlEmpty(String node) {
+ return String.format("<%s/>", node);
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalDeviceDescription.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalDeviceDescription.java
new file mode 100755
index 0000000..8897793
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalDeviceDescription.java
@@ -0,0 +1,98 @@
+/*
+ * 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.drivers.oplink;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.CHANNEL_SPACING;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.START_CENTER_FREQ;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.STOP_CENTER_FREQ;
+import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.drivers.oplink.OplinkNetconfUtility.*;
+
+/**
+ * Retrieves the ports from an Oplink optical netconf device.
+ */
+public class OplinkOpticalDeviceDescription extends AbstractHandlerBehaviour
+ implements DeviceDescriptionDiscovery {
+
+ private static final String KEY_PORTNAME = "port-name";
+ private static final String PORT_DIRECTION = "direction";
+ // log
+ private static final Logger log = getLogger(OplinkOpticalDeviceDescription.class);
+
+ @Override
+ public DeviceDescription discoverDeviceDetails() {
+ log.debug("No description to be added for device");
+ //TODO to be implemented if needed.
+ return null;
+ }
+
+ @Override
+ public List<PortDescription> discoverPortDetails() {
+ log.debug("Port description to be added for device {}", data().deviceId());
+ String reply = netconfGetConfig(handler(), getPortsFilter());
+ List<PortDescription> descriptions = parsePorts(reply);
+ return ImmutableList.copyOf(descriptions);
+ }
+
+ private String getPortsFilter() {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlEmpty(KEY_PORTS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private List<PortDescription> parsePorts(String content) {
+ HierarchicalConfiguration cfg = XmlConfigParser.loadXmlString(content);
+ List<PortDescription> portDescriptions = Lists.newArrayList();
+ List<HierarchicalConfiguration> subtrees = cfg.configurationsAt(KEY_DATA_PORTS);
+ for (HierarchicalConfiguration portConfig : subtrees) {
+ portDescriptions.add(parsePort(portConfig));
+ }
+ return portDescriptions;
+ }
+
+ private PortDescription parsePort(HierarchicalConfiguration cfg) {
+ PortNumber portNumber = PortNumber.portNumber(cfg.getLong(KEY_PORTID));
+ HierarchicalConfiguration portInfo = cfg.configurationAt(KEY_PORT);
+ DefaultAnnotations annotations = DefaultAnnotations.builder()
+ .set(AnnotationKeys.PORT_NAME, portInfo.getString(KEY_PORTNAME))
+ .set(PORT_DIRECTION, portInfo.getString(KEY_PORTDIRECT))
+ .build();
+ return omsPortDescription(portNumber,
+ true,
+ START_CENTER_FREQ,
+ STOP_CENTER_FREQ,
+ CHANNEL_SPACING.frequency(),
+ annotations);
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalFlowRuleProgrammable.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalFlowRuleProgrammable.java
new file mode 100644
index 0000000..01446f2
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalFlowRuleProgrammable.java
@@ -0,0 +1,147 @@
+/*
+ * 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.drivers.oplink;
+
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.onosproject.drivers.oplink.OplinkNetconfUtility.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Flow rule programmable behaviour for oplink optical netconf devices.
+ */
+public class OplinkOpticalFlowRuleProgrammable
+ extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
+
+ // key
+ public static final String KEY_CHID = "wavelength-id";
+ public static final String KEY_SRC = "source";
+ public static final String KEY_DST = "destination";
+ public static final String KEY_SRC_PORTID = String.format("%s.%s", KEY_SRC, KEY_PORTID);
+ public static final String KEY_SRC_CHID = String.format("%s.%s", KEY_SRC, KEY_CHID);
+ public static final String KEY_DST_PORTID = String.format("%s.%s", KEY_DST, KEY_PORTID);
+
+ // log
+ private static final Logger log = getLogger(OplinkOpticalFlowRuleProgrammable.class);
+
+ @Override
+ public Collection<FlowEntry> getFlowEntries() {
+ return parseConnections();
+ }
+
+ @Override
+ public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
+ return applyConnections(rules);
+ }
+
+ @Override
+ public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
+ return removeConnections(rules);
+ }
+
+ private String getConnectionsFilter() {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlEmpty(KEY_CONNS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private Collection<FlowEntry> parseConnections() {
+ log.debug("Fetch connections...");
+ String reply = netconfGetConfig(handler(), getConnectionsFilter());
+ HierarchicalConfiguration cfg = XmlConfigParser.loadXmlString(reply);
+ List<HierarchicalConfiguration> subtrees = cfg.configurationsAt(KEY_DATA_CONNS);
+ Collection<FlowEntry> list = new ArrayList<>();
+ for (HierarchicalConfiguration connection : subtrees) {
+ list.add(new DefaultFlowEntry(parseConnection(connection), FlowEntry.FlowEntryState.ADDED));
+ }
+ return list;
+ }
+
+ private FlowRule parseConnection(HierarchicalConfiguration cfg) {
+ return OplinkOpticalUtility.toFlowRule(this,
+ PortNumber.portNumber(cfg.getString(KEY_SRC_PORTID)),
+ PortNumber.portNumber(cfg.getString(KEY_DST_PORTID)),
+ cfg.getInt(KEY_SRC_CHID));
+
+ }
+
+ private Collection<FlowRule> applyConnections(Collection<FlowRule> rules) {
+ return rules.stream()
+ .filter(c -> applyConnection(c))
+ .collect(Collectors.toList());
+ }
+
+ private boolean applyConnection(FlowRule rule) {
+ log.debug("Applying connection {}", rule);
+ OplinkCrossConnect crossConnect = OplinkOpticalUtility.fromFlowRule(this, rule);
+ // Build xml
+ String connID = Integer.toString(crossConnect.getChannel());
+ String cfg = new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_CONNS))
+ .append(xml(KEY_CONNID, connID))
+ .append(xmlOpen(KEY_SRC))
+ .append(xml(KEY_PORTID, crossConnect.getInPort().name()))
+ .append(xml(KEY_CHID, connID))
+ .append(xmlClose(KEY_SRC))
+ .append(xmlOpen(KEY_DST))
+ .append(xml(KEY_PORTID, crossConnect.getOutPort().name()))
+ .append(xmlClose(KEY_DST))
+ .append(xml(KEY_CHATT, Integer.toString(crossConnect.getAttenuation())))
+ .append(xmlClose(KEY_CONNS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ return netconfEditConfig(handler(), CFG_MODE_MERGE, cfg);
+ }
+
+ private Collection<FlowRule> removeConnections(Collection<FlowRule> rules) {
+ return rules.stream()
+ .filter(c -> removeConnection(c))
+ .collect(Collectors.toList());
+ }
+
+ private boolean removeConnection(FlowRule rule) {
+ log.debug("Removing connection {}", rule);
+ OplinkCrossConnect crossConnect = OplinkOpticalUtility.fromFlowRule(this, rule);
+ // Build xml
+ String connID = Integer.toString(crossConnect.getChannel());
+ String cfg = new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_CONNS))
+ .append(xml(KEY_CONNID, connID))
+ .append(xmlOpen(KEY_SRC))
+ .append(xml(KEY_PORTID, crossConnect.getInPort().name()))
+ .append(xml(KEY_CHID, connID))
+ .append(xmlClose(KEY_SRC))
+ .append(xmlClose(KEY_CONNS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ return netconfEditConfig(handler(), CFG_MODE_REMOVE, cfg);
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalLambdaQuery.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalLambdaQuery.java
new file mode 100644
index 0000000..a28d04d
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalLambdaQuery.java
@@ -0,0 +1,54 @@
+/*
+ * 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.drivers.oplink;
+
+import org.onlab.util.GuavaCollectors;
+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.IntStream;
+
+import static org.onlab.util.Spectrum.CENTER_FREQUENCY;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.CHANNEL_SPACING;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.STOP_CENTER_FREQ;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.START_CENTER_FREQ;
+
+/**
+ * Lambda query implementation for Oplink netconf devices in C band.
+ *
+ * 96 lambdas with 50GHz width (fixed grid).
+ *
+ * Channel id: Nominal central frequency = 193100 GHz + spacingMultiplier * channelSpacing).
+ * Channel (-35 to 60): starting from 191350 GHz to 196100 GHz, Increment by 50GHz.
+ */
+public class OplinkOpticalLambdaQuery extends AbstractHandlerBehaviour implements LambdaQuery {
+
+ private static final int MIN_CHANNEL = (int) Math.round(
+ START_CENTER_FREQ.subtract(CENTER_FREQUENCY).asHz() / CHANNEL_SPACING.frequency().asHz());
+ private static final int MAX_CHANNEL = (int) Math.round(
+ STOP_CENTER_FREQ.subtract(CENTER_FREQUENCY).asHz() / CHANNEL_SPACING.frequency().asHz());
+
+ @Override
+ public Set<OchSignal> queryLambdas(PortNumber port) {
+ return IntStream.rangeClosed(MIN_CHANNEL, MAX_CHANNEL)
+ .mapToObj(x -> OchSignal.newDwdmSlot(CHANNEL_SPACING, x))
+ .collect(GuavaCollectors.toImmutableSet());
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalPowerConfig.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalPowerConfig.java
new file mode 100755
index 0000000..92847f9
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalPowerConfig.java
@@ -0,0 +1,262 @@
+/*
+ * 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.drivers.oplink;
+
+import com.google.common.collect.Range;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onosproject.driver.extensions.OplinkAttenuation;
+import org.onosproject.net.Direction;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.PowerConfig;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.slf4j.Logger;
+
+import java.util.Optional;
+
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.MAX_ATTENUATION;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.MIN_ATTENUATION;
+import static org.onosproject.drivers.oplink.OplinkOpticalUtility.POWER_MULTIPLIER;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.drivers.oplink.OplinkNetconfUtility.*;
+
+/**
+ * Get current or target port/channel power from an Oplink optical netconf device.
+ * Set target port power or channel attenuation to an optical netconf device.
+ */
+public class OplinkOpticalPowerConfig<T> extends AbstractHandlerBehaviour
+ implements PowerConfig<T> {
+
+ // key
+ public static final String KEY_CHNUM = "wavelength-number";
+ public static final String KEY_CHPWR = "wavelength-power";
+ public static final String KEY_CHSTATS = "wavelength-stats";
+ public static final String KEY_OCMSTATS = "ocm-stats";
+ public static final String KEY_PORTDIRECT_RX = "rx";
+ public static final String KEY_PORTDIRECT_TX = "tx";
+ public static final String KEY_PORTTARPWR = "port-target-power";
+ public static final String KEY_PORTCURPWR = "port-current-power";
+ public static final String KEY_PORTPROPERTY = "port-property";
+ public static final String KEY_PORTPWRCAPMINRX = "port-power-capability-min-rx";
+ public static final String KEY_PORTPWRCAPMAXRX = "port-power-capability-max-rx";
+ public static final String KEY_PORTPWRCAPMINTX = "port-power-capability-min-tx";
+ public static final String KEY_PORTPWRCAPMAXTX = "port-power-capability-max-tx";
+ public static final String KEY_PORTS_PORT = String.format("%s.%s", KEY_DATA_PORTS, KEY_PORT);
+ public static final String KEY_PORTS_PORT_PROPERTY = String.format("%s.%s", KEY_PORTS_PORT, KEY_PORTPROPERTY);
+ // log
+ private static final Logger log = getLogger(OplinkOpticalPowerConfig.class);
+
+
+ @Override
+ public Optional<Long> getTargetPower(PortNumber port, T component) {
+ return Optional.ofNullable(acquireTargetPower(port, component));
+ }
+
+ @Override
+ public void setTargetPower(PortNumber port, T component, long power) {
+ if (component instanceof OchSignal) {
+ setChannelTargetPower(port, (OchSignal) component, power);
+ } else {
+ setPortTargetPower(port, power);
+ }
+ }
+
+ @Override
+ public Optional<Long> currentPower(PortNumber port, T component) {
+ return Optional.ofNullable(acquireCurrentPower(port, component));
+ }
+
+ @Override
+ public Optional<Range<Long>> getTargetPowerRange(PortNumber port, T component) {
+ return Optional.ofNullable(getTxPowerRange(port, component));
+ }
+
+ @Override
+ public Optional<Range<Long>> getInputPowerRange(PortNumber port, T component) {
+ return Optional.ofNullable(getRxPowerRange(port, component));
+ }
+
+ private String getPortPowerFilter(PortNumber port, String selection) {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_PORTS))
+ .append(xml(KEY_PORTID, Long.toString(port.toLong())))
+ .append(xmlOpen(KEY_PORT))
+ .append(xmlEmpty(selection))
+ .append(xmlClose(KEY_PORT))
+ .append(xmlClose(KEY_PORTS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private String getChannelPowerFilter(PortNumber port, OchSignal channel) {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_PORTS))
+ .append(xml(KEY_PORTID, Long.toString(port.toLong())))
+ .append(xmlOpen(KEY_PORT))
+ .append(xmlOpen(KEY_OCMSTATS))
+ .append(xml(KEY_CHNUM, Integer.toString(channel.spacingMultiplier())))
+ .append(xmlEmpty(KEY_CHSTATS))
+ .append(xmlClose(KEY_OCMSTATS))
+ .append(xmlClose(KEY_PORT))
+ .append(xmlClose(KEY_PORTS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private String getChannelAttenuationFilter(PortNumber port, OchSignal channel) {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_CONNS))
+ .append(xml(KEY_CONNID, Integer.toString(channel.spacingMultiplier())))
+ .append(xmlEmpty(KEY_CHATT))
+ .append(xmlClose(KEY_CONNS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private String getPowerRangeFilter(PortNumber port, String direction) {
+ return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_PORTS))
+ .append(xml(KEY_PORTID, Long.toString(port.toLong())))
+ .append(xmlOpen(KEY_PORT))
+ .append(xml(KEY_PORTDIRECT, direction))
+ .append(xmlEmpty(KEY_PORTPROPERTY))
+ .append(xmlClose(KEY_PORT))
+ .append(xmlClose(KEY_PORTS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ }
+
+ private Long acquireTargetPower(PortNumber port, T component) {
+ if (component instanceof OchSignal) {
+ return acquireChannelAttenuation(port, (OchSignal) component);
+ }
+ log.debug("Get port{} target power...", port);
+ return acquirePortPower(port, KEY_PORTTARPWR);
+ }
+
+ private Long acquireCurrentPower(PortNumber port, T component) {
+ if (component instanceof OchSignal) {
+ return acquireChannelPower(port, (OchSignal) component);
+ }
+ log.debug("Get port{} current power...", port);
+ return acquirePortPower(port, KEY_PORTCURPWR);
+ }
+
+ private Long acquirePortPower(PortNumber port, String selection) {
+ String reply = netconfGetConfig(handler(), getPortPowerFilter(port, selection));
+ HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT);
+ if (info == null) {
+ return null;
+ }
+ return (long) (info.getDouble(selection) * POWER_MULTIPLIER);
+ }
+
+ private Long acquireChannelAttenuation(PortNumber port, OchSignal channel) {
+ log.debug("Get port{} channel{} attenuation...", port, channel.channelSpacing());
+ String reply = netconfGetConfig(handler(), getChannelAttenuationFilter(port, channel));
+ HierarchicalConfiguration info = configAt(reply, KEY_CONNS);
+ if (info == null) {
+ return null;
+ }
+ return (long) (info.getDouble(KEY_CHATT) * POWER_MULTIPLIER);
+ }
+
+ private Long acquireChannelPower(PortNumber port, OchSignal channel) {
+ log.debug("Get port{} channel{} power...", port, channel.channelSpacing());
+ String reply = netconfGetConfig(handler(), getChannelPowerFilter(port, channel));
+ HierarchicalConfiguration info = configAt(reply, KEY_DATA_CONNS);
+ if (info == null) {
+ return null;
+ }
+ return (long) (info.getDouble(KEY_CHPWR) * POWER_MULTIPLIER);
+ }
+
+ private boolean setPortTargetPower(PortNumber port, long power) {
+ log.debug("Set port{} target power...", port);
+ String cfg = new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
+ .append(xmlOpen(KEY_PORTS))
+ .append(xml(KEY_PORTID, Long.toString(port.toLong())))
+ .append(xmlOpen(KEY_PORT))
+ .append(xml(KEY_PORTTARPWR, Long.toString(power)))
+ .append(xmlClose(KEY_PORT))
+ .append(xmlClose(KEY_PORTS))
+ .append(xmlClose(KEY_OPENOPTICALDEV))
+ .toString();
+ return netconfEditConfig(handler(), CFG_MODE_MERGE, cfg);
+ }
+
+ private boolean setChannelTargetPower(PortNumber port, OchSignal channel, long power) {
+ log.debug("Set port{} channel{} attenuation.", port, channel.channelSpacing());
+ FlowRuleService service = handler().get(FlowRuleService.class);
+ Iterable<FlowEntry> entries = service.getFlowEntries(data().deviceId());
+ for (FlowEntry entry : entries) {
+ OplinkCrossConnect crossConnect = OplinkOpticalUtility.fromFlowRule(this, entry);
+ // The channel port might be input port or output port.
+ if ((port.equals(crossConnect.getInPort()) || port.equals(crossConnect.getOutPort())) &&
+ channel.spacingMultiplier() == crossConnect.getChannel()) {
+ log.debug("Flow is found, modify the flow with attenuation.");
+ // Modify attenuation in treatment
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(crossConnect.getOutPort())
+ .extension(new OplinkAttenuation((int) power), data().deviceId())
+ .build();
+ // Apply the new flow rule
+ service.applyFlowRules(DefaultFlowRule.builder()
+ .forDevice(data().deviceId())
+ .makePermanent()
+ .withSelector(entry.selector())
+ .withTreatment(treatment)
+ .withPriority(entry.priority())
+ .withCookie(entry.id().value())
+ .build());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Range<Long> getPowerRange(PortNumber port, String directionKey, String minKey, String maxKey) {
+ String reply = netconfGetConfig(handler(), getPowerRangeFilter(port, directionKey));
+ HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT_PROPERTY);
+ if (info == null) {
+ return null;
+ }
+ long minPower = (long) (info.getDouble(minKey) * POWER_MULTIPLIER);
+ long maxPower = (long) (info.getDouble(maxKey) * POWER_MULTIPLIER);
+ return Range.closed(minPower, maxPower);
+ }
+
+ private Range<Long> getTxPowerRange(PortNumber port, T component) {
+ if (component instanceof Direction) {
+ log.debug("Get target port{} power range...", port);
+ return getPowerRange(port, KEY_PORTDIRECT_TX, KEY_PORTPWRCAPMINTX, KEY_PORTPWRCAPMAXTX);
+ } else {
+ log.debug("Get channel attenuation range...");
+ return Range.closed(MIN_ATTENUATION, MAX_ATTENUATION);
+ }
+ }
+
+ private Range<Long> getRxPowerRange(PortNumber port, T component) {
+ log.debug("Get input port{} power range...", port);
+ return getPowerRange(port, KEY_PORTDIRECT_RX, KEY_PORTPWRCAPMINRX, KEY_PORTPWRCAPMAXRX);
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalUtility.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalUtility.java
new file mode 100644
index 0000000..9785224
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/OplinkOpticalUtility.java
@@ -0,0 +1,182 @@
+/*
+ * 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.drivers.oplink;
+
+import org.onlab.util.Frequency;
+import org.onosproject.core.CoreService;
+import org.onosproject.driver.extensions.OplinkAttenuation;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Oplink optical utilities.
+ */
+public final class OplinkOpticalUtility {
+
+ // Lambda information supported by device.
+ public static final GridType GRID_TYPE = GridType.DWDM;
+ public static final int SLOT_GRANULARITY = 4;
+ // Channel spacing is 50GHz, 12.5GHz * 4
+ public static final ChannelSpacing CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
+ // Start frequency supported by device.
+ public static final Frequency START_CENTER_FREQ = Frequency.ofGHz(191_350);
+ // Stop frequency supported by device.
+ public static final Frequency STOP_CENTER_FREQ = Frequency.ofGHz(196_100);
+
+ // Power multiply factor, the power accuracy supported by device is 0.01dBm.
+ // Transforms the double typed number to long typed power for ONOS.
+ public static final int POWER_MULTIPLIER = 100;
+ // Attenuation range supported by device, [0, 25dB].
+ public static final long MIN_ATTENUATION = 0L;
+ public static final long MAX_ATTENUATION = 2500L;
+
+ // Default attenuation value if the attenuation instruction is not found.
+ private static final int DEFAULT_ATT = 0;
+ // Default flow priority for an extra flow.
+ private static final int DEFAULT_PRIORITY = 88;
+ // Default application name.
+ private static final String DEFAULT_APP = "org.onosproject.drivers.oplink";
+
+ private OplinkOpticalUtility() {
+ }
+
+ /**
+ * Transforms a flow FlowRule object to an OplinkCrossConnect object.
+ * @param behaviour the parent driver handler
+ * @param rule FlowRule object
+ * @return cross connect object
+ */
+ public static OplinkCrossConnect fromFlowRule(HandlerBehaviour behaviour, FlowRule rule) {
+ // TrafficSelector
+ Set<Criterion> criterions = rule.selector().criteria();
+ int channel = criterions.stream()
+ .filter(c -> c instanceof OchSignalCriterion)
+ .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier())
+ .findAny()
+ .orElse(null);
+ PortNumber inPort = criterions.stream()
+ .filter(c -> c instanceof PortCriterion)
+ .map(c -> ((PortCriterion) c).port())
+ .findAny()
+ .orElse(null);
+ // TrafficTreatment
+ List<Instruction> instructions = rule.treatment().immediate();
+ PortNumber outPort = instructions.stream()
+ .filter(c -> c instanceof Instructions.OutputInstruction)
+ .map(c -> ((Instructions.OutputInstruction) c).port())
+ .findAny()
+ .orElse(null);
+ int attenuation = instructions.stream()
+ .filter(c -> c instanceof Instructions.ExtensionInstructionWrapper)
+ .map(c -> ((Instructions.ExtensionInstructionWrapper) c).extensionInstruction())
+ .filter(c -> c instanceof OplinkAttenuation)
+ .map(c -> ((OplinkAttenuation) c).getAttenuation())
+ .findAny()
+ .orElse(DEFAULT_ATT);
+ return new OplinkCrossConnect(inPort, outPort, channel, attenuation);
+ }
+
+ /**
+ * Finds the FlowRule from flow rule store by the given cross connect information.
+ * Returns an extra flow to remove the flow by ONOS if not found.
+ * @param behaviour the parent driver handler
+ * @param cfg cross connect information
+ * @return the flow rule
+ */
+ public static FlowRule toFlowRule(HandlerBehaviour behaviour, OplinkCrossConnect cfg) {
+ return toFlowRule(behaviour, cfg.getInPort(), cfg.getOutPort(), cfg.getChannel());
+ }
+
+ /**
+ * Finds the FlowRule from flow rule store by the given ports and channel.
+ * Returns an extra flow to remove the flow by ONOS if not found.
+ * @param behaviour the parent driver handler
+ * @param inPort the input port
+ * @param outPort the output port
+ * @param channel the specified channel
+ * @return the flow rule
+ */
+ public static FlowRule toFlowRule(HandlerBehaviour behaviour, PortNumber inPort,
+ PortNumber outPort, Integer channel) {
+ FlowRuleService service = behaviour.handler().get(FlowRuleService.class);
+ Iterable<FlowEntry> entries = service.getFlowEntries(behaviour.data().deviceId());
+ // Try to Find the flow from flow rule store.
+ for (FlowEntry entry : entries) {
+ Set<Criterion> criterions = entry.selector().criteria();
+ // input port
+ PortNumber ip = criterions.stream()
+ .filter(c -> c instanceof PortCriterion)
+ .map(c -> ((PortCriterion) c).port())
+ .findAny()
+ .orElse(null);
+ // channel
+ Integer ch = criterions.stream()
+ .filter(c -> c instanceof OchSignalCriterion)
+ .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier())
+ .findAny()
+ .orElse(null);
+ // output port
+ PortNumber op = entry.treatment().immediate().stream()
+ .filter(c -> c instanceof Instructions.OutputInstruction)
+ .map(c -> ((Instructions.OutputInstruction) c).port())
+ .findAny()
+ .orElse(null);
+ if (inPort.equals(ip) && channel.equals(ch) && outPort.equals(op)) {
+ // Find the flow.
+ return entry;
+ }
+ }
+ // Cannot find the flow from store. So report an extra flow to remove the flow by ONOS.
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(inPort)
+ .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
+ .add(Criteria.matchLambda(Lambda.ochSignal(GRID_TYPE, CHANNEL_SPACING, channel, SLOT_GRANULARITY)))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(outPort)
+ .build();
+ return DefaultFlowRule.builder()
+ .forDevice(behaviour.data().deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(behaviour.handler().get(CoreService.class).getAppId(DEFAULT_APP))
+ .build();
+
+ }
+}
diff --git a/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/package-info.java b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/package-info.java
new file mode 100755
index 0000000..b22120a
--- /dev/null
+++ b/drivers/oplink/src/main/java/org/onosproject/drivers/oplink/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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 for oplink device drivers.
+ */
+package org.onosproject.drivers.oplink;
diff --git a/drivers/oplink/src/main/resources/oplink-drivers.xml b/drivers/oplink/src/main/resources/oplink-drivers.xml
new file mode 100755
index 0000000..5baf905
--- /dev/null
+++ b/drivers/oplink/src/main/resources/oplink-drivers.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<drivers>
+ <driver name="oplink-netconf" manufacturer="Oplink a Molex company" hwVersion="x86-1.0" swVersion="sdn-1.0">
+ <behaviour api="org.onosproject.net.optical.OpticalDevice"
+ impl="org.onosproject.net.optical.DefaultOpticalDevice"/>
+ <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+ impl="org.onosproject.drivers.oplink.OplinkOpticalDeviceDescription"/>
+ <behaviour api="org.onosproject.net.behaviour.PowerConfig"
+ impl="org.onosproject.drivers.oplink.OplinkOpticalPowerConfig"/>
+ <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
+ impl="org.onosproject.drivers.oplink.OplinkOpticalFlowRuleProgrammable"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.drivers.oplink.OplinkOpticalLambdaQuery"/>
+ </driver>
+</drivers>
diff --git a/drivers/pom.xml b/drivers/pom.xml
index 72f90d1..dadca4c 100644
--- a/drivers/pom.xml
+++ b/drivers/pom.xml
@@ -49,6 +49,7 @@
<module>lisp</module>
<module>flowspec</module>
<module>microsemi</module>
+ <module>oplink</module>
</modules>
<!--<properties>
diff --git a/modules.defs b/modules.defs
index 90c2178..71f70c0 100644
--- a/modules.defs
+++ b/modules.defs
@@ -98,6 +98,7 @@
'//drivers/huawei:onos-drivers-huawei-oar',
# Removed until we can handle v1.12 of onos-yang-tools - in the mean time build manually with Maven
# '//drivers/microsemi/ea1000driver:onos-drivers-microsemi-ea1000driver-oar',
+ '//drivers/oplink:onos-drivers-oplink-oar',
]
ONOS_PROVIDERS = [