Driver and flow stats handling for Calient fiber switch S160.
Bump loxigen to 0.4.1.onos-SNAPSHOT.

Change-Id: Ieb8aa4fe716e12f89b83770eff617561f30cdd08
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
index 49ca5a8..1b6810b 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.openflow.controller;
 
+import org.onosproject.net.Device;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
@@ -136,11 +137,11 @@
     void returnRoleReply(RoleState requested, RoleState response);
 
     /**
-     * Indicates if this switch is optical.
+     * Returns the switch device type.
      *
-     * @return true if optical
+     * @return device type
      */
-    boolean isOptical();
+    Device.Type deviceType();
 
     /**
      * Identifies the channel used to communicate with the switch.
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 8ac1e22..2f6357b 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -18,6 +18,7 @@
 
 import org.jboss.netty.channel.Channel;
 import org.onlab.packet.IpAddress;
+import org.onosproject.net.Device;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.openflow.controller.Dpid;
 import org.onosproject.openflow.controller.RoleState;
@@ -95,7 +96,7 @@
     }
 
     @Override
-    public final void sendMsg(OFMessage m) {
+    public void sendMsg(OFMessage m) {
         if (role == RoleState.MASTER && channel.isConnected()) {
             channel.write(Collections.singletonList(m));
         }
@@ -413,8 +414,8 @@
 
 
     @Override
-    public boolean isOptical() {
-        return false;
+    public Device.Type deviceType() {
+        return Device.Type.SWITCH;
     }
 
 
diff --git a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
index 416abd3..4ef4d81 100644
--- a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -38,6 +38,8 @@
 import org.onosproject.openflow.controller.RoleState;
 import org.onosproject.openflow.controller.driver.OpenFlowAgent;
 import org.osgi.service.component.ComponentContext;
+import org.projectfloodlight.openflow.protocol.OFCalientFlowStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFCalientFlowStatsReply;
 import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
 import org.projectfloodlight.openflow.protocol.OFExperimenter;
 import org.projectfloodlight.openflow.protocol.OFFactories;
@@ -55,12 +57,17 @@
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.OFStatsReply;
 import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -290,7 +297,7 @@
                             (OFGroupDescStatsReply) reply);
                     if (groupDescStats != null) {
                         OFGroupDescStatsReply.Builder rep =
-                            OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
+                                OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
                         rep.setEntries(Lists.newLinkedList(groupDescStats));
                         rep.setXid(reply.getXid());
                         executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
@@ -299,16 +306,63 @@
                 case PORT:
                     executorMsgs.submit(new OFMessageHandler(dpid, reply));
                     break;
+                case EXPERIMENTER:
+                    if (reply instanceof OFCalientFlowStatsReply) {
+                        // Convert Calient flow statistics to regular flow stats
+                        // TODO: parse remaining fields such as power levels etc. when we have proper monitoring API
+                        OFFlowStatsReply.Builder fsr = getSwitch(dpid).factory().buildFlowStatsReply();
+                        List<OFFlowStatsEntry> entries = new LinkedList<>();
+                        for (OFCalientFlowStatsEntry entry : ((OFCalientFlowStatsReply) msg).getEntries()) {
+
+                            // Single instruction, i.e., output to port
+                            OFActionOutput action = OFFactories
+                                    .getFactory(msg.getVersion())
+                                    .actions()
+                                    .buildOutput()
+                                    .setPort(entry.getOutPort())
+                                    .build();
+                            OFInstruction instruction = OFFactories
+                                    .getFactory(msg.getVersion())
+                                    .instructions()
+                                    .applyActions(Collections.singletonList(action));
+                            OFFlowStatsEntry fs = getSwitch(dpid).factory().buildFlowStatsEntry()
+                                    .setMatch(entry.getMatch())
+                                    .setTableId(entry.getTableId())
+                                    .setDurationSec(entry.getDurationSec())
+                                    .setDurationNsec(entry.getDurationNsec())
+                                    .setPriority(entry.getPriority())
+                                    .setIdleTimeout(entry.getIdleTimeout())
+                                    .setHardTimeout(entry.getHardTimeout())
+                                    .setFlags(entry.getFlags())
+                                    .setCookie(entry.getCookie())
+                                    .setInstructions(Collections.singletonList(instruction))
+                                    .build();
+                            entries.add(fs);
+                        }
+                        fsr.setEntries(entries);
+
+                        flowStats = publishFlowStats(dpid, fsr.build());
+                        if (flowStats != null) {
+                            OFFlowStatsReply.Builder rep =
+                                    OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply();
+                            rep.setEntries(Lists.newLinkedList(flowStats));
+                            executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
+                        }
+                    } else {
+                        log.warn("Unsupported stats type : {}", reply.getStatsType());
+                    }
+                    break;
                 default:
-                    log.warn("Unsupported stats type : {}", reply.getStatsType());
+                    break;
             }
             break;
         case BARRIER_REPLY:
             executorBarrier.submit(new OFMessageHandler(dpid, msg));
             break;
         case EXPERIMENTER:
-            // Handle optical port stats
-            if (((OFExperimenter) msg).getExperimenter() == 0x748771) {
+            long experimenter = ((OFExperimenter) msg).getExperimenter();
+            if (experimenter == 0x748771) {
+                // LINC-OE port stats
                 OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg;
                 OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus();
                 OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc();
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
index ad10783..0a71a40 100644
--- a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
@@ -19,6 +19,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onosproject.net.Device;
 import org.onosproject.net.driver.DriverData;
 import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.openflow.controller.Dpid;
@@ -181,8 +182,8 @@
         }
 
         @Override
-        public boolean isOptical() {
-            return false;
+        public Device.Type deviceType() {
+            return Device.Type.SWITCH;
         }
 
         @Override