testutils: add new functions to check for dataplane packets

`receive_pkt_check` and `receive_pkt_verify` had slightly different
functionality and neither were sufficient for complex tests. This change
deprecates them and adds new functions.

The high level `verify_packets` function is sufficient for most tests. When
more complex logic is needed the primitive functions `verify_packet`,
`verify_no_packet`, and `verify_no_other_packets` should be used directly.

All OpenFlow 1.0/1.3 tests are updated to use the new functions. The old
functions are left around for compatibility with out of tree tests.
diff --git a/src/python/oftest/testutils.py b/src/python/oftest/testutils.py
index 49f4793..faaeed8 100644
--- a/src/python/oftest/testutils.py
+++ b/src/python/oftest/testutils.py
@@ -552,6 +552,8 @@
     @param yes_ports Set or list of ports that should recieve packet
     @param no_ports Set or list of ports that should not receive packet
     @param assert_if Object that implements assertXXX
+
+    DEPRECATED in favor in verify_packets
     """
 
     # Wait this long for packets that we don't expect to receive.
@@ -591,6 +593,8 @@
     @param egr_port A single port or list of ports
 
     parent must implement dataplane, assertTrue and assertEqual
+
+    DEPRECATED in favor in verify_packets
     """
     exp_pkt_arg = None
     if oftest.config["relax"]:
@@ -802,9 +806,8 @@
                         str(egr_ports))
     parent.dataplane.send(ing_port, str(pkt))
 
-    if exp_pkt is None:
-        exp_pkt = pkt
-    receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port)
+    exp_ports = [port == ofp.OFPP_IN_PORT and ing_port or port for port in egr_ports]
+    verify_packets(parent, exp_pkt, exp_ports)
 
 def flow_match_test_pktout(parent, ing_port, egr_ports,
                            vlan_vid=-1, pkt=None, exp_pkt=None,
@@ -839,9 +842,8 @@
     logging.debug(msg.show())
     parent.controller.message_send(msg)
 
-    if exp_pkt is None:
-        exp_pkt = pkt
-    receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port)
+    exp_ports = [port == ofp.OFPP_IN_PORT and ing_port or port for port in egr_ports]
+    verify_packets(parent, exp_pkt, exp_ports)
 
 def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
     """
@@ -1606,4 +1608,55 @@
         raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
     return ports[:num]
 
+def verify_packet(test, pkt, ofport):
+    """
+    Check that an expected packet is received
+    """
+    logging.debug("Checking for pkt on port %r", ofport)
+    (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
+    test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
+
+def verify_no_packet(test, pkt, ofport):
+    """
+    Check that a particular packet is not received
+    """
+    logging.debug("Negative check for pkt on port %r", ofport)
+    (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt), timeout=0.01)
+    test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
+
+def verify_no_other_packets(test):
+    """
+    Check that no unexpected packets are received
+
+    This is a no-op if the --relax option is in effect.
+    """
+    if oftest.config["relax"]:
+        return
+    logging.debug("Checking for unexpected packets on all ports")
+    (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=0.01)
+    if rcv_pkt != None:
+        logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
+    test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
+
+def verify_packets(test, pkt, ofports):
+    """
+    Check that a packet is received on certain ports
+
+    Also verifies that the packet is not received on any other ports, and that no
+    other packets are received (unless --relax is in effect).
+
+    This covers the common and simplest cases for checking dataplane outputs.
+    For more complex usage, like multiple different packets being output, or
+    multiple packets on the same port, use the primitive verify_packet,
+    verify_no_packet, and verify_no_other_packets functions directly.
+    """
+    pkt = str(pkt)
+    for ofport in openflow_ports():
+        if ofport in ofports:
+            verify_packet(test, pkt, ofport)
+        else:
+            verify_no_packet(test, pkt, ofport)
+    verify_no_other_packets(test)
+
+
 __all__ = list(set(locals()) - _import_blacklist)
diff --git a/tests-1.3/actions.py b/tests-1.3/actions.py
index e5b1e3a..4d48fbe 100644
--- a/tests-1.3/actions.py
+++ b/tests-1.3/actions.py
@@ -50,8 +50,7 @@
 
         logging.info("Sending packet, expecting output to port %d", out_port)
         self.dataplane.send(in_port, pktstr)
-        receive_pkt_check(self.dataplane, pktstr, [out_port],
-                          set(openflow_ports()) - set([out_port]), self)
+        verify_packets(self, pktstr, [out_port])
 
 class OutputMultiple(base_tests.SimpleDataPlane):
     """
@@ -86,8 +85,7 @@
 
         logging.info("Sending packet, expecting output to ports %r", out_ports)
         self.dataplane.send(in_port, pktstr)
-        receive_pkt_check(self.dataplane, pktstr, out_ports,
-                          set(openflow_ports()) - set(out_ports), self)
+        verify_packets(self, pktstr, out_ports)
 
 class BaseModifyPacketTest(base_tests.SimpleDataPlane):
     """
@@ -117,8 +115,8 @@
 
         logging.info("Sending packet, expecting output to port %d", out_port)
         self.dataplane.send(in_port, str(pkt))
-        receive_pkt_check(self.dataplane, str(exp_pkt), [out_port],
-                          set(openflow_ports()) - set([out_port]), self)
+        verify_packets(self, str(exp_pkt), [out_port])
+
 
 class PushVlan(BaseModifyPacketTest):
     """
diff --git a/tests-1.3/basic.py b/tests-1.3/basic.py
index eeedec7..21dd130 100644
--- a/tests-1.3/basic.py
+++ b/tests-1.3/basic.py
@@ -73,7 +73,7 @@
         pkt = str(simple_tcp_packet())
         self.dataplane.send(in_port, pkt)
         verify_no_packet_in(self, pkt, None)
-        receive_pkt_check(self.dataplane, pkt, [], openflow_ports(), self)
+        verify_packets(self, pkt, [])
 
 class OutputExact(base_tests.SimpleDataPlane):
     """
@@ -115,7 +115,7 @@
                     continue
                 logging.info("OutputExact test, ports %d to %d", in_port, out_port)
                 self.dataplane.send(in_port, pkt)
-                receive_pkt_verify(self, [out_port], pkt, in_port)
+                verify_packets(self, pkt, [out_port])
 
 class OutputWildcard(base_tests.SimpleDataPlane):
     """
@@ -154,7 +154,7 @@
                     continue
                 logging.info("OutputWildcard test, ports %d to %d", in_port, out_port)
                 self.dataplane.send(in_port, pkt)
-                receive_pkt_verify(self, [out_port], pkt, in_port)
+                verify_packets(self, pkt, [out_port])
 
 class PacketInExact(base_tests.SimpleDataPlane):
     """
@@ -191,6 +191,7 @@
             logging.info("PacketInExact test, port %d", of_port)
             self.dataplane.send(of_port, pkt)
             verify_packet_in(self, pkt, of_port, ofp.OFPR_ACTION)
+            verify_packets(self, pkt, [])
 
 class PacketInWildcard(base_tests.SimpleDataPlane):
     """
@@ -224,6 +225,7 @@
             logging.info("PacketInWildcard test, port %d", of_port)
             self.dataplane.send(of_port, pkt)
             verify_packet_in(self, pkt, of_port, ofp.OFPR_ACTION)
+            verify_packets(self, pkt, [])
 
 class PacketInMiss(base_tests.SimpleDataPlane):
     """
@@ -258,6 +260,7 @@
             logging.info("PacketInMiss test, port %d", of_port)
             self.dataplane.send(of_port, pkt)
             verify_packet_in(self, pkt, of_port, ofp.OFPR_NO_MATCH)
+            verify_packets(self, pkt, [])
 
 class PacketOut(base_tests.SimpleDataPlane):
     """
@@ -278,7 +281,7 @@
 
             logging.info("PacketOut test, port %d", of_port)
             self.controller.message_send(msg)
-            receive_pkt_verify(self, [of_port], pkt, ofp.OFPP_CONTROLLER)
+            verify_packets(self, pkt, [of_port])
 
 class FlowRemoveAll(base_tests.SimpleProtocol):
     """
diff --git a/tests-1.3/match.py b/tests-1.3/match.py
index c45858f..0b473da 100644
--- a/tests-1.3/match.py
+++ b/tests-1.3/match.py
@@ -73,7 +73,7 @@
             logging.info("Sending matching packet %s, expecting output to port %d", repr(name), out_port)
             pktstr = str(pkt)
             self.dataplane.send(in_port, pktstr)
-            receive_pkt_verify(self, [out_port], pktstr, in_port)
+            verify_packets(self, pktstr, [out_port])
 
         for name, pkt in nonmatching.items():
             logging.info("Sending non-matching packet %s, expecting packet-in", repr(name))
@@ -132,7 +132,7 @@
 
         logging.info("Sending packet on matching ingress port, expecting output to port %d", out_port)
         self.dataplane.send(in_port, pktstr)
-        receive_pkt_verify(self, [out_port], pktstr, in_port)
+        verify_packets(self, pktstr, [out_port])
 
         logging.info("Sending packet on non-matching ingress port, expecting packet-in")
         self.dataplane.send(bad_port, pktstr)
diff --git a/tests/actions.py b/tests/actions.py
index d25108d..1a99deb 100644
--- a/tests/actions.py
+++ b/tests/actions.py
@@ -163,8 +163,7 @@
 
         #Verifying packets recieved on expected dataplane ports
         yes_ports = set(of_ports).difference([ingress_port])
-        receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
-                      self)
+        verify_packets(self, pkt, yes_ports)
 
 
 class ForwardController(base_tests.SimpleDataPlane):
@@ -312,8 +311,7 @@
 
         #Verifying packets recieved on expected dataplane ports
         yes_ports = set(of_ports).difference([ingress_port])
-        receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
-                      self)
+        verify_packets(self, pkt, yes_ports)
 
 class ForwardInport(base_tests.SimpleDataPlane):
     
@@ -358,11 +356,9 @@
         #Send packet matching the flow
         logging.info("Sending packet to dp port " + str(ingress_port))
         self.dataplane.send(ingress_port, str(pkt))
-        yes_ports = [ingress_port]
 
         #Verfying packet recieved on expected dataplane ports
-        receive_pkt_check(self.dataplane, pkt, yes_ports,set(of_ports).difference([ingress_port]),
-                          self)
+        verify_packets(self, pkt, [ingress_port])
 
 class ForwardTable(base_tests.SimpleDataPlane):
    
diff --git a/tests/basic.py b/tests/basic.py
index 6e0e4d0..8f6678d 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -153,24 +153,7 @@
                logging.info("PacketOut to: " + str(dp_port))
                self.controller.message_send(msg)
 
-               exp_pkt_arg = None
-               exp_port = None
-               if config["relax"]:
-                   exp_pkt_arg = outpkt
-                   exp_port = dp_port
-               (of_port, pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
-                                                              exp_pkt=exp_pkt_arg)
-
-               self.assertTrue(pkt is not None, 'Packet not received')
-               logging.info("PacketOut: got pkt from " + str(of_port))
-               if of_port is not None:
-                   self.assertEqual(of_port, dp_port, "Unexpected receive port")
-               if not dataplane.match_exp_pkt(outpkt, pkt):
-                   logging.debug("Sent %s" % format_packet(outpkt))
-                   logging.debug("Resp %s" % format_packet(
-                           str(pkt)[:len(str(outpkt))]))
-               self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
-                                'Response packet does not match send packet')
+               verify_packets(self, outpkt, [dp_port])
 
 class PacketOutMC(base_tests.SimpleDataPlane):
     """
@@ -207,9 +190,7 @@
                logging.info("PacketOut to: " + str(dp_ports))
                self.controller.message_send(msg)
 
-               receive_pkt_check(self.dataplane, outpkt, dp_ports,
-                                 set(of_ports).difference(dp_ports),
-                                 self)
+               verify_packets(self, outpkt, dp_ports)
 
 class FlowStatsGet(base_tests.SimpleProtocol):
     """
diff --git a/tests/bsn_ipmask.py b/tests/bsn_ipmask.py
index 8dd603a..f4c4cbf 100644
--- a/tests/bsn_ipmask.py
+++ b/tests/bsn_ipmask.py
@@ -148,16 +148,16 @@
             
         msg(ip0)
         self.dataplane.send(ports[0], str(pkt0))
-        receive_pkt_verify(self, [ports[1]], pkt0, ports[0])
+        verify_packets(self, str(pkt0), [ports[1]])
 
         msg(ip1)
         self.dataplane.send(ports[0], str(pkt1))
-        receive_pkt_verify(self, [ports[2]], pkt1, ports[0])
+        verify_packets(self, str(pkt1), [ports[2]])
 
         msg(ip2)
         self.dataplane.send(ports[0], str(pkt2))
-        receive_pkt_verify(self, [ports[1]], pkt2, ports[0])
+        verify_packets(self, str(pkt2), [ports[1]])
 
         msg(ip3)
         self.dataplane.send(ports[0], str(pkt3))
-        receive_pkt_verify(self, [ports[2]], pkt3, ports[0])
+        verify_packets(self, str(pkt3), [ports[2]])
diff --git a/tests/bsn_mirror.py b/tests/bsn_mirror.py
index 4e4343d..7f40534 100644
--- a/tests/bsn_mirror.py
+++ b/tests/bsn_mirror.py
@@ -87,6 +87,4 @@
         logging.info("Checking that packet was received from output port %s, "
                      "mirror ports %s and %s" % (
               ports[1], mirror_ports[0], mirror_ports[1]))
-        receive_pkt_check(self.dataplane, pkt,
-                          [ports[1], mirror_ports[0], mirror_ports[1]], [],
-                          self)
+        verify_packets(self, pkt, [ports[1], mirror_ports[0], mirror_ports[1]])
diff --git a/tests/flow_matches.py b/tests/flow_matches.py
index 71e36b8..141ac0c 100644
--- a/tests/flow_matches.py
+++ b/tests/flow_matches.py
@@ -42,41 +42,40 @@
         logging.info("Inserting an all wildcarded flow and sending packets with various match fields")
         logging.info("Expecting all sent packets to match")
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         #Insert an All Wildcarded flow.
         wildcard_all(self,of_ports)
 
         #check for different  match fields and verify packet implements the action specified in the flow
-        pkt1 = simple_tcp_packet(eth_src="00:01:01:01:01:01");
-        self.dataplane.send(of_ports[0], str(pkt1))
-        receive_pkt_check(self.dataplane,pkt1,[yes_ports],no_ports,self)
+        pkt1 = str(simple_tcp_packet(eth_src="00:01:01:01:01:01"))
+        self.dataplane.send(in_port, pkt1)
+        verify_packets(self, pkt1, [egress_port])
        
-        pkt2 = simple_tcp_packet(eth_dst="00:01:01:01:01:01");    
-        self.dataplane.send(of_ports[0], str(pkt2))
-        receive_pkt_check(self.dataplane,pkt2,[yes_ports],no_ports,self)
+        pkt2 = str(simple_tcp_packet(eth_dst="00:01:01:01:01:01"))
+        self.dataplane.send(in_port, pkt2)
+        verify_packets(self, pkt2, [egress_port])
         
-        pkt3 = simple_tcp_packet(ip_src="192.168.2.1");
-        self.dataplane.send(of_ports[0], str(pkt3))
-        receive_pkt_check(self.dataplane,pkt3,[yes_ports],no_ports,self)
+        pkt3 = str(simple_tcp_packet(ip_src="192.168.2.1"))
+        self.dataplane.send(in_port, pkt3)
+        verify_packets(self, pkt3, [egress_port])
         
-        pkt4 = simple_tcp_packet(ip_dst="192.168.2.2");
-        self.dataplane.send(of_ports[0], str(pkt4))
-        receive_pkt_check(self.dataplane,pkt4,[yes_ports],no_ports,self)
+        pkt4 = str(simple_tcp_packet(ip_dst="192.168.2.2"))
+        self.dataplane.send(in_port, pkt4)
+        verify_packets(self, pkt4, [egress_port])
         
-        pkt5 = simple_tcp_packet(ip_tos=2);
-        self.dataplane.send(of_ports[0], str(pkt5))
-        receive_pkt_check(self.dataplane,pkt5,[yes_ports],no_ports,self)
+        pkt5 = str(simple_tcp_packet(ip_tos=2))
+        self.dataplane.send(in_port, pkt5)
+        verify_packets(self, pkt5, [egress_port])
        
-        pkt6 = simple_tcp_packet(tcp_sport=8080);
-        self.dataplane.send(of_ports[0], str(pkt6))
-        receive_pkt_check(self.dataplane,pkt6,[yes_ports],no_ports,self)
+        pkt6 = str(simple_tcp_packet(tcp_sport=8080))
+        self.dataplane.send(in_port, pkt6)
+        verify_packets(self, pkt6, [egress_port])
               
-        pkt7 = simple_tcp_packet(tcp_dport=8081);
-        self.dataplane.send(of_ports[0], str(pkt7))
-        receive_pkt_check(self.dataplane,pkt7,[yes_ports],no_ports,self)
+        pkt7 = str(simple_tcp_packet(tcp_dport=8081))
+        self.dataplane.send(in_port, pkt7)
+        verify_packets(self, pkt7, [egress_port])
 
 
 
@@ -95,9 +94,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Ethernet Source Address ")
         logging.info("Sending matching and non-matching ethernet packets")
@@ -107,15 +105,15 @@
         (pkt,match) = match_ethernet_src_address(self,of_ports)   
 
         #Sending packet matching the flow, verify it implements the action
-        self.dataplane.send(of_ports[0], str(pkt))
+        self.dataplane.send(in_port, str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #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))
-        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
+        self.dataplane.send(in_port, str(pkt2))
+        verify_packet_in(self, str(pkt2), in_port, ofp.OFPR_NO_MATCH)
 
 class EthernetDstAddress(base_tests.SimpleDataPlane):
     
@@ -132,9 +130,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match on Ethernet Destination Address ")
         logging.info("Sending matching and non-matching ethernet packets")
@@ -144,17 +141,17 @@
         (pkt,match) = match_ethernet_dst_address(self,of_ports)
         
         #Send Packet matching the flow 
-        self.dataplane.send(of_ports[0], str(pkt))
+        self.dataplane.send(in_port, str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Send Non-matching packet
         pkt2 = simple_eth_packet(eth_dst='00:01:01:01:01:02');
-        self.dataplane.send(of_ports[0], str(pkt2))
+        self.dataplane.send(in_port, str(pkt2))
         
         #Verify PacketIn event gets triggered
-        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
+        verify_packet_in(self, str(pkt2), in_port, ofp.OFPR_NO_MATCH)
 
 
 class EthernetType(base_tests.SimpleDataPlane):
@@ -172,9 +169,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match on Ethernet Type ")
         logging.info("Sending matching and non-matching ethernet packets")
@@ -184,17 +180,17 @@
         (pkt,match) = match_ethernet_type(self,of_ports)   
 
         #Sending packet matching the flow 
-        self.dataplane.send(of_ports[0], str(pkt))
+        self.dataplane.send(in_port, str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , 
         pkt2 = simple_eth_packet(eth_type=0x0806);
-        self.dataplane.send(of_ports[0], str(pkt2))
+        self.dataplane.send(in_port, str(pkt2))
         
         #verify Packetin event gets triggered.
-        verify_packet_in(self, str(pkt2), of_ports[0], ofp.OFPR_NO_MATCH)
+        verify_packet_in(self, str(pkt2), in_port, ofp.OFPR_NO_MATCH)
 
             
 class IngressPort(base_tests.SimpleDataPlane):
@@ -212,9 +208,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Ingress Port ")
         logging.info("Sending matching and non-matching packets")
@@ -224,10 +219,10 @@
         (pkt,match) = wildcard_all_except_ingress(self,of_ports,priority=0)
         
         #Send Packet matching the flow i.e on in_port specified in the flow
-        self.dataplane.send(of_ports[0], str(pkt))
+        self.dataplane.send(in_port, str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Send Non-Matching Packet 
         self.dataplane.send(of_ports[1],str(pkt))
@@ -248,9 +243,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on VLAN ID ")
         logging.info("Sending matching and non-matching tagged packets")
@@ -263,7 +257,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Send Non-matching packet, i.e packet with different Vlan Id
         pkt2 = simple_tcp_packet(dl_vlan_enable=True,vlan_vid=4);
@@ -287,9 +281,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on VLAN Priority ")
         logging.info("Sending matching and non-matching tagged packets")
@@ -302,7 +295,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Send tagged packet with same vlan_id but different vlan priority
         pkt2 = simple_tcp_packet(dl_vlan_enable=True,vlan_vid=1,vlan_pcp=20);
@@ -326,9 +319,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Multiple Header Fields in L2 ")
         logging.info("Sending matching and non-matching packets")
@@ -340,7 +332,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #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');
@@ -374,9 +366,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Ip_Tos ")
         logging.info("Sending matching and non-matching tcp/ip packets")
@@ -389,7 +380,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_tcp_packet(ip_tos=4);
@@ -411,9 +402,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Ip Protocol ")
         logging.info("Sending matching and non-matching tcp/ip packets")
@@ -426,7 +416,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_icmp_packet();
@@ -449,9 +439,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Tcp Tcp Source Port ")
         logging.info("Sending matching and non-matching tcp packets")
@@ -463,7 +452,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=540);
@@ -485,9 +474,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match on Tcp Destination Port ")
         logging.info("Sending matching and non-matching packets")
@@ -499,7 +487,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_dport=541);
@@ -521,9 +509,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Udp Udp Source Port ")
         logging.info("Sending matching and non-matching tcp packets")
@@ -535,7 +522,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_udp_packet(udp_sport=540);
@@ -557,9 +544,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match on Udp Destination Port ")
         logging.info("Sending matching and non-matching packets")
@@ -571,7 +557,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_udp_packet(udp_dport=541);
@@ -593,9 +579,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on ICMP type")
         logging.info("Sending matching and non-matching ICMP packets")
@@ -607,7 +592,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_icmp_packet(icmp_type=10);
@@ -629,9 +614,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on ICMP type")
         logging.info("Sending matching and non-matching ICMP packets")
@@ -643,7 +627,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_icmp_packet(icmp_code=10);
@@ -665,9 +649,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Arp Protocol Opcode")
         logging.info("Sending matching and non-matching arp packets")
@@ -680,7 +663,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_arp_packet(arp_op=2)
@@ -702,9 +685,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Arp Protocol ")
         logging.info("Sending matching and non-matching arp packets")
@@ -717,7 +699,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_arp_packet(ip_snd="10.10.0.10");
@@ -739,9 +721,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting a flow with match on Arp Protocol ")
         logging.info("Sending matching and non-matching arp packets")
@@ -754,7 +735,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
         
         #Create a non-matching packet , verify packet_in get generated
         pkt2 = simple_arp_packet(ip_tgt="10.10.0.10");
@@ -777,9 +758,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match for Exact Match ")
         logging.info("Sending matching and non-matching packets")
@@ -791,7 +771,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet , verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=540);
@@ -814,9 +794,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
         
         logging.info("Inserting a flow with match on Multiple Header Field L4 ")
         logging.info("Sending matching and non-matching packets")
@@ -828,7 +807,7 @@
         self.dataplane.send(of_ports[0], str(pkt))
 
         #Verify packet implements the action specified in the flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
         #Sending non matching packet (tcp_dport different), verify Packetin event gets triggered.
         pkt2 = simple_tcp_packet(tcp_sport=111,tcp_dport=541);
@@ -856,9 +835,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[2]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = egress_port
+        in_port = of_ports[0]
+        egress_port = of_ports[2]
     
         logging.info("Inserting a flow with Exact Match (low priority)")
         logging.info("Inserting an overlapping wildcarded flow (higher priority)")
@@ -873,7 +851,7 @@
         self.dataplane.send(of_ports[0], str(pkt2))
 
         #verify it implements the action specified in Exact Match Flow
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
 
 class WildcardMatchPrio(base_tests.SimpleDataPlane):
@@ -891,9 +869,8 @@
         #Clear Switch State
         delete_all_flows(self.controller)
 
-        egress_port=of_ports[1]
-        no_ports=set(of_ports).difference([egress_port])
-        yes_ports = of_ports[1]
+        in_port = of_ports[0]
+        egress_port = of_ports[1]
     
         logging.info("Inserting two wildcarded flows with priorities ")
         logging.info("Sending packets matching the flows")
@@ -904,7 +881,7 @@
 
         #Sending packet matching both the flows , verify it implements the action specified by Higher Priority flow
         self.dataplane.send(of_ports[0], str(pkt1))
-        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        verify_packets(self, pkt, [egress_port])
 
 
 
diff --git a/tests/nicira_dec_ttl.py b/tests/nicira_dec_ttl.py
index 39b7f21..66e5757 100644
--- a/tests/nicira_dec_ttl.py
+++ b/tests/nicira_dec_ttl.py
@@ -36,9 +36,10 @@
                                          ofp.action.output(port=portC)])
         self.controller.message_send(msg)
 
-        receive_pkt_check(self.dataplane, simple_tcp_packet(ip_ttl=2), [portA], [], self)
-        receive_pkt_check(self.dataplane, simple_tcp_packet(ip_ttl=1), [portB], [], self)
-        receive_pkt_check(self.dataplane, simple_tcp_packet(ip_ttl=0), [], [portC], self)
+        verify_packet(self, simple_tcp_packet(ip_ttl=2), portA)
+        verify_packet(self, simple_tcp_packet(ip_ttl=1), portB)
+        verify_no_packet(self, simple_tcp_packet(ip_ttl=0), portC)
+        verify_no_other_packets(self)
 
 @nonstandard
 class TtlDecrementZeroTtl(base_tests.SimpleDataPlane):
@@ -59,5 +60,6 @@
                                          ofp.action.output(port=portB)])
         self.controller.message_send(msg)
 
-        receive_pkt_check(self.dataplane, simple_tcp_packet(ip_ttl=0), [portA], [], self)
-        receive_pkt_check(self.dataplane, simple_tcp_packet(ip_ttl=0), [], [portB], self)
+        verify_packet(self, simple_tcp_packet(ip_ttl=0), portA)
+        verify_no_packet(self, simple_tcp_packet(ip_ttl=0), portB)
+        verify_no_other_packets(self)
diff --git a/tests/pktact.py b/tests/pktact.py
index 04edf95..cceb13e 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -495,11 +495,7 @@
             logging.info("Sending packet to dp port " + 
                            str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
-            yes_ports = set([egress_port1, egress_port2])
-            no_ports = set(of_ports).difference(yes_ports)
-
-            receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
-                              self)
+            verify_packets(self, pkt, [egress_port1, egress_port2])
 
 class DirectMCNonIngress(base_tests.SimpleDataPlane):
     """
@@ -547,8 +543,7 @@
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
             yes_ports = set(of_ports).difference([ingress_port])
-            receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
-                              self)
+            verify_packets(self, pkt, yes_ports)
 
 
 class DirectMC(base_tests.SimpleDataPlane):
@@ -598,7 +593,7 @@
 
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
-            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
+            verify_packets(self, pkt, of_ports)
 
 class Flood(base_tests.SimpleDataPlane):
     """
@@ -651,8 +646,7 @@
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
             yes_ports = set(of_ports).difference([ingress_port])
-            receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
-                              self)
+            verify_packets(self, pkt, yes_ports)
 
 class FloodPlusIngress(base_tests.SimpleDataPlane):
     """
@@ -695,7 +689,7 @@
 
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
-            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
+            verify_packets(self, pkt, of_ports)
 
 class All(base_tests.SimpleDataPlane):
     """
@@ -739,8 +733,7 @@
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
             yes_ports = set(of_ports).difference([ingress_port])
-            receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
-                              self)
+            verify_packets(self, pkt, yes_ports)
 
 class AllPlusIngress(base_tests.SimpleDataPlane):
     """
@@ -783,7 +776,7 @@
 
             logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
-            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
+            verify_packets(self, pkt, of_ports)
             
 class FloodMinusPort(base_tests.SimpleDataPlane):
     """
@@ -843,7 +836,7 @@
             self.dataplane.send(ingress_port, str(pkt))
             no_ports = set([ingress_port, no_flood_port])
             yes_ports = set(of_ports).difference(no_ports)
-            receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
+            verify_packets(self, pkt, yes_ports)
 
             # Turn no flood off again
             rv = port_config_set(self.controller, no_flood_port,
@@ -856,7 +849,7 @@
             self.dataplane.send(ingress_port, str(pkt))
             no_ports = set([ingress_port])
             yes_ports = set(of_ports).difference(no_ports)
-            receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
+            verify_packets(self, pkt, yes_ports)
 
             #@todo Should check no other packets received
 
@@ -1007,7 +1000,7 @@
         logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
         logging.debug("Send packet: " + str(inp) + " to " + str(egp))
         self.dataplane.send(inp, str(pkt))
-        receive_pkt_verify(self, egp, pkt, inp)
+        verify_packets(self, pkt, [egp])
 
 
        
@@ -1305,7 +1298,7 @@
         of_ports = config["port_map"].keys()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         ing_port = of_ports[0]
-        egr_ports = of_ports[1]
+        egress_port = of_ports[1]
         
         delete_all_flows(self.controller)
 
@@ -1321,19 +1314,19 @@
         vid_act = ofp.action.set_vlan_vid()
         vid_act.vlan_vid = new_vid
         request = flow_msg_create(self, untagged_pkt, ing_port=ing_port, 
-                                  wildcards=wildcards, egr_ports=egr_ports,
+                                  wildcards=wildcards, egr_ports=egress_port,
                                   action_list=[vid_act])
         flow_msg_install(self, request)
 
         logging.debug("Send untagged packet: " + str(ing_port) + " to " + 
-                        str(egr_ports))
+                        str(egress_port))
         self.dataplane.send(ing_port, str(untagged_pkt))
-        receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
+        verify_packets(self, exp_pkt, [egress_port])
 
         logging.debug("Send tagged packet: " + str(ing_port) + " to " + 
-                        str(egr_ports))
+                        str(egress_port))
         self.dataplane.send(ing_port, str(tagged_pkt))
-        receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
+        verify_packets(self, exp_pkt, [egress_port])
 
 class ModifyVlanPcp(BaseMatchCase):
     """