Discover LINC-OE switch and ports.
diff --git a/core/api/src/main/java/org/onlab/onos/net/Device.java b/core/api/src/main/java/org/onlab/onos/net/Device.java
index 9e6018e..4e3478f 100644
--- a/core/api/src/main/java/org/onlab/onos/net/Device.java
+++ b/core/api/src/main/java/org/onlab/onos/net/Device.java
@@ -9,7 +9,7 @@
      * Coarse classification of the type of the infrastructure device.
      */
     public enum Type {
-        SWITCH, ROUTER, FIREWALL, BALANCER, IPS, IDS, CONTROLLER, OTHER
+        SWITCH, ROUTER, ROADM, FIREWALL, BALANCER, IPS, IDS, CONTROLLER, OTHER
     }
 
     /**
diff --git a/openflow/api/pom.xml b/openflow/api/pom.xml
index 4e91328..59d05a2 100644
--- a/openflow/api/pom.xml
+++ b/openflow/api/pom.xml
@@ -30,7 +30,7 @@
             <groupId>org.projectfloodlight</groupId>
             <artifactId>openflowj</artifactId>
             <!-- FIXME once experimenter gets merged to upstream -->
-            <version>0.3.8-optical_experimenter2</version>
+            <version>0.3.8-optical_experimenter3</version>
         </dependency>
         <dependency>
             <groupId>io.netty</groupId>
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
index 24e119c..6fd02bc 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
@@ -112,4 +112,13 @@
      */
     void returnRoleAssertFailure(RoleState role);
 
+
+    /**
+     * Indicates if this switch is optical.
+     *
+     * @return true if optical
+     */
+    public boolean isOptical();
+
+
 }
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 4334395..00bbaca 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -374,4 +374,9 @@
         return this.desc.getSerialNum();
     }
 
+    @Override
+    public boolean isOptical() {
+        return false;
+    }
+
 }
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
index 1a48183..5ee4039 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
@@ -399,12 +399,12 @@
                 h.sw.setPortDescReply(h.portDescReply);
                 h.sw.setConnected(true);
                 h.sw.setChannel(h.channel);
-                boolean success = h.sw.connectSwitch();
-
-                if (!success) {
-                    disconnectDuplicate(h);
-                    return;
-                }
+//                boolean success = h.sw.connectSwitch();
+//
+//                if (!success) {
+//                    disconnectDuplicate(h);
+//                    return;
+//                }
                 // set switch information
 
 
@@ -462,6 +462,8 @@
                     throws IOException, SwitchStateException {
                 if (m.getType() == OFType.ECHO_REQUEST) {
                     processOFEchoRequest(h, (OFEchoRequest) m);
+                } else if (m.getType() == OFType.ECHO_REPLY) {
+                    processOFEchoReply(h, (OFEchoReply) m);
                 } else if (m.getType() == OFType.ROLE_REPLY) {
                     h.sw.handleRole(m);
                 } else if (m.getType() == OFType.ERROR) {
@@ -479,6 +481,12 @@
                     } else {
                         h.sw.processDriverHandshakeMessage(m);
                         if (h.sw.isDriverHandshakeComplete()) {
+                            boolean success = h.sw.connectSwitch();
+
+                            if (!success) {
+                                disconnectDuplicate(h);
+                                return;
+                            }
                             h.setState(ACTIVE);
                         }
                     }
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
index 640cea8..1332729 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
@@ -59,7 +59,7 @@
 
         String sw = desc.getSwDesc();
         if (sw.startsWith("LINC-OE")) {
-            log.debug("Optical Emulator LINC-OE with DPID:{} found..", dpid);
+            log.warn("Optical Emulator LINC-OE with DPID:{} found..", dpid);
             return new OFOpticalSwitchImplLINC13(dpid, desc);
         }
 
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFOpticalSwitchImplLINC13.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFOpticalSwitchImplLINC13.java
index 79a162e..d65a15f 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFOpticalSwitchImplLINC13.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/OFOpticalSwitchImplLINC13.java
@@ -6,6 +6,7 @@
 import org.onlab.onos.openflow.controller.Dpid;
 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
+import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
 import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
 import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
@@ -14,7 +15,10 @@
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFOxmList;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFPortOptical;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
@@ -43,12 +47,13 @@
     private final AtomicBoolean driverHandshakeComplete;
     private long barrierXidToWaitFor = -1;
 
+    private OFPortDescStatsReply wPorts;
+
     private final Logger log =
             LoggerFactory.getLogger(OFOpticalSwitchImplLINC13.class);
 
     OFOpticalSwitchImplLINC13(Dpid dpid, OFDescStatsReply desc) {
         super(dpid);
-        //setAttribute("optical", "true");
         driverHandshakeComplete = new AtomicBoolean(false);
         setSwitchDescription(desc);
     }
@@ -62,7 +67,7 @@
 
     @Override
     public void startDriverHandshake() {
-        log.debug("Starting driver handshake for sw {}", getStringId());
+        log.warn("Starting driver handshake for sw {}", getStringId());
         if (startDriverHandshakeCalled) {
             throw new SwitchDriverSubHandshakeAlreadyStarted();
         }
@@ -70,6 +75,8 @@
         try {
             sendHandshakeOFExperimenterPortDescRequest();
         } catch (IOException e) {
+            log.error("LINC-OE exception while sending experimenter port desc:",
+                     e.getMessage());
             e.printStackTrace();
         }
     }
@@ -84,7 +91,7 @@
 
     @Override
     public void processDriverHandshakeMessage(OFMessage m) {
-        if (!startDriverHandshakeCalled) {
+         if (!startDriverHandshakeCalled) {
             throw new SwitchDriverSubHandshakeNotStarted();
         }
         if (driverHandshakeComplete.get()) {
@@ -109,38 +116,49 @@
             case PACKET_IN:
                 break;
             case PORT_STATUS:
+                log.warn("****LINC-OE Port Status {} {}", getStringId(), m);
+                processOFPortStatus((OFCircuitPortStatus) m);
                 break;
             case QUEUE_GET_CONFIG_REPLY:
                 break;
             case ROLE_REPLY:
                 break;
             case STATS_REPLY:
-                log.debug("LINC-OE : Received stats reply message {}", m);
-                processHandshakeOFExperimenterPortDescRequest(
-                        (OFCircuitPortsReply) m);
-                driverHandshakeComplete.set(true);
-                try {
+                OFStatsReply stats = (OFStatsReply) m;
+                if (stats.getStatsType() == OFStatsType.EXPERIMENTER) {
+                    log.warn("LINC-OE : Received stats reply message {}", m);
+                    processHandshakeOFExperimenterPortDescRequest(
+                            (OFCircuitPortsReply) m);
+                    driverHandshakeComplete.set(true);
+                }
+                /*try {
                     testMA();
                     testReverseMA();
                 } catch (IOException e) {
                     e.printStackTrace();
-                }
+                }*/
                 break;
             default:
-                log.debug("Received message {} during switch-driver " +
-                                  "subhandshake " + "from switch {} ... " +
-                                  "Ignoring message", m,
-                          getStringId());
+                log.warn("Received message {} during switch-driver " +
+                                 "subhandshake " + "from switch {} ... " +
+                                 "Ignoring message", m,
+                         getStringId());
 
         }
     }
 
+    //Todo
+    public void processOFPortStatus(OFCircuitPortStatus ps) {
+        log.debug("LINC-OE ..OF Port Status :", ps);
+
+    }
 
     private void processHandshakeOFExperimenterPortDescRequest(
             OFCircuitPortsReply sr) {
         Collection<OFPortOptical> entries = sr.getEntries();
         List<OFPortDesc> ofPortDescList = new ArrayList<>(entries.size());
         for (OFPortOptical entry : entries) {
+            log.warn("LINC:OE port message {}", entry.toString());
             ofPortDescList.add(factory().buildPortDesc().
                     setPortNo(entry.getPortNo())
                                            .setConfig(entry.getConfig())
@@ -148,11 +166,16 @@
                                            .setHwAddr(entry.getHwAddr())
                                            .setName(entry.getName())
                                            .build());
+
         }
-        setPortDescReply(factory().buildPortDescStatsReply().
+        setExperimenterPortDescReply(factory().buildPortDescStatsReply().
                 setEntries(ofPortDescList).build());
     }
 
+    private void setExperimenterPortDescReply(OFPortDescStatsReply reply) {
+        wPorts = reply;
+    }
+
 
     private void sendHandshakeOFExperimenterPortDescRequest() throws
             IOException {
@@ -160,11 +183,22 @@
         OFCircuitPortsRequest circuitPortsRequest = factory()
                 .buildCircuitPortsRequest().setXid(getNextTransactionId())
                 .build();
-        log.debug("LINC-OE : Sending experimented circuit port stats " +
-                          "message " +
-                          "{}",
-                  circuitPortsRequest.toString());
-        sendMsg(Collections.<OFMessage>singletonList(circuitPortsRequest));
+        log.warn("LINC-OE : Sending experimented circuit port stats " +
+                         "message " +
+                         "{}",
+                 circuitPortsRequest.toString());
+        this.write(Collections.<OFMessage>singletonList(circuitPortsRequest));
+    }
+
+
+    @Override
+    public List<OFPortDesc> getPorts() {
+        List<OFPortDesc> portEntries = new ArrayList<>();
+        portEntries.addAll(ports.getEntries());
+        if (wPorts != null) {
+            portEntries.addAll(wPorts.getEntries());
+        }
+        return Collections.unmodifiableList(portEntries);
     }
 
 
@@ -533,7 +567,7 @@
 
     @Override
     public void write(OFMessage msg) {
-        this.sendMsg(msg);
+        this.channel.write(Collections.singletonList(msg));
     }
 
     @Override
@@ -546,4 +580,10 @@
         return false;
     }
 
+    @Override
+    public boolean isOptical() {
+        return true;
+    }
+
+
 }
diff --git a/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java b/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
index 285635a..09fa546 100644
--- a/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
+++ b/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
@@ -165,6 +165,11 @@
         }
 
         @Override
+        public boolean isOptical() {
+            return false;
+        }
+
+        @Override
         public void setAgent(OpenFlowAgent agent) {
         }
 
diff --git a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
index 8958fb6..8dbff56 100644
--- a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -118,8 +118,10 @@
             DeviceId did = deviceId(uri(dpid));
             OpenFlowSwitch sw = controller.getSwitch(dpid);
 
+            Device.Type deviceType = sw.isOptical() ? Device.Type.ROADM :
+                    Device.Type.SWITCH;
             DeviceDescription description =
-                    new DefaultDeviceDescription(did.uri(), Device.Type.SWITCH,
+                    new DefaultDeviceDescription(did.uri(), deviceType,
                                                  sw.manfacturerDescription(),
                                                  sw.hardwareDescription(),
                                                  sw.softwareDescription(),
diff --git a/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java b/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
index 8196cb8..f0e1c73 100644
--- a/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
+++ b/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
@@ -360,6 +360,11 @@
         public void returnRoleAssertFailure(RoleState role) {
         }
 
+        @Override
+        public boolean isOptical() {
+            return false;
+        }
+
     }
 
 }
diff --git a/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
index 7fca158..a6c6930 100644
--- a/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
+++ b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
@@ -467,5 +467,10 @@
         public void returnRoleAssertFailure(RoleState role) {
         }
 
+        @Override
+        public boolean isOptical() {
+            return false;
+        }
+
     }
 }
diff --git a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
index 37971e3..43c1051 100644
--- a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
+++ b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
@@ -398,6 +398,11 @@
         public void returnRoleAssertFailure(RoleState role) {
         }
 
+        @Override
+        public boolean isOptical() {
+            return false;
+        }
+
     }
 
 }