Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/DefaultPacketContext.java b/of/api/src/main/java/org/onlab/onos/of/controller/DefaultPacketContext.java
index 7ad2fec..8d3d91e 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/DefaultPacketContext.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/DefaultPacketContext.java
@@ -80,4 +80,9 @@
         return pktin.getInPort().getPortNumber();
     }
 
+    @Override
+    public byte[] unparsed() {
+        return pktin.getData().clone();
+    }
+
 }
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java b/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java
index c4f785e..536dd7f 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java
@@ -44,6 +44,12 @@
     public Ethernet parsed();
 
     /**
+     * Provide an unparsed copy of the data.
+     * @return the unparsed form of the payload.
+     */
+    public byte[] unparsed();
+
+    /**
      * Provide the dpid of the switch where the packet in arrived.
      * @return the dpid of the switch.
      */
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/OpenFlowControllerImpl.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/OpenFlowControllerImpl.java
index 2a27ba9..b0a6305 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/OpenFlowControllerImpl.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/OpenFlowControllerImpl.java
@@ -41,247 +41,244 @@
             new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
 
     protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
-    protected Set<OpenFlowSwitchListener> ofEventListener =
-            new HashSet<>();
+    protected Set<OpenFlowSwitchListener> ofEventListener = new HashSet<>();
 
-            protected List<PacketListener> ofPacketListener =
-                    new ArrayList<>();
+    protected List<PacketListener> ofPacketListener = new ArrayList<>();
 
-                    private final Controller ctrl = new Controller();
+    private final Controller ctrl = new Controller();
 
-                    @Activate
-                    public void activate() {
-                        ctrl.start(agent);
+    @Activate
+    public void activate() {
+        ctrl.start(agent);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        ctrl.stop();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getSwitches() {
+        return connectedSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getMasterSwitches() {
+        return activeMasterSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getEqualSwitches() {
+        return activeEqualSwitches.values();
+    }
+
+    @Override
+    public OpenFlowSwitch getSwitch(Dpid dpid) {
+        return connectedSwitches.get(dpid);
+    }
+
+    @Override
+    public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
+        return activeMasterSwitches.get(dpid);
+    }
+
+    @Override
+    public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
+        return activeEqualSwitches.get(dpid);
+    }
+
+    @Override
+    public void addListener(OpenFlowSwitchListener listener) {
+        if (!ofEventListener.contains(listener)) {
+            this.ofEventListener.add(listener);
+        }
+    }
+
+    @Override
+    public void removeListener(OpenFlowSwitchListener listener) {
+        this.ofEventListener.remove(listener);
+    }
+
+    @Override
+    public void addPacketListener(int priority, PacketListener listener) {
+        ofPacketListener.add(priority, listener);
+    }
+
+    @Override
+    public void removePacketListener(PacketListener listener) {
+        ofPacketListener.remove(listener);
+    }
+
+    @Override
+    public void write(Dpid dpid, OFMessage msg) {
+        this.getSwitch(dpid).sendMsg(msg);
+    }
+
+    @Override
+    public void processPacket(Dpid dpid, OFMessage msg) {
+        switch (msg.getType()) {
+        case PORT_STATUS:
+            for (OpenFlowSwitchListener l : ofEventListener) {
+                l.portChanged(dpid, (OFPortStatus) msg);
+            }
+            break;
+        case PACKET_IN:
+            for (PacketListener p : ofPacketListener) {
+                p.handlePacket(DefaultPacketContext
+                        .packetContextFromPacketIn(this.getSwitch(dpid),
+                                (OFPacketIn) msg));
+            }
+            break;
+        default:
+            log.warn("Handling message type {} not yet implemented {}",
+                    msg.getType(), msg);
+        }
+    }
+
+    @Override
+    public void setRole(Dpid dpid, RoleState role) {
+        getSwitch(dpid).setRole(role);
+    }
+
+    /**
+     * Implementation of an OpenFlow Agent which is responsible for
+     * keeping track of connected switches and the state in which
+     * they are.
+     */
+    public class OpenFlowSwitchAgent implements OpenFlowAgent {
+
+        private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
+        private final Lock switchLock = new ReentrantLock();
+
+        @Override
+        public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
+            if (connectedSwitches.get(dpid) != null) {
+                log.error("Trying to add connectedSwitch but found a previous "
+                        + "value for dpid: {}", dpid);
+                return false;
+            } else {
+                log.error("Added switch {}", dpid);
+                connectedSwitches.put(dpid, sw);
+                for (OpenFlowSwitchListener l : ofEventListener) {
+                    l.switchAdded(dpid);
+                }
+                return true;
+            }
+        }
+
+        @Override
+        public boolean validActivation(Dpid dpid) {
+            if (connectedSwitches.get(dpid) == null) {
+                log.error("Trying to activate switch but is not in "
+                        + "connected switches: dpid {}. Aborting ..",
+                        dpid);
+                return false;
+            }
+            if (activeMasterSwitches.get(dpid) != null ||
+                    activeEqualSwitches.get(dpid) != null) {
+                log.error("Trying to activate switch but it is already "
+                        + "activated: dpid {}. Found in activeMaster: {} "
+                        + "Found in activeEqual: {}. Aborting ..", new Object[]{
+                                dpid,
+                                (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
+                                        (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
+                return false;
+            }
+            return true;
+        }
+
+
+        @Override
+        public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                if (!validActivation(dpid)) {
+                    return false;
+                }
+                activeMasterSwitches.put(dpid, sw);
+                return true;
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+        @Override
+        public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                if (!validActivation(dpid)) {
+                    return false;
+                }
+                activeEqualSwitches.put(dpid, sw);
+                log.info("Added Activated EQUAL Switch {}", dpid);
+                return true;
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+        @Override
+        public void transitionToMasterSwitch(Dpid dpid) {
+            switchLock.lock();
+            try {
+                if (activeMasterSwitches.containsKey(dpid)) {
+                    return;
+                }
+                OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
+                if (sw == null) {
+                    sw = getSwitch(dpid);
+                    if (sw == null) {
+                        log.error("Transition to master called on sw {}, but switch "
+                                + "was not found in controller-cache", dpid);
+                        return;
                     }
-
-                    @Deactivate
-                    public void deactivate() {
-                        ctrl.stop();
-                    }
-
-                    @Override
-                    public Iterable<OpenFlowSwitch> getSwitches() {
-                        return connectedSwitches.values();
-                    }
-
-                    @Override
-                    public Iterable<OpenFlowSwitch> getMasterSwitches() {
-                        return activeMasterSwitches.values();
-                    }
-
-                    @Override
-                    public Iterable<OpenFlowSwitch> getEqualSwitches() {
-                        return activeEqualSwitches.values();
-                    }
-
-                    @Override
-                    public OpenFlowSwitch getSwitch(Dpid dpid) {
-                        return connectedSwitches.get(dpid);
-                    }
-
-                    @Override
-                    public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
-                        return activeMasterSwitches.get(dpid);
-                    }
-
-                    @Override
-                    public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
-                        return activeEqualSwitches.get(dpid);
-                    }
-
-                    @Override
-                    public void addListener(OpenFlowSwitchListener listener) {
-                        if (!ofEventListener.contains(listener)) {
-                            this.ofEventListener.add(listener);
-                        }
-                    }
-
-                    @Override
-                    public void removeListener(OpenFlowSwitchListener listener) {
-                        this.ofEventListener.remove(listener);
-                    }
-
-                    @Override
-                    public void addPacketListener(int priority, PacketListener listener) {
-                        ofPacketListener.add(priority, listener);
-                    }
-
-                    @Override
-                    public void removePacketListener(PacketListener listener) {
-                        ofPacketListener.remove(listener);
-                    }
-
-                    @Override
-                    public void write(Dpid dpid, OFMessage msg) {
-                        this.getSwitch(dpid).sendMsg(msg);
-                    }
-
-                    @Override
-                    public void processPacket(Dpid dpid, OFMessage msg) {
-                        switch (msg.getType()) {
-                        case PORT_STATUS:
-                            for (OpenFlowSwitchListener l : ofEventListener) {
-                                l.portChanged(dpid, (OFPortStatus) msg);
-                            }
-                            break;
-                        case PACKET_IN:
-                            for (PacketListener p : ofPacketListener) {
-                                //TODO fix me!
-                                p.handlePacket(DefaultPacketContext
-                                        .packetContextFromPacketIn(this.getSwitch(dpid),
-                                                (OFPacketIn) msg));
-                            }
-                            break;
-                        default:
-                            log.warn("Handling message type {} not yet implemented {}",
-                                    msg.getType(), msg);
-                        }
-                    }
-
-                    @Override
-                    public void setRole(Dpid dpid, RoleState role) {
-                        getSwitch(dpid).setRole(role);
-                    }
-
-                    /**
-                     * Implementation of an OpenFlow Agent which is responsible for
-                     * keeping track of connected switches and the state in which
-                     * they are.
-                     */
-                    public class OpenFlowSwitchAgent implements OpenFlowAgent {
-
-                        private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
-                        private final Lock switchLock = new ReentrantLock();
-
-                        @Override
-                        public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
-                            if (connectedSwitches.get(dpid) != null) {
-                                log.error("Trying to add connectedSwitch but found a previous "
-                                        + "value for dpid: {}", dpid);
-                                return false;
-                            } else {
-                                log.error("Added switch {}", dpid);
-                                connectedSwitches.put(dpid, sw);
-                                for (OpenFlowSwitchListener l : ofEventListener) {
-                                    l.switchAdded(dpid);
-                                }
-                                return true;
-                            }
-                        }
-
-                        @Override
-                        public boolean validActivation(Dpid dpid) {
-                            if (connectedSwitches.get(dpid) == null) {
-                                log.error("Trying to activate switch but is not in "
-                                        + "connected switches: dpid {}. Aborting ..",
-                                        dpid);
-                                return false;
-                            }
-                            if (activeMasterSwitches.get(dpid) != null ||
-                                    activeEqualSwitches.get(dpid) != null) {
-                                log.error("Trying to activate switch but it is already "
-                                        + "activated: dpid {}. Found in activeMaster: {} "
-                                        + "Found in activeEqual: {}. Aborting ..", new Object[]{
-                                                dpid,
-                                                (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
-                                                        (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
-                                return false;
-                            }
-                            return true;
-                        }
+                }
+                log.info("Transitioned switch {} to MASTER", dpid);
+                activeMasterSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
+        }
 
 
-                        @Override
-                        public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
-                            switchLock.lock();
-                            try {
-                                if (!validActivation(dpid)) {
-                                    return false;
-                                }
-                                activeMasterSwitches.put(dpid, sw);
-                                return true;
-                            } finally {
-                                switchLock.unlock();
-                            }
-                        }
+        @Override
+        public void transitionToEqualSwitch(Dpid dpid) {
+            switchLock.lock();
+            try {
+                if (activeEqualSwitches.containsKey(dpid)) {
+                    return;
+                }
+                OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+                if (sw == null) {
+                    log.error("Transition to equal called on sw {}, but switch "
+                            + "was not found in controller-cache", dpid);
+                    return;
+                }
+                log.info("Transitioned switch {} to EQUAL", dpid);
+                activeEqualSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
 
-                        @Override
-                        public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
-                            switchLock.lock();
-                            try {
-                                if (!validActivation(dpid)) {
-                                    return false;
-                                }
-                                activeEqualSwitches.put(dpid, sw);
-                                log.info("Added Activated EQUAL Switch {}", dpid);
-                                return true;
-                            } finally {
-                                switchLock.unlock();
-                            }
-                        }
+        }
 
-                        @Override
-                        public void transitionToMasterSwitch(Dpid dpid) {
-                            switchLock.lock();
-                            try {
-                                if (activeMasterSwitches.containsKey(dpid)) {
-                                    return;
-                                }
-                                OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
-                                if (sw == null) {
-                                    sw = getSwitch(dpid);
-                                    if (sw == null) {
-                                        log.error("Transition to master called on sw {}, but switch "
-                                                + "was not found in controller-cache", dpid);
-                                        return;
-                                    }
-                                }
-                                log.info("Transitioned switch {} to MASTER", dpid);
-                                activeMasterSwitches.put(dpid, sw);
-                            } finally {
-                                switchLock.unlock();
-                            }
-                        }
+        @Override
+        public void removeConnectedSwitch(Dpid dpid) {
+            connectedSwitches.remove(dpid);
+            OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+            if (sw == null) {
+                sw = activeEqualSwitches.remove(dpid);
+            }
+            for (OpenFlowSwitchListener l : ofEventListener) {
+                l.switchRemoved(dpid);
+            }
+        }
 
-
-                        @Override
-                        public void transitionToEqualSwitch(Dpid dpid) {
-                            switchLock.lock();
-                            try {
-                                if (activeEqualSwitches.containsKey(dpid)) {
-                                    return;
-                                }
-                                OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
-                                if (sw == null) {
-                                    log.error("Transition to equal called on sw {}, but switch "
-                                            + "was not found in controller-cache", dpid);
-                                    return;
-                                }
-                                log.info("Transitioned switch {} to EQUAL", dpid);
-                                activeEqualSwitches.put(dpid, sw);
-                            } finally {
-                                switchLock.unlock();
-                            }
-
-                        }
-
-                        @Override
-                        public void removeConnectedSwitch(Dpid dpid) {
-                            connectedSwitches.remove(dpid);
-                            OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
-                            if (sw == null) {
-                                sw = activeEqualSwitches.remove(dpid);
-                            }
-                            for (OpenFlowSwitchListener l : ofEventListener) {
-                                l.switchRemoved(dpid);
-                            }
-                        }
-
-                        @Override
-                        public void processMessage(Dpid dpid, OFMessage m) {
-                            processPacket(dpid, m);
-                        }
-                    }
+        @Override
+        public void processMessage(Dpid dpid, OFMessage m) {
+            processPacket(dpid, m);
+        }
+    }
 
 
 }
diff --git a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
index 9396f91..f250660 100644
--- a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
+++ b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
@@ -21,9 +21,9 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -85,6 +85,7 @@
     private final boolean useBDDP;
     private final OpenFlowController ctrl;
     private final LinkProviderService linkProvider;
+    private final Map<Integer, OFPortDesc> ports;
 
     /**
      * Instantiates discovery manager for the given physical switch. Creates a
@@ -103,6 +104,7 @@
         this.linkProvider = providerService;
         this.slowPorts = Collections.synchronizedSet(new HashSet<Integer>());
         this.fastPorts = Collections.synchronizedSet(new HashSet<Integer>());
+        this.ports = new ConcurrentHashMap<>();
         this.portProbeCount = new HashMap<Integer, AtomicInteger>();
         this.lldpPacket = new ONLabLddp();
         this.lldpPacket.setSwitch(this.sw.getId());
@@ -140,7 +142,7 @@
      */
     public void addPort(final OFPortDesc port) {
         // Ignore ports that are not on this switch, or already booted. */
-
+        this.ports.put(port.getPortNo().getPortNumber(), port);
         synchronized (this) {
             this.log.debug("sending init probe to port {}",
                     port.getPortNo().getPortNumber());
@@ -274,12 +276,10 @@
      * Handles an incoming LLDP packet. Creates link in topology and sends ACK
      * to port where LLDP originated.
      */
-    @SuppressWarnings("rawtypes")
-    public void handleLLDP(final Ethernet eth, Integer inPort) {
+    public void handleLLDP(final byte[] pkt, Integer inPort) {
 
-        final byte[] pkt = eth.serialize();
-
-        if (ONLabLddp.isOVXLLDP(pkt)) {
+        short ethType = ONLabLddp.isOVXLLDP(pkt);
+        if (ethType == Ethernet.TYPE_LLDP || ethType == Ethernet.TYPE_BSN) {
             final Integer dstPort = inPort;
             final DPIDandPort dp = ONLabLddp.parseLLDP(pkt);
             final OpenFlowSwitch srcSwitch = ctrl.getSwitch(new Dpid(dp.getDpid()));
@@ -296,7 +296,7 @@
                     DeviceId.deviceId("of:" + Long.toHexString(sw.getId())),
                     PortNumber.portNumber(dstPort));
             LinkDescription ld;
-            if (eth.getEtherType() == Ethernet.TYPE_BSN) {
+            if (ethType == Ethernet.TYPE_BSN) {
                 ld = new DefaultLinkDescription(src, dst, Type.INDIRECT);
             } else {
                 ld = new DefaultLinkDescription(src, dst, Type.DIRECT);
@@ -307,13 +307,8 @@
         }
     }
 
-    private OFPortDesc findPort(List<OFPortDesc> ports, Integer inPort) {
-        for (OFPortDesc p : ports) {
-            if (p.getPortNo().getPortNumber() == inPort) {
-                return p;
-            }
-        }
-        return null;
+    private OFPortDesc findPort(Integer inPort) {
+        return ports.get(inPort);
     }
 
     /**
@@ -333,7 +328,7 @@
                 final Integer portNumber = fastIterator.next();
                 final int probeCount = this.portProbeCount.get(portNumber)
                         .getAndIncrement();
-                OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
+                OFPortDesc port = findPort(portNumber);
                 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
                     this.log.debug("sending fast probe to port");
 
@@ -368,7 +363,7 @@
                 if (this.slowIterator.hasNext()) {
                     final int portNumber = this.slowIterator.next();
                     this.log.debug("sending slow probe to port {}", portNumber);
-                    OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
+                    OFPortDesc port = findPort(portNumber);
 
                     OFPacketOut pkt = this.createLLDPPacketOut(port);
                     this.sendMsg(pkt);
diff --git a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
index 737ef00..af0bb65 100644
--- a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
+++ b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
@@ -87,7 +87,7 @@
             if (ld == null) {
                 return;
             }
-            ld.handleLLDP(pktCtx.parsed(),
+            ld.handleLLDP(pktCtx.unparsed(),
                     pktCtx.inPort());
 
         }
diff --git a/utils/misc/src/main/java/org/onlab/packet/ONLabLddp.java b/utils/misc/src/main/java/org/onlab/packet/ONLabLddp.java
index 520d670..a58387b 100644
--- a/utils/misc/src/main/java/org/onlab/packet/ONLabLddp.java
+++ b/utils/misc/src/main/java/org/onlab/packet/ONLabLddp.java
@@ -30,7 +30,6 @@
  * Refer to IEEE Std 802.1ABTM-2009 for more information.
  *
  */
-@SuppressWarnings("rawtypes")
 public class ONLabLddp extends LLDP {
 
     private static final Logger log = LoggerFactory.getLogger(ONLabLddp.class);
@@ -308,28 +307,34 @@
      * @param packet
      * @return
      */
-    public static boolean isOVXLLDP(byte[] packet) {
+    public static short isOVXLLDP(byte[] packet) {
         if (packet.length < OVX_LLDP_SIZE) {
-            return false;
+            return -1;
         }
 
         // Extra offset due to VLAN tag
         final ByteBuffer bb = ByteBuffer.wrap(packet);
         int offset = 0;
-        if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
-                && bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
+        short ethType = bb.getShort(ETHERTYPE_OFFSET);
+        if (ethType != Ethernet.TYPE_LLDP
+                && ethType != Ethernet.TYPE_BSN) {
             offset = 4;
+            ethType = bb.getShort(ETHERTYPE_OFFSET + offset);
+            if (ethType != Ethernet.TYPE_LLDP
+                    && ethType != Ethernet.TYPE_BSN) {
+                return -1;
+            }
         }
 
         // Compare packet's organizationally specific TLVs to the expected
         // values
         for (int i = 0; i < OUI_TLV.length; i++) {
             if (packet[NAME_TLV_OFFSET + offset + i] != OUI_TLV[i]) {
-                return false;
+                return -1;
             }
         }
 
-        return true;
+        return ethType;
     }
 
     /**