Add driver for oplink netconf device.
Change-Id: I3c8a2e5ba3f79df48a2212b25664821891b6d2ae
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();
+
+ }
+}