move testutils to src/python/oftest

testutils.py needs to be in a common location for different directories of
tests to use it.
diff --git a/tests/FuncUtils.py b/tests/FuncUtils.py
index 6951293..d12c388 100644
--- a/tests/FuncUtils.py
+++ b/tests/FuncUtils.py
@@ -13,7 +13,7 @@
 import logging
 import types
 import basic
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 
 #################### Functions for various types of flow_mod  ##########################################################################################
diff --git a/tests/actions.py b/tests/actions.py
index f512a02..6bcfb8c 100644
--- a/tests/actions.py
+++ b/tests/actions.py
@@ -20,7 +20,7 @@
 import basic
 import time
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
diff --git a/tests/basic.py b/tests/basic.py
index 721f953..53947b4 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -31,7 +31,7 @@
 
 import oftest.illegal_message as illegal_message
 
-from testutils import *
+from oftest.testutils import *
 
 #@var basic_port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/bsn_ipmask.py b/tests/bsn_ipmask.py
index cb64cb5..489b980 100644
--- a/tests/bsn_ipmask.py
+++ b/tests/bsn_ipmask.py
@@ -9,7 +9,7 @@
 import oftest.message as message
 import basic
 
-from testutils import *
+from oftest.testutils import *
 
 #@var port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/caps.py b/tests/caps.py
index a3355f2..93403ea 100644
--- a/tests/caps.py
+++ b/tests/caps.py
@@ -15,7 +15,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 
 #@var caps_port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/cxn.py b/tests/cxn.py
index aa2c61b..b658074 100644
--- a/tests/cxn.py
+++ b/tests/cxn.py
@@ -17,7 +17,7 @@
 import oftest.dataplane as dataplane
 import oftest.action as action
 
-from testutils import *
+from oftest.testutils import *
 
 #@var cxn_port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/detailed_contr_sw_messages.py b/tests/detailed_contr_sw_messages.py
index 158f787..d45935d 100644
--- a/tests/detailed_contr_sw_messages.py
+++ b/tests/detailed_contr_sw_messages.py
@@ -17,7 +17,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
diff --git a/tests/flow_expire.py b/tests/flow_expire.py
index ab5b68a..9be5fdd 100644
--- a/tests/flow_expire.py
+++ b/tests/flow_expire.py
@@ -17,7 +17,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 
 #@var port_map Local copy of the configuration map from OF port
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 63e6cb5..3017eed 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -74,7 +74,7 @@
 import pktact
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 
 #@var port_map Local copy of the configuration map from OF port
diff --git a/tests/flow_stats.py b/tests/flow_stats.py
index 9c7170e..8ff8b69 100644
--- a/tests/flow_stats.py
+++ b/tests/flow_stats.py
@@ -17,7 +17,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 
 #@var fs_port_map Local copy of the configuration map from OF port
diff --git a/tests/load.py b/tests/load.py
index 7b18252..d09608e 100644
--- a/tests/load.py
+++ b/tests/load.py
@@ -31,7 +31,7 @@
 import basic
 import time
 
-from testutils import *
+from oftest.testutils import *
 
 #@var load_port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/oft b/tests/oft
index 193b7a4..83dfb4f 100755
--- a/tests/oft
+++ b/tests/oft
@@ -122,7 +122,7 @@
     # Running from source tree
     sys.path.insert(0, pydir)
 
-import testutils
+import oftest.testutils
 import oftest.ofutils
 
 try:
@@ -553,7 +553,7 @@
     _verb = 2
 
 oftest.ofutils.default_timeout = config["default_timeout"]
-testutils.MINSIZE = config['minsize']
+oftest.testutils.MINSIZE = config['minsize']
 
 if os.getuid() != 0 and not config["allow_user"]:
     print "ERROR: Super-user privileges required. Please re-run with " \
@@ -568,14 +568,14 @@
 if __name__ == "__main__":
     logging.info("*** TEST RUN START: " + time.asctime())
     result = unittest.TextTestRunner(verbosity=_verb).run(suite)
-    if testutils.skipped_test_count > 0:
+    if oftest.testutils.skipped_test_count > 0:
         ts = " tests"
-        if testutils.skipped_test_count == 1: ts = " test"
-        logging.info("Skipped " + str(testutils.skipped_test_count) + ts)
-        print("Skipped " + str(testutils.skipped_test_count) + ts)
+        if oftest.testutils.skipped_test_count == 1: ts = " test"
+        logging.info("Skipped " + str(oftest.testutils.skipped_test_count) + ts)
+        print("Skipped " + str(oftest.testutils.skipped_test_count) + ts)
     logging.info("*** TEST RUN END  : " + time.asctime())
     if result.failures or result.errors:
         # exit(1) hangs sometimes
         os._exit(1)
-    if testutils.skipped_test_count > 0 and config["fail_skipped"]:
+    if oftest.testutils.skipped_test_count > 0 and config["fail_skipped"]:
         os._exit(1)
diff --git a/tests/openflow_protocol_messages.py b/tests/openflow_protocol_messages.py
index 8f2593f..c8ad1b8 100644
--- a/tests/openflow_protocol_messages.py
+++ b/tests/openflow_protocol_messages.py
@@ -18,7 +18,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
diff --git a/tests/pktact.py b/tests/pktact.py
index 660aa07..fd1b014 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -30,7 +30,7 @@
 import basic
 import time
 
-from testutils import *
+from oftest.testutils import *
 
 #@var port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/port_stats.py b/tests/port_stats.py
index 0964774..96d3cc5 100644
--- a/tests/port_stats.py
+++ b/tests/port_stats.py
@@ -17,7 +17,7 @@
 import oftest.parse as parse
 import basic
 
-from testutils import *
+from oftest.testutils import *
 from time import sleep
 
 #@var fs_port_map Local copy of the configuration map from OF port
diff --git a/tests/serial_failover.py b/tests/serial_failover.py
index d12040e..311dde1 100644
--- a/tests/serial_failover.py
+++ b/tests/serial_failover.py
@@ -17,7 +17,7 @@
 import oftest.dataplane as dataplane
 import oftest.action as action
 
-from testutils import *
+from oftest.testutils import *
 
 #@var serial_failover_port_map Local copy of the configuration map from OF port
 # numbers to OS interfaces
diff --git a/tests/testutils.py b/tests/testutils.py
deleted file mode 100644
index 0d2dd09..0000000
--- a/tests/testutils.py
+++ /dev/null
@@ -1,887 +0,0 @@
-
-import sys
-import copy
-
-try:
-    import scapy.all as scapy
-except:
-    try:
-        import scapy as scapy
-    except:
-        sys.exit("Need to install scapy for packet parsing")
-
-import oftest.controller as controller
-import oftest.cstruct as ofp
-import oftest.message as message
-import oftest.dataplane as dataplane
-import oftest.action as action
-import oftest.parse as parse
-import logging
-import types
-import time
-
-global skipped_test_count
-skipped_test_count = 0
-
-# Some useful defines
-IP_ETHERTYPE = 0x800
-TCP_PROTOCOL = 0x6
-UDP_PROTOCOL = 0x11
-
-MINSIZE = 0
-
-def clear_switch(parent, port_list, logger):
-    """
-    Clear the switch configuration
-
-    @param parent Object implementing controller and assert equal
-    @param logger Logging object
-    """
-    for port in port_list:
-        clear_port_config(parent, port, logger)
-    delete_all_flows(parent.controller, logger)
-
-def delete_all_flows(ctrl, logger):
-    """
-    Delete all flows on the switch
-    @param ctrl The controller object for the test
-    @param logger Logging object
-    """
-
-    logger.info("Deleting all flows")
-    msg = message.flow_mod()
-    msg.match.wildcards = ofp.OFPFW_ALL
-    msg.out_port = ofp.OFPP_NONE
-    msg.command = ofp.OFPFC_DELETE
-    msg.buffer_id = 0xffffffff
-    return ctrl.message_send(msg)
-
-def clear_port_config(parent, port, logger):
-    """
-    Clear the port configuration (currently only no flood setting)
-
-    @param parent Object implementing controller and assert equal
-    @param logger Logging object
-    """
-    rv = port_config_set(parent.controller, port,
-                         0, ofp.OFPPC_NO_FLOOD, logger)
-    self.assertEqual(rv, 0, "Failed to reset port config")
-
-def required_wildcards(parent):
-    w = test_param_get(parent.config, 'required_wildcards', default='default')
-    if w == 'l3-l4':
-        return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
-                | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
-    else:
-        return 0
-
-def simple_tcp_packet(pktlen=100, 
-                      dl_dst='00:01:02:03:04:05',
-                      dl_src='00:06:07:08:09:0a',
-                      dl_vlan_enable=False,
-                      dl_vlan=0,
-                      dl_vlan_pcp=0,
-                      dl_vlan_cfi=0,
-                      ip_src='192.168.0.1',
-                      ip_dst='192.168.0.2',
-                      ip_tos=0,
-                      tcp_sport=1234,
-                      tcp_dport=80
-                      ):
-    """
-    Return a simple dataplane TCP packet
-
-    Supports a few parameters:
-    @param len Length of packet in bytes w/o CRC
-    @param dl_dst Destinatino MAC
-    @param dl_src Source MAC
-    @param dl_vlan_enable True if the packet is with vlan, False otherwise
-    @param dl_vlan VLAN ID
-    @param dl_vlan_pcp VLAN priority
-    @param ip_src IP source
-    @param ip_dst IP destination
-    @param ip_tos IP ToS
-    @param tcp_dport TCP destination port
-    @param ip_sport TCP source port
-
-    Generates a simple TCP request.  Users
-    shouldn't assume anything about this packet other than that
-    it is a valid ethernet/IP/TCP frame.
-    """
-
-    if MINSIZE > pktlen:
-        pktlen = MINSIZE
-
-    # Note Dot1Q.id is really CFI
-    if (dl_vlan_enable):
-        pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
-            scapy.Dot1Q(prio=dl_vlan_pcp, id=dl_vlan_cfi, vlan=dl_vlan)/ \
-            scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
-            scapy.TCP(sport=tcp_sport, dport=tcp_dport)
-    else:
-        pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
-            scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
-            scapy.TCP(sport=tcp_sport, dport=tcp_dport)
-
-    pkt = pkt/("D" * (pktlen - len(pkt)))
-
-    return pkt
-
-def simple_icmp_packet(pktlen=60, 
-                      dl_dst='00:01:02:03:04:05',
-                      dl_src='00:06:07:08:09:0a',
-                      dl_vlan_enable=False,
-                      dl_vlan=0,
-                      dl_vlan_pcp=0,
-                      ip_src='192.168.0.1',
-                      ip_dst='192.168.0.2',
-                      ip_tos=0,
-                      icmp_type=8,
-                      icmp_code=0
-                      ):
-    """
-    Return a simple ICMP packet
-
-    Supports a few parameters:
-    @param len Length of packet in bytes w/o CRC
-    @param dl_dst Destinatino MAC
-    @param dl_src Source MAC
-    @param dl_vlan_enable True if the packet is with vlan, False otherwise
-    @param dl_vlan VLAN ID
-    @param dl_vlan_pcp VLAN priority
-    @param ip_src IP source
-    @param ip_dst IP destination
-    @param ip_tos IP ToS
-    @param icmp_type ICMP type
-    @param icmp_code ICMP code
-
-    Generates a simple ICMP ECHO REQUEST.  Users
-    shouldn't assume anything about this packet other than that
-    it is a valid ethernet/ICMP frame.
-    """
-
-    if MINSIZE > pktlen:
-        pktlen = MINSIZE
-
-    if (dl_vlan_enable):
-        pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
-            scapy.Dot1Q(prio=dl_vlan_pcp, id=0, vlan=dl_vlan)/ \
-            scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
-            scapy.ICMP(type=icmp_type, code=icmp_code)
-    else:
-        pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
-            scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
-            scapy.ICMP(type=icmp_type, code=icmp_code)
-
-    pkt = pkt/("0" * (pktlen - len(pkt)))
-
-    return pkt
-
-def simple_eth_packet(pktlen=60,
-                      dl_dst='00:01:02:03:04:05',
-                      dl_src='01:80:c2:00:00:00',
-                      dl_type=0x88cc):
-
-    if MINSIZE > pktlen:
-        pktlen = MINSIZE
-
-    pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=dl_type)
-
-    pkt = pkt/("0" * (pktlen - len(pkt)))
-
-    return pkt
-
-def do_barrier(ctrl):
-    """
-    Do a barrier command
-    Return 0 on success, -1 on error
-    """
-    b = message.barrier_request()
-    (resp, pkt) = ctrl.transact(b)
-    # We'll trust the transaction processing in the controller that xid matched
-    if not resp:
-        return -1
-    return 0
-
-def port_config_get(controller, port_no, logger):
-    """
-    Get a port's configuration
-
-    Gets the switch feature configuration and grabs one port's
-    configuration
-
-    @returns (hwaddr, config, advert) The hwaddress, configuration and
-    advertised values
-    """
-    request = message.features_request()
-    reply, pkt = controller.transact(request)
-    logger.debug(reply.show())
-    if reply is None:
-        logger.warn("Get feature request failed")
-        return None, None, None
-    for idx in range(len(reply.ports)):
-        if reply.ports[idx].port_no == port_no:
-            return (reply.ports[idx].hw_addr, reply.ports[idx].config,
-                    reply.ports[idx].advertised)
-    
-    logger.warn("Did not find port number for port config")
-    return None, None, None
-
-def port_config_set(controller, port_no, config, mask, logger):
-    """
-    Set the port configuration according the given parameters
-
-    Gets the switch feature configuration and updates one port's
-    configuration value according to config and mask
-    """
-    logger.info("Setting port " + str(port_no) + " to config " + str(config))
-    request = message.features_request()
-    reply, pkt = controller.transact(request)
-    if reply is None:
-        return -1
-    logger.debug(reply.show())
-    for idx in range(len(reply.ports)):
-        if reply.ports[idx].port_no == port_no:
-            break
-    if idx >= len(reply.ports):
-        return -1
-    mod = message.port_mod()
-    mod.port_no = port_no
-    mod.hw_addr = reply.ports[idx].hw_addr
-    mod.config = config
-    mod.mask = mask
-    mod.advertise = reply.ports[idx].advertised
-    rv = controller.message_send(mod)
-    return rv
-
-def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if, logger,
-                      config):
-    """
-    Check for proper receive packets across all ports
-    @param dp The dataplane object
-    @param pkt Expected packet; may be None if yes_ports is empty
-    @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
-    """
-    exp_pkt_arg = None
-    if config and config["relax"]:
-        exp_pkt_arg = pkt
-
-    for ofport in yes_ports:
-        logger.debug("Checking for pkt on port " + str(ofport))
-        (rcv_port, rcv_pkt, pkt_time) = dp.poll(
-            port_number=ofport, exp_pkt=exp_pkt_arg)
-        assert_if.assertTrue(rcv_pkt is not None, 
-                             "Did not receive pkt on " + str(ofport))
-        if not dataplane.match_exp_pkt(pkt, rcv_pkt):
-            logger.debug("Sent %s" % format_packet(pkt))
-            logger.debug("Resp %s" % format_packet(rcv_pkt))
-        assert_if.assertTrue(dataplane.match_exp_pkt(pkt, rcv_pkt),
-                             "Response packet does not match send packet " +
-                             "on port " + str(ofport))
-    if len(no_ports) > 0:
-        time.sleep(1)
-    for ofport in no_ports:
-        logger.debug("Negative check for pkt on port " + str(ofport))
-        (rcv_port, rcv_pkt, pkt_time) = dp.poll(
-            port_number=ofport, timeout=1, exp_pkt=exp_pkt_arg)
-        assert_if.assertTrue(rcv_pkt is None, 
-                             "Unexpected pkt on port " + str(ofport))
-
-
-def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
-    """
-    Receive a packet and verify it matches an expected value
-    @param egr_port A single port or list of ports
-
-    parent must implement dataplane, assertTrue and assertEqual
-    """
-    exp_pkt_arg = None
-    if parent.config["relax"]:
-        exp_pkt_arg = exp_pkt
-
-    if type(egr_ports) == type([]):
-        egr_port_list = egr_ports
-    else:
-        egr_port_list = [egr_ports]
-
-    # Expect a packet from each port on egr port list
-    for egr_port in egr_port_list:
-        check_port = egr_port
-        if egr_port == ofp.OFPP_IN_PORT:
-            check_port = ing_port
-        (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
-            port_number=check_port, exp_pkt=exp_pkt_arg)
-
-        if rcv_pkt is None:
-            parent.logger.error("ERROR: No packet received from " + 
-                                str(check_port))
-
-        parent.assertTrue(rcv_pkt is not None,
-                          "Did not receive packet port " + str(check_port))
-        parent.logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
-                            str(rcv_port))
-
-        if str(exp_pkt) != str(rcv_pkt):
-            parent.logger.error("ERROR: Packet match failed.")
-            parent.logger.debug("Expected len " + str(len(exp_pkt)) + ": "
-                                + str(exp_pkt).encode('hex'))
-            parent.logger.debug("Received len " + str(len(rcv_pkt)) + ": "
-                                + str(rcv_pkt).encode('hex'))
-        parent.assertEqual(str(exp_pkt), str(rcv_pkt),
-                           "Packet match error on port " + str(check_port))
-
-def match_verify(parent, req_match, res_match):
-    """
-    Verify flow matches agree; if they disagree, report where
-
-    parent must implement assertEqual
-    Use str() to ensure content is compared and not pointers
-    """
-
-    parent.assertEqual(req_match.wildcards, res_match.wildcards,
-                       'Match failed: wildcards: ' + hex(req_match.wildcards) +
-                       " != " + hex(res_match.wildcards))
-    parent.assertEqual(req_match.in_port, res_match.in_port,
-                       'Match failed: in_port: ' + str(req_match.in_port) +
-                       " != " + str(res_match.in_port))
-    parent.assertEqual(str(req_match.dl_src), str(res_match.dl_src),
-                       'Match failed: dl_src: ' + str(req_match.dl_src) +
-                       " != " + str(res_match.dl_src))
-    parent.assertEqual(str(req_match.dl_dst), str(res_match.dl_dst),
-                       'Match failed: dl_dst: ' + str(req_match.dl_dst) +
-                       " != " + str(res_match.dl_dst))
-    parent.assertEqual(req_match.dl_vlan, res_match.dl_vlan,
-                       'Match failed: dl_vlan: ' + str(req_match.dl_vlan) +
-                       " != " + str(res_match.dl_vlan))
-    parent.assertEqual(req_match.dl_vlan_pcp, res_match.dl_vlan_pcp,
-                       'Match failed: dl_vlan_pcp: ' + 
-                       str(req_match.dl_vlan_pcp) + " != " + 
-                       str(res_match.dl_vlan_pcp))
-    parent.assertEqual(req_match.dl_type, res_match.dl_type,
-                       'Match failed: dl_type: ' + str(req_match.dl_type) +
-                       " != " + str(res_match.dl_type))
-
-    if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
-        and (req_match.dl_type == IP_ETHERTYPE)):
-        parent.assertEqual(req_match.nw_tos, res_match.nw_tos,
-                           'Match failed: nw_tos: ' + str(req_match.nw_tos) +
-                           " != " + str(res_match.nw_tos))
-        parent.assertEqual(req_match.nw_proto, res_match.nw_proto,
-                           'Match failed: nw_proto: ' + str(req_match.nw_proto) +
-                           " != " + str(res_match.nw_proto))
-        parent.assertEqual(req_match.nw_src, res_match.nw_src,
-                           'Match failed: nw_src: ' + str(req_match.nw_src) +
-                           " != " + str(res_match.nw_src))
-        parent.assertEqual(req_match.nw_dst, res_match.nw_dst,
-                           'Match failed: nw_dst: ' + str(req_match.nw_dst) +
-                           " != " + str(res_match.nw_dst))
-
-        if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
-            and ((req_match.nw_proto == TCP_PROTOCOL)
-                 or (req_match.nw_proto == UDP_PROTOCOL))):
-            parent.assertEqual(req_match.tp_src, res_match.tp_src,
-                               'Match failed: tp_src: ' + 
-                               str(req_match.tp_src) +
-                               " != " + str(res_match.tp_src))
-            parent.assertEqual(req_match.tp_dst, res_match.tp_dst,
-                               'Match failed: tp_dst: ' + 
-                               str(req_match.tp_dst) +
-                               " != " + str(res_match.tp_dst))
-
-def flow_removed_verify(parent, request=None, pkt_count=-1, byte_count=-1):
-    """
-    Receive a flow removed msg and verify it matches expected
-
-    @params parent Must implement controller, assertEqual
-    @param pkt_count If >= 0, verify packet count
-    @param byte_count If >= 0, verify byte count
-    """
-    (response, raw) = parent.controller.poll(ofp.OFPT_FLOW_REMOVED, 2)
-    parent.assertTrue(response is not None, 'No flow removed message received')
-
-    if request is None:
-        return
-
-    parent.assertEqual(request.cookie, response.cookie,
-                       "Flow removed cookie error: " +
-                       hex(request.cookie) + " != " + hex(response.cookie))
-
-    req_match = request.match
-    res_match = response.match
-    verifyMatchField(req_match, res_match)
-
-    if (req_match.wildcards != 0):
-        parent.assertEqual(request.priority, response.priority,
-                           'Flow remove prio mismatch: ' + 
-                           str(request,priority) + " != " + 
-                           str(response.priority))
-        parent.assertEqual(response.reason, ofp.OFPRR_HARD_TIMEOUT,
-                           'Flow remove reason is not HARD TIMEOUT:' +
-                           str(response.reason))
-        if pkt_count >= 0:
-            parent.assertEqual(response.packet_count, pkt_count,
-                               'Flow removed failed, packet count: ' + 
-                               str(response.packet_count) + " != " +
-                               str(pkt_count))
-        if byte_count >= 0:
-            parent.assertEqual(response.byte_count, byte_count,
-                               'Flow removed failed, byte count: ' + 
-                               str(response.byte_count) + " != " + 
-                               str(byte_count))
-
-def packet_to_flow_match(parent, packet):
-    match = parse.packet_to_flow_match(packet)
-    match.wildcards |= required_wildcards(parent)
-    return match
-
-def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
-               egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
-    """
-    Create a flow message
-
-    Match on packet with given wildcards.  
-    See flow_match_test for other parameter descriptoins
-    @param egr_queue if not None, make the output an enqueue action
-    @param in_band if True, do not wildcard ingress port
-    @param egr_ports None (drop), single port or list of ports
-    """
-    match = parse.packet_to_flow_match(pkt)
-    parent.assertTrue(match is not None, "Flow match from pkt failed")
-    if wildcards is None:
-        wildcards = required_wildcards(parent)
-    if in_band:
-        wildcards &= ~ofp.OFPFW_IN_PORT
-    match.wildcards = wildcards
-    match.in_port = ing_port
-
-    if type(egr_ports) == type([]):
-        egr_port_list = egr_ports
-    else:
-        egr_port_list = [egr_ports]
-
-    request = message.flow_mod()
-    request.match = match
-    request.buffer_id = 0xffffffff
-    if check_expire:
-        request.flags |= ofp.OFPFF_SEND_FLOW_REM
-        request.hard_timeout = 1
-
-    if action_list is not None:
-        for act in action_list:
-            parent.logger.debug("Adding action " + act.show())
-            rv = request.actions.add(act)
-            parent.assertTrue(rv, "Could not add action" + act.show())
-
-    # Set up output/enqueue action if directed
-    if egr_queue is not None:
-        parent.assertTrue(egr_ports is not None, "Egress port not set")
-        act = action.action_enqueue()
-        for egr_port in egr_port_list:
-            act.port = egr_port
-            act.queue_id = egr_queue
-            rv = request.actions.add(act)
-            parent.assertTrue(rv, "Could not add enqueue action " + 
-                              str(egr_port) + " Q: " + str(egr_queue))
-    elif egr_ports is not None:
-        for egr_port in egr_port_list:
-            act = action.action_output()
-            act.port = egr_port
-            rv = request.actions.add(act)
-            parent.assertTrue(rv, "Could not add output action " + 
-                              str(egr_port))
-
-    parent.logger.debug(request.show())
-
-    return request
-
-def flow_msg_install(parent, request, clear_table_override=None):
-    """
-    Install a flow mod message in the switch
-
-    @param parent Must implement controller, assertEqual, assertTrue
-    @param request The request, all set to go
-    @param clear_table If true, clear the flow table before installing
-    """
-
-    clear_table = test_param_get(parent.config, 'clear_table', default=True)
-    if(clear_table_override != None):
-        clear_table = clear_table_override
-
-    if clear_table: 
-        parent.logger.debug("Clear flow table")
-        rc = delete_all_flows(parent.controller, parent.logger)
-        parent.assertEqual(rc, 0, "Failed to delete all flows")
-        parent.assertEqual(do_barrier(parent.controller), 0, "Barrier failed")
-
-    parent.logger.debug("Insert flow")
-    rv = parent.controller.message_send(request)
-    parent.assertTrue(rv != -1, "Error installing flow mod")
-    parent.assertEqual(do_barrier(parent.controller), 0, "Barrier failed")
-
-def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
-                              dl_vlan=-1, pkt=None, exp_pkt=None,
-                              action_list=None, check_expire=False):
-    """
-    Flow match test on single TCP packet
-    @param egr_ports A single port or list of ports
-
-    Run test with packet through switch from ing_port to egr_port
-    See flow_match_test for parameter descriptions
-    """
-
-    if wildcards is None:
-        wildcards = required_wildcards(parent)
-    parent.logger.info("Pkt match test: " + str(ing_port) + " to " + 
-                       str(egr_ports))
-    parent.logger.debug("  WC: " + hex(wildcards) + " vlan: " + str(dl_vlan) +
-                    " expire: " + str(check_expire))
-    if pkt is None:
-        pkt = simple_tcp_packet(dl_vlan_enable=(dl_vlan >= 0), dl_vlan=dl_vlan)
-
-    request = flow_msg_create(parent, pkt, ing_port=ing_port, 
-                              wildcards=wildcards, egr_ports=egr_ports,
-                              action_list=action_list)
-
-    flow_msg_install(parent, request)
-
-    parent.logger.debug("Send packet: " + str(ing_port) + " to " + 
-                        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)
-
-    if check_expire:
-        #@todo Not all HW supports both pkt and byte counters
-        flow_removed_verify(parent, request, pkt_count=1, byte_count=len(pkt))
-
-def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
-    """
-    Generate a list of ports avoiding those in the exclude list
-    @param parent Supplies logger
-    @param of_ports List of OF port numbers
-    @param how_many Number of ports to be added to the list
-    @param exclude_list List of ports not to be used
-    @returns An empty list if unable to find enough ports
-    """
-
-    if how_many == 0:
-        return []
-
-    count = 0
-    egr_ports = []
-    for egr_idx in range(len(of_ports)): 
-        if of_ports[egr_idx] not in exclude_list:
-            egr_ports.append(of_ports[egr_idx])
-            count += 1
-            if count >= how_many:
-                return egr_ports
-    parent.logger.debug("Could not generate enough egress ports for test")
-    return []
-    
-def flow_match_test(parent, port_map, wildcards=None, dl_vlan=-1, pkt=None, 
-                    exp_pkt=None, action_list=None, check_expire=False, 
-                    max_test=0, egr_count=1, ing_port=False):
-    """
-    Run flow_match_test_port_pair on all port pairs
-
-    @param max_test If > 0 no more than this number of tests are executed.
-    @param parent Must implement controller, dataplane, assertTrue, assertEqual
-    and logger
-    @param pkt If not None, use this packet for ingress
-    @param wildcards For flow match entry
-    @param dl_vlan If not -1, and pkt is None, create a pkt w/ VLAN tag
-    @param exp_pkt If not None, use this as the expected output pkt; els use pkt
-    @param action_list Additional actions to add to flow mod
-    @param check_expire Check for flow expiration message
-    @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
-    """
-    if wildcards is None:
-        wildcards = required_wildcards(parent)
-    of_ports = port_map.keys()
-    of_ports.sort()
-    parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
-    test_count = 0
-
-    if egr_count == -1:
-        egr_count = test_param_get(parent.config, 'egr_count', default=2)
-    
-    for ing_idx in range(len(of_ports)):
-        ingress_port = of_ports[ing_idx]
-        egr_ports = get_egr_list(parent, of_ports, egr_count, 
-                                 exclude_list=[ingress_port])
-        if ing_port:
-            egr_ports.append(ofp.OFPP_IN_PORT)
-        if len(egr_ports) == 0:
-            parent.assertTrue(0, "Failed to generate egress port list")
-
-        flow_match_test_port_pair(parent, ingress_port, egr_ports, 
-                                  wildcards=wildcards, dl_vlan=dl_vlan, 
-                                  pkt=pkt, exp_pkt=exp_pkt,
-                                  action_list=action_list,
-                                  check_expire=check_expire)
-        test_count += 1
-        if (max_test > 0) and (test_count > max_test):
-            parent.logger.info("Ran " + str(test_count) + " tests; exiting")
-            return
-
-def test_param_get(config, key, default=None):
-    """
-    Return value passed via test-params if present
-
-    @param config The configuration structure for OFTest
-    @param key The lookup key
-    @param default Default value to use if not found
-
-    If the pair 'key=val' appeared in the string passed to --test-params
-    on the command line, return val (as interpreted by exec).  Otherwise
-    return default value.
-
-    WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS; 
-    eg egr_count, not egr-count.
-    """
-    try:
-        exec config["test_params"]
-    except:
-        return default
-
-    s = "val = " + str(key)
-    try:
-        exec s
-        return val
-    except:
-        return default
-
-def action_generate(parent, field_to_mod, mod_field_vals):
-    """
-    Create an action to modify the field indicated in field_to_mod
-
-    @param parent Must implement, assertTrue
-    @param field_to_mod The field to modify as a string name
-    @param mod_field_vals Hash of values to use for modified values
-    """
-
-    act = None
-
-    if field_to_mod in ['pktlen']:
-        return None
-
-    if field_to_mod == 'dl_dst':
-        act = action.action_set_dl_dst()
-        act.dl_addr = parse.parse_mac(mod_field_vals['dl_dst'])
-    elif field_to_mod == 'dl_src':
-        act = action.action_set_dl_src()
-        act.dl_addr = parse.parse_mac(mod_field_vals['dl_src'])
-    elif field_to_mod == 'dl_vlan_enable':
-        if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
-            act = action.action_strip_vlan()
-        # Add VLAN tag is handled by dl_vlan field
-        # Will return None in this case
-    elif field_to_mod == 'dl_vlan':
-        act = action.action_set_vlan_vid()
-        act.vlan_vid = mod_field_vals['dl_vlan']
-    elif field_to_mod == 'dl_vlan_pcp':
-        act = action.action_set_vlan_pcp()
-        act.vlan_pcp = mod_field_vals['dl_vlan_pcp']
-    elif field_to_mod == 'ip_src':
-        act = action.action_set_nw_src()
-        act.nw_addr = parse.parse_ip(mod_field_vals['ip_src'])
-    elif field_to_mod == 'ip_dst':
-        act = action.action_set_nw_dst()
-        act.nw_addr = parse.parse_ip(mod_field_vals['ip_dst'])
-    elif field_to_mod == 'ip_tos':
-        act = action.action_set_nw_tos()
-        act.nw_tos = mod_field_vals['ip_tos']
-    elif field_to_mod == 'tcp_sport':
-        act = action.action_set_tp_src()
-        act.tp_port = mod_field_vals['tcp_sport']
-    elif field_to_mod == 'tcp_dport':
-        act = action.action_set_tp_dst()
-        act.tp_port = mod_field_vals['tcp_dport']
-    else:
-        parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
-
-    return act
-
-def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={}, 
-                     mod_fields={}, check_test_params=False):
-    """
-    Set up the ingress and expected packet and action list for a test
-
-    @param parent Must implement, assertTrue, config hash and logger
-    @param start_field_values Field values to use for ingress packet (optional)
-    @param mod_field_values Field values to use for modified packet (optional)
-    @param mod_fields The list of fields to be modified by the switch in the test.
-    @params check_test_params If True, will check the parameters vid, add_vlan
-    and strip_vlan from the command line.
-
-    Returns a triple:  pkt-to-send, expected-pkt, action-list
-    """
-
-    new_actions = []
-
-    base_pkt_params = {}
-    base_pkt_params['pktlen'] = 100
-    base_pkt_params['dl_dst'] = '00:DE:F0:12:34:56'
-    base_pkt_params['dl_src'] = '00:23:45:67:89:AB'
-    base_pkt_params['dl_vlan_enable'] = False
-    base_pkt_params['dl_vlan'] = 2
-    base_pkt_params['dl_vlan_pcp'] = 0
-    base_pkt_params['ip_src'] = '192.168.0.1'
-    base_pkt_params['ip_dst'] = '192.168.0.2'
-    base_pkt_params['ip_tos'] = 0
-    base_pkt_params['tcp_sport'] = 1234
-    base_pkt_params['tcp_dport'] = 80
-    for keyname in start_field_vals.keys():
-        base_pkt_params[keyname] = start_field_vals[keyname]
-
-    mod_pkt_params = {}
-    mod_pkt_params['pktlen'] = 100
-    mod_pkt_params['dl_dst'] = '00:21:0F:ED:CB:A9'
-    mod_pkt_params['dl_src'] = '00:ED:CB:A9:87:65'
-    mod_pkt_params['dl_vlan_enable'] = False
-    mod_pkt_params['dl_vlan'] = 3
-    mod_pkt_params['dl_vlan_pcp'] = 7
-    mod_pkt_params['ip_src'] = '10.20.30.40'
-    mod_pkt_params['ip_dst'] = '50.60.70.80'
-    mod_pkt_params['ip_tos'] = 0xf0
-    mod_pkt_params['tcp_sport'] = 4321
-    mod_pkt_params['tcp_dport'] = 8765
-    for keyname in mod_field_vals.keys():
-        mod_pkt_params[keyname] = mod_field_vals[keyname]
-
-    # Check for test param modifications
-    strip = False
-    if check_test_params:
-        add_vlan = test_param_get(parent.config, 'add_vlan')
-        strip_vlan = test_param_get(parent.config, 'strip_vlan')
-        vid = test_param_get(parent.config, 'vid')
-
-        if add_vlan and strip_vlan:
-            parent.assertTrue(0, "Add and strip VLAN both specified")
-
-        if vid:
-            base_pkt_params['dl_vlan_enable'] = True
-            base_pkt_params['dl_vlan'] = vid
-            if 'dl_vlan' in mod_fields:
-                mod_pkt_params['dl_vlan'] = vid + 1
-
-        if add_vlan:
-            base_pkt_params['dl_vlan_enable'] = False
-            mod_pkt_params['dl_vlan_enable'] = True
-            mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
-            mod_fields.append('pktlen')
-            mod_fields.append('dl_vlan_enable')
-            if 'dl_vlan' not in mod_fields:
-                mod_fields.append('dl_vlan')
-        elif strip_vlan:
-            base_pkt_params['dl_vlan_enable'] = True
-            mod_pkt_params['dl_vlan_enable'] = False
-            mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
-            mod_fields.append('dl_vlan_enable')
-            mod_fields.append('pktlen')
-
-    # Build the ingress packet
-    ingress_pkt = simple_tcp_packet(**base_pkt_params)
-
-    # Build the expected packet, modifying the indicated fields
-    for item in mod_fields:
-        base_pkt_params[item] = mod_pkt_params[item]
-        act = action_generate(parent, item, mod_pkt_params)
-        if act:
-            new_actions.append(act)
-
-    expected_pkt = simple_tcp_packet(**base_pkt_params)
-
-    return (ingress_pkt, expected_pkt, new_actions)
-
-# Generate a simple "drop" flow mod
-# If in_band is true, then only drop from first test port
-def flow_mod_gen(port_map, in_band):
-    request = message.flow_mod()
-    request.match.wildcards = ofp.OFPFW_ALL
-    if in_band:
-        request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
-        for of_port, ifname in port_map.items(): # Grab first port
-            break
-        request.match.in_port = of_port
-    request.buffer_id = 0xffffffff
-    return request
-
-def skip_message_emit(parent, s):
-    """
-    Print out a 'skipped' message to stderr
-
-    @param s The string to print out to the log file
-    @param parent Must implement config and logger objects
-    """
-    global skipped_test_count
-
-    skipped_test_count += 1
-    parent.logger.info("Skipping: " + s)
-    if parent.config["dbg_level"] < logging.WARNING:
-        sys.stderr.write("(skipped) ")
-    else:
-        sys.stderr.write("(S)")
-
-
-def all_stats_get(parent):
-    """
-    Get the aggregate stats for all flows in the table
-    @param parent Test instance with controller connection and assert
-    @returns dict with keys flows, packets, bytes, active (flows), 
-    lookups, matched
-    """
-    stat_req = message.aggregate_stats_request()
-    stat_req.match = ofp.ofp_match()
-    stat_req.match.wildcards = ofp.OFPFW_ALL
-    stat_req.table_id = 0xff
-    stat_req.out_port = ofp.OFPP_NONE
-
-    rv = {}
-
-    (reply, pkt) = parent.controller.transact(stat_req)
-    parent.assertTrue(len(reply.stats) == 1, "Did not receive flow stats reply")
-
-    for obj in reply.stats:
-        (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count, 
-                                                  obj.packet_count, obj.byte_count)
-        break
-
-    request = message.table_stats_request()
-    (reply , pkt) = parent.controller.transact(request)
-
-    
-    (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
-    for obj in reply.stats:
-        rv["active"] += obj.active_count
-        rv["lookups"] += obj.lookup_count
-        rv["matched"] += obj.matched_count
-
-    return rv
-
-FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' 
-                for x in range(256)])
-
-def hex_dump_buffer(src, length=16):
-    """
-    Convert src to a hex dump string and return the string
-    @param src The source buffer
-    @param length The number of bytes shown in each line
-    @returns A string showing the hex dump
-    """
-    result = ["\n"]
-    for i in xrange(0, len(src), length):
-       chars = src[i:i+length]
-       hex = ' '.join(["%02x" % ord(x) for x in chars])
-       printable = ''.join(["%s" % ((ord(x) <= 127 and
-                                     FILTER[ord(x)]) or '.') for x in chars])
-       result.append("%04x  %-*s  %s\n" % (i, length*3, hex, printable))
-    return ''.join(result)
-
-def format_packet(pkt):
-    return "Packet length %d \n%s" % (len(str(pkt)), 
-                                      hex_dump_buffer(str(pkt)))