Merge branch 'testutils'
diff --git a/src/python/oftest/testutils.py b/src/python/oftest/testutils.py
index 6609fc6..40b24ed 100644
--- a/src/python/oftest/testutils.py
+++ b/src/python/oftest/testutils.py
@@ -17,6 +17,7 @@
 import oftest.controller
 import oftest.dataplane
 import oftest.parse
+import oftest.ofutils
 import ofp
 
 global skipped_test_count
@@ -1307,4 +1308,102 @@
         test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
                         "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
 
+def packet_in_match(msg, data, in_port=None, reason=None):
+    """
+    Check whether the packet_in message 'msg' has fields matching 'data',
+    'in_port', and 'reason'.
+
+    This function handles truncated packet_in data. The 'in_port' and 'reason'
+    parameters are optional.
+
+    @param msg packet_in message
+    @param data Expected packet_in data
+    @param in_port Expected packet_in in_port, or None
+    @param reason Expected packet_in reason, or None
+    """
+
+    if in_port and in_port != msg.in_port:
+        logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, msg.in_port)
+        return False
+
+    if reason and reason != msg.reason:
+        logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
+        return False
+
+    # Check that one of the packets is a prefix of the other.
+    # The received packet may be either truncated or padded, but not both.
+    # (Some of the padding may be truncated but that's irrelevant). We
+    # need to check that the smaller packet is a prefix of the larger one.
+    # Note that this check succeeds if the switch sends a zero-length
+    # packet-in.
+    compare_len = min(len(msg.data), len(data))
+    if data[:compare_len] != msg.data[:compare_len]:
+        logging.debug("Incorrect packet_in data")
+        logging.debug("Expected %s" % format_packet(data[:compare_len]))
+        logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
+        return False
+
+    return True
+
+def verify_packet_in(test, data, in_port, reason, controller=None):
+    """
+    Assert that the controller receives a packet_in message matching data 'data'
+    from port 'in_port' with reason 'reason'. Does not trigger the packet_in
+    itself, that's up to the test case.
+
+    @param test Instance of base_tests.SimpleProtocol
+    @param pkt String to expect as the packet_in data
+    @param in_port OpenFlow port number to expect as the packet_in in_port
+    @param reason One of OFPR_* to expect as the packet_in reason
+    @param controller Controller instance, defaults to test.controller
+    @returns The received packet-in message
+    """
+
+    if controller == None:
+        controller = test.controller
+
+    end_time = time.time() + oftest.ofutils.default_timeout
+
+    while True:
+        msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
+        if not msg:
+            # Timeout
+            break
+        elif packet_in_match(msg, data, in_port, reason):
+            # Found a matching message
+            break
+
+    test.assertTrue(msg is not None, 'Packet in message not received on port %d' % in_port)
+    return msg
+
+def verify_no_packet_in(test, data, in_port, controller=None):
+    """
+    Assert that the controller does not receive a packet_in message matching
+    data 'data' from port 'in_port'.
+
+    @param test Instance of base_tests.SimpleProtocol
+    @param pkt String to expect as the packet_in data
+    @param in_port OpenFlow port number to expect as the packet_in in_port
+    @param controller Controller instance, defaults to test.controller
+    """
+
+    if controller == None:
+        controller = test.controller
+
+    # Negative test, need to wait a short amount of time before checking we
+    # didn't receive the message.
+    time.sleep(0.5)
+
+    # Check every packet_in queued in the controller
+    while True:
+        msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
+        if msg == None:
+            # No more queued packet_in messages
+            break
+        elif packet_in_match(msg, data, in_port, None):
+            # Found a matching message
+            break
+
+    test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
+
 __all__ = list(set(locals()) - _import_blacklist)
diff --git a/tests/actions.py b/tests/actions.py
index 2791d5a..d25108d 100644
--- a/tests/actions.py
+++ b/tests/actions.py
@@ -66,9 +66,7 @@
                 "Packet received on port " + str(rcv_port))
 
         #Verify packets not sent on control plane either
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=1)
-        self.assertTrue(response is None,
-                        'Packets not received on control plane')
+        verify_no_packet_in(self, str(pkt), of_ports[0])
 
 
 class Announcement(base_tests.SimpleDataPlane):
@@ -215,9 +213,7 @@
             self.dataplane.send(ingress_port, str(pkt))
 
             #Verifying packet recieved on the control plane port
-            (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=10)
-            self.assertTrue(response is not None,
-                        'Packet in message not received by controller')
+            verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
     
 
 
diff --git a/tests/basic.py b/tests/basic.py
index 5312c1a..6e0e4d0 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -91,29 +91,7 @@
 
                logging.info("PKT IN test with %s, port %s" % (pt, of_port))
                self.dataplane.send(of_port, str(pkt))
-               #@todo Check for unexpected messages?
-               count = 0
-               while True:
-                   (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
-                   if not response:  # Timeout
-                       break
-                   if dataplane.match_exp_pkt(pkt, response.data): # Got match
-                       break
-                   if not config["relax"]:  # Only one attempt to match
-                       break
-                   count += 1
-                   if count > 10:   # Too many tries
-                       break
-
-               self.assertTrue(response is not None, 
-                               'Packet in message not received on port ' + 
-                               str(of_port))
-               if not dataplane.match_exp_pkt(pkt, response.data):
-                   logging.debug("Sent %s" % format_packet(pkt))
-                   logging.debug("Resp %s" % format_packet(response.data))
-                   self.assertTrue(False,
-                                   'Response packet does not match send packet' +
-                                   ' for port ' + str(of_port))
+               verify_packet_in(self, str(pkt), of_port, ofp.OFPR_NO_MATCH)
 
 class PacketInBroadcastCheck(base_tests.SimpleDataPlane):
     """
diff --git a/tests/default_drop.py b/tests/default_drop.py
index 574593f..975e056 100644
--- a/tests/default_drop.py
+++ b/tests/default_drop.py
@@ -23,21 +23,6 @@
         do_barrier(self.controller)
 
         for of_port in config["port_map"].keys():
-            pkt = simple_tcp_packet()
-            self.dataplane.send(of_port, str(pkt))
-            count = 0
-            while True:
-                (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
-                if not response:  # Timeout
-                    break
-                if dataplane.match_exp_pkt(pkt, response.data): # Got match
-                    break
-                if not config["relax"]:  # Only one attempt to match
-                    break
-                count += 1
-                if count > 10:   # Too many tries
-                    break
-
-            self.assertTrue(response is None, 
-                            'Packet in message received on port ' + 
-                            str(of_port))
+            pkt = str(simple_tcp_packet())
+            self.dataplane.send(of_port, pkt)
+            verify_no_packet_in(self, pkt, of_port)
diff --git a/tests/flow_matches.py b/tests/flow_matches.py
index 721d68b..2216899 100644
--- a/tests/flow_matches.py
+++ b/tests/flow_matches.py
@@ -115,9 +115,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_eth_packet(eth_src='00:01:01:01:01:02');
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packets")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class EthernetDstAddress(base_tests.SimpleDataPlane):
     
@@ -156,8 +154,7 @@
         self.dataplane.send(of_ports[0], str(pkt2))
         
         #Verify PacketIn event gets triggered
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class EthernetType(base_tests.SimpleDataPlane):
@@ -197,8 +194,7 @@
         self.dataplane.send(of_ports[0], str(pkt2))
         
         #verify Packetin event gets triggered.
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non-matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
             
 class IngressPort(base_tests.SimpleDataPlane):
@@ -237,8 +233,7 @@
         self.dataplane.send(of_ports[1],str(pkt))
 
         #Verify PacketIn event gets triggered
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non-matching packet")
+        verify_packet_in(self, str(pkt), of_ports[1], ofp.OFPR_NO_MATCH)
 
 class VlanId(base_tests.SimpleDataPlane):
 
@@ -275,8 +270,7 @@
         self.dataplane.send(of_ports[0], str(pkt2))
         
         #Verify PacketIn event gets triggered
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class VlanPCP(base_tests.SimpleDataPlane):
 
@@ -315,8 +309,7 @@
         self.dataplane.send(of_ports[0], str(pkt2))
 
         #Verify Packet_In event gets triggered
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
        
 class MultipleHeaderFieldL2(base_tests.SimpleDataPlane):
     
@@ -352,24 +345,19 @@
         #Sending non matching packet (only eth_dst is different) , verify Packetin event gets triggered.
         pkt2 = simple_eth_packet(eth_type=0x88cc,eth_src='00:01:01:01:01:01',eth_dst='00:01:01:02:01:01');
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
         #Sending non matching packet (only eth_src is different) , verify Packetin event gets triggered.
         pkt2 = simple_eth_packet(eth_type=0x88cc,eth_src='00:01:01:01:01:02',eth_dst='00:01:01:01:01:02');
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
         #Sending non matching packet (only ether_type is different) , verify Packetin event gets triggered.
         pkt2 = simple_eth_packet(eth_type=0x0806,eth_src='00:01:01:01:01:01',eth_dst='00:01:01:01:01:02');
         self.dataplane.send(of_ports[0], str(pkt2))
         
         #Verify packet_in event gets triggered
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class IpTos(base_tests.SimpleDataPlane):
 
@@ -406,8 +394,7 @@
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_tcp_packet(ip_tos=4);
         self.dataplane.send(of_ports[0], str(pkt2))
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class IpProtocol(base_tests.SimpleDataPlane):
 
@@ -444,8 +431,7 @@
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_icmp_packet();
         self.dataplane.send(of_ports[0], str(pkt2))
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class TcpSrcPort(base_tests.SimpleDataPlane):
@@ -482,9 +468,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=540);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class TcpDstPort(base_tests.SimpleDataPlane):
     
@@ -520,9 +504,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_dport=541);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=10)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class UdpSrcPort(base_tests.SimpleDataPlane):
     
@@ -558,9 +540,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_udp_packet(udp_sport=540);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class UdpDstPort(base_tests.SimpleDataPlane):
     
@@ -596,9 +576,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_udp_packet(udp_dport=541);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=10)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class ICMPType(base_tests.SimpleDataPlane):
     
@@ -634,9 +612,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_icmp_packet(icmp_type=10);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class ICMPCode(base_tests.SimpleDataPlane):
     
@@ -672,9 +648,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_icmp_packet(icmp_code=10);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class ArpSenderIP(base_tests.SimpleDataPlane):
@@ -712,8 +686,7 @@
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_arp_packet(ip_snd="10.10.0.10");
         self.dataplane.send(of_ports[0], str(pkt2))
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 class ArpTargetIP(base_tests.SimpleDataPlane):
 
@@ -750,8 +723,7 @@
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_arp_packet(ip_tgt="10.10.0.10");
         self.dataplane.send(of_ports[0], str(pkt2))
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class ExactMatch(base_tests.SimpleDataPlane):
@@ -788,9 +760,7 @@
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=540);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class MultipleHeaderFieldL4(base_tests.SimpleDataPlane):
@@ -827,16 +797,12 @@
         #Sending non matching packet (tcp_dport different), verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=111,tcp_dport=541);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
         #Sending non matching packet (tcp_sport different), verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=100,tcp_dport=112);
         self.dataplane.send(of_ports[0], str(pkt2))
-        
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
-        self.assertTrue(response is not None, "PacketIn not received for non matching packet")
+        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
 
 
 class ExactMatchPrio(base_tests.SimpleDataPlane):
diff --git a/tests/message_types.py b/tests/message_types.py
index 599764a..743dae1 100644
--- a/tests/message_types.py
+++ b/tests/message_types.py
@@ -316,9 +316,7 @@
             self.dataplane.send(of_ports[0],str(pkt))
 
             #Verify packet_in generated
-            (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=3)
-            self.assertTrue(response is not None,
-                        'Packet In not received on control plane')
+            response = verify_packet_in(self, str(pkt), of_ports[0], ofp.OFPR_NO_MATCH)
 
             #Verify buffer_id field and data field
             if response.buffer_id == 0xFFFFFFFF:
@@ -375,12 +373,7 @@
             self.dataplane.send(of_ports[0], str(pkt))
 
             #Verifying packet_in recieved on the control plane 
-            (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=10)
-            self.assertTrue(response is not None,
-                        'Packet in message not received by controller')
-
-            #Verify the reason field is OFPR_ACTION
-            self.assertEqual(response.reason,ofp.OFPR_ACTION,"PacketIn reason field is incorrect")
+            response = verify_packet_in(self, str(pkt), of_ports[0], ofp.OFPR_ACTION)
 
             #Verify buffer_id field and data field
             if response.buffer_id != 0xFFFFFFFF :
@@ -419,19 +412,11 @@
         self.dataplane.send(of_ports[0],str(pkt))
 
         #Verify packet_in generated
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=3)
-        self.assertTrue(response is not None,
-                        'Packet In not received on control plane')
+        response = verify_packet_in(self, str(pkt), of_ports[0], ofp.OFPR_NO_MATCH)
 
         #Verify Frame Total Length Field in Packet_in 
         self.assertEqual(response.total_len,len(str(pkt)), "PacketIn total_len field is incorrect")
 
-        #Verify in_port field in Packet_in
-        self.assertEqual(response.in_port,of_ports[0],"PacketIn in_port or recieved port field is incorrect")
-
-        #Verify the reason field in Packet_in is OFPR_NO_MATCH
-        self.assertEqual(response.reason,ofp.OFPR_NO_MATCH,"PacketIn reason field is incorrect")
-
         #Verify data field 
         self.assertTrue(len(response.data) == len(str(pkt)), "Complete Data packet was not sent")
 
@@ -473,12 +458,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verifying packet_in recieved on the control plane 
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, timeout=10)
-        self.assertTrue(response is not None,
-                    'Packet in message not received by controller')
-
-        #Verify the reason field is OFPR_ACTION
-        self.assertEqual(response.reason,ofp.OFPR_ACTION,"PacketIn reason field is incorrect")
+        response = verify_packet_in(self, str(pkt), of_ports[0], ofp.OFPR_ACTION)
 
         #Verify Frame Total Length Field in Packet_in 
         self.assertEqual(response.total_len,len(str(pkt)), "PacketIn total_len field is incorrect")
@@ -486,9 +466,6 @@
         #verify the data field
         self.assertEqual(len(response.data),len(str(pkt)),"Complete Data Packet was not sent")
 
-        #Verify in_port field in Packet_in
-        self.assertEqual(response.in_port,of_ports[0],"PacketIn in_port or recieved port field is incorrect")
-
 
 @nonstandard
 class PortStatusMessage(base_tests.SimpleDataPlane):
diff --git a/tests/nicira_role.py b/tests/nicira_role.py
index a10d8b8..5eeca25 100644
--- a/tests/nicira_role.py
+++ b/tests/nicira_role.py
@@ -96,30 +96,20 @@
     """
     def runTest(self):
         delete_all_flows(self.controller)
+        ingress_port = config["port_map"].keys()[0]
+        pkt = str(simple_tcp_packet())
 
         set_role(self, NX_ROLE_MASTER)
-        self.verify_packetin(True)
+        self.dataplane.send(ingress_port, pkt)
+        verify_packet_in(self, pkt, ingress_port, ofp.OFPR_NO_MATCH)
 
         set_role(self, NX_ROLE_SLAVE)
-        self.verify_packetin(False)
+        self.dataplane.send(ingress_port, pkt)
+        verify_no_packet_in(self, pkt, ingress_port)
 
         set_role(self, NX_ROLE_OTHER)
-        self.verify_packetin(True)
-
-    def verify_packetin(self, enabled):
-        ingress_port = config["port_map"].keys()[0]
-        self.dataplane.send(ingress_port, str(simple_tcp_packet()))
-
-        if enabled:
-            timeout = -1
-        else:
-            timeout = 0.5
-        msg, _ = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN, timeout=timeout)
-
-        if enabled:
-            self.assertTrue(msg != None, "Expected a packet-in message")
-        else:
-            self.assertTrue(msg == None, "Did not expect a packet-in message")
+        self.dataplane.send(ingress_port, pkt)
+        verify_packet_in(self, pkt, ingress_port, ofp.OFPR_NO_MATCH)
 
 @nonstandard
 @disabled
@@ -232,9 +222,7 @@
         self.dataplane.send(ingress_port, pkt)
 
         for con in self.controllers:
-            msg, _ = con.poll(ofp.OFPT_PACKET_IN)
-            self.assertTrue(msg != None)
-            self.assertEquals(msg.data, pkt)
+            verify_packet_in(self, pkt, ingress_port, ofp.OFPR_NO_MATCH, controller=con)
 
     def tearDown(self):
         for con in self.controllers:
diff --git a/tests/openflow_protocol_messages.py b/tests/openflow_protocol_messages.py
index b30da7c..50c7eae 100644
--- a/tests/openflow_protocol_messages.py
+++ b/tests/openflow_protocol_messages.py
@@ -275,10 +275,7 @@
         logging.info("Sending packet to dp port " + str(ingress_port) +
                    ", expecting packet_in on control plane" )
       
-        (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_PACKET_IN,
-                                               timeout=2)
-        self.assertTrue(response is not None, 
-                               'Packet in event is not sent to the controller') 
+        verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_NO_MATCH)
 
 
 class Hello(base_tests.SimpleDataPlane):
diff --git a/tests/pktact.py b/tests/pktact.py
index 829a90e..f803cfd 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -196,17 +196,7 @@
                         str(ingress_port))
         self.dataplane.send(ingress_port, str(pkt))
 
-        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
-
-        self.assertTrue(response is not None,
-                        'Packet in message not received by controller')
-        if not dataplane.match_exp_pkt(pkt, response.data):
-            logging.debug("Sent %s" % format_packet(pkt))
-            logging.debug("Resp %s" % format_packet(response.data))
-            self.assertTrue(False,
-                            'Response packet does not match send packet' +
-                             ' for controller port')
-
+        verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
 
 class DirectPacketQueue(base_tests.SimpleDataPlane):
     """
@@ -419,31 +409,8 @@
                 logging.info("Sending packet to dp port " + 
                                str(ingress_port))
                 self.dataplane.send(ingress_port, str(pkt))
-                
-                exp_pkt_arg = None
-                exp_port = None
 
-                count = 0
-                while True:
-                    (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
-                    if not response:  # Timeout
-                        break
-                    if dataplane.match_exp_pkt(pkt, response.data): # Got match
-                        break
-                    if not config["relax"]:  # Only one attempt to match
-                        break
-                    count += 1
-                    if count > 10:   # Too many tries
-                        break
-
-                self.assertTrue(response is not None, 
-                               'Packet in message not received by controller')
-                if not dataplane.match_exp_pkt(pkt, response.data):
-                    logging.debug("Sent %s" % format_packet(pkt))
-                    logging.debug("Resp %s" % format_packet(response.data))
-                    self.assertTrue(False,
-                                    'Response packet does not match send packet' +
-                                    ' for controller port')
+                verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
 
                 # FIXME: instead of sleeping, keep requesting queue stats until
                 # the expected queue counter increases or some large timeout is