Merge into master from pull request #102:
Support polling for specific message classes (https://github.com/floodlight/oftest/pull/102)
diff --git a/src/python/loxi/of13/message.py b/src/python/loxi/of13/message.py
index 8e1610a..f4716fc 100644
--- a/src/python/loxi/of13/message.py
+++ b/src/python/loxi/of13/message.py
@@ -1469,6 +1469,90 @@
 
 experimenter.subtypes[6035143] = bsn_header
 
+class bsn_arp_idle(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 60
+
+    def __init__(self, xid=None, vlan_vid=None, ipv4_addr=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if vlan_vid != None:
+            self.vlan_vid = vlan_vid
+        else:
+            self.vlan_vid = 0
+        if ipv4_addr != None:
+            self.ipv4_addr = ipv4_addr
+        else:
+            self.ipv4_addr = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!H", self.vlan_vid))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.ipv4_addr))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_arp_idle()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 60)
+        obj.vlan_vid = reader.read("!H")[0]
+        reader.skip(2)
+        obj.ipv4_addr = reader.read("!L")[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.vlan_vid != other.vlan_vid: return False
+        if self.ipv4_addr != other.ipv4_addr: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_arp_idle {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("vlan_vid = ");
+                q.text("%#x" % self.vlan_vid)
+                q.text(","); q.breakable()
+                q.text("ipv4_addr = ");
+                q.text(util.pretty_ipv4(self.ipv4_addr))
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[60] = bsn_arp_idle
+
 class bsn_bw_clear_data_reply(bsn_header):
     version = 4
     type = 4
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index c0eb1ca..2f95a8e 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -301,9 +301,6 @@
                     handled = self.handlers["all"](self, msg, rawmsg)
 
                 if not handled: # Not handled, enqueue
-                    self.logger.debug("Enqueuing pkt type %s (%d)",
-                                      ofp.ofp_type_map.get(hdr_type, "unknown"),
-                                      hdr_type)
                     with self.packets_cv:
                         if len(self.packets) >= self.max_pkts:
                             self.packets.pop(0)
@@ -587,34 +584,26 @@
         If an error occurs, (None, None) is returned
         """
 
-        exp_msg_str = "unspecified"
-        if exp_msg is not None:
-            exp_msg_str = cfg_ofp.ofp_type_map.get(exp_msg, "unknown (%d)" %
-                                               exp_msg)
-
-        if exp_msg is not None:
-            self.logger.debug("Poll for %s", exp_msg_str)
+        if exp_msg is None:
+            self.logger.warn("DEPRECATED polling for any message class")
+            klass = None
+        elif isinstance(exp_msg, int):
+            klass = cfg_ofp.message.message.subtypes[exp_msg]
+        elif issubclass(exp_msg, cfg_ofp.message.message):
+            klass = exp_msg
         else:
-            self.logger.debug("Poll for any OF message")
+            raise ValueError("Unexpected exp_msg argument %r", exp_msg)
+
+        self.logger.debug("Polling for %s", klass.__name__)
 
         # Take the packet from the queue
         def grab():
-            if len(self.packets) > 0:
-                if exp_msg is None:
-                    self.logger.debug("Looking for any packet")
-                    (msg, pkt) = self.packets.pop(0)
-                    return (msg, pkt)
-                else:
-                    self.logger.debug("Looking for %s", exp_msg_str)
-                    for i in range(len(self.packets)):
-                        msg = self.packets[i][0]
-                        msg_str = cfg_ofp.ofp_type_map.get(msg.type, "unknown (%d)" % msg.type)
-                        self.logger.debug("Checking packets[%d] %s) against %s", i, msg_str, exp_msg_str)
-                        if msg.type == exp_msg:
-                            (msg, pkt) = self.packets.pop(i)
-                            return (msg, pkt)
+            for i, (msg, pkt) in enumerate(self.packets):
+                if klass is None or isinstance(msg, klass):
+                    self.logger.debug("Got %s message", msg.__class__.__name__)
+                    return self.packets.pop(i)
             # Not found
-            self.logger.debug("Packet not in queue")
+            self.logger.debug("%s message not in queue", klass.__name__)
             return None
 
         with self.packets_cv:
@@ -622,7 +611,6 @@
 
         if ret != None:
             (msg, pkt) = ret
-            self.logger.debug("Got message %s" % str(msg))
             return (msg, pkt)
         else:
             return (None, None)