Modified CienaWaverServer driver to change frequency rather then
channels when installing flows. Channels are not consistent amongst
the devices in a sense that different devices are using different
frequency schemes to represent channels.

Change-Id: Idb12ccd0c4dbdb89e61160b455b959b4c36034cb
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java
index d0e78fc..5e05232 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java
@@ -30,6 +30,7 @@
 import java.util.List;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 import static org.slf4j.LoggerFactory.getLogger;
@@ -62,8 +63,8 @@
         }
         // Apply the valid rules on the device
         Collection<FlowRule> added = rules.stream()
-                .map(r -> createCrossConnectFlowRule(r))
-                .filter(xc -> installCrossConnect(xc))
+                .map(this::createCrossConnectFlowRule)
+                .filter(this::installCrossConnect)
                 .collect(Collectors.toList());
         restCiena.setCrossConnectCache(added);
         return added;
@@ -79,8 +80,8 @@
             return Collections.emptyList();
         }
         Collection<FlowRule> removed = rules.stream()
-                .map(r -> createCrossConnectFlowRule(r))
-                .filter(xc -> xc != null)
+                .map(this::createCrossConnectFlowRule)
+                .filter(Objects::nonNull)
                 .collect(Collectors.toList());
         restCiena.removeCrossConnectCache(removed);
         return removed;
@@ -88,7 +89,7 @@
 
     private CrossConnectFlowRule createCrossConnectFlowRule(FlowRule r) {
         List<PortNumber> linePorts = CienaRestDevice.getLinesidePortId().stream()
-                .map(p -> PortNumber.portNumber(p))
+                .map(PortNumber::portNumber)
                 .collect(Collectors.toList());
         try {
             return new CrossConnectFlowRule(r, linePorts);
@@ -129,7 +130,7 @@
         /*
          * rule is installed in three steps
          * 1- disable port
-         * 2- change channel
+         * 2- change frequency
          * 3- enable port
          */
         try {
@@ -143,8 +144,8 @@
         if (!restCiena.disablePort(outPort)) {
             return false;
         }
-        //2- change channel
-        if (!restCiena.changeChannel(signal, outPort)) {
+        //2- change frequency
+        if (!restCiena.changeFrequency(signal, outPort)) {
             return false;
         }
         //3- enable port
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
index 0fce654..361d538 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
@@ -67,7 +67,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 public class CienaRestDevice {
-    private static final Frequency BASE_FREQUENCY = Frequency.ofGHz(193_950);
+    private static final Frequency CENTER_FREQUENCY = Frequency.ofGHz(195_950);
     private static final String ENABLED = "enabled";
     private static final String DISABLED = "disabled";
     private static final String VALUE = "value";
@@ -101,6 +101,7 @@
     private static final String CHANNEL_URI = TRANSMITTER_URI + "/" + LINE_SYSTEM_CHANNEL_NUMBER;
     private static final String ACTIVE_ALARMS_URL = ALARM_KEY + "/" + ACTIVE;
     private static final List<String> LINESIDE_PORT_ID = ImmutableList.of("4", "48");
+    private static final ChannelSpacing CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
 
     private final Logger log = getLogger(getClass());
 
@@ -166,10 +167,10 @@
 
     }
 
-    private String genFrequencyChangeRequest(long frequency) {
+    private String genFrequencyChangeRequest(double frequency) {
         String request = "{\n" +
                 "\"" + FREQUENCY_KEY + "\": {\n" +
-                "\"" + VALUE + "\": " + Long.toString(frequency) + "\n" +
+                "\"" + VALUE + "\": " + Double.toString(frequency) + "\n" +
                 "}\n" +
                 "}";
         log.debug("request:\n{}", request);
@@ -249,7 +250,7 @@
 
     public final boolean changeFrequency(OchSignal signal, PortNumber outPort) {
         String uri = genUri(FREQUENCY_URI, outPort);
-        long frequency = toFrequency(signal);
+        double frequency = signal.centralFrequency().asGHz();
         String request = genFrequencyChangeRequest(frequency);
         boolean response = putNoReply(uri, request);
         if (!response) {
@@ -271,13 +272,7 @@
         return response;
     }
 
-    private final long toFrequency(OchSignal signal) {
-        double frequency = BASE_FREQUENCY.asGHz() +
-                (signal.channelSpacing().frequency().asGHz() * (double) signal.slotGranularity());
-        return Double.valueOf(frequency).longValue();
-    }
-
-    private final int getChannel(PortNumber port) {
+    private int getChannel(PortNumber port) {
         try {
             String uri = genUri(CHANNEL_URI, port);
             JsonNode response = get(uri);
@@ -290,6 +285,25 @@
 
     }
 
+    private int getChannelFromFrequency(Frequency frequency) {
+        return (int) CENTER_FREQUENCY.subtract(frequency)
+                .floorDivision(CHANNEL_SPACING.frequency().asHz()).asHz();
+
+    }
+
+    private Frequency getFrequency(PortNumber port) {
+        try {
+            String uri = genUri(FREQUENCY_URI, port);
+            JsonNode response = get(uri);
+            return Frequency.ofGHz(response.get(FREQUENCY_KEY).get(VALUE).asDouble());
+        } catch (IOException e) {
+            // this is expected for client side ports as they don't contain channel data
+            log.error("unable to get frequency for port {} on device {}:\n{}", port, deviceId, e);
+            return null;
+        }
+
+    }
+
     private AlarmEntityId getAlarmSource(String instance) {
         AlarmEntityId source;
         if (instance.contains(PORT)) {
@@ -346,8 +360,8 @@
         try {
             List<JsonNode> alarms = Lists.newArrayList(get(ACTIVE_ALARMS_URL).get(ACTIVE).elements());
             return alarms.stream()
-                    .map(a -> newAlarmFromJsonNode(a))
-                    .filter(a -> a != null)
+                    .map(this::newAlarmFromJsonNode)
+                    .filter(Objects::nonNull)
                     .collect(Collectors.toList());
         } catch (IOException e) {
             log.error("unable to get active alarms for device {}:\n", deviceId, e);
@@ -362,17 +376,17 @@
         return ports.stream()
                 .filter(p -> LINESIDE_PORT_ID.contains(p.number().name()))
                 .map(p -> fetchRule(p.number()))
-                .filter(p -> p != null)
+                .filter(Objects::nonNull)
                 .map(fr -> new DefaultFlowEntry(fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
                 .collect(Collectors.toList());
     }
 
     private FlowRule fetchRule(PortNumber port) {
-        int channel = getChannel(port);
-        if (channel == -1) {
+        Frequency frequency = getFrequency(port);
+        if (frequency == null) {
             return null;
         }
-
+        int channel = getChannelFromFrequency(frequency);
         /*
          * both inPort and outPort will be same as WaveServer only deal with same port ptp-indexes
          * channel and spaceMultiplier are same.
@@ -382,7 +396,7 @@
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchInPort(port)
                 .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
-                .add(Criteria.matchLambda(OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, channel)))
+                .add(Criteria.matchLambda(OchSignal.newDwdmSlot(CHANNEL_SPACING, channel)))
                 .build();
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                 .setOutput(port)
@@ -394,7 +408,7 @@
             return null;
         }
 
-        FlowRule fr = DefaultFlowRule.builder()
+        return DefaultFlowRule.builder()
                 .forDevice(deviceId)
                 .makePermanent()
                 .withSelector(selector)
@@ -402,8 +416,6 @@
                 .withPriority(lookup.getRight())
                 .withCookie(lookup.getLeft().value())
                 .build();
-
-        return fr;
     }
 
     public List<Alarm> getAlarms() {