Merge branch 'master' into kenc

Conflicts:
	tests/cxn.py - manually resolved
diff --git a/README b/README
index 0c8ba3d..a8cd199 100644
--- a/README
+++ b/README
@@ -126,7 +126,7 @@
         4A. Check out openflow (preferably at the same level as oftest):
             git clone git://openflowswitch.org/openflow.git
         4B. cd openflow; ./boot.sh; ./configure; make
-        4C. cd ../oftest/tests
+        4C. cd ../oftest
         4D. Run the switch startup script:
             sudo ./run_switch.py; Now you can run oft (see below).
         4F. Use --help to see command line switches.  If you use a port
diff --git a/oft b/oft
index 3e26d52..58b8912 100755
--- a/oft
+++ b/oft
@@ -30,28 +30,20 @@
 <pre>
     dbg_level         : logging module value of debug level
     port_map          : Map of dataplane OpenFlow port to OS interface names
-    test_mod_map      : Dictionary indexed by module names and whose value
-                        is the module reference
-    all_tests         : Dictionary indexed by module reference and whose
-                        value is a list of functions in that module
 </pre>
 
-Each test may be assigned a priority by setting test_prio["TestName"] in 
-the respective module.  For now, the only use of this is to avoid 
+Each test may be assigned a priority by setting the "priority" property
+in the class definition.  For now, the only use of this is to avoid
 automatic inclusion of tests into the default list.  This is done by
-setting the test_prio value less than 0.  Eventually we may add ordering
+setting the priority value less than 0.  Eventually we may add ordering
 of test execution by test priority.
 
 To add a test to the system, either: edit an existing test case file (like
 basic.py) to add a test class which inherits from unittest.TestCase (directly
-or indirectly); or add a new file which includes a function definition 
-test_set_init(config).  Preferably the file is in the same directory as existing
-tests, though you can specify the directory on the command line.  The file
-should not be called "all" as that's reserved for the test-spec.
-
-If you add a new file, the test_set_init function should record the port
-map object from the configuration along with whatever other configuration 
-information it may need.
+or indirectly); or add a new file with the test case class.  Preferably the
+file is in the same directory as existing tests, though you can specify the
+directory on the command line.  The file should not be called "all" as that's
+reserved for the test-spec.
 
 TBD:  To add configuration to the system, first add an entry to config_default
 below.  If you want this to be a command line parameter, edit config_setup
@@ -72,10 +64,7 @@
 use the parameter --platform=gp104 on the command line. You can also use the
 --platform-dir option to change which directory is searched.
 
-The current model for test sets is basic.py.  The current convention is
-that the test set should implement a function test_set_init which takes
-an oft configuration dictionary and returns a unittest.TestSuite object.
-Future test sets should do the same thing.
+The current model for test sets is basic.py.
 
 Default setup:
 
@@ -94,17 +83,12 @@
 Examine oft.log if things don't work.
 
 @todo Support per-component debug levels (esp controller vs dataplane)
-@todo Consider moving oft up a level
+@todo Allow specification of priority to override prio check
 
 Current test case setup:
-    Files in the tests direcoty that contain a function test_set_init are
-considered test files.
-    The function test_set_init examines the test_spec config variable
-and generates a suite of tests.
-    Support a command line option --test_mod so that all tests in that
-module will be run.
-    Support all to specify all tests from the module.
-
+    File with the .py extension in the test directory are considered test files.
+    Support a command line option --test-spec to choose the tests to run.
+    Support test-spec "all" to specify all tests.
 """
 
 import sys
@@ -116,6 +100,8 @@
 import os
 import imp
 import random
+import signal
+import fnmatch
 
 root_dir = os.path.dirname(os.path.realpath(__file__))
 
@@ -124,6 +110,9 @@
     # Running from source tree
     sys.path.insert(0, pydir)
 
+import oftest
+from oftest import config
+
 try:
     import oftest.message
 except:
@@ -198,7 +187,7 @@
     "Convert options class to OFT configuration dictionary"
     cfg = config_default.copy()
     for key in cfg.keys():
-        cfg[key] = eval("opts." + key)
+        cfg[key] = getattr(opts, key)
 
     # Special case checks
     if opts.debug not in DEBUG_LEVELS.keys():
@@ -223,8 +212,7 @@
 
     #@todo parse port map as option?
     # Set up default values
-    for key in cfg_dflt.keys():
-        eval("parser.set_defaults("+key+"=cfg_dflt['"+key+"'])")
+    parser.set_defaults(**cfg_dflt)
 
     #@todo Add options via dictionary
     plat_help = """Set the platform type.  Valid values include:
@@ -259,7 +247,7 @@
                       help="List only test names.", default=False)
     parser.add_option("--list", action="store_true",
                       help="List all tests and exit")
-    parser.add_option("--verbose", action="store_true",
+    parser.add_option("-v", "--verbose", action="store_true",
                       help="Short cut for --debug=verbose")
     parser.add_option("--relax", action="store_true",
                       help="Relax packet match checks allowing other packets")
@@ -324,61 +312,101 @@
                         level=config["dbg_level"],
                         format=_format, datefmt=_datefmt)
 
-def test_list_generate(config):
-    """Generate the list of all known tests indexed by module name
+def load_test_modules(config):
+    """
+    Load tests from the test_dir directory.
 
-    Conventions:  Test files must implement the function test_set_init
-
-    Test cases are classes that implement runTest
+    Test cases are subclasses of unittest.TestCase
 
     @param config The oft configuration dictionary
-    @returns An array of triples (mod-name, module, [tests]) where 
-    mod-name is the string (filename) of the module, module is the
-    value returned from __import__'ing the module and [tests] is an
-    array of strings giving the test cases from the module.  
+    @returns A dictionary from test module names to tuples of
+    (module, dictionary from test names to test classes).
     """
 
-    # Find and import test files
-    p1 = Popen(["find", config["test_dir"], "-type","f"], stdout = PIPE)
-    p2 = Popen(["xargs", "grep", "-l", "-e", "^def test_set_init"], 
-                stdin=p1.stdout, stdout=PIPE)
+    result = {}
 
-    all_tests = {}
-    mod_name_map = {}
-    # There's an extra empty entry at the end of the list 
-    filelist = p2.communicate()[0].split("\n")[:-1]
-    for file in filelist:
-        if file[-1:] == '~' or file[0] == '#':
-            continue
-        modname = os.path.splitext(os.path.basename(file))[0]
+    for root, dirs, filenames in os.walk(config["test_dir"]):
+        # Iterate over each python file
+        for filename in fnmatch.filter(filenames, '[!.]*.py'):
+            modname = os.path.splitext(os.path.basename(filename))[0]
 
-        try:
-            if sys.modules.has_key(modname):
-                mod = sys.modules[modname]
+            try:
+                if sys.modules.has_key(modname):
+                    mod = sys.modules[modname]
+                else:
+                    mod = imp.load_module(modname, *imp.find_module(modname, [root]))
+            except:
+                logging.warning("Could not import file " + filename)
+                raise
+
+            # Find all testcases defined in the module
+            tests = dict((k, v) for (k, v) in mod.__dict__.items() if type(v) == type and
+                                                                      issubclass(v, unittest.TestCase))
+            if tests:
+                result[modname] = (mod, tests)
+
+    return result
+
+def prune_tests(test_spec, test_modules):
+    """
+    Return tests matching a given test-spec.
+    @param test_spec A test-spec string.
+    @param test_modules Same format as the output of load_test_modules.
+    @returns Same format as the output of load_test_modules.
+    """
+    result = {}
+    for (spec_modname, spec_testname) in parse_test_spec(test_spec):
+        matched = False
+        for (modname, (mod, tests)) in test_modules.items():
+            if (spec_modname == None or spec_modname == modname):
+                for (testname, test) in tests.items():
+                    if (spec_testname == None or spec_testname == testname):
+                            result.setdefault(modname, (mod, {}))
+                            result[modname][1][testname] = test
+                            matched = True
+        if not matched:
+            if spec_modname and spec_testname:
+                el = "%s.%s" % (spec_modname, spec_testname)
             else:
-                mod = imp.load_module(modname, *imp.find_module(modname, [os.path.dirname(file)]))
-        except:
-            logging.warning("Could not import file " + file)
-            raise
+                el = spec_modname or spec_testname or "all"
+            die("test-spec element %s did not match any tests" % el)
+    return result
 
-        tests = [k for k in dir(mod) if type(getattr(mod, k)) == type and
-                                        issubclass(getattr(mod, k), unittest.TestCase)]
-        if tests:
-            mod_name_map[modname] = mod
-            all_tests[mod] = tests
+def parse_test_spec(test_spec):
+    """
+    The input string is split on commas and each element is parsed
+    individually into a module name and test name. Either may be None
+    for a wildcard. The case of the first letter resolves ambiguity
+    of whether a word is a test or module name. The special string
+    "all" results in both fields wildcarded.
 
-    config["all_tests"] = all_tests
-    config["mod_name_map"] = mod_name_map
+    Examples:
+      basic.Echo -> ("basic", "Echo")
+      basic -> ("basic", None)
+      Echo -> (None, "Echo")
+      all -> (None, None)
+    """
+    results = []
+    for ts_entry in test_spec.split(","):
+        parts = ts_entry.split(".")
+        if len(parts) == 1:
+            if ts_entry == "all":
+                results.append((None, None))
+            elif ts_entry[0].isupper():
+                results.append((None, ts_entry))
+            else:
+                results.append((ts_entry, None))
+        elif len(parts) == 2:
+            results.append((parts[0], parts[1]))
+        else:
+            die("Bad test spec: " + ts_entry)
+    return results
 
 def die(msg, exit_val=1):
     print msg
     logging.critical(msg)
     sys.exit(exit_val)
 
-def add_test(suite, mod, name):
-    logging.info("Adding test " + mod.__name__ + "." + name)
-    suite.addTest(eval("mod." + name)())
-
 def _space_to(n, str):
     """
     Generate a string of spaces to achieve width n given string str
@@ -389,29 +417,27 @@
         return " " * spaces
     return " "
 
-def test_prio_get(mod, test):
+def test_prio_get(test):
     """
     Return the priority of a test
 
     If test is in "skip list" from profile, return the skip value
 
-    If set in the test_prio variable for the module, return
+    If the priority property is set in the class, return
     that value.  Otherwise return 100 (default)
     """
-    if test in profile_mod.skip_test_list:
-        logging.info("Skipping test %s due to profile" % test)
+    if test.__name__ in profile_mod.skip_test_list:
+        logging.info("Skipping test %s due to profile" % test.__name__)
         return TEST_PRIO_SKIP
-    if 'test_prio' in dir(mod):
-        if test in mod.test_prio.keys():
-            return mod.test_prio[test]
-    return TEST_PRIO_DEFAULT
+    return getattr(test, "priority", TEST_PRIO_DEFAULT)
 
 #
 # Main script
 #
 
-# Get configuration, set up logging, import platform from file
-(config, args) = config_setup(config_default)
+# Setup global configuration
+(new_config, args) = config_setup(config_default)
+oftest.config.update(new_config)
 
 logging_setup(config)
 logging.info("++++++++ " + time.asctime() + " ++++++++")
@@ -419,49 +445,40 @@
 # Allow tests to import each other
 sys.path.append(config["test_dir"])
 
-test_list_generate(config)
-oft_config = config
+test_modules = prune_tests(config["test_spec"], load_test_modules(config))
 
 load_profile(config)
 
 # Check if test list is requested; display and exit if so
 if config["list"]:
-    did_print = False
     mod_count = 0
     test_count = 0
     print "\nTest List:"
-    for mod in config["all_tests"].keys():
-        if config["test_spec"] != "all" and \
-                config["test_spec"] != mod.__name__:
-            continue
+    for (modname, (mod, tests)) in test_modules.items():
         mod_count += 1
-        did_print = True
         desc = mod.__doc__.strip()
         desc = desc.split('\n')[0]
         start_str = "  Module " + mod.__name__ + ": "
         print start_str + _space_to(22, start_str) + desc
-        for test in config["all_tests"][mod]:
+        for (testname, test) in tests.items():
             try:
-                desc = eval('mod.' + test + '.__doc__.strip()')
+                desc = test.__doc__.strip()
                 desc = desc.split('\n')[0]
             except:
                 desc = "No description"
-            if test_prio_get(mod, test) < 0:
-                start_str = "  * " + test + ":"
+            if test_prio_get(test) < 0:
+                start_str = "  * " + testname + ":"
             else:
-                start_str = "    " + test + ":"
+                start_str = "    " + testname + ":"
             if len(start_str) > 22:
                 desc = "\n" + _space_to(22, "") + desc
             print start_str + _space_to(22, start_str) + desc
             test_count += 1
         print
-    if not did_print:
-        print "No tests found for " + config["test_spec"]
-    else:
-        print "%d modules shown with a total of %d tests" % \
-            (mod_count, test_count)
-        print
-        print "Tests preceded by * are not run by default"
+    print "%d modules shown with a total of %d tests" % \
+        (mod_count, test_count)
+    print
+    print "Tests preceded by * are not run by default"
     print "Tests marked (TP1) after name take --test-params including:"
     print "    'vid=N;strip_vlan=bool;add_vlan=bool'"
     print "Note that --profile may override which tests are run"
@@ -469,66 +486,28 @@
 
 # Check if test list is requested; display and exit if so
 if config["list_test_names"]:
-    for mod in config["all_tests"].keys():
-        if config["test_spec"] != "all" and \
-                config["test_spec"] != mod.__name__:
-            continue
-        desc = mod.__doc__.strip()
-        desc = desc.split('\n')[0]
-        for test in config["all_tests"][mod]:
-            if test_prio_get(mod, test) >= 0:
-                print "%s.%s" % (mod.__name__, test)
+    for (modname, (mod, tests)) in test_modules.items():
+        for (testname, test) in tests.items():
+            if test_prio_get(test) >= 0:
+                print "%s.%s" % (modname, testname)
     sys.exit(0)
 
 # Generate the test suite
 #@todo Decide if multiple suites are ever needed
 suite = unittest.TestSuite()
 
-#@todo Allow specification of priority to override prio check
-if config["test_spec"] == "all":
-    for mod in config["all_tests"].keys(): 
-       for test in config["all_tests"][mod]:
-           # For now, a way to avoid tests
-           if test_prio_get(mod, test) >= 0:
-               add_test(suite, mod, test)
-
-else:
-    for ts_entry in config["test_spec"].split(","):
-        parts = ts_entry.split(".")
-
-        if len(parts) == 1: # Either a module or test name
-            if ts_entry in config["mod_name_map"].keys():
-                mod = config["mod_name_map"][ts_entry]
-                for test in config["all_tests"][mod]:
-                    if test_prio_get(mod, test) >= 0:
-                        add_test(suite, mod, test)
-            else: # Search for matching tests
-                test_found = False
-                for mod in config["all_tests"].keys():
-                    if ts_entry in config["all_tests"][mod]:
-                        add_test(suite, mod, ts_entry)
-                        test_found = True
-                if not test_found:
-                    die("Could not find module or test: " + ts_entry)
-
-        elif len(parts) == 2: # module.test
-            if parts[0] not in config["mod_name_map"]:
-                die("Unknown module in test spec: " + ts_entry)
-            mod = config["mod_name_map"][parts[0]]
-            if parts[1] in config["all_tests"][mod]:
-                add_test(suite, mod, parts[1])
-            else:
-                die("No known test matches: " + ts_entry)
-
-        else:
-            die("Bad test spec: " + ts_entry)
+for (modname, (mod, tests)) in test_modules.items():
+    for (testname, test) in tests.items():
+        if test_prio_get(test) >= 0:
+            logging.info("Adding test " + modname + "." + testname)
+            suite.addTest(test())
 
 # Load the platform module
 platform_name = config["platform"]
 logging.info("Importing platform: " + platform_name)
 platform_mod = None
 try:
-    platform_mod = imp.load_module(platform_name, *imp.find_module(platform_name, [config["platform_dir"], config["test_dir"]]))
+    platform_mod = imp.load_module(platform_name, *imp.find_module(platform_name, [config["platform_dir"]]))
 except:
     logging.warn("Failed to import " + platform_name + " platform module")
     raise
@@ -545,14 +524,6 @@
 logging.debug("Configuration: " + str(config))
 logging.info("OF port map: " + str(config["port_map"]))
 
-# Init the test sets
-for (modname,mod) in config["mod_name_map"].items():
-    try:
-        mod.test_set_init(config)
-    except:
-        logging.warning("Could not run test_set_init for " + modname)
-        raise
-
 if config["dbg_level"] == logging.CRITICAL:
     _verb = 0
 elif config["dbg_level"] >= logging.WARNING:
@@ -566,12 +537,15 @@
 if os.getuid() != 0 and not config["allow_user"]:
     print "ERROR: Super-user privileges required. Please re-run with " \
           "sudo or as root."
-    exit(1)
+    sys.exit(1)
 
 if config["random_seed"] is not None:
     logging.info("Random seed: %d" % config["random_seed"])
     random.seed(config["random_seed"])
 
+# Remove python's signal handler which raises KeyboardError. Exiting from an
+# exception waits for all threads to terminate which might not happen.
+signal.signal(signal.SIGINT, signal.SIG_DFL)
 
 if __name__ == "__main__":
     logging.info("*** TEST RUN START: " + time.asctime())
diff --git a/tests/run_switch.py b/run_switch.py
similarity index 100%
rename from tests/run_switch.py
rename to run_switch.py
diff --git a/src/python/oftest/__init__.py b/src/python/oftest/__init__.py
index 802dc75..c1cbb78 100644
--- a/src/python/oftest/__init__.py
+++ b/src/python/oftest/__init__.py
@@ -1 +1,5 @@
 '''Docstring to silence pylint; ignores --ignore option for __init__.py'''
+
+# Global config dictionary
+# Populated by oft.
+config = {}
diff --git a/src/python/oftest/base_tests.py b/src/python/oftest/base_tests.py
new file mode 100644
index 0000000..3664d9f
--- /dev/null
+++ b/src/python/oftest/base_tests.py
@@ -0,0 +1,142 @@
+"""
+Base classes for test cases
+
+Tests will usually inherit from one of these classes to have the controller
+and/or dataplane automatically set up.
+"""
+
+import logging
+import unittest
+
+from oftest import config
+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
+
+from oftest.testutils import *
+
+class SimpleProtocol(unittest.TestCase):
+    """
+    Root class for setting up the controller
+    """
+
+    def setUp(self):
+        logging.info("** START TEST CASE " + str(self))
+        self.controller = controller.Controller(
+            host=config["controller_host"],
+            port=config["controller_port"])
+        # clean_shutdown should be set to False to force quit app
+        self.clean_shutdown = True
+        self.controller.start()
+        #@todo Add an option to wait for a pkt transaction to ensure version
+        # compatibilty?
+        self.controller.connect(timeout=20)
+
+        # By default, respond to echo requests
+        self.controller.keep_alive = True
+        
+        if not self.controller.active:
+            raise Exception("Controller startup failed")
+        if self.controller.switch_addr is None: 
+            raise Exception("Controller startup failed (no switch addr)")
+        logging.info("Connected " + str(self.controller.switch_addr))
+        request = message.features_request()
+        reply, pkt = self.controller.transact(request)
+        self.assertTrue(reply is not None,
+                        "Did not complete features_request for handshake")
+        self.supported_actions = reply.actions
+        logging.info("Supported actions: " + hex(self.supported_actions))
+
+    def inheritSetup(self, parent):
+        """
+        Inherit the setup of a parent
+
+        This allows running at test from within another test.  Do the
+        following:
+
+        sub_test = SomeTestClass()  # Create an instance of the test class
+        sub_test.inheritSetup(self) # Inherit setup of parent
+        sub_test.runTest()          # Run the test
+
+        Normally, only the parent's setUp and tearDown are called and
+        the state after the sub_test is run must be taken into account
+        by subsequent operations.
+        """
+        logging.info("** Setup " + str(self) + " inheriting from "
+                          + str(parent))
+        self.controller = parent.controller
+        self.supported_actions = parent.supported_actions
+        
+    def tearDown(self):
+        logging.info("** END TEST CASE " + str(self))
+        self.controller.shutdown()
+        #@todo Review if join should be done on clean_shutdown
+        if self.clean_shutdown:
+            self.controller.join()
+
+    def runTest(self):
+        # Just a simple sanity check as illustration
+        logging.info("Running simple proto test")
+        self.assertTrue(self.controller.switch_socket is not None,
+                        str(self) + 'No connection to switch')
+
+    def assertTrue(self, cond, msg):
+        if not cond:
+            logging.error("** FAILED ASSERTION: " + msg)
+        unittest.TestCase.assertTrue(self, cond, msg)
+
+class SimpleDataPlane(SimpleProtocol):
+    """
+    Root class that sets up the controller and dataplane
+    """
+    def setUp(self):
+        SimpleProtocol.setUp(self)
+        self.dataplane = dataplane.DataPlane(config)
+        for of_port, ifname in config["port_map"].items():
+            self.dataplane.port_add(ifname, of_port)
+
+    def inheritSetup(self, parent):
+        """
+        Inherit the setup of a parent
+
+        See SimpleProtocol.inheritSetup
+        """
+        SimpleProtocol.inheritSetup(self, parent)
+        self.dataplane = parent.dataplane
+
+    def tearDown(self):
+        logging.info("Teardown for simple dataplane test")
+        SimpleProtocol.tearDown(self)
+        if hasattr(self, 'dataplane'):
+            self.dataplane.kill(join_threads=self.clean_shutdown)
+        logging.info("Teardown done")
+
+    def runTest(self):
+        self.assertTrue(self.controller.switch_socket is not None,
+                        str(self) + 'No connection to switch')
+        # self.dataplane.show()
+        # Would like an assert that checks the data plane
+
+class DataPlaneOnly(unittest.TestCase):
+    """
+    Root class that sets up only the dataplane
+    """
+
+    def setUp(self):
+        self.clean_shutdown = True
+        logging.info("** START DataPlaneOnly CASE " + str(self))
+        self.dataplane = dataplane.DataPlane(config)
+        for of_port, ifname in config["port_map"].items():
+            self.dataplane.port_add(ifname, of_port)
+
+    def tearDown(self):
+        logging.info("Teardown for simple dataplane test")
+        self.dataplane.kill(join_threads=self.clean_shutdown)
+        logging.info("Teardown done")
+
+    def runTest(self):
+        logging.info("DataPlaneOnly")
+        # self.dataplane.show()
+        # Would like an assert that checks the data plane
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index 0769437..cfe2eda 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -104,7 +104,6 @@
         self.socs = []
         self.connect_cv = Condition()
         self.message_cv = Condition()
-        self.disconnect_cv = Condition()
 
         # Counters
         self.socket_errors = 0
@@ -290,17 +289,19 @@
                 sock.close()
                 return 0
 
-            (sock, addr) = self.listen_socket.accept()
+            try:
+                (sock, addr) = self.listen_socket.accept()
+            except:
+                self.logger.warning("Error on listen socket accept")
+                return -1
             self.socs.append(sock)
             self.logger.info("Incoming connection from %s" % str(addr))
 
             with self.connect_cv:
                 (self.switch_socket, self.switch_addr) = (sock, addr)
+                if self.initial_hello:
+                    self.message_send(hello())
                 self.connect_cv.notify() # Notify anyone waiting
-
-            if self.initial_hello:
-                self.message_send(hello())
-                ## @fixme Check return code
         elif s and s == self.switch_socket:
             for idx in range(3): # debug: try a couple of times
                 try:
@@ -403,8 +404,8 @@
             self.switch_socket.close()
             self.switch_socket = None
             self.switch_addr = None
-            with self.disconnect_cv:
-                self.disconnect_cv.notifyAll()
+            with self.connect_cv:
+                self.connect_cv.notifyAll()
 
     def wait_disconnected(self, timeout=-1):
         """
@@ -412,8 +413,8 @@
         @return Boolean, True if disconnected
         """
 
-        with self.disconnect_cv:
-            timed_wait(self.disconnect_cv, 
+        with self.connect_cv:
+            timed_wait(self.connect_cv, 
                        lambda: True if not self.switch_socket else None, 
                        timeout=timeout)
         return self.switch_socket is None
diff --git a/src/python/oftest/dataplane.py b/src/python/oftest/dataplane.py
index aa434a7..8d9b1a2 100644
--- a/src/python/oftest/dataplane.py
+++ b/src/python/oftest/dataplane.py
@@ -299,12 +299,6 @@
                          ", port %d, length mismatch %d != %d" %
                          (port_number, bytes, len(packet)))
 
-    def _oldest_packet_find(self):
-        # Find port with oldest packet
-        oft_assert(min_port != -1, "Could not find port when pkts pending")
-
-        return min_port
-
     # Returns the port with the oldest packet, or None if no packets are queued.
     def oldest_port(self):
         min_port = None
diff --git a/src/python/oftest/netutils.py b/src/python/oftest/netutils.py
index 613ac66..c7c8051 100644
--- a/src/python/oftest/netutils.py
+++ b/src/python/oftest/netutils.py
@@ -36,6 +36,7 @@
 
 # From netpacket/packet.h
 PACKET_ADD_MEMBERSHIP  = 1
+PACKET_DROP_MEMBERSHIP = 2
 PACKET_MR_PROMISC      = 1
 
 # From bits/socket.h
@@ -47,13 +48,6 @@
   s.close()
   return ifreq
 
-def get_if_hwaddr(iff):
-  addrfamily, mac = struct.unpack("16xh6s8x",get_if(iff,SIOCGIFHWADDR))
-  if addrfamily in [ARPHDR_ETHER,ARPHDR_LOOPBACK]:
-      return str2mac(mac)
-  else:
-      raise Exception("Unsupported address family (%i)"%addrfamily)
-
 def get_if_index(iff):
   return int(struct.unpack("I",get_if(iff, SIOCGIFINDEX)[16:20])[0])
 
diff --git a/src/python/oftest/parse.py b/src/python/oftest/parse.py
index 11d6983..8826c0c 100644
--- a/src/python/oftest/parse.py
+++ b/src/python/oftest/parse.py
@@ -201,7 +201,7 @@
     @param mac_str The string to convert
     @return Array of 6 integer values
     """
-    return map(lambda val:eval("0x" + val), mac_str.split(":"))
+    return map(lambda val: int(val, 16), mac_str.split(":"))
 
 def parse_ip(ip_str):
     """
@@ -212,7 +212,7 @@
     @param ip_str The string to convert
     @return Integer value
     """
-    array = map(lambda val:eval(val),ip_str.split("."))
+    array = map(lambda val: int(val), ip_str.split("."))
     val = 0
     for a in array:
         val <<= 8
diff --git a/src/python/oftest/testutils.py b/src/python/oftest/testutils.py
index 0d2dd09..3be9c32 100644
--- a/src/python/oftest/testutils.py
+++ b/src/python/oftest/testutils.py
@@ -10,6 +10,7 @@
     except:
         sys.exit("Need to install scapy for packet parsing")
 
+from oftest import config
 import oftest.controller as controller
 import oftest.cstruct as ofp
 import oftest.message as message
@@ -30,25 +31,13 @@
 
 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):
+def delete_all_flows(ctrl):
     """
     Delete all flows on the switch
     @param ctrl The controller object for the test
-    @param logger Logging object
     """
 
-    logger.info("Deleting all flows")
+    logging.info("Deleting all flows")
     msg = message.flow_mod()
     msg.match.wildcards = ofp.OFPFW_ALL
     msg.out_port = ofp.OFPP_NONE
@@ -56,19 +45,8 @@
     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')
+    w = test_param_get('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)
@@ -203,7 +181,7 @@
         return -1
     return 0
 
-def port_config_get(controller, port_no, logger):
+def port_config_get(controller, port_no):
     """
     Get a port's configuration
 
@@ -215,31 +193,31 @@
     """
     request = message.features_request()
     reply, pkt = controller.transact(request)
-    logger.debug(reply.show())
+    logging.debug(reply.show())
     if reply is None:
-        logger.warn("Get feature request failed")
+        logging.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")
+    logging.warn("Did not find port number for port config")
     return None, None, None
 
-def port_config_set(controller, port_no, config, mask, logger):
+def port_config_set(controller, port_no, config, mask):
     """
     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))
+    logging.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())
+    logging.debug(reply.show())
     for idx in range(len(reply.ports)):
         if reply.ports[idx].port_no == port_no:
             break
@@ -254,8 +232,7 @@
     rv = controller.message_send(mod)
     return rv
 
-def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if, logger,
-                      config):
+def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
     """
     Check for proper receive packets across all ports
     @param dp The dataplane object
@@ -265,25 +242,25 @@
     @param assert_if Object that implements assertXXX
     """
     exp_pkt_arg = None
-    if config and config["relax"]:
+    if config["relax"]:
         exp_pkt_arg = pkt
 
     for ofport in yes_ports:
-        logger.debug("Checking for pkt on port " + str(ofport))
+        logging.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))
+            logging.debug("Sent %s" % format_packet(pkt))
+            logging.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))
+        logging.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, 
@@ -298,7 +275,7 @@
     parent must implement dataplane, assertTrue and assertEqual
     """
     exp_pkt_arg = None
-    if parent.config["relax"]:
+    if config["relax"]:
         exp_pkt_arg = exp_pkt
 
     if type(egr_ports) == type([]):
@@ -315,19 +292,19 @@
             port_number=check_port, exp_pkt=exp_pkt_arg)
 
         if rcv_pkt is None:
-            parent.logger.error("ERROR: No packet received from " + 
+            logging.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 " + 
+        logging.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)) + ": "
+            logging.error("ERROR: Packet match failed.")
+            logging.debug("Expected len " + str(len(exp_pkt)) + ": "
                                 + str(exp_pkt).encode('hex'))
-            parent.logger.debug("Received len " + str(len(rcv_pkt)) + ": "
+            logging.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))
@@ -390,47 +367,6 @@
                                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)
@@ -470,7 +406,7 @@
 
     if action_list is not None:
         for act in action_list:
-            parent.logger.debug("Adding action " + act.show())
+            logging.debug("Adding action " + act.show())
             rv = request.actions.add(act)
             parent.assertTrue(rv, "Could not add action" + act.show())
 
@@ -492,7 +428,7 @@
             parent.assertTrue(rv, "Could not add output action " + 
                               str(egr_port))
 
-    parent.logger.debug(request.show())
+    logging.debug(request.show())
 
     return request
 
@@ -505,24 +441,24 @@
     @param clear_table If true, clear the flow table before installing
     """
 
-    clear_table = test_param_get(parent.config, 'clear_table', default=True)
+    clear_table = test_param_get('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)
+        logging.debug("Clear flow table")
+        rc = delete_all_flows(parent.controller)
         parent.assertEqual(rc, 0, "Failed to delete all flows")
         parent.assertEqual(do_barrier(parent.controller), 0, "Barrier failed")
 
-    parent.logger.debug("Insert flow")
+    logging.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):
+                              action_list=None):
     """
     Flow match test on single TCP packet
     @param egr_ports A single port or list of ports
@@ -533,10 +469,9 @@
 
     if wildcards is None:
         wildcards = required_wildcards(parent)
-    parent.logger.info("Pkt match test: " + str(ing_port) + " to " + 
+    logging.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))
+    logging.debug("  WC: " + hex(wildcards) + " vlan: " + str(dl_vlan))
     if pkt is None:
         pkt = simple_tcp_packet(dl_vlan_enable=(dl_vlan >= 0), dl_vlan=dl_vlan)
 
@@ -546,7 +481,7 @@
 
     flow_msg_install(parent, request)
 
-    parent.logger.debug("Send packet: " + str(ing_port) + " to " + 
+    logging.debug("Send packet: " + str(ing_port) + " to " + 
                         str(egr_ports))
     parent.dataplane.send(ing_port, str(pkt))
 
@@ -554,14 +489,10 @@
         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 parent Supplies logging
     @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
@@ -579,24 +510,23 @@
             count += 1
             if count >= how_many:
                 return egr_ports
-    parent.logger.debug("Could not generate enough egress ports for test")
+    logging.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, 
+                    exp_pkt=None, action_list=None,
                     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
+    and logging
     @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:
@@ -607,7 +537,7 @@
     test_count = 0
 
     if egr_count == -1:
-        egr_count = test_param_get(parent.config, 'egr_count', default=2)
+        egr_count = test_param_get('egr_count', default=2)
     
     for ing_idx in range(len(of_ports)):
         ingress_port = of_ports[ing_idx]
@@ -621,18 +551,16 @@
         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)
+                                  action_list=action_list)
         test_count += 1
         if (max_test > 0) and (test_count > max_test):
-            parent.logger.info("Ran " + str(test_count) + " tests; exiting")
+            logging.info("Ran " + str(test_count) + " tests; exiting")
             return
 
-def test_param_get(config, key, default=None):
+def test_param_get(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
 
@@ -707,11 +635,11 @@
     return act
 
 def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={}, 
-                     mod_fields={}, check_test_params=False):
+                     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 parent Must implement assertTrue
     @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.
@@ -756,9 +684,9 @@
     # 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')
+        add_vlan = test_param_get('add_vlan')
+        strip_vlan = test_param_get('strip_vlan')
+        vid = test_param_get('vid')
 
         if add_vlan and strip_vlan:
             parent.assertTrue(0, "Add and strip VLAN both specified")
@@ -816,13 +744,13 @@
     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
+    @param parent Must implement config object
     """
     global skipped_test_count
 
     skipped_test_count += 1
-    parent.logger.info("Skipping: " + s)
-    if parent.config["dbg_level"] < logging.WARNING:
+    logging.info("Skipping: " + s)
+    if config["dbg_level"] < logging.WARNING:
         sys.stderr.write("(skipped) ")
     else:
         sys.stderr.write("(S)")
diff --git a/tests/FuncUtils.py b/tests/FuncUtils.py
index d12c388..5cfcb6a 100644
--- a/tests/FuncUtils.py
+++ b/tests/FuncUtils.py
@@ -12,7 +12,7 @@
 import oftest.parse as parse
 import logging
 import types
-import basic
+import oftest.base_tests as base_tests
 from oftest.testutils import *
 from time import sleep
 
diff --git a/tests/actions.py b/tests/actions.py
index cd54093..590a91c 100644
--- a/tests/actions.py
+++ b/tests/actions.py
@@ -10,62 +10,40 @@
 
 import unittest
 import random
+import time
 
+from oftest import config
 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 basic
-import time
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
-ac_port_map = None
-ac_logger = None
-ac_config = None
-of_ports = None
-
-def test_set_init(config):
-    basic.test_set_init(config)
-    
-    global ac_port_map
-    global ac_logger
-    global ac_config
-    global of_ports
-
-    ac_logger = logging.getLogger("Running Actions test-suite")
-    ac_logger.info("Initializing test set")
-    ac_port_map = config["port_map"]
-    ac_config = config
-    
-    of_ports = ac_port_map.keys()
-    of_ports.sort()
-
-   
-
-class NoAction(basic.SimpleDataPlane):
+class NoAction(base_tests.SimpleDataPlane):
 
     """NoActionDrop : no action added to flow , drops the packet."""
 
     def runTest(self):
         
-        ac_logger.info("Running No_Action test")
+        logging.info("Running No_Action test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Install a flow without action")
-        ac_logger.info("Send packets matching that flow")
-        ac_logger.info("Expecting switch to drop all packets")
+        logging.info("Install a flow without action")
+        logging.info("Send packets matching that flow")
+        logging.info("Expecting switch to drop all packets")
 
         # Insert a flow wildcard all without any action 
         pkt = simple_tcp_packet()
@@ -98,17 +76,17 @@
                         'Packets not received on control plane')
 
 
-class Announcement(basic.SimpleDataPlane):
+class Announcement(base_tests.SimpleDataPlane):
     
     """Announcement : Get all supported actions by the switch.
     Send OFPT_FEATURES_REQUEST to get features supported by sw."""
 
     def runTest(self):
 
-        ac_logger.info("Running Announcement test")
+        logging.info("Running Announcement test")
 
-        ac_logger.info("Sending Features_Request")
-        ac_logger.info("Expecting Features Reply with supported actions")
+        logging.info("Sending Features_Request")
+        logging.info("Expecting Features Reply with supported actions")
 
         # Sending Features_Request
         request = message.features_request()
@@ -142,29 +120,29 @@
         if(reply.actions &1<<ofp.OFPAT_ENQUEUE):
             supported_actions.append('OFPAT_ENQUEUE')
         
-        ac_logger.info(supported_actions)
+        logging.info(supported_actions)
         
 
-class ForwardAll(basic.SimpleDataPlane):
+class ForwardAll(base_tests.SimpleDataPlane):
     
     """ForwardAll : Packet is sent to all dataplane ports
     except ingress port when output action.port = OFPP_ALL"""
 
     def runTest(self):
 
-        ac_logger.info("Running Forward_All test")
+        logging.info("Running Forward_All test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow with output action port OFPP_ALL")
-        ac_logger.info("Send packet matching the flow")
-        ac_logger.info("Expecting packet on all dataplane ports except ingress_port")
+        logging.info("Insert a flow with output action port OFPP_ALL")
+        logging.info("Send packet matching the flow")
+        logging.info("Expecting packet on all dataplane ports except ingress_port")
         
         #Create a packet
         pkt = simple_tcp_packet()
@@ -172,7 +150,7 @@
         act = action.action_output()
 
         #Delete all flows 
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         ingress_port=of_ports[0]
         match.in_port = ingress_port
@@ -184,41 +162,41 @@
         act.port = ofp.OFPP_ALL
         request.actions.add(act)
         
-        ac_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         #Send Packet matching the flow
-        ac_logger.info("Sending packet to dp port " + str(ingress_port))
+        logging.info("Sending packet to dp port " + str(ingress_port))
         self.dataplane.send(ingress_port, str(pkt))
 
         #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, ac_logger, ac_config)
+                      self)
 
 
-class ForwardController(basic.SimpleDataPlane):
+class ForwardController(base_tests.SimpleDataPlane):
     
     """ForwardController : Packet is sent to controller 
     output.port = OFPP_CONTROLLER"""
 
     def runTest(self):
         
-        ac_logger.info("Running Forward_Controller test")
+        logging.info("Running Forward_Controller test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow with output action port OFPP_CONTROLLER")
-        ac_logger.info("Send packet matching the flow")
-        ac_logger.info("Expecting packet on the control plane")
+        logging.info("Insert a flow with output action port OFPP_CONTROLLER")
+        logging.info("Send packet matching the flow")
+        logging.info("Expecting packet on the control plane")
         
         #Create packet
         pkt = simple_tcp_packet()
@@ -227,7 +205,7 @@
 
         for ingress_port in of_ports:
             #Delete all flows 
-            rv = delete_all_flows(self.controller, ac_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
             match.in_port = ingress_port
@@ -238,13 +216,13 @@
             act.port = ofp.OFPP_CONTROLLER
             request.actions.add(act)
 
-            ac_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
             
             #Send packet matching the flow
-            ac_logger.info("Sending packet to dp port " + str(ingress_port))
+            logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
 
             #Verifying packet recieved on the control plane port
@@ -254,26 +232,26 @@
     
 
 
-class ForwardLocal(basic.SimpleDataPlane):
+class ForwardLocal(base_tests.SimpleDataPlane):
    
     """ForwardLocal : Packet is sent to  OFPP_LOCAL port . 
         TBD : To verify packet recieved in the local networking stack of switch"""
 
     def runTest(self):
 
-        ac_logger.info("Running Forward_Local test")
+        logging.info("Running Forward_Local test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow with output action port OFPP_LOCAL")
-        ac_logger.info("Send packet matching the flow")
-        ac_logger.info("Expecting packet in the local networking stack of switch")
+        logging.info("Insert a flow with output action port OFPP_LOCAL")
+        logging.info("Send packet matching the flow")
+        logging.info("Expecting packet in the local networking stack of switch")
         
         #Clear switch state
         pkt = simple_tcp_packet()
@@ -282,7 +260,7 @@
 
         for ingress_port in of_ports:
             #Delete the flows
-            rv = delete_all_flows(self.controller, ac_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
             match.in_port = ingress_port
@@ -292,19 +270,19 @@
             act.port = ofp.OFPP_LOCAL
             request.actions.add(act)
 
-            ac_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
             #Send packet matching the flow
-            ac_logger.info("Sending packet to dp port " + str(ingress_port))
+            logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
 
             #TBD: Verification of packets being recieved.
 
 
-class ForwardFlood(basic.SimpleDataPlane):
+class ForwardFlood(base_tests.SimpleDataPlane):
     
     """Forward:Flood : Packet is sent to all dataplane ports
     except ingress port when output action.port = OFPP_FLOOD 
@@ -313,18 +291,18 @@
     
     def runTest(self):
 
-        ac_logger.info("Running Forward_Flood test")
-        of_ports = ac_port_map.keys()
+        logging.info("Running Forward_Flood test")
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow with output action port OFPP_FORWARD")
-        ac_logger.info("Send packet matching the flow")
-        ac_logger.info("Expecting packet on all the ports except the input port")
+        logging.info("Insert a flow with output action port OFPP_FORWARD")
+        logging.info("Send packet matching the flow")
+        logging.info("Expecting packet on all the ports except the input port")
         
         #Create a packet
         pkt = simple_tcp_packet()
@@ -332,7 +310,7 @@
         act = action.action_output()
 
         #Delete all flows 
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         ingress_port=of_ports[0]
         match.in_port = ingress_port
@@ -344,40 +322,40 @@
         act.port = ofp.OFPP_FLOOD
         request.actions.add(act)
         
-        ac_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         #Send Packet matching the flow
-        ac_logger.info("Sending packet to dp port " + str(ingress_port))
+        logging.info("Sending packet to dp port " + str(ingress_port))
         self.dataplane.send(ingress_port, str(pkt))
 
         #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, ac_logger, ac_config)
+                      self)
 
-class ForwardInport(basic.SimpleDataPlane):
+class ForwardInport(base_tests.SimpleDataPlane):
     
     """ ForwardInPort : Packet sent to virtual port IN_PORT
     If the output.port = OFPP.INPORT then the packet is sent to the input port itself"""
 
     def runTest(self):
 
-        ac_logger.info("Running Forward_Inport test")
+        logging.info("Running Forward_Inport test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow with output action port OFPP_INPORT")
-        ac_logger.info("Send packet matching the flow")
-        ac_logger.info("Expecting packet on the input port")
+        logging.info("Insert a flow with output action port OFPP_INPORT")
+        logging.info("Send packet matching the flow")
+        logging.info("Expecting packet on the input port")
         
         #Create a packet
         pkt = simple_tcp_packet()
@@ -385,7 +363,7 @@
         act = action.action_output()
 
         #Delete the flows
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         ingress_port=of_ports[0]
         match.in_port = ingress_port
@@ -396,21 +374,21 @@
         act.port = ofp.OFPP_IN_PORT
             
         request.actions.add(act)
-        ac_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         #Send packet matching the flow
-        ac_logger.info("Sending packet to dp port " + str(ingress_port))
+        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, ac_logger, ac_config)      
+                          self)
 
-class ForwardTable(basic.SimpleDataPlane):
+class ForwardTable(base_tests.SimpleDataPlane):
    
     """ForwardTable : Perform actions in flow table. Only for packet-out messages.
         If the output action.port in the packetout message = OFP.TABLE , then 
@@ -418,19 +396,19 @@
 
     def runTest(self):
 
-        ac_logger.info("Running Forward_Table test")
+        logging.info("Running Forward_Table test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
         
-        ac_logger.info("Insert a flow F with output action port set to some egress_port")
-        ac_logger.info("Send packet out message (matching flow F) with action.port = OFP.TABLE")
-        ac_logger.info("Expecting packet on the egress_port")
+        logging.info("Insert a flow F with output action port set to some egress_port")
+        logging.info("Send packet out message (matching flow F) with action.port = OFP.TABLE")
+        logging.info("Expecting packet on the egress_port")
         
         #Insert a all wildcarded flow
         (pkt,match) = Wildcard_All(self,of_ports)
@@ -451,25 +429,25 @@
         self.assertTrue(pkt is not None, 'Packet not received')
 
 
-class AddVlanTag(basic.SimpleDataPlane):
+class AddVlanTag(base_tests.SimpleDataPlane):
     
     """AddVlanTag : Adds VLAN Tag to untagged packet."""
 
     def runTest(self):
 
-        ac_logger.info("Running Add_vlan_tag test")
+        logging.info("Running Add_vlan_tag test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- set vlan id, if not skip the test")
-        ac_logger.info("Insert a flow with set vid action")
-        ac_logger.info("Send packet matching the flow , verify recieved packet has vid set")
+        logging.info("Verify if switch supports the action -- set vlan id, if not skip the test")
+        logging.info("Insert a flow with set vid action")
+        logging.info("Send packet matching the flow , verify recieved packet has vid set")
         
         #Verify set_vlan_id is a supported action
         sup_acts = sw_supported_actions(self)
@@ -488,28 +466,28 @@
         vid_act.vlan_vid = new_vid
 
         #Insert flow with action -- set vid , Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, 
                         exp_pkt=exp_pkt, action_list=[vid_act])
 
-class ModifyVlanTag(basic.SimpleDataPlane):
+class ModifyVlanTag(base_tests.SimpleDataPlane):
 
     """ModifyVlanTag : Modifies VLAN Tag to tagged packet."""
     
     def runTest(self):
 
-        ac_logger.info("Running Modify_Vlan_Tag test")
+        logging.info("Running Modify_Vlan_Tag test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify vlan id, if not skip the test")
-        ac_logger.info("Insert a flow with action --set vid ")
-        ac_logger.info("Send tagged packet matching the flow , verify recieved packet has vid rewritten")
+        logging.info("Verify if switch supports the action -- modify vlan id, if not skip the test")
+        logging.info("Insert a flow with action --set vid ")
+        logging.info("Send tagged packet matching the flow , verify recieved packet has vid rewritten")
         
         #Verify set_vlan_id is a supported action
         sup_acts = sw_supported_actions(self)
@@ -526,28 +504,28 @@
         vid_act.vlan_vid = new_vid
         
         #Insert flow with action -- set vid , Send packet matching the flow.Verify recieved packet is expected packet.
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
         
-class VlanPrio1(basic.SimpleDataPlane):
+class VlanPrio1(base_tests.SimpleDataPlane):
    
     """AddVlanPrioUntaggedPkt : Add VLAN priority to untagged packet."""
     
     def runTest(self):
 
-        ac_logger.info("Running vlan_Prio_1 test")
+        logging.info("Running vlan_Prio_1 test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- set vlan priority, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set vlan priority ")
-        ac_logger.info("Send untagged packet matching the flow , verify recieved packet has specified VLAN priority and has vid set tO 0 ")
+        logging.info("Verify if switch supports the action -- set vlan priority, if not skip the test")
+        logging.info("Insert a flow with action -- set vlan priority ")
+        logging.info("Send untagged packet matching the flow , verify recieved packet has specified VLAN priority and has vid set tO 0 ")
         
         #Verify set_vlan_priority is a supported action
         sup_acts = sw_supported_actions(self)
@@ -564,29 +542,29 @@
         act.vlan_pcp = vlan_pcp
 
         #Insert flow with action -- set vLAN priority, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                                 action_list=[act])
 
 
-class VlanPrio2(basic.SimpleDataPlane):
+class VlanPrio2(base_tests.SimpleDataPlane):
     
     """ModifyVlanPrio : Modify VLAN priority to tagged packet."""
     
     def runTest(self):
         
-        ac_logger.info("Running Vlan_Prio_2 test")
+        logging.info("Running Vlan_Prio_2 test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- set vlan priority, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set vlan priority ")
-        ac_logger.info("Send tagged packet matching the flow, verify recieved packet has vlan priority rewritten")
+        logging.info("Verify if switch supports the action -- set vlan priority, if not skip the test")
+        logging.info("Insert a flow with action -- set vlan priority ")
+        logging.info("Send tagged packet matching the flow, verify recieved packet has vlan priority rewritten")
         
         #Verify set_vlan_priority is a supported action
         sup_acts = sw_supported_actions(self,"true")
@@ -604,29 +582,29 @@
         vid_act.vlan_pcp = new_vlan_pcp
 
         #Insert flow with action -- set vLAN priority, Send tagged packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
 
 
-class ModifyL2Src(basic.SimpleDataPlane):
+class ModifyL2Src(base_tests.SimpleDataPlane):
     
     """ModifyL2Src :Modify the source MAC address"""
 
     def runTest(self):
 
-        ac_logger.info("Running Modify_L2_Src test")
+        logging.info("Running Modify_L2_Src test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l2_src, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set etherent src address")
-        ac_logger.info("Send packet matching the flow, verify recieved packet src address rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l2_src, if not skip the test")
+        logging.info("Insert a flow with action -- set etherent src address")
+        logging.info("Send packet matching the flow, verify recieved packet src address rewritten ")
 
         #Verify set_dl_src is a supported action
         sup_acts = sw_supported_actions(self,use_cache="true")
@@ -639,29 +617,29 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set src address, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 
-class ModifyL2Dst(basic.SimpleDataPlane):
+class ModifyL2Dst(base_tests.SimpleDataPlane):
     
     """ModifyL2SDSt :Modify the dest MAC address"""
 
     def runTest(self):
 
-        ac_logger.info("Running Modify_L2_Dst test")
+        logging.info("Running Modify_L2_Dst test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l2_dst, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set etherent dst address ")
-        ac_logger.info("Send packet matching the flow, verify recieved packet dst address rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l2_dst, if not skip the test")
+        logging.info("Insert a flow with action -- set etherent dst address ")
+        logging.info("Send packet matching the flow, verify recieved packet dst address rewritten ")
 
         #Verify set_dl_dst is a supported action
         sup_acts = sw_supported_actions(self)
@@ -674,28 +652,28 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set dst address, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
-class ModifyL3Src(basic.SimpleDataPlane):
+class ModifyL3Src(base_tests.SimpleDataPlane):
     
     """ModifyL3Src : Modify the source IP address of an IP packet """
 
     def runTest(self):
 
-        ac_logger.info("Running Modify_L3_Src test")
+        logging.info("Running Modify_L3_Src test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l3_src, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set network src address ")
-        ac_logger.info("Send packet matching the flow, verify recieved packet network src address rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l3_src, if not skip the test")
+        logging.info("Insert a flow with action -- set network src address ")
+        logging.info("Send packet matching the flow, verify recieved packet network src address rewritten ")
         
         #Verify set_nw_src is a supported action
         sup_acts = sw_supported_actions(self)
@@ -708,28 +686,28 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set nw src address, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
-class ModifyL3Dst(basic.SimpleDataPlane):
+class ModifyL3Dst(base_tests.SimpleDataPlane):
     
     """ModifyL3Dst :Modify the dest IP address of an IP packet"""
     
     def runTest(self):
 
-        ac_logger.info("Running Modify_L3_Dst test")
+        logging.info("Running Modify_L3_Dst test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l3_dst, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set network dst address ")
-        ac_logger.info("Send packet matching the flow, verify recieved packet network dst address rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l3_dst, if not skip the test")
+        logging.info("Insert a flow with action -- set network dst address ")
+        logging.info("Send packet matching the flow, verify recieved packet network dst address rewritten ")
 
         #Verify set_nw_dst is a supported action
         sup_acts = sw_supported_actions(self,use_cache="true")
@@ -742,29 +720,29 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set nw dst address, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 
-class ModifyL4Src(basic.SimpleDataPlane):
+class ModifyL4Src(base_tests.SimpleDataPlane):
     
     """ModifyL4Src : Modify the source TCP port of a TCP packet"""
     
     def runTest(self):
 
-        ac_logger.info("Running Modify_L4_Src test")
+        logging.info("Running Modify_L4_Src test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l4_src, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set src tcp port")
-        ac_logger.info("Send packet matching the flow, verify recieved packet src tcp port is rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l4_src, if not skip the test")
+        logging.info("Insert a flow with action -- set src tcp port")
+        logging.info("Send packet matching the flow, verify recieved packet src tcp port is rewritten ")
         
         #Verify set_tp_src is a supported action
         sup_acts = sw_supported_actions(self,use_cache="true")
@@ -777,28 +755,28 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set tcp src port, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
-class ModifyL4Dst(basic.SimpleDataPlane):
+class ModifyL4Dst(base_tests.SimpleDataPlane):
     
     """ ModifyL4Dst: Modify the dest TCP port of a TCP packet """
 
     def runTest(self):
 
-        ac_logger.info("Running Modify_L4_Dst test")
+        logging.info("Running Modify_L4_Dst test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_l4_dst, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set dst tcp port")
-        ac_logger.info("Send packet matching the flow, verify recieved packet dst tcp port is rewritten ")
+        logging.info("Verify if switch supports the action -- modify_l4_dst, if not skip the test")
+        logging.info("Insert a flow with action -- set dst tcp port")
+        logging.info("Send packet matching the flow, verify recieved packet dst tcp port is rewritten ")
        
         #Verify set_tp_dst is a supported action
         sup_acts = sw_supported_actions(self,use_cache="true")
@@ -811,28 +789,28 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set tcp dst port, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
-class ModifyTos(basic.SimpleDataPlane):
+class ModifyTos(base_tests.SimpleDataPlane):
     
     """ModifyTOS :Modify the IP type of service of an IP packet"""
    
     def runTest(self):
 
-        ac_logger.info("Running Modify_Tos test")
+        logging.info("Running Modify_Tos test")
 
-        of_ports = ac_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rv = delete_all_flows(self.controller, ac_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
-        ac_logger.info("Verify if switch supports the action -- modify_tos, if not skip the test")
-        ac_logger.info("Insert a flow with action -- set type of service ")
-        ac_logger.info("Send packet matching the flow, verify recieved packet has TOS rewritten ")
+        logging.info("Verify if switch supports the action -- modify_tos, if not skip the test")
+        logging.info("Insert a flow with action -- set type of service ")
+        logging.info("Send packet matching the flow, verify recieved packet has TOS rewritten ")
        
         #Verify set_tos is a supported action
         sup_acts = sw_supported_actions(self,use_cache="true")
@@ -845,5 +823,5 @@
                                                 check_test_params=True)
         
         #Insert flow with action -- set TOS, Send packet matching the flow, Verify recieved packet is expected packet
-        flow_match_test(self, ac_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
diff --git a/tests/basic.py b/tests/basic.py
index 53947b4..113640a 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -7,221 +7,33 @@
 
 Current Assumptions:
 
-  The function test_set_init is called with a complete configuration
-dictionary prior to the invocation of any tests from this file.
-
   The switch is actively attempting to contact the controller at the address
-indicated oin oft_config
+indicated in oftest.config.
 
 """
 
 import time
-import signal
 import sys
 import logging
 
 import unittest
 import random
 
+from oftest import config
 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.base_tests as base_tests
 
 import oftest.illegal_message as illegal_message
 
 from oftest.testutils import *
 
-#@var basic_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-basic_port_map = None
-#@var basic_logger Local logger object
-basic_logger = None
-#@var basic_config Local copy of global configuration data
-basic_config = None
-
-test_prio = {}
-
 TEST_VID_DEFAULT = 2
 
-def test_set_init(config):
-    """
-    Set up function for basic test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    global basic_port_map
-    global basic_logger
-    global basic_config
-
-    basic_logger = logging.getLogger("basic")
-    basic_logger.info("Initializing test set")
-    basic_port_map = config["port_map"]
-    basic_config = config
-
-class SimpleProtocol(unittest.TestCase):
-    """
-    Root class for setting up the controller
-    """
-
-    def sig_handler(self, v1, v2):
-        basic_logger.critical("Received interrupt signal; exiting")
-        print "Received interrupt signal; exiting"
-        self.clean_shutdown = False
-        self.tearDown()
-        raise KeyboardInterrupt
-
-    def setUp(self):
-        self.logger = basic_logger
-        self.config = basic_config
-        #@todo Test cases shouldn't monkey with signals; move SIGINT handler
-        # to top-level oft
-        try:
-           signal.signal(signal.SIGINT, self.sig_handler)
-        except ValueError, e:
-           basic_logger.info("Could not set SIGINT handler: %s" % e)
-        basic_logger.info("** START TEST CASE " + str(self))
-        self.controller = controller.Controller(
-            host=basic_config["controller_host"],
-            port=basic_config["controller_port"])
-        # clean_shutdown should be set to False to force quit app
-        self.clean_shutdown = True
-        self.controller.start()
-        #@todo Add an option to wait for a pkt transaction to ensure version
-        # compatibilty?
-        self.controller.connect(timeout=20)
-
-        # By default, respond to echo requests
-        self.controller.keep_alive = True
-        
-        if not self.controller.active:
-            raise Exception("Controller startup failed")
-        if self.controller.switch_addr is None: 
-            raise Exception("Controller startup failed (no switch addr)")
-        basic_logger.info("Connected " + str(self.controller.switch_addr))
-        request = message.features_request()
-        reply, pkt = self.controller.transact(request)
-        self.assertTrue(reply is not None,
-                        "Did not complete features_request for handshake")
-        self.supported_actions = reply.actions
-        basic_logger.info("Supported actions: " + hex(self.supported_actions))
-
-    def inheritSetup(self, parent):
-        """
-        Inherit the setup of a parent
-
-        This allows running at test from within another test.  Do the
-        following:
-
-        sub_test = SomeTestClass()  # Create an instance of the test class
-        sub_test.inheritSetup(self) # Inherit setup of parent
-        sub_test.runTest()          # Run the test
-
-        Normally, only the parent's setUp and tearDown are called and
-        the state after the sub_test is run must be taken into account
-        by subsequent operations.
-        """
-        self.logger = parent.logger
-        self.config = parent.config
-        basic_logger.info("** Setup " + str(self) + " inheriting from "
-                          + str(parent))
-        self.controller = parent.controller
-        self.supported_actions = parent.supported_actions
-        
-    def tearDown(self):
-        basic_logger.info("** END TEST CASE " + str(self))
-        self.controller.shutdown()
-        #@todo Review if join should be done on clean_shutdown
-        if self.clean_shutdown:
-            self.controller.join()
-
-    def runTest(self):
-        # Just a simple sanity check as illustration
-        basic_logger.info("Running simple proto test")
-        self.assertTrue(self.controller.switch_socket is not None,
-                        str(self) + 'No connection to switch')
-
-    def assertTrue(self, cond, msg):
-        if not cond:
-            basic_logger.error("** FAILED ASSERTION: " + msg)
-        unittest.TestCase.assertTrue(self, cond, msg)
-
-test_prio["SimpleProtocol"] = 1
-
-class SimpleDataPlane(SimpleProtocol):
-    """
-    Root class that sets up the controller and dataplane
-    """
-    def setUp(self):
-        SimpleProtocol.setUp(self)
-        self.dataplane = dataplane.DataPlane(self.config)
-        for of_port, ifname in basic_port_map.items():
-            self.dataplane.port_add(ifname, of_port)
-
-    def inheritSetup(self, parent):
-        """
-        Inherit the setup of a parent
-
-        See SimpleProtocol.inheritSetup
-        """
-        SimpleProtocol.inheritSetup(self, parent)
-        self.dataplane = parent.dataplane
-
-    def tearDown(self):
-        basic_logger.info("Teardown for simple dataplane test")
-        SimpleProtocol.tearDown(self)
-        if hasattr(self, 'dataplane'):
-            self.dataplane.kill(join_threads=self.clean_shutdown)
-        basic_logger.info("Teardown done")
-
-    def runTest(self):
-        self.assertTrue(self.controller.switch_socket is not None,
-                        str(self) + 'No connection to switch')
-        # self.dataplane.show()
-        # Would like an assert that checks the data plane
-
-class DataPlaneOnly(unittest.TestCase):
-    """
-    Root class that sets up only the dataplane
-    """
-
-    def sig_handler(self, v1, v2):
-        basic_logger.critical("Received interrupt signal; exiting")
-        print "Received interrupt signal; exiting"
-        self.clean_shutdown = False
-        self.tearDown()
-        raise KeyboardInterrupt
-
-    def setUp(self):
-        self.clean_shutdown = True
-        self.logger = basic_logger
-        self.config = basic_config
-        #@todo Test cases shouldn't monkey with signals; move SIGINT handler
-        # to top-level oft
-        try:
-           signal.signal(signal.SIGINT, self.sig_handler)
-        except ValueError, e:
-           basic_logger.info("Could not set SIGINT handler: %s" % e)
-        basic_logger.info("** START DataPlaneOnly CASE " + str(self))
-        self.dataplane = dataplane.DataPlane(self.config)
-        for of_port, ifname in basic_port_map.items():
-            self.dataplane.port_add(ifname, of_port)
-
-    def tearDown(self):
-        basic_logger.info("Teardown for simple dataplane test")
-        self.dataplane.kill(join_threads=self.clean_shutdown)
-        basic_logger.info("Teardown done")
-
-    def runTest(self):
-        basic_logger.info("DataPlaneOnly")
-        # self.dataplane.show()
-        # Would like an assert that checks the data plane
-
-test_prio["DataPlaneOnly"] = -1
-
-class Echo(SimpleProtocol):
+class Echo(base_tests.SimpleProtocol):
     """
     Test echo response with no data
     """
@@ -236,7 +48,7 @@
                          'response xid != request xid')
         self.assertEqual(len(response.data), 0, 'response data non-empty')
 
-class EchoWithData(SimpleProtocol):
+class EchoWithData(base_tests.SimpleProtocol):
     """
     Test echo response with short string data
     """
@@ -253,7 +65,7 @@
         self.assertEqual(request.data, response.data,
                          'response data does not match request')
 
-class PacketIn(SimpleDataPlane):
+class PacketIn(base_tests.SimpleDataPlane):
     """
     Test packet in function
 
@@ -265,13 +77,13 @@
         # Send packet to dataplane, once to each port
         # Poll controller with expect message type packet in
 
-        rc = delete_all_flows(self.controller, basic_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
 
-        for of_port in basic_port_map.keys():
+        for of_port in config["port_map"].keys():
             for pkt, pt in [
                (simple_tcp_packet(), "simple TCP packet"),
                (simple_tcp_packet(dl_vlan_enable=True,dl_vlan=vid,pktlen=108), 
@@ -279,7 +91,7 @@
                (simple_eth_packet(), "simple Ethernet packet"),
                (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
 
-               basic_logger.info("PKT IN test with %s, port %s" % (pt, of_port))
+               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
@@ -289,7 +101,7 @@
                        break
                    if dataplane.match_exp_pkt(pkt, response.data): # Got match
                        break
-                   if not basic_config["relax"]:  # Only one attempt to match
+                   if not config["relax"]:  # Only one attempt to match
                        break
                    count += 1
                    if count > 10:   # Too many tries
@@ -299,25 +111,28 @@
                                'Packet in message not received on port ' + 
                                str(of_port))
                if not dataplane.match_exp_pkt(pkt, response.data):
-                   basic_logger.debug("Sent %s" % format_packet(pkt))
-                   basic_logger.debug("Resp %s" % format_packet(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))
 
-class PacketInDefaultDrop(SimpleDataPlane):
+class PacketInDefaultDrop(base_tests.SimpleDataPlane):
     """
     Test packet in function
 
     Send a packet to each dataplane port and verify that a packet
     in message is received from the controller for each
     """
+
+    priority = -1
+
     def runTest(self):
-        rc = delete_all_flows(self.controller, basic_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-        for of_port in basic_port_map.keys():
+        for of_port in config["port_map"].keys():
             pkt = simple_tcp_packet()
             self.dataplane.send(of_port, str(pkt))
             count = 0
@@ -327,7 +142,7 @@
                     break
                 if dataplane.match_exp_pkt(pkt, response.data): # Got match
                     break
-                if not basic_config["relax"]:  # Only one attempt to match
+                if not config["relax"]:  # Only one attempt to match
                     break
                 count += 1
                 if count > 10:   # Too many tries
@@ -337,10 +152,7 @@
                             'Packet in message received on port ' + 
                             str(of_port))
 
-test_prio["PacketInDefaultDrop"] = -1
-
-
-class PacketInBroadcastCheck(SimpleDataPlane):
+class PacketInBroadcastCheck(base_tests.SimpleDataPlane):
     """
     Check if bcast pkts leak when no flows are present
 
@@ -348,28 +160,29 @@
     Send in a broadcast pkt
     Look for the packet on other dataplane ports.
     """
+
+    priority = -1
+
     def runTest(self):
         # Need at least two ports
-        self.assertTrue(len(basic_port_map) > 1, "Too few ports for test")
+        self.assertTrue(len(config["port_map"]) > 1, "Too few ports for test")
 
-        rc = delete_all_flows(self.controller, basic_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-        of_ports = basic_port_map.keys()
+        of_ports = config["port_map"].keys()
         d_port = of_ports[0]
         pkt = simple_eth_packet(dl_dst='ff:ff:ff:ff:ff:ff')
 
-        basic_logger.info("BCast Leak Test, send to port %s" % d_port)
+        logging.info("BCast Leak Test, send to port %s" % d_port)
         self.dataplane.send(d_port, str(pkt))
 
         (of_port, pkt_in, pkt_time) = self.dataplane.poll(exp_pkt=pkt)
         self.assertTrue(pkt_in is None,
                         'BCast packet received on port ' + str(of_port))
 
-test_prio["PacketInBroadcastCheck"] = -1
-
-class PacketOut(SimpleDataPlane):
+class PacketOut(base_tests.SimpleDataPlane):
     """
     Test packet out function
 
@@ -381,11 +194,11 @@
         # Send packet to dataplane
         # Poll controller with expect message type packet in
 
-        rc = delete_all_flows(self.controller, basic_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # These will get put into function
-        of_ports = basic_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         for dp_port in of_ports:
             for outpkt, opt in [
@@ -393,37 +206,37 @@
                (simple_eth_packet(), "simple Ethernet packet"),
                (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
 
-               basic_logger.info("PKT OUT test with %s, port %s" % (opt, dp_port))
+               logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
                msg = message.packet_out()
                msg.data = str(outpkt)
                act = action.action_output()
                act.port = dp_port
                self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
 
-               basic_logger.info("PacketOut to: " + str(dp_port))
+               logging.info("PacketOut to: " + str(dp_port))
                rv = self.controller.message_send(msg)
                self.assertTrue(rv == 0, "Error sending out message")
 
                exp_pkt_arg = None
                exp_port = None
-               if basic_config["relax"]:
+               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')
-               basic_logger.info("PacketOut: got pkt from " + str(of_port))
+               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):
-                   basic_logger.debug("Sent %s" % format_packet(outpkt))
-                   basic_logger.debug("Resp %s" % format_packet(
+                   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')
 
-class PacketOutMC(SimpleDataPlane):
+class PacketOutMC(base_tests.SimpleDataPlane):
     """
     Test packet out to multiple output ports
 
@@ -435,11 +248,11 @@
         # Send packet to dataplane
         # Poll controller with expect message type packet in
 
-        rc = delete_all_flows(self.controller, basic_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # These will get put into function
-        of_ports = basic_port_map.keys()
+        of_ports = config["port_map"].keys()
         random.shuffle(of_ports)
         for num_ports in range(1,len(of_ports)+1):
             for outpkt, opt in [
@@ -448,7 +261,7 @@
                (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
 
                dp_ports = of_ports[0:num_ports]
-               basic_logger.info("PKT OUT test with " + opt +
+               logging.info("PKT OUT test with " + opt +
                                  ", ports " + str(dp_ports))
                msg = message.packet_out()
                msg.data = str(outpkt)
@@ -458,28 +271,31 @@
                   self.assertTrue(msg.actions.add(act),
                                   'Could not add action to msg')
 
-               basic_logger.info("PacketOut to: " + str(dp_ports))
+               logging.info("PacketOut to: " + str(dp_ports))
                rv = self.controller.message_send(msg)
                self.assertTrue(rv == 0, "Error sending out message")
 
                receive_pkt_check(self.dataplane, outpkt, dp_ports,
                                  set(of_ports).difference(dp_ports),
-                                 self, basic_logger, basic_config)
+                                 self)
 
-class FlowStatsGet(SimpleProtocol):
+class FlowStatsGet(base_tests.SimpleProtocol):
     """
     Get stats 
 
     Simply verify stats get transaction
     """
+
+    priority = -1
+
     def runTest(self):
-        basic_logger.info("Running StatsGet")
-        basic_logger.info("Inserting trial flow")
-        request = flow_mod_gen(basic_port_map, True)
+        logging.info("Running StatsGet")
+        logging.info("Inserting trial flow")
+        request = flow_mod_gen(config["port_map"], True)
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Failed to insert test flow")
         
-        basic_logger.info("Sending flow request")
+        logging.info("Sending flow request")
         request = message.flow_stats_request()
         request.out_port = ofp.OFPP_NONE
         request.table_id = 0xff
@@ -487,47 +303,45 @@
         response, pkt = self.controller.transact(request)
         self.assertTrue(response is not None,
                         "Did not get response for flow stats")
-        basic_logger.debug(response.show())
+        logging.debug(response.show())
 
-test_prio["FlowStatsGet"] = -1
-
-class TableStatsGet(SimpleProtocol):
+class TableStatsGet(base_tests.SimpleProtocol):
     """
     Get table stats 
 
     Simply verify table stats get transaction
     """
     def runTest(self):
-        basic_logger.info("Running TableStatsGet")
-        basic_logger.info("Inserting trial flow")
-        request = flow_mod_gen(basic_port_map, True)
+        logging.info("Running TableStatsGet")
+        logging.info("Inserting trial flow")
+        request = flow_mod_gen(config["port_map"], True)
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Failed to insert test flow")
         
-        basic_logger.info("Sending table stats request")
+        logging.info("Sending table stats request")
         request = message.table_stats_request()
         response, pkt = self.controller.transact(request)
         self.assertTrue(response is not None,
                         "Did not get reply for table stats")
-        basic_logger.debug(response.show())
+        logging.debug(response.show())
 
-class DescStatsGet(SimpleProtocol):
+class DescStatsGet(base_tests.SimpleProtocol):
     """
     Get stats 
 
     Simply verify stats get transaction
     """
     def runTest(self):
-        basic_logger.info("Running DescStatsGet")
+        logging.info("Running DescStatsGet")
         
-        basic_logger.info("Sending stats request")
+        logging.info("Sending stats request")
         request = message.desc_stats_request()
         response, pkt = self.controller.transact(request)
         self.assertTrue(response is not None,
                         "Did not get reply for desc stats")
-        basic_logger.debug(response.show())
+        logging.debug(response.show())
 
-class FlowMod(SimpleProtocol):
+class FlowMod(base_tests.SimpleProtocol):
     """
     Insert a flow
 
@@ -535,12 +349,12 @@
     """
 
     def runTest(self):
-        basic_logger.info("Running " + str(self))
-        request = flow_mod_gen(basic_port_map, True)
+        logging.info("Running " + str(self))
+        request = flow_mod_gen(config["port_map"], True)
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
 
-class PortConfigMod(SimpleProtocol):
+class PortConfigMod(base_tests.SimpleProtocol):
     """
     Modify a bit in port config and verify changed
 
@@ -550,57 +364,55 @@
     """
 
     def runTest(self):
-        basic_logger.info("Running " + str(self))
-        for of_port, ifname in basic_port_map.items(): # Grab first port
+        logging.info("Running " + str(self))
+        for of_port, ifname in config["port_map"].items(): # Grab first port
             break
 
-        (hw_addr, config, advert) = \
-            port_config_get(self.controller, of_port, basic_logger)
-        self.assertTrue(config is not None, "Did not get port config")
+        (hw_addr, port_config, advert) = \
+            port_config_get(self.controller, of_port)
+        self.assertTrue(port_config is not None, "Did not get port config")
 
-        basic_logger.debug("No flood bit port " + str(of_port) + " is now " + 
-                           str(config & ofp.OFPPC_NO_FLOOD))
+        logging.debug("No flood bit port " + str(of_port) + " is now " + 
+                           str(port_config & ofp.OFPPC_NO_FLOOD))
 
         rv = port_config_set(self.controller, of_port,
-                             config ^ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
-                             basic_logger)
+                             port_config ^ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
         self.assertTrue(rv != -1, "Error sending port mod")
 
         # Verify change took place with same feature request
-        (hw_addr, config2, advert) = \
-            port_config_get(self.controller, of_port, basic_logger)
-        basic_logger.debug("No flood bit port " + str(of_port) + " is now " + 
-                           str(config2 & ofp.OFPPC_NO_FLOOD))
-        self.assertTrue(config2 is not None, "Did not get port config2")
-        self.assertTrue(config2 & ofp.OFPPC_NO_FLOOD !=
-                        config & ofp.OFPPC_NO_FLOOD,
+        (hw_addr, port_config2, advert) = \
+            port_config_get(self.controller, of_port)
+        logging.debug("No flood bit port " + str(of_port) + " is now " + 
+                           str(port_config2 & ofp.OFPPC_NO_FLOOD))
+        self.assertTrue(port_config2 is not None, "Did not get port config2")
+        self.assertTrue(port_config2 & ofp.OFPPC_NO_FLOOD !=
+                        port_config & ofp.OFPPC_NO_FLOOD,
                         "Bit change did not take")
         # Set it back
-        rv = port_config_set(self.controller, of_port, config, 
-                             ofp.OFPPC_NO_FLOOD, basic_logger)
+        rv = port_config_set(self.controller, of_port, port_config,
+                             ofp.OFPPC_NO_FLOOD)
         self.assertTrue(rv != -1, "Error sending port mod")
 
-class PortConfigModErr(SimpleProtocol):
+class PortConfigModErr(base_tests.SimpleProtocol):
     """
     Modify a bit in port config on an invalid port and verify
     error message is received.
     """
 
     def runTest(self):
-        basic_logger.info("Running " + str(self))
+        logging.info("Running " + str(self))
 
         # pick a random bad port number
         bad_port = random.randint(1, ofp.OFPP_MAX)
         count = 0
-        while (count < 50) and (bad_port in basic_port_map.keys()):
+        while (count < 50) and (bad_port in config["port_map"].keys()):
             bad_port = random.randint(1, ofp.OFPP_MAX)
             count = count + 1
         self.assertTrue(count < 50, "Error selecting bad port")
-        basic_logger.info("Select " + str(bad_port) + " as invalid port")
+        logging.info("Select " + str(bad_port) + " as invalid port")
 
         rv = port_config_set(self.controller, bad_port,
-                             ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
-                             basic_logger)
+                             ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
         self.assertTrue(rv != -1, "Error sending port mod")
 
         # poll for error message
@@ -609,9 +421,9 @@
             if not response:  # Timeout
                 break
             if response.code == ofp.OFPPMFC_BAD_PORT:
-                basic_logger.info("Received error message with OFPPMFC_BAD_PORT code")
+                logging.info("Received error message with OFPPMFC_BAD_PORT code")
                 break
-            if not basic_config["relax"]:  # Only one attempt to match
+            if not config["relax"]:  # Only one attempt to match
                 break
             count += 1
             if count > 10:   # Too many tries
@@ -619,13 +431,13 @@
 
         self.assertTrue(response is not None, 'Did not receive error message')
 
-class BadMessage(SimpleProtocol):
+class BadMessage(base_tests.SimpleProtocol):
     """
     Send a message with a bad type and verify an error is returned
     """
 
     def runTest(self):
-        basic_logger.info("Running " + str(self))
+        logging.info("Running " + str(self))
         request = illegal_message.illegal_message_type()
 
         reply, pkt = self.controller.transact(request)
diff --git a/tests/bsn_ipmask.py b/tests/bsn_ipmask.py
index 489b980..70ca990 100644
--- a/tests/bsn_ipmask.py
+++ b/tests/bsn_ipmask.py
@@ -4,37 +4,14 @@
 
 import logging
 
+from oftest import config
 import oftest.controller as controller
 import oftest.cstruct as ofp
 import oftest.message as message
-import basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 
-#@var port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-im_port_map = None
-#@var im_logger Local logger object
-im_logger = None
-#@var im_config Local copy of global configuration data
-im_config = None
-
-# For test priority
-#@var test_prio Set test priority for local tests
-test_prio = {}
-
-def test_set_init(config):
-    basic.test_set_init(config)
-
-    global im_port_map
-    global im_logger
-    global im_config
-
-    im_logger = logging.getLogger("ipmask")
-    im_logger.info("Initializing test set")
-    im_port_map = config["port_map"]
-    im_config = config
-
 def normal_ip_mask(index):
     """
     Return the IP mask for the given wildcard index 0 - 63 per the OF 1.0 spec
@@ -59,16 +36,19 @@
     else:
         return (1 << (63 - index)) - 1
 
-class BSNConfigIPMask(basic.SimpleDataPlane):
+class BSNConfigIPMask(base_tests.SimpleDataPlane):
     """
     Exercise BSN vendor extension for configuring IP source/dest match mask
     """
+
+    priority = -1
+
     def bsn_set_ip_mask(self, index, mask):
         """
         Use the BSN_SET_IP_MASK vendor command to change the IP mask for the
         given wildcard index
         """
-        im_logger.info("Setting index %d to mask is %s" % (index, mask))
+        logging.info("Setting index %d to mask is %s" % (index, mask))
         m = message.vendor()
         m.vendor = 0x005c16c7
         m.data = struct.pack("!LBBBBL", 0, index, 0, 0, 0, mask)
@@ -99,39 +79,39 @@
                          "IP src must be wildcarded")
         for index in range(0, 64):
             mask = self.bsn_get_ip_mask(index)
-            im_logger.info("Index %d mask is %s" %
+            logging.info("Index %d mask is %s" %
                            (index, scapy.utils.ltoa(mask)))
             self.assertEqual(mask, normal_ip_mask(index), "Unexpected IP mask")
 
         for index in range(0, 64):
             mask = normal_ip_mask(index)
             if mask == 0:
-                im_logger.info("Skipping IP wildcard index %d" % index)
+                logging.info("Skipping IP wildcard index %d" % index)
             else:
-                im_logger.info("Testing IP wildcard index %d" % index)
+                logging.info("Testing IP wildcard index %d" % index)
                 self.check_ip_mask(True, index, mask)
                 self.check_ip_mask(False, index, mask)
 
-        im_logger.info("Setting fancy IP masks")
+        logging.info("Setting fancy IP masks")
         for index in range(0, 64):
             self.bsn_set_ip_mask(index, fancy_ip_mask(index))
         for index in range(0, 64):
             mask = self.bsn_get_ip_mask(index)
-            im_logger.info("Index %d mask is %s" %
+            logging.info("Index %d mask is %s" %
                            (index, scapy.utils.ltoa(mask)))
             self.assertEqual(mask, fancy_ip_mask(index), "Unexpected IP mask")
 
         for index in range(0, 64):
             mask = fancy_ip_mask(index)
             if mask == 0:
-                im_logger.info("Skipping IP wildcard index %d" % index)
+                logging.info("Skipping IP wildcard index %d" % index)
             else:
-                im_logger.info("Testing IP wildcard index %d" % index)
+                logging.info("Testing IP wildcard index %d" % index)
                 self.check_ip_mask(True, index, mask)
                 self.check_ip_mask(False, index, mask)
 
     def check_ip_mask(self, source, index, mask):
-        ports = im_port_map.keys()
+        ports = config["port_map"].keys()
 
         # For each mask we install two flow entries, one which matches
         # on IP source or dest addr all-0s (modulo the mask) and
@@ -156,7 +136,7 @@
            pkt1 = simple_tcp_packet(ip_src=ip1)
            pkt2 = simple_tcp_packet(ip_src=ip2)
            pkt3 = simple_tcp_packet(ip_src=ip3)
-           msg = lambda ip: im_logger.info("Testing source IP %s" % ip)
+           msg = lambda ip: logging.info("Testing source IP %s" % ip)
         else:
            wildcards = ((ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_DST_MASK)
                         | (index << ofp.OFPFW_NW_DST_SHIFT))
@@ -164,9 +144,9 @@
            pkt1 = simple_tcp_packet(ip_dst=ip1)
            pkt2 = simple_tcp_packet(ip_dst=ip2)
            pkt3 = simple_tcp_packet(ip_dst=ip3)
-           msg = lambda ip: im_logger.info("Testing dest IP %s" % ip)
+           msg = lambda ip: logging.info("Testing dest IP %s" % ip)
 
-        rc = delete_all_flows(self.controller, im_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         rc = self.controller.message_send(flow_msg_create(
@@ -195,6 +175,3 @@
         msg(ip3)
         self.dataplane.send(ports[0], str(pkt3))
         receive_pkt_verify(self, [ports[2]], pkt3, ports[0])
-
-# Don't run by default
-test_prio["BSNConfigIPMask"] = -1
diff --git a/tests/caps.py b/tests/caps.py
index 93403ea..fe90310 100644
--- a/tests/caps.py
+++ b/tests/caps.py
@@ -7,46 +7,17 @@
 
 import unittest
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 
-#@var caps_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-caps_port_map = None
-#@var caps_logger Local logger object
-caps_logger = None
-#@var caps_config Local copy of global configuration data
-caps_config = None
-
-# For test priority
-test_prio = {}
-
-def test_set_init(config):
-    """
-    Set up function for caps test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global caps_port_map
-    global caps_logger
-    global caps_config
-
-    caps_logger = logging.getLogger("caps")
-    caps_logger.info("Initializing caps test set")
-    caps_port_map = config["port_map"]
-    caps_config = config
-
-
 def flow_caps_common(obj, is_exact=True):
     """
     The common function for 
@@ -55,11 +26,10 @@
     @param is_exact If True, checking exact match; else wildcard
     """
 
-    global caps_port_map
-    of_ports = caps_port_map.keys()
+    of_ports = config["port_map"].keys()
     of_ports.sort()
 
-    rv = delete_all_flows(obj.controller, caps_logger)
+    rv = delete_all_flows(obj.controller)
     obj.assertEqual(rv, 0, "Failed to delete all flows")
 
     pkt = simple_tcp_packet()
@@ -78,23 +48,23 @@
 
     request.match = match
     request.buffer_id = 0xffffffff      # set to NONE
-    caps_logger.info(request.show())
+    logging.info(request.show())
 
     tstats = message.table_stats_request()
     try:  # Determine the table index to check (or "all")
-        table_idx = caps_config["caps_table_idx"]
+        table_idx = config["caps_table_idx"]
     except:
         table_idx = -1  # Accumulate all table counts
 
     # Make sure we can install at least one flow
-    caps_logger.info("Inserting initial flow")
+    logging.info("Inserting initial flow")
     rv = obj.controller.message_send(request)
     obj.assertTrue(rv != -1, "Error installing flow mod")
     obj.assertEqual(do_barrier(obj.controller), 0, "Barrier failed")
     flow_count = 1
 
-    caps_logger.info("Table idx: " + str(table_idx))
-    caps_logger.info("Check every " + str(count_check) + " inserts")
+    logging.info("Table idx: " + str(table_idx))
+    logging.info("Check every " + str(count_check) + " inserts")
 
     while True:
         request.match.nw_src += 1
@@ -104,7 +74,7 @@
             obj.assertEqual(do_barrier(obj.controller), 0, "Barrier failed")
             response, pkt = obj.controller.transact(tstats)
             obj.assertTrue(response is not None, "Get tab stats failed")
-            caps_logger.info(response.show())
+            logging.info(response.show())
             if table_idx == -1:  # Accumulate for all tables
                 active_flows = 0
                 for stats in response.stats:
@@ -114,11 +84,11 @@
             if active_flows != flow_count:
                 break
 
-    caps_logger.error("RESULT: " + str(flow_count) + " flows inserted")
-    caps_logger.error("RESULT: " + str(active_flows) + " flows reported")
+    logging.error("RESULT: " + str(flow_count) + " flows inserted")
+    logging.error("RESULT: " + str(active_flows) + " flows reported")
 
 
-class FillTableExact(basic.SimpleProtocol):
+class FillTableExact(base_tests.SimpleProtocol):
     """
     Fill the flow table with exact matches; can take a while
 
@@ -135,13 +105,14 @@
     the parameter "caps_table_idx" in the configuration array,
     you can control which table to check.
     """
+
+    priority = -1
+
     def runTest(self):
-        caps_logger.info("Running " + str(self))
+        logging.info("Running " + str(self))
         flow_caps_common(self)
 
-test_prio["FillTableExact"] = -1
-
-class FillTableWC(basic.SimpleProtocol):
+class FillTableWC(base_tests.SimpleProtocol):
     """
     Fill the flow table with wildcard matches
 
@@ -160,8 +131,9 @@
     you can control which table to check.
 
     """
-    def runTest(self):
-        caps_logger.info("Running " + str(self))
-        flow_caps_common(self, is_exact=False)
 
-test_prio["FillTableWC"] = -1
+    priority = -1
+
+    def runTest(self):
+        logging.info("Running " + str(self))
+        flow_caps_common(self, is_exact=False)
diff --git a/tests/cxn.py b/tests/cxn.py
index a4b3d8a..d311391 100644
--- a/tests/cxn.py
+++ b/tests/cxn.py
@@ -4,13 +4,13 @@
 """
 
 import time
-import signal
 import sys
 import logging
 
 import unittest
 import random
 
+from oftest import config
 import oftest.controller as controller
 import oftest.cstruct as ofp
 import oftest.message as message
@@ -19,47 +19,15 @@
 
 from oftest.testutils import *
 
-#@var cxn_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-cxn_port_map = None
-#@var cxn_logger Local logger object
-cxn_logger = None
-#@var cxn_config Local copy of global configuration data
-cxn_config = None
-
-test_prio = {}
-
-def test_set_init(config):
-    """
-    Set up function for connection test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    global cxn_port_map
-    global cxn_logger
-    global cxn_config
-
-    cxn_logger = logging.getLogger("cxn")
-    cxn_logger.info("Initializing test set")
-    cxn_port_map = config["port_map"]
-    cxn_config = config
-
 class BaseHandshake(unittest.TestCase):
     """
     Base handshake case to set up controller, but do not send hello.
     """
 
+    priority = -1
     controllers = []
     default_timeout = 2
 
-    def sig_handler(self, v1, v2):
-        cxn_logger.critical("Received interrupt signal; exiting")
-        print "Received interrupt signal; exiting"
-        self.clean_shutdown = False
-        self.tearDown()
-        sys.exit(1)
-
     def controllerSetup(self, host, port):
         con = controller.Controller(host=host,port=port)
 
@@ -72,21 +40,13 @@
         self.controllers.append(con)
 
     def setUp(self):
-        self.logger = cxn_logger
-        self.config = cxn_config
-        #@todo Test cases shouldn't monkey with signals; move SIGINT handler
-        # to top-level oft
-        try:
-           signal.signal(signal.SIGINT, self.sig_handler)
-        except ValueError, e:
-           cxn_logger.info("Could not set SIGINT handler: %s" % e)
-        cxn_logger.info("** START TEST CASE " + str(self))
+        logging.info("** START TEST CASE " + str(self))
 
-        self.default_timeout = test_param_get(cxn_config,
-                                              'default_timeout') or 2
+        self.default_timeout = test_param_get('default_timeout',
+                                              default=2)
 
     def tearDown(self):
-        cxn_logger.info("** END TEST CASE " + str(self))
+        logging.info("** END TEST CASE " + str(self))
         for con in self.controllers:
             con.shutdown()
             if self.clean_shutdown:
@@ -98,23 +58,22 @@
 
     def assertTrue(self, cond, msg):
         if not cond:
-            cxn_logger.error("** FAILED ASSERTION: " + msg)
+            logging.error("** FAILED ASSERTION: " + msg)
         unittest.TestCase.assertTrue(self, cond, msg)
 
-test_prio["BaseHandshake"] = -1
-
 class HandshakeNoHello(BaseHandshake):
     """
     TCP connect to switch, but do not sent hello,
     and wait for disconnect.
     """
     def runTest(self):
-        self.controllerSetup(cxn_config["controller_host"],
-                             cxn_config["controller_port"])
+        self.controllerSetup(config["controller_host"],
+                             config["controller_port"])
         self.controllers[0].connect(self.default_timeout)
-        cxn_logger.info("TCP Connected " + 
-                        str(self.controllers[0].switch_addr))
-        cxn_logger.info("Hello not sent, waiting for timeout")
+
+        logging.info("TCP Connected " + 
+                     str(self.controllers[0].switch_addr))
+        logging.info("Hello not sent, waiting for timeout")
 
         # wait for controller to die
         count = 0
@@ -127,15 +86,16 @@
     and wait for disconnect.
     """
     def runTest(self):
-        self.controllerSetup(cxn_config["controller_host"],
-                             cxn_config["controller_port"])
+        self.controllerSetup(config["controller_host"],
+                             config["controller_port"])
         self.controllers[0].connect(self.default_timeout)
-        cxn_logger.info("TCP Connected " + 
-                                    str(self.controllers[0].switch_addr))
-        cxn_logger.info("Sending hello")
+
+        logging.info("TCP Connected " + 
+                     str(self.controllers[0].switch_addr))
+        logging.info("Sending hello")
         self.controllers[0].message_send(message.hello())
 
-        cxn_logger.info("Features request not sent, waiting for timeout")
+        logging.info("Features request not sent, waiting for timeout")
 
         # wait for controller to die
         count = 0
@@ -147,13 +107,15 @@
     Complete handshake and respond to echo request, but otherwise do nothing.
     Good for manual testing.
     """
+
+    priority = -1
+
     def runTest(self):
-        self.num_controllers = test_param_get(cxn_config, 
-                                              'num_controllers') or 1
+        self.num_controllers = test_param_get('num_controllers', default=1)
 
         for i in range(self.num_controllers):
-            self.controllerSetup(cxn_config["controller_host"],
-                                 cxn_config["controller_port"]+i)
+            self.controllerSetup(config["controller_host"],
+                                 config["controller_port"]+i)
         for i in range(self.num_controllers):
             self.controllers[i].handshake_done = False
 
@@ -163,14 +125,14 @@
             for con in self.controllers:
                 if con.switch_socket and con.handshake_done:
                     if count < 7:
-                        cxn_logger.info(con.host + ":" + str(con.port) + 
-                                        ": maintaining connection to " +
-                                        str(con.switch_addr))
+                        logging.info(con.host + ":" + str(con.port) + 
+                                     ": maintaining connection to " +
+                                     str(con.switch_addr))
                         count = count + 1
                     else:
-                        cxn_logger.info(con.host + ":" + str(con.port) + 
-                                        ": disconnecting from " +
-                                        str(con.switch_addr))
+                        logging.info(con.host + ":" + str(con.port) + 
+                                     ": disconnecting from " +
+                                     str(con.switch_addr))
                         con.disconnect()
                         con.handshake_done = False
                         count = 0
@@ -180,23 +142,22 @@
                     # ensure version compatibilty?
                     con.connect(self.default_timeout)
                     if not con.switch_socket:
-                        cxn_logger.info("Did not connect to switch")
+                        logging.info("Did not connect to switch")
                         continue
-                    cxn_logger.info("TCP Connected " + str(con.switch_addr))
-                    cxn_logger.info("Sending hello")
+                    logging.info("TCP Connected " + str(con.switch_addr))
+                    logging.info("Sending hello")
                     con.message_send(message.hello())
                     request = message.features_request()
                     reply, pkt = con.transact(request, 
                                               timeout=self.default_timeout)
                     if reply:
-                        cxn_logger.info("Handshake complete with " + 
-                                        str(con.switch_addr))
+                        logging.info("Handshake complete with " + 
+                                    str(con.switch_addr))
                         con.handshake_done = True
                         con.keep_alive = True
                     else:
-                        cxn_logger.info("Did not complete features_request for handshake")
+                        logging.info("Did not complete features_request " +
+                                     "for handshake")
                         con.disconnect()
                         con.handshake_done = False
 
-test_prio["HandshakeAndKeepalive"] = -1
-
diff --git a/tests/detailed_contr_sw_messages.py b/tests/detailed_contr_sw_messages.py
index d45935d..c969030 100644
--- a/tests/detailed_contr_sw_messages.py
+++ b/tests/detailed_contr_sw_messages.py
@@ -9,56 +9,38 @@
 import unittest
 import random
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
-cs_port_map = None
-cs_logger = None
-cs_config = None
-
-def test_set_init(config):
-   
-
-    basic.test_set_init(config)
-
-    global cs_port_map
-    global cs_logger
-    global cs_config
-
-    cs_logger = logging.getLogger("Detailed controller to switch messages")
-    cs_logger.info("Initializing test set")
-    cs_port_map = config["port_map"]
-    cs_config = config
-
-
-class OverlapChecking(basic.SimpleDataPlane):
+class OverlapChecking(base_tests.SimpleDataPlane):
     
     """Verify that if overlap check flag is set in the flow entry and an overlapping flow is inserted then an error 
         is generated and switch refuses flow entry"""
     
     def runTest(self):
         
-        cs_logger.info("Running Overlap_Checking test")
+        logging.info("Running Overlap_Checking test")
        
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear Switch State
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting two overlapping flows")
-        cs_logger.info("Expecting switch to return an error")
+        logging.info("Inserting two overlapping flows")
+        logging.info("Expecting switch to return an error")
 
         #Insert a flow F with wildcarded all fields
         (pkt,match) = Wildcard_All(self,of_ports)
@@ -101,24 +83,24 @@
                                'Error Message code is not overlap')
 
 
-class NoOverlapChecking(basic.SimpleDataPlane):
+class NoOverlapChecking(base_tests.SimpleDataPlane):
 
     """Verify that without overlap check flag set, overlapping flows can be created."""  
     
     def runTest(self):
      
-        cs_logger.info("Running No_Overlap_Checking test")
+        logging.info("Running No_Overlap_Checking test")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear Switch State
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting two overlapping flows")
-        cs_logger.info("Expecting switch to insert the flows without generating errors")
+        logging.info("Inserting two overlapping flows")
+        logging.info("Expecting switch to insert the flows without generating errors")
 
         #Build a flow F with wildcarded all fields.
         (pkt,match) = Wildcard_All(self,of_ports)
@@ -133,24 +115,24 @@
         Verify_TableStats(self,active_entries=2)
 
 
-class IdenticalFlows(basic.SimpleDataPlane):
+class IdenticalFlows(base_tests.SimpleDataPlane):
     
     """Verify that adding two identical flows overwrites the existing one and clears counters"""
 
     def runTest(self):
         
-        cs_logger.info("Running Identical_Flows test ")
+        logging.info("Running Identical_Flows test ")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting two identical flows one by one")
-        cs_logger.info("Expecting switch to overwrite the first flow and clear the counters associated with it ")
+        logging.info("Inserting two identical flows one by one")
+        logging.info("Expecting switch to overwrite the first flow and clear the counters associated with it ")
         
         # Create and add flow-1, check on dataplane it is active.
         (pkt,match) = Wildcard_All(self,of_ports)
@@ -174,24 +156,24 @@
         Verify_FlowStats(self,match,byte_count=0,packet_count=0)
 
    
-class EmerFlowTimeout(basic.SimpleProtocol): 
+class EmerFlowTimeout(base_tests.SimpleProtocol): 
 
     """Timeout values are not allowed for emergency flows"""
 
     def runTest(self):
 
-        cs_logger.info("Running Emergency_Flow_Timeout test")
+        logging.info("Running Emergency_Flow_Timeout test")
         
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting an emergency flow with timeout values")
-        cs_logger.info("Expecting switch to generate error ")
+        logging.info("Inserting an emergency flow with timeout values")
+        logging.info("Expecting switch to generate error ")
         
         #Insert an emergency flow 
         pkt = simple_tcp_packet()
@@ -209,7 +191,7 @@
         act.port = of_ports[1]
         
         request.actions.add(act)
-        cs_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Flow addition did not fail.")
 
@@ -226,23 +208,23 @@
                                'Error Message code is not bad emergency timeout')
 
 
-class MissingModifyAdd(basic.SimpleDataPlane):
+class MissingModifyAdd(base_tests.SimpleDataPlane):
 
     """If a modify does not match an existing flow, the flow gets added """
     
     def runTest(self):
         
-        cs_logger.info("Running Missing_Modify_Add test")
+        logging.info("Running Missing_Modify_Add test")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
-        cs_logger.info("Inserting a flow-modify that does not match an existing flow")
-        cs_logger.info("Expecting flow to get added i.e OFPFC_MODIFY command should be taken as OFPFC_ADD ")
+        logging.info("Inserting a flow-modify that does not match an existing flow")
+        logging.info("Expecting flow to get added i.e OFPFC_MODIFY command should be taken as OFPFC_ADD ")
 
         #Clear Switch State
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         #Generate a flow-mod,command OFPC_MODIFY 
@@ -257,7 +239,7 @@
         act3.port = of_ports[1]
         self.assertTrue(request.actions.add(act3), "could not add action")
 
-        cs_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed") 
@@ -266,24 +248,24 @@
         Verify_TableStats(self,active_entries=1)
 
 
-class ModifyAction(basic.SimpleDataPlane):
+class ModifyAction(base_tests.SimpleDataPlane):
 
     """A modified flow preserves counters"""
     
     def runTest(self):
         
-        cs_logger.info("Running Modify_Action test ")
+        logging.info("Running Modify_Action test ")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting a Flow and incrementing flow counters. Modifying the flow action")
-        cs_logger.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
+        logging.info("Inserting a Flow and incrementing flow counters. Modifying the flow action")
+        logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
            
         #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A , output to of_port[1]
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
@@ -304,24 +286,24 @@
         Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
 
 
-class StrictModifyAction(basic.SimpleDataPlane):
+class StrictModifyAction(base_tests.SimpleDataPlane):
 
     """Strict Modify Flow also changes action preserves counters"""
 
     def runTest(self):
         
-        cs_logger.info("Running Strict_Modify_Action test")
+        logging.info("Running Strict_Modify_Action test")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting Flows and incrementing flow counters. Strict Modify the flow action ")
-        cs_logger.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
+        logging.info("Inserting Flows and incrementing flow counters. Strict Modify the flow action ")
+        logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
         
         #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
@@ -348,24 +330,24 @@
         Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
 
 
-class DeleteNonexistingFlow(basic.SimpleDataPlane):
+class DeleteNonexistingFlow(base_tests.SimpleDataPlane):
     
     """Request deletion of non-existing flow"""
     
     def runTest(self):
         
-        cs_logger.info("Delete_NonExisting_Flow test begins")
+        logging.info("Delete_NonExisting_Flow test begins")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Deleting a non-existing flow")
-        cs_logger.info("Expecting switch to ignore the command , without generating errors")
+        logging.info("Deleting a non-existing flow")
+        logging.info("Expecting switch to ignore the command , without generating errors")
 
         # Issue a delete command 
         msg = message.flow_mod()
@@ -382,7 +364,7 @@
 
 
         
-class SendFlowRem(basic.SimpleDataPlane):
+class SendFlowRem(base_tests.SimpleDataPlane):
     
     """Check deletion of flows happens and generates messages as configured.
     If Send Flow removed message Flag is set in the flow entry, the flow deletion of that respective flow should generate the flow removed message, 
@@ -390,19 +372,19 @@
 
     def runTest(self):
 
-        cs_logger.info("Running Send_Flow_Rem test ")
+        logging.info("Running Send_Flow_Rem test ")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear swicth state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting flows F1 and F2 without and with send_flow_removed_message flag set ")
-        cs_logger.info("Deleting the flows")
-        cs_logger.info("Expecting flow removed message only for F2")
+        logging.info("Inserting flows F1 and F2 without and with send_flow_removed_message flag set ")
+        logging.info("Deleting the flows")
+        logging.info("Expecting flow removed message only for F2")
 
         # Insert flow-1 with F without OFPFF_SEND_FLOW_REM flag set.
         (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -432,7 +414,7 @@
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         # Delete the flow-2
-        rc2 = delete_all_flows(self.controller, cs_logger)
+        rc2 = delete_all_flows(self.controller)
         self.assertEqual(rc2, 0, "Failed to delete all flows")
 
         # Verify flow removed message is generated for the FLOW-2
@@ -443,24 +425,24 @@
                         'Did not receive flow removed message for this flow')
 
 
-class DeleteEmerFlow(basic.SimpleProtocol):
+class DeleteEmerFlow(base_tests.SimpleProtocol):
 
     """Delete emergency flow and verify no message is generated.An emergency flow deletion will not generate flow-removed messages even if 
     Send Flow removed message flag was set during the emergency flow entry"""
 
     def runTest(self):
 
-        cs_logger.info("Running Delete_Emer_Flow")
+        logging.info("Running Delete_Emer_Flow")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         
         #Clear switch state        
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting a emergency flow with send_flow_removed flag set")
-        cs_logger.info("Expecting no flow_removed_message on the deletion of the emergency flow")
+        logging.info("Inserting a emergency flow with send_flow_removed flag set")
+        logging.info("Expecting no flow_removed_message on the deletion of the emergency flow")
         
         # Insert a flow with emergency bit set.
         pkt = simple_tcp_packet()
@@ -486,25 +468,25 @@
                         'Test Failed ')
 
 
-class StrictVsNonstrict(basic.SimpleDataPlane):
+class StrictVsNonstrict(base_tests.SimpleDataPlane):
 
     """Delete and verify strict and non-strict behaviors
     This test compares the behavior of delete strict and non-strict"""
 
     def runTest(self):
         
-        cs_logger.info("Strict_Vs_Nonstrict test begins")
+        logging.info("Strict_Vs_Nonstrict test begins")
         
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         
-        cs_logger.info("Inserting a flow with exact match")
-        cs_logger.info("Issue Strict Delete command , verify it gets deleted")     
+        logging.info("Inserting a flow with exact match")
+        logging.info("Issue Strict Delete command , verify it gets deleted")     
         
         #Insert F with an exact Match 
         (pkt,match) = Exact_Match(self,of_ports)  
@@ -514,9 +496,9 @@
         Strict_Delete(self,match)
         Verify_TableStats(self,active_entries=0)
 
-        cs_logger.info("Inserting two overlapping flows")
-        cs_logger.info("Issue Strict Delete command ")
-        cs_logger.info("Expecting only one flow gets deleted , because Strict Delete matches on wildcards as well")     
+        logging.info("Inserting two overlapping flows")
+        logging.info("Issue Strict Delete command ")
+        logging.info("Expecting only one flow gets deleted , because Strict Delete matches on wildcards as well")     
         
         #Insert Flow T with match on all , except one wildcarded ( say src adddress ). 
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
@@ -529,9 +511,9 @@
         Strict_Delete(self,match1)
         Verify_TableStats(self,active_entries=1) 
 
-        cs_logger.info("Inserting two overlapping flows")
-        cs_logger.info("Issue Non-Strict Delete command ")
-        cs_logger.info("Expecting both the flow gets deleted , because wildcards are active")    
+        logging.info("Inserting two overlapping flows")
+        logging.info("Issue Non-Strict Delete command ")
+        logging.info("Expecting both the flow gets deleted , because wildcards are active")    
 
         #Insert T and T' again . 
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
@@ -542,9 +524,9 @@
         NonStrict_Delete(self,match1)
         Verify_TableStats(self,active_entries=0)
 
-        cs_logger.info("Inserting three overlapping flows with different priorities")
-        cs_logger.info("Issue Non-Strict Delete command ")
-        cs_logger.info("Expecting all the flows to get deleted")  
+        logging.info("Inserting three overlapping flows with different priorities")
+        logging.info("Issue Non-Strict Delete command ")
+        logging.info("Expecting all the flows to get deleted")  
   
         #Insert T , add Priority P (say 100 ) 
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
@@ -560,9 +542,9 @@
         NonStrict_Delete(self,match1,priority=200)
         Verify_TableStats(self,active_entries=0)
 
-        cs_logger.info("Inserting three overlapping flows with different priorities")
-        cs_logger.info("Issue Strict Delete command ")
-        cs_logger.info("Expecting only one to get deleted because here priorities & wildcards are being matched")  
+        logging.info("Inserting three overlapping flows with different priorities")
+        logging.info("Issue Strict Delete command ")
+        logging.info("Expecting only one to get deleted because here priorities & wildcards are being matched")  
 
         #Issue Strict-Delete and verify only T'' gets deleted. 
         (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
@@ -573,26 +555,26 @@
 
         
    
-class Outport1(basic.SimpleDataPlane):
+class Outport1(base_tests.SimpleDataPlane):
 
     """Delete flows filtered by action outport.If the out_port field in the delete command contains a value other than OFPP_NONE,
     it introduces a constraint when matching. This constraint is that the rule must contain an output action directed at that port."""
 
     def runTest(self):
         
-        cs_logger.info("Outport1 test begins")
+        logging.info("Outport1 test begins")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting a flow with output action --> of_port[1]")
-        cs_logger.info("Deleting the flow but with out_port set to of_port[2]")
-        cs_logger.info("Expecting switch to filter the delete command")
+        logging.info("Inserting a flow with output action --> of_port[1]")
+        logging.info("Deleting the flow but with out_port set to of_port[2]")
+        logging.info("Expecting switch to filter the delete command")
         
         #Build and send Flow-1 with action output to of_port[1]
         (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -614,8 +596,8 @@
         # Verify flow will not get deleted, active_entries in table_stats_request = 1
         Verify_TableStats(self,active_entries=1)
 
-        cs_logger.info("Deleting the flow with out_port set to of_port[1]")
-        cs_logger.info("Expecting switch to delete the flow")
+        logging.info("Deleting the flow with out_port set to of_port[1]")
+        logging.info("Expecting switch to delete the flow")
 
         #Send Delete command with contraint out_port = of_ports[1]
         msg7 = message.flow_mod()
@@ -632,24 +614,24 @@
         Verify_TableStats(self,active_entries=0)
 
 
-class IdleTimeout(basic.SimpleDataPlane):
+class IdleTimeout(base_tests.SimpleDataPlane):
 
     """ Verify that idle timeout is implemented"""
 
     def runTest(self):
         
-        cs_logger.info("Running Idle_Timeout test ")
+        logging.info("Running Idle_Timeout test ")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
         
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting flow entry with idle_timeout set. Also send_flow_removed_message flag set")
-        cs_logger.info("Expecting the flow entry to delete with given idle_timeout")
+        logging.info("Inserting flow entry with idle_timeout set. Also send_flow_removed_message flag set")
+        logging.info("Expecting the flow entry to delete with given idle_timeout")
 
         #Insert a flow entry with idle_timeout=1.Send_Flow_Rem flag set
         msg9 = message.flow_mod()
@@ -676,24 +658,24 @@
                          'Flow was not alive for 1 sec')
 
 
-class Outport2(basic.SimpleDataPlane):
+class Outport2(base_tests.SimpleDataPlane):
 
     """Add, modify flows with outport set. This field is ignored by ADD, MODIFY, and MODIFY STRICT messages."""
 
     def runTest(self):
         
-        cs_logger.info("Running Outport2 test ")
+        logging.info("Running Outport2 test ")
 
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Adding and modifying flow with out_port fields set")
-        cs_logger.info("Expecting switch to ignore out_port")
+        logging.info("Adding and modifying flow with out_port fields set")
+        logging.info("Expecting switch to ignore out_port")
 
         # Create and add flow-1,Action A ,output to port of_port[1], out_port set to of_ports[2]
         (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -716,24 +698,24 @@
 
 
 
-class HardTimeout(basic.SimpleDataPlane):
+class HardTimeout(base_tests.SimpleDataPlane):
 
     """ Verify that hard timeout is implemented """
 
     def runTest(self):
 
-        cs_logger.info("Running Hard_Timeout test ")
+        logging.info("Running Hard_Timeout test ")
         
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting flow entry with hard_timeout set. Also send_flow_removed_message flag set")
-        cs_logger.info("Expecting the flow entry to delete with given hard_timeout")
+        logging.info("Inserting flow entry with hard_timeout set. Also send_flow_removed_message flag set")
+        logging.info("Expecting the flow entry to delete with given hard_timeout")
 
         # Insert a flow entry with hardtimeout=1 and send_flow_removed flag set
         msg9 = message.flow_mod()
@@ -760,7 +742,7 @@
                          'Flow was not alive for 1 sec')
 
 
-class FlowTimeout(basic.SimpleDataPlane):
+class FlowTimeout(base_tests.SimpleDataPlane):
   
     """Verify that Flow removed messages are generated as expected
     Flow removed messages being generated when flag is set, is already tested in the above tests 
@@ -769,18 +751,18 @@
     
     def runTest(self):
 
-        cs_logger.info("Running Flow_Timeout test ")
+        logging.info("Running Flow_Timeout test ")
         
-        of_ports = cs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, cs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        cs_logger.info("Inserting flow entry with hard_timeout set and send_flow_removed_message flag not set")
-        cs_logger.info("Expecting the flow entry to delete, but no flow removed message")
+        logging.info("Inserting flow entry with hard_timeout set and send_flow_removed_message flag not set")
+        logging.info("Expecting the flow entry to delete, but no flow removed message")
 
         # Insert a flow with hard_timeout = 1 but no Send_Flow_Rem flag set
         pkt = simple_tcp_packet()
diff --git a/tests/flow_expire.py b/tests/flow_expire.py
index 9be5fdd..ad35f23 100644
--- a/tests/flow_expire.py
+++ b/tests/flow_expire.py
@@ -9,44 +9,19 @@
 import unittest
 import random
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 
-#@var port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-fe_port_map = None
-#@var fe_logger Local logger object
-fe_logger = None
-#@var fe_config Local copy of global configuration data
-fe_config = None
-
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global fe_port_map
-    global fe_logger
-    global fe_config
-
-    fe_logger = logging.getLogger("flow_expire")
-    fe_logger.info("Initializing test set")
-    fe_port_map = config["port_map"]
-    fe_config = config
-
-class FlowExpire(basic.SimpleDataPlane):
+class FlowExpire(base_tests.SimpleDataPlane):
     """
     Verify flow expire messages are properly generated.
 
@@ -55,16 +30,14 @@
     Verify the flow expiration message is received
     """
     def runTest(self):
-        global fe_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fe_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
-        rc = delete_all_flows(self.controller, fe_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         pkt = simple_tcp_packet()
@@ -74,13 +47,13 @@
                         "Could not generate flow match from pkt")
         act = action.action_output()
 
-        of_ports = fe_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
         ingress_port = of_ports[0]
         egress_port  = of_ports[1]
-        fe_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
         
         match.in_port = ingress_port
@@ -94,7 +67,7 @@
         act.port = egress_port
         self.assertTrue(request.actions.add(act), "Could not add action")
         
-        fe_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 3017eed..e3dc1a7 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -64,6 +64,7 @@
 import random
 import time
 
+from oftest import config
 import oftest.controller  as controller
 import oftest.cstruct     as ofp
 import oftest.message     as message
@@ -72,41 +73,11 @@
 import oftest.action_list as action_list
 import oftest.parse       as parse
 import pktact
-import basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 
-#@var port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-fq_port_map = None
-#@var fq_logger Local logger object
-fq_logger = None
-#@var fq_config Local copy of global configuration data
-fq_config = None
-
-# For test priority
-test_prio = {}
-
-
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global fq_port_map
-    global fq_logger
-    global fq_config
-
-    fq_logger = logging.getLogger("flowq")
-    fq_logger.info("Initializing test set")
-    fq_port_map = config["port_map"]
-    fq_config = config
-
 
 def flip_coin():
     return random.randint(1, 100) <= 50
@@ -176,11 +147,11 @@
             self.dl_addrs.append(rand_dl_addr())
             i = i + 1
     
-        if test_param_get(fq_config, "vlans", []) != []:
-           self.vlans = test_param_get(fq_config, "vlans", [])
+        if test_param_get("vlans", []) != []:
+           self.vlans = test_param_get("vlans", [])
 
-           fq_logger.info("Overriding VLAN ids to:")
-           fq_logger.info(self.vlans)
+           logging.info("Overriding VLAN ids to:")
+           logging.info(self.vlans)
         else:
            self.vlans = []
            i = 0
@@ -423,7 +394,7 @@
         return True
 
     def actions_equal(self, x):
-        if test_param_get(fq_config, "conservative_ordered_actions", True):
+        if test_param_get("conservative_ordered_actions", True):
             # Compare actions lists as unordered
             
             aa = copy.deepcopy(x.actions.actions)
@@ -527,10 +498,10 @@
         # Action lists are ordered, so pick an ordered random subset of
         # supported actions
 
-        actions_force = test_param_get(fq_config, "actions_force", 0)
+        actions_force = test_param_get("actions_force", 0)
         if actions_force != 0:
-            fq_logger.info("Forced actions:")
-            fq_logger.info(actions_bmap_to_str(actions_force))
+            logging.info("Forced actions:")
+            logging.info(actions_bmap_to_str(actions_force))
 
         ACTION_MAX_LEN = 65535 # @fixme Should be test param?
         supported_actions = []
@@ -636,14 +607,14 @@
 
         # By default, test with conservative ordering conventions
         # This should probably be indicated in a profile
-        if test_param_get(fq_config, "conservative_ordered_actions", True):
+        if test_param_get("conservative_ordered_actions", True):
             self.rand_actions_ordered(fi, valid_actions, valid_ports, valid_queues)
             return self
 
-        actions_force = test_param_get(fq_config, "actions_force", 0)
+        actions_force = test_param_get("actions_force", 0)
         if actions_force != 0:
-            fq_logger.info("Forced actions:")
-            fq_logger.info(actions_bmap_to_str(actions_force))
+            logging.info("Forced actions:")
+            logging.info(actions_bmap_to_str(actions_force))
 
         ACTION_MAX_LEN = 65535 # @fixme Should be test param?
         supported_actions = []
@@ -727,8 +698,8 @@
     def rand(self, fi, wildcards_force, valid_wildcards, valid_actions, valid_ports,
              valid_queues):
         if wildcards_force != 0:
-            fq_logger.info("Wildcards forced:")
-            fq_logger.info(wildcards_to_str(wildcards_force))
+            logging.info("Wildcards forced:")
+            logging.info(wildcards_to_str(wildcards_force))
         
         # Start with no wildcards, i.e. everything specified
         self.match.wildcards = 0
@@ -1236,17 +1207,17 @@
         self.removed_msgs = []
 
     def error_handler(self, controller, msg, rawmsg):
-        fq_logger.info("Got an ERROR message, type=%d, code=%d" \
+        logging.info("Got an ERROR message, type=%d, code=%d" \
                           % (msg.type, msg.code) \
                           )
-        fq_logger.info("Message header:")
-        fq_logger.info(msg.header.show())
+        logging.info("Message header:")
+        logging.info(msg.header.show())
         self.error_msgs.append(msg)
 
     def removed_handler(self, controller, msg, rawmsg):
-        fq_logger.info("Got a REMOVED message")
-        fq_logger.info("Message header:")
-        fq_logger.info(msg.header.show())
+        logging.info("Got a REMOVED message")
+        logging.info("Message header:")
+        logging.info(msg.header.show())
         self.removed_msgs.append(msg)
 
     def controller_set(self, controller):
@@ -1262,15 +1233,15 @@
         request = message.features_request()
         (self.sw_features, pkt) = self.controller.transact(request)
         if self.sw_features is None:
-            fq_logger.error("Get switch features failed")
+            logging.error("Get switch features failed")
             return False
         self.valid_ports = map(lambda x: x.port_no, self.sw_features.ports)
-        fq_logger.info("Ports reported by switch:")
-        fq_logger.info(self.valid_ports)
-        ports_override = test_param_get(fq_config, "ports", [])
+        logging.info("Ports reported by switch:")
+        logging.info(self.valid_ports)
+        ports_override = test_param_get("ports", [])
         if ports_override != []:
-            fq_logger.info("Overriding ports to:")
-            fq_logger.info(ports_override)
+            logging.info("Overriding ports to:")
+            logging.info(ports_override)
             self.valid_ports = ports_override
         
         # TBD - OFPP_LOCAL is returned by OVS is switch features --
@@ -1286,16 +1257,16 @@
 #                                  ofp.OFPP_CONTROLLER \
 #                                  ] \
 #                                 )
-        fq_logger.info("Supported actions reported by switch:")
-        fq_logger.info("0x%x=%s" \
+        logging.info("Supported actions reported by switch:")
+        logging.info("0x%x=%s" \
                        % (self.sw_features.actions, \
                           actions_bmap_to_str(self.sw_features.actions) \
                           ) \
                        )
-        actions_override = test_param_get(fq_config, "actions", -1)
+        actions_override = test_param_get("actions", -1)
         if actions_override != -1:
-            fq_logger.info("Overriding supported actions to:")
-            fq_logger.info(actions_bmap_to_str(actions_override))
+            logging.info("Overriding supported actions to:")
+            logging.info(actions_bmap_to_str(actions_override))
             self.sw_features.actions = actions_override
         return True
 
@@ -1304,24 +1275,24 @@
         request = message.table_stats_request()
         (self.tbl_stats, pkt) = self.controller.transact(request)
         if self.tbl_stats is None:
-            fq_logger.error("Get table stats failed")
+            logging.error("Get table stats failed")
             return False
         i = 0
         for ts in self.tbl_stats.stats:
-            fq_logger.info("Supported wildcards for table %d reported by switch:"
+            logging.info("Supported wildcards for table %d reported by switch:"
                            % (i)
                            )
-            fq_logger.info("0x%x=%s" \
+            logging.info("0x%x=%s" \
                            % (ts.wildcards, \
                               wildcards_to_str(ts.wildcards) \
                               ) \
                            )
-            wildcards_override = test_param_get(fq_config, "wildcards", -1)
+            wildcards_override = test_param_get("wildcards", -1)
             if wildcards_override != -1:
-                fq_logger.info("Overriding supported wildcards for table %d to:"
+                logging.info("Overriding supported wildcards for table %d to:"
                                % (i)
                                )
-                fq_logger.info(wildcards_to_str(wildcards_override))
+                logging.info(wildcards_to_str(wildcards_override))
                 ts.wildcards = wildcards_override
             i = i + 1
         return True
@@ -1333,17 +1304,17 @@
         request.queue_id = ofp.OFPQ_ALL
         (self.queue_stats, pkt) = self.controller.transact(request)
         if self.queue_stats is None:
-            fq_logger.error("Get queue stats failed")
+            logging.error("Get queue stats failed")
             return False
         self.valid_queues = map(lambda x: (x.port_no, x.queue_id), \
                                 self.queue_stats.stats \
                                 )
-        fq_logger.info("(Port, queue) pairs reported by switch:")
-        fq_logger.info(self.valid_queues)
-        queues_override = test_param_get(fq_config, "queues", [])
+        logging.info("(Port, queue) pairs reported by switch:")
+        logging.info(self.valid_queues)
+        queues_override = test_param_get("queues", [])
         if queues_override != []:
-            fq_logger.info("Overriding (port, queue) pairs to:")
-            fq_logger.info(queues_override)
+            logging.info("Overriding (port, queue) pairs to:")
+            logging.info(queues_override)
             self.valid_queues = queues_override
         return True
 
@@ -1380,7 +1351,7 @@
                 self.flow_stats.stats.extend(resp.stats)
             n = n + 1
             if len(self.flow_stats.stats) > limit:
-                fq_logger.error("Too many flows returned")
+                logging.error("Too many flows returned")
                 return False
             if (resp.flags & 1) == 0:
                 break                   # No more responses expected
@@ -1396,7 +1367,7 @@
         if flow_cfg.send_rem:
             flow_mod_msg.flags = flow_mod_msg.flags | ofp.OFPFF_SEND_FLOW_REM
         flow_mod_msg.header.xid = random.randrange(1,0xffffffff)
-        fq_logger.info("Sending flow_mod(add), xid=%d"
+        logging.info("Sending flow_mod(add), xid=%d"
                         % (flow_mod_msg.header.xid)
                         )
         return (self.controller.message_send(flow_mod_msg) != -1)
@@ -1408,7 +1379,7 @@
         flow_mod_msg.buffer_id   = 0xffffffff
         flow_cfg.to_flow_mod_msg(flow_mod_msg)
         flow_mod_msg.header.xid = random.randrange(1,0xffffffff)
-        fq_logger.info("Sending flow_mod(mod), xid=%d"
+        logging.info("Sending flow_mod(mod), xid=%d"
                         % (flow_mod_msg.header.xid)
                         )
         return (self.controller.message_send(flow_mod_msg) != -1)
@@ -1422,7 +1393,7 @@
         flow_mod_msg.out_port    = ofp.OFPP_NONE
         flow_cfg.to_flow_mod_msg(flow_mod_msg)
         flow_mod_msg.header.xid = random.randrange(1,0xffffffff)
-        fq_logger.info("Sending flow_mod(del), xid=%d"
+        logging.info("Sending flow_mod(del), xid=%d"
                         % (flow_mod_msg.header.xid)
                         )
         return (self.controller.message_send(flow_mod_msg) != -1)
@@ -1434,42 +1405,42 @@
 
     def errors_verify(self, num_exp, type = 0, code = 0):
         result = True
-        fq_logger.info("Expecting %d error messages" % (num_exp))
+        logging.info("Expecting %d error messages" % (num_exp))
         num_got = len(self.error_msgs)
-        fq_logger.info("Got %d error messages" % (num_got))
+        logging.info("Got %d error messages" % (num_got))
         if num_got != num_exp:
-            fq_logger.error("Incorrect number of error messages received")
+            logging.error("Incorrect number of error messages received")
             result = False
         if num_exp == 0:
             return result
         elif num_exp == 1:
-            fq_logger.info("Expecting error message, type=%d, code=%d" \
+            logging.info("Expecting error message, type=%d, code=%d" \
                             % (type, code) \
                             )
             f = False
             for e in self.error_msgs:
                 if e.type == type and e.code == code:
-                    fq_logger.info("Got it")
+                    logging.info("Got it")
                     f = True
             if not f:
-                fq_logger.error("Did not get it")
+                logging.error("Did not get it")
                 result = False
         else:
-            fq_logger.error("Can't expect more than 1 error message type")
+            logging.error("Can't expect more than 1 error message type")
             result = False
         return result
 
     def removed_verify(self, num_exp):
         result = True
-        fq_logger.info("Expecting %d removed messages" % (num_exp))
+        logging.info("Expecting %d removed messages" % (num_exp))
         num_got = len(self.removed_msgs)
-        fq_logger.info("Got %d removed messages" % (num_got))
+        logging.info("Got %d removed messages" % (num_got))
         if num_got != num_exp:
-            fq_logger.error("Incorrect number of removed messages received")
+            logging.error("Incorrect number of removed messages received")
             result = False
         if num_exp < 2:
             return result
-        fq_logger.error("Can't expect more than 1 error message type")
+        logging.error("Can't expect more than 1 error message type")
         return False
 
     # modf == True <=> Verify for flow modify, else for add/delete
@@ -1477,88 +1448,88 @@
         result = True
     
         # Verify flow count in switch
-        fq_logger.info("Reading table stats")
-        fq_logger.info("Expecting %d flows" % (self.flow_tbl.count()))
+        logging.info("Reading table stats")
+        logging.info("Expecting %d flows" % (self.flow_tbl.count()))
         if not self.tbl_stats_get():
-            fq_logger.error("Get table stats failed")
+            logging.error("Get table stats failed")
             return False
         n = 0
         for ts in self.tbl_stats.stats:
             n = n + ts.active_count
-        fq_logger.info("Table stats reported %d active flows" \
+        logging.info("Table stats reported %d active flows" \
                           % (n) \
                           )
         if n != self.flow_tbl.count():
-            fq_logger.error("Incorrect number of active flows reported")
+            logging.error("Incorrect number of active flows reported")
             result = False
     
         # Read flows from switch
-        fq_logger.info("Retrieving flows from switch")
-        fq_logger.info("Expecting %d flows" % (self.flow_tbl.count()))
+        logging.info("Retrieving flows from switch")
+        logging.info("Expecting %d flows" % (self.flow_tbl.count()))
         if not self.flow_stats_get():
-            fq_logger.error("Get flow stats failed")
+            logging.error("Get flow stats failed")
             return False
-        fq_logger.info("Retrieved %d flows" % (len(self.flow_stats.stats)))
+        logging.info("Retrieved %d flows" % (len(self.flow_stats.stats)))
     
         # Verify flows returned by switch
     
         if len(self.flow_stats.stats) != self.flow_tbl.count():
-            fq_logger.error("Switch reported incorrect number of flows")
+            logging.error("Switch reported incorrect number of flows")
             result = False
     
-        fq_logger.info("Verifying received flows")
+        logging.info("Verifying received flows")
         for fc in self.flow_tbl.values():
             fc.matched = False
         for fs in self.flow_stats.stats:
             flow_in = Flow_Cfg()
             flow_in.from_flow_stat(fs)
-            fq_logger.info("Received flow:")
-            fq_logger.info(str(flow_in))
+            logging.info("Received flow:")
+            logging.info(str(flow_in))
             fc = self.flow_tbl.find(flow_in)
             if fc is None:
-                fq_logger.error("Received flow:")
-                fq_logger.error(str(flow_in))
-                fq_logger.error("does not match any defined flow")
+                logging.error("Received flow:")
+                logging.error(str(flow_in))
+                logging.error("does not match any defined flow")
                 result = False
             elif fc.matched:
-                fq_logger.error("Received flow:")
-                fq_logger.error(str(flow_in))
-                fq_logger.error("re-matches defined flow:")
-                fq_logger.info(str(fc))
+                logging.error("Received flow:")
+                logging.error(str(flow_in))
+                logging.error("re-matches defined flow:")
+                logging.info(str(fc))
                 result = False
             else:
-                fq_logger.info("matched")
+                logging.info("matched")
                 if modf:
                     # Check for modify
                     
                     if flow_in.cookie != fc.cookie:
-                        fq_logger.warning("Defined flow:")
-                        fq_logger.warning(str(fc))
-                        fq_logger.warning("Received flow:")
-                        fq_logger.warning(str(flow_in))
-                        fq_logger.warning("cookies do not match")
+                        logging.warning("Defined flow:")
+                        logging.warning(str(fc))
+                        logging.warning("Received flow:")
+                        logging.warning(str(flow_in))
+                        logging.warning("cookies do not match")
                     if not flow_in.actions_equal(fc):
-                        fq_logger.error("Defined flow:")
-                        fq_logger.error(str(fc))
-                        fq_logger.error("Received flow:")
-                        fq_logger.error(str(flow_in))
-                        fq_logger.error("actions do not match")
+                        logging.error("Defined flow:")
+                        logging.error(str(fc))
+                        logging.error("Received flow:")
+                        logging.error(str(flow_in))
+                        logging.error("actions do not match")
                 else:
                     # Check for add/delete
                     
                     if not flow_in == fc:
-                        fq_logger.error("Defined flow:")
-                        fq_logger.error(str(fc))
-                        fq_logger.error("Received flow:")
-                        fq_logger.error(str(flow_in))
-                        fq_logger.error("non-key portions of flow do not match")
+                        logging.error("Defined flow:")
+                        logging.error(str(fc))
+                        logging.error("Received flow:")
+                        logging.error(str(flow_in))
+                        logging.error("non-key portions of flow do not match")
                         result = False
                 fc.matched = True
         for fc in self.flow_tbl.values():
             if not fc.matched:
-                fq_logger.error("Defined flow:")
-                fq_logger.error(str(fc))
-                fq_logger.error("was not returned by switch")
+                logging.error("Defined flow:")
+                logging.error(str(fc))
+                logging.error("was not returned by switch")
                 result = False
     
         return result
@@ -1596,7 +1567,7 @@
 # 7. Test PASSED iff all flows sent to switch in step 3 above are returned
 #    in step 5 above; else test FAILED
 
-class Flow_Add_5(basic.SimpleProtocol):
+class Flow_Add_5(base_tests.SimpleProtocol):
     """
     Test FLOW_ADD_5 from draft top-half test plan
     
@@ -1605,14 +1576,14 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Add_5 TEST BEGIN")
+        logging.info("Flow_Add_5 TEST BEGIN")
 
-        num_flows = test_param_get(fq_config, "num_flows", 100)
+        num_flows = test_param_get("num_flows", 100)
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -1629,7 +1600,7 @@
             for ts in sw.tbl_stats.stats:
                 num_flows = num_flows + ts.max_entries
 
-        fq_logger.info("Generating %d flows" % (num_flows))        
+        logging.info("Generating %d flows" % (num_flows))        
 
         # Dream up some flow information, i.e. space to chose from for
         # random flow parameter generation
@@ -1644,10 +1615,10 @@
 
         # Send flow table to switch
 
-        fq_logger.info("Sending flow adds to switch")
+        logging.info("Sending flow adds to switch")
         for fc in ft.values():          # Randomizes order of sending
-            fq_logger.info("Adding flow:")
-            fq_logger.info(str(fc));
+            logging.info("Adding flow:")
+            logging.info(str(fc));
             self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
         # Do barrier, to make sure all flows are in
@@ -1670,7 +1641,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Add_5 TEST FAILED")
-        fq_logger.info("Flow_Add_5 TEST PASSED")
+        logging.info("Flow_Add_5 TEST PASSED")
 
 
 # FLOW ADD 5_1
@@ -1696,25 +1667,26 @@
 
 # Disabled.
 # Should be DUT dependent.
-test_prio["Flow_Add_5_1"] = -1
 
-class Flow_Add_5_1(basic.SimpleProtocol):
+class Flow_Add_5_1(base_tests.SimpleProtocol):
     """
     Test FLOW_ADD_5.1 from draft top-half test plan
 
     INPUTS
     None
     """
+
+    priority = -1
     
     def runTest(self):
-        fq_logger.info("Flow_Add_5_1 TEST BEGIN")
+        logging.info("Flow_Add_5_1 TEST BEGIN")
 
-        num_flows = test_param_get(fq_config, "num_flows", 100)
+        num_flows = test_param_get("num_flows", 100)
         
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -1750,10 +1722,10 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
-        fq_logger.info("should be canonicalized as:")
-        fq_logger.info(str(fcc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
+        logging.info("should be canonicalized as:")
+        logging.info(str(fcc))
         fc.send_rem = False
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
@@ -1777,7 +1749,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Add_5_1 TEST FAILED")
-        fq_logger.info("Flow_Add_5_1 TEST PASSED")
+        logging.info("Flow_Add_5_1 TEST PASSED")
 
 
 # FLOW ADD 6
@@ -1813,9 +1785,8 @@
 
 # Disabled because of bogus capacity reported by OVS.
 # Should be DUT dependent.
-test_prio["Flow_Add_6"] = -1
 
-class Flow_Add_6(basic.SimpleProtocol):
+class Flow_Add_6(base_tests.SimpleProtocol):
     """
     Test FLOW_ADD_6 from draft top-half test plan
     
@@ -1823,13 +1794,15 @@
     num_flows - Number of flows to generate
     """
 
+    priority = -1
+
     def runTest(self):
-        fq_logger.info("Flow_Add_6 TEST BEGIN")
+        logging.info("Flow_Add_6 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -1843,8 +1816,8 @@
         for ts in sw.tbl_stats.stats:
             num_flows = num_flows + ts.max_entries
 
-        fq_logger.info("Switch capacity is %d flows" % (num_flows))        
-        fq_logger.info("Generating %d flows" % (num_flows))        
+        logging.info("Switch capacity is %d flows" % (num_flows))        
+        logging.info("Generating %d flows" % (num_flows))        
 
         # Dream up some flow information, i.e. space to chose from for
         # random flow parameter generation
@@ -1859,10 +1832,10 @@
 
         # Send flow table to switch
 
-        fq_logger.info("Sending flow adds to switch")
+        logging.info("Sending flow adds to switch")
         for fc in ft.values():          # Randomizes order of sending
-            fq_logger.info("Adding flow:")
-            fq_logger.info(str(fc));
+            logging.info("Adding flow:")
+            logging.info(str(fc));
             self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
         # Do barrier, to make sure all flows are in
@@ -1880,7 +1853,7 @@
 
         # Dream up one more flow
 
-        fq_logger.info("Creating one more flow")
+        logging.info("Creating one more flow")
         while True:
             fc = Flow_Cfg()
             fc.rand(fi, \
@@ -1897,8 +1870,8 @@
         # Send one-more flow
 
         fc.send_rem = False
-        fq_logger.info("Sending flow add switch")
-        fq_logger.info(str(fc));
+        logging.info("Sending flow add switch")
+        logging.info(str(fc));
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
         # Do barrier, to make sure all flows are in
@@ -1922,7 +1895,7 @@
             result = False
 
         self.assertTrue(result, "Flow_add_6 TEST FAILED")
-        fq_logger.info("Flow_add_6 TEST PASSED")
+        logging.info("Flow_add_6 TEST PASSED")
 
 
 # FLOW ADD 7
@@ -1947,7 +1920,7 @@
 # 6. Test PASSED iff 1 flow returned by switch, matching configuration of F2;
 #    else test FAILED
 
-class Flow_Add_7(basic.SimpleProtocol):
+class Flow_Add_7(base_tests.SimpleProtocol):
     """
     Test FLOW_ADD_7 from draft top-half test plan
     
@@ -1956,12 +1929,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Add_7 TEST BEGIN")
+        logging.info("Flow_Add_7 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -1991,8 +1964,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
@@ -2012,8 +1985,8 @@
 
         # Send that to the switch
         
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc2))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc2))
         fc2.send_rem = False
         self.assertTrue(sw.flow_add(fc2), "Failed to add flow")
         ft.insert(fc2)
@@ -2038,7 +2011,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Add_7 TEST FAILED")
-        fq_logger.info("Flow_Add_7 TEST PASSED")
+        logging.info("Flow_Add_7 TEST PASSED")
 
 
 # FLOW ADD 8
@@ -2069,7 +2042,7 @@
 #    - overlapping flow is not in flow table
 #    else test FAILED
 
-class Flow_Add_8(basic.SimpleProtocol):
+class Flow_Add_8(base_tests.SimpleProtocol):
     """
     Test FLOW_ADD_8 from draft top-half test plan
     
@@ -2078,12 +2051,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Add_8 TEST BEGIN")
+        logging.info("Flow_Add_8 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2116,8 +2089,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
@@ -2139,14 +2112,14 @@
             wn = "OFPFW_NW_DST"
         else:
             wn = all_wildcard_names[w]
-        fq_logger.info("Wildcarding out %s" % (wn))
+        logging.info("Wildcarding out %s" % (wn))
         fc2.match.wildcards = fc2.match.wildcards | w
         fc2 = fc2.canonical()
 
         # Send that to the switch, with overlap checking
         
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc2))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc2))
         fc2.send_rem = False
         self.assertTrue(sw.flow_add(fc2, True), "Failed to add flow")
 
@@ -2172,7 +2145,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Add_8 TEST FAILED")
-        fq_logger.info("Flow_Add_8 TEST PASSED")
+        logging.info("Flow_Add_8 TEST PASSED")
 
 
 # FLOW MODIFY 1
@@ -2196,7 +2169,7 @@
 # 6. Verify flow table in switch
 # 7. Test PASSED iff flow returned by switch is F'; else FAILED
 
-class Flow_Mod_1(basic.SimpleProtocol):
+class Flow_Mod_1(base_tests.SimpleProtocol):
     """
     Test FLOW_MOD_1 from draft top-half test plan
     
@@ -2205,12 +2178,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Mod_1 TEST BEGIN")
+        logging.info("Flow_Mod_1 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2240,8 +2213,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
@@ -2261,8 +2234,8 @@
 
         # Send that to the switch
         
-        fq_logger.info("Sending strict flow mod to switch:")
-        fq_logger.info(str(fc2))
+        logging.info("Sending strict flow mod to switch:")
+        logging.info(str(fc2))
         fc2.send_rem = False
         self.assertTrue(sw.flow_mod(fc2, True), "Failed to modify flow")
         ft.insert(fc2)
@@ -2287,7 +2260,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Mod_1 TEST FAILED")
-        fq_logger.info("Flow_Mod_1 TEST PASSED")
+        logging.info("Flow_Mod_1 TEST PASSED")
 
 
 # FLOW MODIFY 2
@@ -2321,7 +2294,7 @@
 #    action list;
 #    else test FAILED
         
-class Flow_Mod_2(basic.SimpleProtocol):
+class Flow_Mod_2(base_tests.SimpleProtocol):
     """
     Test FLOW_MOD_2 from draft top-half test plan
     
@@ -2330,14 +2303,14 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Mod_2 TEST BEGIN")
+        logging.info("Flow_Mod_2 TEST BEGIN")
 
-        num_flows = test_param_get(fq_config, "num_flows", 100)
+        num_flows = test_param_get("num_flows", 100)
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2361,10 +2334,10 @@
 
         # Send flow table to switch
 
-        fq_logger.info("Sending flow adds to switch")
+        logging.info("Sending flow adds to switch")
         for fc in ft.values():          # Randomizes order of sending
-            fq_logger.info("Adding flow:")
-            fq_logger.info(str(fc));
+            logging.info("Adding flow:")
+            logging.info(str(fc));
             self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
         # Do barrier, to make sure all flows are in
@@ -2426,9 +2399,9 @@
             if n > 1:
                 break
                     
-        fq_logger.info("Modifying %d flows" % (n))
-        fq_logger.info("Sending flow mod to switch:")
-        fq_logger.info(str(mfc))
+        logging.info("Modifying %d flows" % (n))
+        logging.info("Sending flow mod to switch:")
+        logging.info(str(mfc))
         self.assertTrue(sw.flow_mod(mfc, False), "Failed to modify flow")
 
         # Do barrier, to make sure all flows are in
@@ -2454,7 +2427,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Mod_2 TEST FAILED")
-        fq_logger.info("Flow_Mod_2 TEST PASSED")
+        logging.info("Flow_Mod_2 TEST PASSED")
 
 
 # FLOW MODIFY 3
@@ -2474,7 +2447,7 @@
 # 3. Verify flow table in switch
 # 4. Test PASSED iff flow defined in step 2 above verified; else FAILED
 
-class Flow_Mod_3(basic.SimpleProtocol):
+class Flow_Mod_3(base_tests.SimpleProtocol):
     """
     Test FLOW_MOD_3 from draft top-half test plan
     
@@ -2483,12 +2456,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Mod_3 TEST BEGIN")
+        logging.info("Flow_Mod_3 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2518,8 +2491,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow mod to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow mod to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_mod(fc, True), "Failed to modify flows")
@@ -2545,7 +2518,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Mod_3 TEST FAILED")
-        fq_logger.info("Flow_Mod_3 TEST PASSED")
+        logging.info("Flow_Mod_3 TEST PASSED")
 
 
 # FLOW MODIFY 3_1
@@ -2567,7 +2540,7 @@
 # 5. Verify flow table in switch
 # 6. Test PASSED iff flow defined in step 2 and 4 above verified; else FAILED
 
-class Flow_Mod_3_1(basic.SimpleProtocol):
+class Flow_Mod_3_1(base_tests.SimpleProtocol):
     """
     Test FLOW_MOD_3_1 from draft top-half test plan
     
@@ -2576,12 +2549,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Mod_3_1 TEST BEGIN")
+        logging.info("Flow_Mod_3_1 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2611,8 +2584,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow mod to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow mod to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_mod(fc, True), "Failed to modify flows")
@@ -2639,8 +2612,8 @@
 
         # Send same flow to the switch again
 
-        fq_logger.info("Sending flow mod to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow mod to switch:")
+        logging.info(str(fc))
         self.assertTrue(sw.flow_mod(fc, True), "Failed to modify flows")
 
         # Do barrier, to make sure all flows are in
@@ -2660,7 +2633,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Mod_3_1 TEST FAILED")
-        fq_logger.info("Flow_Mod_3_1 TEST PASSED")
+        logging.info("Flow_Mod_3_1 TEST PASSED")
 
 
 # FLOW DELETE 1
@@ -2683,7 +2656,7 @@
 #    less flow removed in step 3 above, are returned in step 4 above;
 #    else test FAILED
 
-class Flow_Del_1(basic.SimpleProtocol):
+class Flow_Del_1(base_tests.SimpleProtocol):
     """
     Test FLOW_DEL_1 from draft top-half test plan
     
@@ -2692,12 +2665,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Del_1 TEST BEGIN")
+        logging.info("Flow_Del_1 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2727,8 +2700,8 @@
 
         # Send it to the switch
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = False
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
@@ -2748,8 +2721,8 @@
 
         # Delete strictly
         
-        fq_logger.info("Sending strict flow del to switch:")
-        fq_logger.info(str(fc2))
+        logging.info("Sending strict flow del to switch:")
+        logging.info(str(fc2))
         self.assertTrue(sw.flow_del(fc2, True), "Failed to delete flow")
         ft.delete(fc)
 
@@ -2773,7 +2746,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Del_1 TEST FAILED")
-        fq_logger.info("Flow_Del_1 TEST PASSED")
+        logging.info("Flow_Del_1 TEST PASSED")
 
 
 # FLOW DELETE 2
@@ -2805,7 +2778,7 @@
 #    in step 7 above;
 #    else test FAILED
 
-class Flow_Del_2(basic.SimpleProtocol):
+class Flow_Del_2(base_tests.SimpleProtocol):
     """
     Test FLOW_DEL_2 from draft top-half test plan
     
@@ -2814,14 +2787,14 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Del_2 TEST BEGIN")
+        logging.info("Flow_Del_2 TEST BEGIN")
 
-        num_flows = test_param_get(fq_config, "num_flows", 100)
+        num_flows = test_param_get("num_flows", 100)
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -2845,10 +2818,10 @@
 
         # Send flow table to switch
 
-        fq_logger.info("Sending flow adds to switch")
+        logging.info("Sending flow adds to switch")
         for fc in ft.values():          # Randomizes order of sending
-            fq_logger.info("Adding flow:")
-            fq_logger.info(str(fc));
+            logging.info("Adding flow:")
+            logging.info(str(fc));
             self.assertTrue(sw.flow_add(fc), "Failed to add flow")
 
         # Do barrier, to make sure all flows are in
@@ -2910,9 +2883,9 @@
             if n > 1:
                 break
                     
-        fq_logger.info("Deleting %d flows" % (n))
-        fq_logger.info("Sending flow del to switch:")
-        fq_logger.info(str(dfc))
+        logging.info("Deleting %d flows" % (n))
+        logging.info("Sending flow del to switch:")
+        logging.info(str(dfc))
         self.assertTrue(sw.flow_del(dfc, False), "Failed to delete flows")
 
         # Do barrier, to make sure all flows are in
@@ -2938,7 +2911,7 @@
             result = False
 
         self.assertTrue(result, "Flow_Del_2 TEST FAILED")
-        fq_logger.info("Flow_Del_2 TEST PASSED")
+        logging.info("Flow_Del_2 TEST PASSED")
 
 
 # FLOW DELETE 4
@@ -2964,7 +2937,7 @@
 #    asynch message was received; else test FAILED
 
 
-class Flow_Del_4(basic.SimpleProtocol):
+class Flow_Del_4(base_tests.SimpleProtocol):
     """
     Test FLOW_DEL_4 from draft top-half test plan
     
@@ -2973,12 +2946,12 @@
     """
 
     def runTest(self):
-        fq_logger.info("Flow_Del_4 TEST BEGIN")
+        logging.info("Flow_Del_4 TEST BEGIN")
 
         # Clear all flows from switch
 
-        fq_logger.info("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, fq_logger)
+        logging.info("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # Get switch capabilites
@@ -3008,8 +2981,8 @@
 
         # Send it to the switch. with "notify on removed"
 
-        fq_logger.info("Sending flow add to switch:")
-        fq_logger.info(str(fc))
+        logging.info("Sending flow add to switch:")
+        logging.info(str(fc))
         ft = Flow_Tbl()
         fc.send_rem = True
         self.assertTrue(sw.flow_add(fc), "Failed to add flow")
@@ -3029,8 +3002,8 @@
 
         # Delete strictly
         
-        fq_logger.info("Sending strict flow del to switch:")
-        fq_logger.info(str(fc2))
+        logging.info("Sending strict flow del to switch:")
+        logging.info(str(fc2))
         self.assertTrue(sw.flow_del(fc2, True), "Failed to delete flow")
         ft.delete(fc)
 
@@ -3057,5 +3030,5 @@
             result = False
 
         self.assertTrue(result, "Flow_Del_4 TEST FAILED")
-        fq_logger.info("Flow_Del_4 TEST PASSED")
+        logging.info("Flow_Del_4 TEST PASSED")
         
diff --git a/tests/flow_stats.py b/tests/flow_stats.py
index 8ff8b69..2144278 100644
--- a/tests/flow_stats.py
+++ b/tests/flow_stats.py
@@ -9,25 +9,18 @@
 import unittest
 import random
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 
-#@var fs_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-fs_port_map = None
-#@var fs_logger Local logger object
-fs_logger = None
-#@var fs_config Local copy of global configuration data
-fs_config = None
-
 # TODO: ovs has problems with VLAN id?
 WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
                    # (ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP),
@@ -44,33 +37,15 @@
                    ofp.OFPFW_DL_VLAN_PCP,
                    ofp.OFPFW_NW_TOS]
 
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global fs_port_map
-    global fs_logger
-    global fs_config
-
-    fs_logger = logging.getLogger("flow_stats")
-    fs_logger.info("Initializing test set")
-    fs_port_map = config["port_map"]
-    fs_config = config
-
 def sendPacket(obj, pkt, ingress_port, egress_port, test_timeout):
 
-    fs_logger.info("Sending packet to dp port " + str(ingress_port) +
+    logging.info("Sending packet to dp port " + str(ingress_port) +
                    ", expecting output on " + str(egress_port))
     obj.dataplane.send(ingress_port, str(pkt))
 
     exp_pkt_arg = None
     exp_port = None
-    if fs_config["relax"]:
+    if config["relax"]:
         exp_pkt_arg = pkt
         exp_port = egress_port
 
@@ -78,7 +53,7 @@
                                                        exp_pkt=exp_pkt_arg)
     obj.assertTrue(rcv_pkt is not None,
                    "Packet not received on port " + str(egress_port))
-    fs_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
+    logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
                     str(rcv_port))
     obj.assertEqual(rcv_port, egress_port,
                     "Packet received on port " + str(rcv_port) +
@@ -86,7 +61,7 @@
     obj.assertEqual(str(pkt), str(rcv_pkt),
                     'Response packet does not match send packet')
 
-class SingleFlowStats(basic.SimpleDataPlane):
+class SingleFlowStats(base_tests.SimpleDataPlane):
     """
     Verify flow stats are properly retrieved.
 
@@ -105,7 +80,7 @@
 
         all_packets_received = 0
         for i in range(0,test_timeout):
-            fs_logger.info("Sending stats request")
+            logging.info("Sending stats request")
             response, pkt = self.controller.transact(stat_req,
                                                      timeout=test_timeout)
             self.assertTrue(response is not None, 
@@ -119,7 +94,7 @@
                 #obj.match.pad2 = [0, 0]
                 #self.assertEqual(match, obj.match,
                 #                 "Matches do not match")
-                fs_logger.info("Received " + str(obj.packet_count) + " packets")
+                logging.info("Received " + str(obj.packet_count) + " packets")
                 if obj.packet_count == packet_count:
                     all_packets_received = 1
 
@@ -131,16 +106,14 @@
                         "Packet count does not match number sent")
 
     def runTest(self):
-        global fs_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
-        rc = delete_all_flows(self.controller, fs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # build packet
@@ -154,7 +127,7 @@
         # build flow
         ingress_port = of_ports[0];
         egress_port = of_ports[1];
-        fs_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
         match.in_port = ingress_port
         flow_mod_msg = message.flow_mod()
@@ -167,7 +140,7 @@
         self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
        
         # send flow
-        fs_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(flow_mod_msg)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
@@ -177,7 +150,7 @@
 
         # send packet N times
         num_sends = random.randint(10,20)
-        fs_logger.info("Sending " + str(num_sends) + " test packets")
+        logging.info("Sending " + str(num_sends) + " test packets")
         for i in range(0,num_sends):
             sendPacket(self, pkt, ingress_port, egress_port,
                        test_timeout)
@@ -189,7 +162,7 @@
             self.verifyStats(match, egress_port, test_timeout, num_sends)
 
 
-class TwoFlowStats(basic.SimpleDataPlane):
+class TwoFlowStats(base_tests.SimpleDataPlane):
     """
     Verify flow stats are properly retrieved.
 
@@ -219,7 +192,7 @@
         act.port = egress_port
         self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
 
-        fs_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
 
         return flow_mod_msg
@@ -233,7 +206,7 @@
             #obj.match.pad2 = [0, 0]
             #self.assertEqual(match, obj.match,
             #                 "Matches do not match")
-           fs_logger.info("Received " + str(obj.packet_count)
+           logging.info("Received " + str(obj.packet_count)
                           + " packets")
            total_packets += obj.packet_count
         return total_packets
@@ -246,7 +219,7 @@
 
         all_packets_received = 0
         for i in range(0,test_timeout):
-            fs_logger.info("Sending stats request")
+            logging.info("Sending stats request")
             # TODO: move REPLY_MORE handling to controller.transact?
             response, pkt = self.controller.transact(stat_req,
                                                      timeout=test_timeout)
@@ -270,19 +243,17 @@
                         " does not match number sent " + str(packet_count))
 
     def runTest(self):
-        global fs_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) >= 3, "Not enough ports for test")
         ingress_port = of_ports[0];
         egress_port1 = of_ports[1];
         egress_port2 = of_ports[2];
 
-        rc = delete_all_flows(self.controller, fs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         pkt1 = simple_tcp_packet()
@@ -291,37 +262,37 @@
         pkt2 = simple_tcp_packet(dl_src='0:7:7:7:7:7')
         flow_mod_msg2 = self.buildFlowModMsg(pkt2, ingress_port, egress_port2)
        
-        fs_logger.info("Inserting flow1")
+        logging.info("Inserting flow1")
         rv = self.controller.message_send(flow_mod_msg1)
         self.assertTrue(rv != -1, "Error installing flow mod")
-        fs_logger.info("Inserting flow2")
+        logging.info("Inserting flow2")
         rv = self.controller.message_send(flow_mod_msg2)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         num_pkt1s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt1s) + " pkt1s")
+        logging.info("Sending " + str(num_pkt1s) + " pkt1s")
         num_pkt2s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt2s) + " pkt2s")
+        logging.info("Sending " + str(num_pkt2s) + " pkt2s")
         for i in range(0,num_pkt1s):
             sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
         for i in range(0,num_pkt2s):
             sendPacket(self, pkt2, ingress_port, egress_port2, test_timeout)
             
         match1 = packet_to_flow_match(self, pkt1)
-        fs_logger.info("Verifying flow1's " + str(num_pkt1s) + " packets")
+        logging.info("Verifying flow1's " + str(num_pkt1s) + " packets")
         self.verifyStats(match1, ofp.OFPP_NONE, test_timeout, num_pkt1s)
         match2 = packet_to_flow_match(self, pkt2)
-        fs_logger.info("Verifying flow2's " + str(num_pkt2s) + " packets")
+        logging.info("Verifying flow2's " + str(num_pkt2s) + " packets")
         self.verifyStats(match2, ofp.OFPP_NONE, test_timeout, num_pkt2s)
         match1.wildcards |= ofp.OFPFW_DL_SRC
-        fs_logger.info("Verifying combined " + str(num_pkt1s+num_pkt2s) + " packets")
+        logging.info("Verifying combined " + str(num_pkt1s+num_pkt2s) + " packets")
         self.verifyStats(match1, ofp.OFPP_NONE, test_timeout, 
                          num_pkt1s+num_pkt2s)
         # TODO: sweep through the wildcards to verify matching?
 
 
-class AggregateStats(basic.SimpleDataPlane):
+class AggregateStats(base_tests.SimpleDataPlane):
     """
     Verify aggregate flow stats are properly retrieved.
 
@@ -349,7 +320,7 @@
         act.port = egress_port
         self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
 
-        fs_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
 
         return flow_mod_msg
@@ -363,7 +334,7 @@
 
         all_packets_received = 0
         for i in range(0,test_timeout):
-            fs_logger.info("Sending stats request")
+            logging.info("Sending stats request")
             response, pkt = self.controller.transact(stat_req,
                                                      timeout=test_timeout)
             self.assertTrue(response is not None, 
@@ -374,7 +345,7 @@
                 self.assertTrue(obj.flow_count == flow_count,
                                 "Flow count " + str(obj.flow_count) +
                                 " does not match expected " + str(flow_count))
-                fs_logger.info("Received " + str(obj.packet_count) + " packets")
+                logging.info("Received " + str(obj.packet_count) + " packets")
                 if obj.packet_count == packet_count:
                     all_packets_received = 1
 
@@ -386,19 +357,17 @@
                         "Packet count does not match number sent")
 
     def runTest(self):
-        global fs_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) >= 3, "Not enough ports for test")
         ingress_port = of_ports[0];
         egress_port1 = of_ports[1];
         egress_port2 = of_ports[2];
 
-        rc = delete_all_flows(self.controller, fs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         pkt1 = simple_tcp_packet()
@@ -407,18 +376,18 @@
         pkt2 = simple_tcp_packet(dl_src='0:7:7:7:7:7')
         flow_mod_msg2 = self.buildFlowModMsg(pkt2, ingress_port, egress_port2)
        
-        fs_logger.info("Inserting flow1")
+        logging.info("Inserting flow1")
         rv = self.controller.message_send(flow_mod_msg1)
         self.assertTrue(rv != -1, "Error installing flow mod")
-        fs_logger.info("Inserting flow2")
+        logging.info("Inserting flow2")
         rv = self.controller.message_send(flow_mod_msg2)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
         num_pkt1s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt1s) + " pkt1s")
+        logging.info("Sending " + str(num_pkt1s) + " pkt1s")
         num_pkt2s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt2s) + " pkt2s")
+        logging.info("Sending " + str(num_pkt2s) + " pkt2s")
         for i in range(0,num_pkt1s):
             sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
         for i in range(0,num_pkt2s):
diff --git a/tests/load.py b/tests/load.py
index d09608e..e913445 100644
--- a/tests/load.py
+++ b/tests/load.py
@@ -5,11 +5,8 @@
 namespace as different groups of tests will likely define 
 similar identifiers.
 
-  The function test_set_init is called with a complete configuration
-dictionary prior to the invocation of any tests from this file.
-
-  The switch is actively attempting to contact the controller at the address
-indicated in oft_config
+The switch is actively attempting to contact the controller at the address
+indicated in config.
 
 In general these test cases make some assumption about the external
 configuration of the switch under test.  For now, the assumption is
@@ -22,47 +19,19 @@
 
 import unittest
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 import time
 
 from oftest.testutils import *
 
-#@var load_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-load_port_map = None
-#@var load_logger Local logger object
-load_logger = None
-#@var load_config Local copy of global configuration data
-load_config = None
-
-# For test priority
-#@var test_prio Set test priority for local tests
-test_prio = {}
-
-
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    global load_port_map
-    global load_logger
-    global load_config
-
-    load_logger = logging.getLogger("load")
-    load_logger.info("Initializing test set")
-    load_port_map = config["port_map"]
-    load_config = config
-
-class LoadBarrier(basic.SimpleProtocol):
+class LoadBarrier(base_tests.SimpleProtocol):
     """
     Test barrier under load with loopback
 
@@ -75,11 +44,14 @@
     The test succeeds if the barrier response is received.  Otherwise
     the test fails.
     """
+
+    priority = -1
+
     def runTest(self):
         # Set up flow to send from port 1 to port 2 and copy to CPU
         # Test parameter gives LB port base (assumes consecutive)
-        lb_port = test_param_get(self.config, 'lb_port', default=1)
-        barrier_count = test_param_get(self.config, 'barrier_count', 
+        lb_port = test_param_get('lb_port', default=1)
+        barrier_count = test_param_get('barrier_count', 
                                        default=10)
 
         # Set controller to filter packet ins
@@ -114,21 +86,18 @@
         act = action.action_output()
         act.port = lb_port + 1
         self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
-        load_logger.info("Sleeping before starting storm")
+        logging.info("Sleeping before starting storm")
         time.sleep(1) # Root causing issue with fast disconnects
-        load_logger.info("Sending packet out to %d" % (lb_port + 1))
+        logging.info("Sending packet out to %d" % (lb_port + 1))
         rv = self.controller.message_send(msg)
         self.assertTrue(rv == 0, "Error sending out message")
 
         for idx in range(0, barrier_count):
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
             # To do:  Add some interesting functionality here
-            load_logger.info("Barrier %d completed" % idx)
+            logging.info("Barrier %d completed" % idx)
 
         # Clear the flow table when done
-        load_logger.debug("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, load_logger)
+        logging.debug("Deleting all flows from switch")
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
-
-# Do not run by default; still mysterious disconnects often
-test_prio["LoadBarrier"] = -1
diff --git a/tests/openflow_protocol_messages.py b/tests/openflow_protocol_messages.py
index c8ad1b8..43ce062 100644
--- a/tests/openflow_protocol_messages.py
+++ b/tests/openflow_protocol_messages.py
@@ -10,56 +10,37 @@
 import unittest
 import random
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 from FuncUtils import *
 
-
-of_port_map = None
-of_logger = None
-of_config = None
-
-def test_set_init(config):
-   
-
-    basic.test_set_init(config)
-
-    global of_port_map
-    global of_logger
-    global of_config
-
-    of_logger = logging.getLogger("Start Openflow_Protocol_Messages Conformance Test-suite")
-    of_logger.info("Initializing test set")
-    of_port_map = config["port_map"]
-    of_config = config
-
-
-class FeaturesRequest(basic.SimpleProtocol): 
+class FeaturesRequest(base_tests.SimpleProtocol): 
 
     """Verify Features_Request-Reply is implemented 
     a) Send OFPT_FEATURES_REQUEST
 	b) Verify OFPT_FEATURES_REPLY is received without errors"""
 
     def runTest(self):
-        of_logger.info("Running Features_Request test")
+        logging.info("Running Features_Request test")
         
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         
         #Clear switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         
-        of_logger.info("Sending Features_Request")
-        of_logger.info("Expecting Features_Reply")
+        logging.info("Sending Features_Request")
+        logging.info("Expecting Features_Reply")
 
         request = message.features_request()
         rv = self.controller.message_send(request)
@@ -71,7 +52,7 @@
                         'Did not receive Features Reply')
 
 
-class ConfigurationRequest(basic.SimpleProtocol):
+class ConfigurationRequest(base_tests.SimpleProtocol):
     
     """Check basic Get Config request is implemented
     a) Send OFPT_GET_CONFIG_REQUEST
@@ -79,17 +60,17 @@
 
     def runTest(self):
 
-        of_logger.info("Running Configuration_Request test ")
+        logging.info("Running Configuration_Request test ")
         
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Sending OFPT_GET_CONFIG_REQUEST ")
-        of_logger.info("Expecting OFPT_GET_CONFIG_REPLY ")
+        logging.info("Sending OFPT_GET_CONFIG_REQUEST ")
+        logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
 
         request = message.get_config_request()
         rv = self.controller.message_send(request)
@@ -100,7 +81,7 @@
         self.assertTrue(response is not None, 
                         'Did not receive OFPT_GET_CONFIG_REPLY')
 
-class ModifyStateAdd(basic.SimpleProtocol):
+class ModifyStateAdd(base_tests.SimpleProtocol):
     
     """Check basic Flow Add request is implemented
     a) Send  OFPT_FLOW_MOD , command = OFPFC_ADD 
@@ -108,17 +89,17 @@
 
     def runTest(self):
 
-        of_logger.info("Running Modify_State_Add test")
+        logging.info("Running Modify_State_Add test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         
         #Clear switch state
-        rc = delete_all_flows(self.controller,of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Inserting a flow entry")
-        of_logger.info("Expecting active_count=1 in table_stats_reply")
+        logging.info("Inserting a flow entry")
+        logging.info("Expecting active_count=1 in table_stats_reply")
 
         #Insert a flow entry matching on ingress_port
         (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -127,7 +108,7 @@
         Verify_TableStats(self,active_entries=1)
 
 
-class ModifyStateDelete(basic.SimpleProtocol):
+class ModifyStateDelete(base_tests.SimpleProtocol):
     
     """Check Basic Flow Delete request is implemented
     a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
@@ -137,17 +118,17 @@
 
     def runTest(self):
 
-        of_logger.info("Running Modify_State_Delete test")
+        logging.info("Running Modify_State_Delete test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         #Clear switch state
-        rc = delete_all_flows(self.controller,of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Inserting a flow entry and then deleting it")
-        of_logger.info("Expecting the active_count=0 in table_stats_reply")
+        logging.info("Inserting a flow entry and then deleting it")
+        logging.info("Expecting the active_count=0 in table_stats_reply")
 
         #Insert a flow matching on ingress_port 
         (Pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -163,7 +144,7 @@
 
       
 
-class ModifyStateModify(basic.SimpleDataPlane):
+class ModifyStateModify(base_tests.SimpleDataPlane):
     
     """Verify basic Flow Modify request is implemented
     a) Send OFPT_FLOW_MOD, command = OFPFC_ADD, Action A 
@@ -172,17 +153,17 @@
 
     def runTest(self):
 
-        of_logger.info("Running Modify_State_Modify test")
+        logging.info("Running Modify_State_Modify test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Inserting a flow entry and then modifying it")
-        of_logger.info("Expecting the Test Packet to implement the modified action")
+        logging.info("Inserting a flow entry and then modifying it")
+        logging.info("Expecting the Test Packet to implement the modified action")
 
         # Insert a flow matching on ingress_port with action A (output to of_port[1])    
         (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -194,7 +175,7 @@
         SendPacket(self,pkt,of_ports[0],of_ports[2])
                        
 
-class ReadState(basic.SimpleProtocol):
+class ReadState(base_tests.SimpleProtocol):
     
     """Test that a basic Read state request (like flow_stats_get request) does not generate an error
     a) Send OFPT_FLOW_MOD, command = OFPFC_ADD
@@ -203,17 +184,17 @@
 
     def runTest(self):
 
-        of_logger.info("Running Read_State test")
+        logging.info("Running Read_State test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         #Clear switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Inserting a flow entry and then sending flow_stats request")
-        of_logger.info("Expecting the a flow_stats_reply without errors")
+        logging.info("Inserting a flow entry and then sending flow_stats request")
+        logging.info("Expecting the a flow_stats_reply without errors")
 
         # Insert a flow with match on ingress_port
         (pkt,match ) = Wildcard_All_Except_Ingress(self,of_ports)
@@ -221,7 +202,7 @@
         #Verify Flow_Stats request does not generate errors
         Verify_FlowStats(self,match)
         
-class PacketOut(basic.SimpleDataPlane):
+class PacketOut(base_tests.SimpleDataPlane):
     
     """Test packet out function
     a) Send packet out message for each dataplane port.
@@ -229,17 +210,17 @@
     
     def runTest(self):
 
-        of_logger.info("Running Packet_Out test")
+        logging.info("Running Packet_Out test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
        
         #Clear Switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
-        of_logger.info("Sending a packet-out for each dataplane port")
-        of_logger.info("Expecting the packet on appropriate dataplane port")
+        logging.info("Sending a packet-out for each dataplane port")
+        logging.info("Expecting the packet on appropriate dataplane port")
 
         for dp_port in of_ports:
             for outpkt, opt in [
@@ -253,13 +234,13 @@
                 act.port = dp_port
                 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
 
-                of_logger.info("PacketOut to: " + str(dp_port))
+                logging.info("PacketOut to: " + str(dp_port))
                 rv = self.controller.message_send(msg)
                 self.assertTrue(rv == 0, "Error sending out message")
 
                 exp_pkt_arg = None
                 exp_port = None
-                if of_config["relax"]:
+                if config["relax"]:
                     exp_pkt_arg = outpkt
                     exp_port = dp_port
                 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=2, 
@@ -267,18 +248,18 @@
                                                                 exp_pkt=exp_pkt_arg)
                 
                 self.assertTrue(pkt is not None, 'Packet not received')
-                of_logger.info("PacketOut: got pkt from " + str(of_port))
+                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):
-                    of_logger.debug("Sent %s" % format_packet(outpkt))
-                    of_logger.debug("Resp %s" % format_packet(
+                    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')
 
         
-class PacketIn(basic.SimpleDataPlane):
+class PacketIn(base_tests.SimpleDataPlane):
     
     """Test basic packet_in function
     a) Send a simple tcp packet to a dataplane port, without any flow-entry 
@@ -286,24 +267,24 @@
     
     def runTest(self):
         
-        of_logger.info("Running Packet_In test")
+        logging.info("Running Packet_In test")
 
-        of_ports = of_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         ingress_port = of_ports[0]
 
         #Clear Switch state
-        rc = delete_all_flows(self.controller, of_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-        of_logger.info("Sending a Simple tcp packet a dataplane port")
-        of_logger.info("Expecting a packet_in event on the control plane")
+        logging.info("Sending a Simple tcp packet a dataplane port")
+        logging.info("Expecting a packet_in event on the control plane")
 
         # Send  packet on dataplane port and verify packet_in event gets generated.
         pkt = simple_tcp_packet()
         self.dataplane.send(ingress_port, str(pkt))
-        of_logger.info("Sending packet to dp port " + str(ingress_port) +
+        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,
@@ -312,7 +293,7 @@
                                'Packet in event is not sent to the controller') 
 
 
-class Hello(basic.SimpleDataPlane):
+class Hello(base_tests.SimpleDataPlane):
     
     """Test Hello messages are implemented
     a) Create Hello messages from controller
@@ -321,10 +302,10 @@
 
     def runTest(self):
         
-        of_logger.info("Running Hello test")
+        logging.info("Running Hello test")
 
-        of_logger.info("Sending Hello")
-        of_logger.info("Expecting a Hello on the control plane with version--1.0.0")
+        logging.info("Sending Hello")
+        logging.info("Expecting a Hello on the control plane with version--1.0.0")
         
         #Send Hello message
         request = message.hello()
@@ -336,7 +317,7 @@
 
 
 
-class EchoWithoutBody(basic.SimpleProtocol):
+class EchoWithoutBody(base_tests.SimpleProtocol):
     
     """Test basic echo-reply is implemented
     a)  Send echo-request from the controller side, note echo body is empty here.
@@ -344,10 +325,10 @@
     
     def runTest(self):
 
-        of_logger.info("Running Echo_Without_Body test")
+        logging.info("Running Echo_Without_Body test")
 
-        of_logger.info("Sending Echo Request")
-        of_logger.info("Expecting a Echo Reply with version--1.0.0 and same xid")
+        logging.info("Sending Echo Request")
+        logging.info("Expecting a Echo Reply with version--1.0.0 and same xid")
 
         # Send echo_request
         request = message.echo_request()
@@ -359,7 +340,7 @@
         self.assertEqual(len(response.data), 0, 'response data non-empty')
 
 
-class BarrierRequestReply(basic.SimpleProtocol):
+class BarrierRequestReply(base_tests.SimpleProtocol):
 
     """ Check basic Barrier request is implemented
     a) Send OFPT_BARRIER_REQUEST
@@ -367,10 +348,10 @@
     
     def runTest(self):
 
-        of_logger.info("Running Barrier_Request_Reply test")
+        logging.info("Running Barrier_Request_Reply test")
 
-        of_logger.info("Sending Barrier Request")
-        of_logger.info("Expecting a Barrier Reply with same xid")
+        logging.info("Sending Barrier Request")
+        logging.info("Expecting a Barrier Reply with same xid")
 
         #Send Barrier Request
         request = message.barrier_request()
diff --git a/tests/pktact.py b/tests/pktact.py
index fd1b014..10dbdb3 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -7,43 +7,28 @@
 namespace as different groups of tests will likely define 
 similar identifiers.
 
-  The function test_set_init is called with a complete configuration
-dictionary prior to the invocation of any tests from this file.
-
-  The switch is actively attempting to contact the controller at the address
-indicated oin oft_config
+The switch is actively attempting to contact the controller at the address
+indicated in config.
 
 """
 
 import copy
-
 import logging
-
+import time
 import unittest
 
+from oftest import config
 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 basic
-import time
+import oftest.base_tests as base_tests
+import basic # for IterCases
 
 from oftest.testutils import *
 
-#@var port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-pa_port_map = None
-#@var pa_logger Local logger object
-pa_logger = None
-#@var pa_config Local copy of global configuration data
-pa_config = None
-
-# For test priority
-#@var test_prio Set test priority for local tests
-test_prio = {}
-
 WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
                    ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
                    ofp.OFPFW_DL_SRC,
@@ -90,25 +75,7 @@
 
 TEST_VID_DEFAULT = 2
 
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global pa_port_map
-    global pa_logger
-    global pa_config
-
-    pa_logger = logging.getLogger("pkt_act")
-    pa_logger.info("Initializing test set")
-    pa_port_map = config["port_map"]
-    pa_config = config
-
-class DirectPacket(basic.SimpleDataPlane):
+class DirectPacket(base_tests.SimpleDataPlane):
     """
     Send packet to single egress port
 
@@ -122,7 +89,7 @@
         self.handleFlow()
 
     def handleFlow(self, pkttype='TCP'):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -137,12 +104,12 @@
         act = action.action_output()
 
         for idx in range(len(of_ports)):
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
             ingress_port = of_ports[idx]
             egress_port = of_ports[(idx + 1) % len(of_ports)]
-            pa_logger.info("Ingress " + str(ingress_port) + 
+            logging.info("Ingress " + str(ingress_port) + 
                              " to egress " + str(egress_port))
 
             match.in_port = ingress_port
@@ -154,31 +121,31 @@
             act.port = egress_port
             self.assertTrue(request.actions.add(act), "Could not add action")
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + 
+            logging.info("Sending packet to dp port " + 
                            str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
 
             exp_pkt_arg = None
             exp_port = None
-            if pa_config["relax"]:
+            if config["relax"]:
                 exp_pkt_arg = pkt
                 exp_port = egress_port
 
             (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
                                                                 exp_pkt=exp_pkt_arg)
             self.assertTrue(rcv_pkt is not None, "Did not receive packet")
-            pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
+            logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
                          str(rcv_port))
             self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
             self.assertEqual(str(pkt), str(rcv_pkt),
                              'Response packet does not match send packet')
 
-class DirectPacketController(basic.SimpleDataPlane):
+class DirectPacketController(base_tests.SimpleDataPlane):
     """
     Send packet to the controller port
 
@@ -192,7 +159,7 @@
         self.handleFlow()
 
     def handleFlow(self, pkttype='TCP'):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
 
@@ -206,7 +173,7 @@
                         "Could not generate flow match from pkt")
         act = action.action_output()
 
-        rv = delete_all_flows(self.controller, pa_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
         ingress_port = of_ports[0]
@@ -220,12 +187,12 @@
         act.max_len = 65535
         self.assertTrue(request.actions.add(act), "Could not add action")
 
-        pa_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(request)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-        pa_logger.info("Sending packet to dp port " +
+        logging.info("Sending packet to dp port " +
                         str(ingress_port))
         self.dataplane.send(ingress_port, str(pkt))
 
@@ -234,14 +201,14 @@
         self.assertTrue(response is not None,
                         'Packet in message not received by controller')
         if not dataplane.match_exp_pkt(pkt, response.data):
-            pa_logger.debug("Sent %s" % format_packet(pkt))
-            pa_logger.debug("Resp %s" % format_packet(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')
 
 
-class DirectPacketQueue(basic.SimpleDataPlane):
+class DirectPacketQueue(base_tests.SimpleDataPlane):
     """
     Send packet to single queue on single egress port
 
@@ -263,7 +230,7 @@
         return result
 
     def handleFlow(self, pkttype='TCP'):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -291,12 +258,12 @@
             egress_port = of_ports[(idx + 1) % len(of_ports)]
 
             for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
-                pa_logger.info("Ingress " + str(ingress_port)
+                logging.info("Ingress " + str(ingress_port)
                                + " to egress " + str(egress_port)
                                + " queue " + str(egress_queue_id)
                                )
 
-                rv = delete_all_flows(self.controller, pa_logger)
+                rv = delete_all_flows(self.controller)
                 self.assertEqual(rv, 0, "Failed to delete all flows")
 
                 match.in_port = ingress_port
@@ -309,7 +276,7 @@
                 act.queue_id = egress_queue_id
                 self.assertTrue(request.actions.add(act), "Could not add action")
 
-                pa_logger.info("Inserting flow")
+                logging.info("Inserting flow")
                 rv = self.controller.message_send(request)
                 self.assertTrue(rv != -1, "Error installing flow mod")
                 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
@@ -322,20 +289,20 @@
                 (qs_before, p) = self.controller.transact(request)
                 self.assertNotEqual(qs_before, None, "Queue stats request failed")
 
-                pa_logger.info("Sending packet to dp port " + 
+                logging.info("Sending packet to dp port " + 
                                str(ingress_port))
                 self.dataplane.send(ingress_port, str(pkt))
                 
                 exp_pkt_arg = None
                 exp_port = None
-                if pa_config["relax"]:
+                if config["relax"]:
                     exp_pkt_arg = pkt
                     exp_port = egress_port
                     
                     (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
                                                                         exp_pkt=exp_pkt_arg)
                     self.assertTrue(rcv_pkt is not None, "Did not receive packet")
-                    pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
+                    logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
                                     str(rcv_port))
                     self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
                     self.assertEqual(str(pkt), str(rcv_pkt),
@@ -363,7 +330,7 @@
                                  )
                     
 
-class DirectPacketControllerQueue(basic.SimpleDataPlane):
+class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
     """
     Send a packet from each of the openflow ports
     to each of the queues configured on the controller port.
@@ -387,7 +354,7 @@
         return result
 
     def handleFlow(self, pkttype='TCP'):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -414,17 +381,17 @@
             ingress_port = of_ports[idx]
             egress_port = ofp.OFPP_CONTROLLER
 
-            pa_logger.info("Ingress port " + str(ingress_port)
+            logging.info("Ingress port " + str(ingress_port)
                            + ", controller port queues " 
                            + str(self.portQueuesGet(queue_stats, egress_port)))
 
             for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
-                pa_logger.info("Ingress " + str(ingress_port)
+                logging.info("Ingress " + str(ingress_port)
                                + " to egress " + str(egress_port)
                                + " queue " + str(egress_queue_id)
                                )
 
-                rv = delete_all_flows(self.controller, pa_logger)
+                rv = delete_all_flows(self.controller)
                 self.assertEqual(rv, 0, "Failed to delete all flows")
 
                 match.in_port = ingress_port
@@ -437,7 +404,7 @@
                 act.queue_id = egress_queue_id
                 self.assertTrue(request.actions.add(act), "Could not add action")
 
-                pa_logger.info("Inserting flow")
+                logging.info("Inserting flow")
                 rv = self.controller.message_send(request)
                 self.assertTrue(rv != -1, "Error installing flow mod")
                 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
@@ -450,20 +417,21 @@
                 (qs_before, p) = self.controller.transact(request)
                 self.assertNotEqual(qs_before, None, "Queue stats request failed")
 
-                pa_logger.info("Sending packet to dp port " + 
+                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 basic_config["relax"]:  # Only one attempt to match
+                    if not config["relax"]:  # Only one attempt to match
                         break
                     count += 1
                     if count > 10:   # Too many tries
@@ -472,8 +440,8 @@
                 self.assertTrue(response is not None, 
                                'Packet in message not received by controller')
                 if not dataplane.match_exp_pkt(pkt, response.data):
-                    basic_logger.debug("Sent %s" % format_packet(pkt))
-                    basic_logger.debug("Resp %s" % format_packet(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')
@@ -514,7 +482,7 @@
     def runTest(self):
         self.handleFlow(pkttype='ICMP')
 
-class DirectTwoPorts(basic.SimpleDataPlane):
+class DirectTwoPorts(base_tests.SimpleDataPlane):
     """
     Send packet to two egress ports
 
@@ -525,7 +493,7 @@
     Verify the packet is received at the two egress ports
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
 
@@ -537,13 +505,13 @@
         act = action.action_output()
 
         for idx in range(len(of_ports)):
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
             ingress_port = of_ports[idx]
             egress_port1 = of_ports[(idx + 1) % len(of_ports)]
             egress_port2 = of_ports[(idx + 2) % len(of_ports)]
-            pa_logger.info("Ingress " + str(ingress_port) + 
+            logging.info("Ingress " + str(ingress_port) + 
                            " to egress " + str(egress_port1) + " and " +
                            str(egress_port2))
 
@@ -556,23 +524,23 @@
             self.assertTrue(request.actions.add(act), "Could not add action1")
             act.port = egress_port2
             self.assertTrue(request.actions.add(act), "Could not add action2")
-            # pa_logger.info(request.show())
+            # logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + 
+            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, pa_logger, pa_config)
+                              self)
 
-class DirectMCNonIngress(basic.SimpleDataPlane):
+class DirectMCNonIngress(base_tests.SimpleDataPlane):
     """
     Multicast to all non-ingress ports
 
@@ -585,7 +553,7 @@
     Does not use the flood action
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
 
@@ -597,10 +565,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + 
+            logging.info("Ingress " + str(ingress_port) + 
                            " all non-ingress ports")
             match.in_port = ingress_port
 
@@ -613,21 +581,21 @@
                 act.port = egress_port
                 self.assertTrue(request.actions.add(act), 
                                 "Could not add output to " + str(egress_port))
-            pa_logger.debug(request.show())
+            logging.debug(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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, pa_logger, pa_config)
+                              self)
 
 
-class DirectMC(basic.SimpleDataPlane):
+class DirectMC(base_tests.SimpleDataPlane):
     """
     Multicast to all ports including ingress
 
@@ -640,7 +608,7 @@
     Does not use the flood action
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
 
@@ -652,10 +620,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
+            logging.info("Ingress " + str(ingress_port) + " to all ports")
             match.in_port = ingress_port
 
             request = message.flow_mod()
@@ -668,19 +636,18 @@
                     act.port = egress_port
                 self.assertTrue(request.actions.add(act), 
                                 "Could not add output to " + str(egress_port))
-            # pa_logger.info(request.show())
+            # logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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,
-                              pa_logger, pa_config)
+            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
 
-class Flood(basic.SimpleDataPlane):
+class Flood(base_tests.SimpleDataPlane):
     """
     Flood to all ports except ingress
 
@@ -691,7 +658,7 @@
     Verify the packet is received at all other ports
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -703,10 +670,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
+            logging.info("Ingress " + str(ingress_port) + " to all ports")
             match.in_port = ingress_port
 
             request = message.flow_mod()
@@ -715,20 +682,20 @@
             act.port = ofp.OFPP_FLOOD
             self.assertTrue(request.actions.add(act), 
                             "Could not add flood port action")
-            pa_logger.info(request.show())
+            logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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, pa_logger, pa_config)
+                              self)
 
-class FloodPlusIngress(basic.SimpleDataPlane):
+class FloodPlusIngress(base_tests.SimpleDataPlane):
     """
     Flood to all ports plus send to ingress port
 
@@ -740,7 +707,7 @@
     Verify the packet is received at all other ports
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -752,10 +719,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
+            logging.info("Ingress " + str(ingress_port) + " to all ports")
             match.in_port = ingress_port
 
             request = message.flow_mod()
@@ -767,19 +734,18 @@
             act.port = ofp.OFPP_IN_PORT
             self.assertTrue(request.actions.add(act), 
                             "Could not add ingress port for output")
-            pa_logger.info(request.show())
+            logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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,
-                              pa_logger, pa_config)
+            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
 
-class All(basic.SimpleDataPlane):
+class All(base_tests.SimpleDataPlane):
     """
     Send to OFPP_ALL port
 
@@ -790,7 +756,7 @@
     Verify the packet is received at all other ports
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -802,10 +768,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
+            logging.info("Ingress " + str(ingress_port) + " to all ports")
             match.in_port = ingress_port
 
             request = message.flow_mod()
@@ -814,20 +780,20 @@
             act.port = ofp.OFPP_ALL
             self.assertTrue(request.actions.add(act), 
                             "Could not add ALL port action")
-            pa_logger.info(request.show())
+            logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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, pa_logger, pa_config)
+                              self)
 
-class AllPlusIngress(basic.SimpleDataPlane):
+class AllPlusIngress(base_tests.SimpleDataPlane):
     """
     Send to OFPP_ALL port and ingress port
 
@@ -839,7 +805,7 @@
     Verify the packet is received at all other ports
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
@@ -851,10 +817,10 @@
         act = action.action_output()
 
         for ingress_port in of_ports:
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
-            pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
+            logging.info("Ingress " + str(ingress_port) + " to all ports")
             match.in_port = ingress_port
 
             request = message.flow_mod()
@@ -866,19 +832,18 @@
             act.port = ofp.OFPP_IN_PORT
             self.assertTrue(request.actions.add(act), 
                             "Could not add ingress port for output")
-            pa_logger.info(request.show())
+            logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            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,
-                              pa_logger, pa_config)
+            receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
             
-class FloodMinusPort(basic.SimpleDataPlane):
+class FloodMinusPort(base_tests.SimpleDataPlane):
     """
     Config port with No_Flood and test Flood action
 
@@ -891,7 +856,7 @@
     the ingress port and the no_flood port
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
 
@@ -903,15 +868,14 @@
         act = action.action_output()
 
         for idx in range(len(of_ports)):
-            rv = delete_all_flows(self.controller, pa_logger)
+            rv = delete_all_flows(self.controller)
             self.assertEqual(rv, 0, "Failed to delete all flows")
 
             ingress_port = of_ports[idx]
             no_flood_idx = (idx + 1) % len(of_ports)
             no_flood_port = of_ports[no_flood_idx]
             rv = port_config_set(self.controller, no_flood_port,
-                                 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
-                                 pa_logger)
+                                 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
             self.assertEqual(rv, 0, "Failed to set port config")
 
             match.in_port = ingress_port
@@ -922,24 +886,23 @@
             act.port = ofp.OFPP_FLOOD
             self.assertTrue(request.actions.add(act), 
                             "Could not add flood port action")
-            pa_logger.info(request.show())
+            logging.info(request.show())
 
-            pa_logger.info("Inserting flow")
+            logging.info("Inserting flow")
             rv = self.controller.message_send(request)
             self.assertTrue(rv != -1, "Error installing flow mod")
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
-            pa_logger.info("No flood port is " + str(no_flood_port))
+            logging.info("Sending packet to dp port " + str(ingress_port))
+            logging.info("No flood port is " + str(no_flood_port))
             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,
-                              pa_logger, pa_config)
+            receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
 
             # Turn no flood off again
             rv = port_config_set(self.controller, no_flood_port,
-                                 0, ofp.OFPPC_NO_FLOOD, pa_logger)
+                                 0, ofp.OFPPC_NO_FLOOD)
             self.assertEqual(rv, 0, "Failed to reset port config")
 
             #@todo Should check no other packets received
@@ -948,12 +911,11 @@
 
 ################################################################
 
-class BaseMatchCase(basic.SimpleDataPlane):
+class BaseMatchCase(base_tests.SimpleDataPlane):
     def setUp(self):
-        basic.SimpleDataPlane.setUp(self)
-        self.logger = pa_logger
+        base_tests.SimpleDataPlane.setUp(self)
     def runTest(self):
-        self.logger.info("BaseMatchCase")
+        logging.info("BaseMatchCase")
 
 class ExactMatch(BaseMatchCase):
     """
@@ -967,7 +929,7 @@
     """
 
     def runTest(self):
-        flow_match_test(self, pa_port_map)
+        flow_match_test(self, config["port_map"])
 
 class ExactMatchTagged(BaseMatchCase):
     """
@@ -975,24 +937,22 @@
     """
 
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
-        flow_match_test(self, pa_port_map, dl_vlan=vid)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
+        flow_match_test(self, config["port_map"], dl_vlan=vid)
 
 class ExactMatchTaggedMany(BaseMatchCase):
     """
     ExactMatchTagged with many VLANS
     """
 
+    priority = -1
+
     def runTest(self):
         for vid in range(2,100,10):
-            flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
+            flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
         for vid in range(100,4000,389):
-            flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
-        flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
-
-# Don't run by default
-test_prio["ExactMatchTaggedMany"] = -1
-
+            flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
+        flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
 
 class SingleWildcardMatchPriority(BaseMatchCase):
     """
@@ -1004,14 +964,14 @@
         self.flowMsgs = {}
 
     def _ClearTable(self):
-        rc = delete_all_flows(self.controller, self.logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
     def runTest(self):
         
         self._Init()
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         # Delete the initial flow table
@@ -1039,7 +999,7 @@
             self._ClearTable()
 
         # Sanity check flow at lower priority from pA to pB
-        self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
+        logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
                          % (portA, portB, portC, prioHigher, prioLower))
 
         # Sanity check flow at lower priority from pA to pC
@@ -1072,7 +1032,7 @@
                                   wildcards=wildcards,
                                   egr_ports=egp)
         request.priority = prio
-        self.logger.debug("Install flow with priority " + str(prio))
+        logging.debug("Install flow with priority " + str(prio))
         flow_msg_install(self, request, clear_table_override=False)
         self.flowMsgs[prio] = request
         
@@ -1082,7 +1042,7 @@
             msg.command = ofp.OFPFC_DELETE_STRICT
             # This *must* be set for DELETE
             msg.out_port = ofp.OFPP_NONE
-            self.logger.debug("Remove flow with priority " + str(prio))
+            logging.debug("Remove flow with priority " + str(prio))
             self.controller.message_send(msg)
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
         else:
@@ -1093,10 +1053,8 @@
         if pkt == None:
             pkt = self.pkt
 
-        self.logger.info("Pkt match test: " + str(inp) + 
-                         " to " + str(egp))
-        self.logger.debug("Send packet: " + str(inp) + " to " 
-                            + str(egp))
+        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)
 
@@ -1108,7 +1066,7 @@
 
         self._Init()
 
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         # Install an entry from 0 -> 1 @ prio 1000
@@ -1140,7 +1098,7 @@
         
         self._Init()
 
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         self._ClearTable()
@@ -1175,7 +1133,7 @@
         
         self._Init()
 
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
 
         self._ClearTable()
@@ -1210,7 +1168,7 @@
     Verify flow_expiration message is correct when command option is set
     """
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
         for wc in WILDCARD_VALUES:
             wc |= required_wildcards(self)
             if wc & ofp.OFPFW_DL_VLAN:
@@ -1218,7 +1176,7 @@
                 dl_vlan = vid
             else:
                 dl_vlan = -1
-            flow_match_test(self, pa_port_map, wildcards=wc, 
+            flow_match_test(self, config["port_map"], wildcards=wc, 
                             dl_vlan=dl_vlan, max_test=10)
 
 class SingleWildcardMatchTagged(BaseMatchCase):
@@ -1226,10 +1184,10 @@
     SingleWildcardMatch with tagged packets
     """
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
         for wc in WILDCARD_VALUES:
             wc |= required_wildcards(self)
-            flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
+            flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
                             max_test=10)
 
 class AllExceptOneWildcardMatch(BaseMatchCase):
@@ -1244,7 +1202,7 @@
     Verify flow_expiration message is correct when command option is set
     """
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
         for all_exp_one_wildcard in NO_WILDCARD_VALUES:
             all_exp_one_wildcard |= required_wildcards(self)
             if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
@@ -1252,7 +1210,7 @@
                 dl_vlan = vid
             else:
                 dl_vlan = -1
-            flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
+            flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
                             dl_vlan=dl_vlan)
 
 class AllExceptOneWildcardMatchTagged(BaseMatchCase):
@@ -1260,10 +1218,10 @@
     Match one field with tagged packets
     """
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
         for all_exp_one_wildcard in NO_WILDCARD_VALUES:
             all_exp_one_wildcard |= required_wildcards(self)
-            flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
+            flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
                             dl_vlan=vid)
 
 class AllWildcardMatch(BaseMatchCase):
@@ -1278,15 +1236,15 @@
     Verify flow_expiration message is correct when command option is set
     """
     def runTest(self):
-        flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
+        flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
 
 class AllWildcardMatchTagged(BaseMatchCase):
     """
     AllWildcardMatch with tagged packets
     """
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
-        flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL, 
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
+        flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL, 
                         dl_vlan=vid)
 
     
@@ -1309,39 +1267,42 @@
         vid_act = action.action_set_vlan_vid()
         vid_act.vlan_vid = new_vid
 
-        flow_match_test(self, pa_port_map, pkt=pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, 
                         exp_pkt=exp_pkt, action_list=[vid_act])
 
-class PacketOnly(basic.DataPlaneOnly):
+class PacketOnly(base_tests.DataPlaneOnly):
     """
     Just send a packet thru the switch
     """
+
+    priority = -1
+
     def runTest(self):
         pkt = simple_tcp_packet()
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         ing_port = of_ports[0]
-        pa_logger.info("Sending packet to " + str(ing_port))
-        pa_logger.debug("Data: " + str(pkt).encode('hex'))
+        logging.info("Sending packet to " + str(ing_port))
+        logging.debug("Data: " + str(pkt).encode('hex'))
         self.dataplane.send(ing_port, str(pkt))
 
-class PacketOnlyTagged(basic.DataPlaneOnly):
+class PacketOnlyTagged(base_tests.DataPlaneOnly):
     """
     Just send a packet thru the switch
     """
+
+    priority = -1
+
     def runTest(self):
-        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+        vid = test_param_get('vid', default=TEST_VID_DEFAULT)
         pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         ing_port = of_ports[0]
-        pa_logger.info("Sending packet to " + str(ing_port))
-        pa_logger.debug("Data: " + str(pkt).encode('hex'))
+        logging.info("Sending packet to " + str(ing_port))
+        logging.debug("Data: " + str(pkt).encode('hex'))
         self.dataplane.send(ing_port, str(pkt))
 
-test_prio["PacketOnly"] = -1
-test_prio["PacketOnlyTagged"] = -1
-
 class ModifyVID(BaseMatchCase):
     """
     Modify the VLAN ID in the VLAN tag of a tagged packet
@@ -1363,7 +1324,7 @@
         vid_act = action.action_set_vlan_vid()
         vid_act.vlan_vid = new_vid
 
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act], ing_port=self.ing_port)
 
 class ModifyVIDToIngress(ModifyVID):
@@ -1388,12 +1349,12 @@
             skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
             return
 
-        of_ports = pa_port_map.keys()
+        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]
         
-        rv = delete_all_flows(self.controller, pa_logger)
+        rv = delete_all_flows(self.controller)
         self.assertEqual(rv, 0, "Failed to delete all flows")
 
         len_untagged = 100
@@ -1412,12 +1373,12 @@
                                   action_list=[vid_act])
         flow_msg_install(self, request)
 
-        pa_logger.debug("Send untagged packet: " + str(ing_port) + " to " + 
+        logging.debug("Send untagged packet: " + str(ing_port) + " to " + 
                         str(egr_ports))
         self.dataplane.send(ing_port, str(untagged_pkt))
         receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
 
-        pa_logger.debug("Send tagged packet: " + str(ing_port) + " to " + 
+        logging.debug("Send tagged packet: " + str(ing_port) + " to " + 
                         str(egr_ports))
         self.dataplane.send(ing_port, str(tagged_pkt))
         receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
@@ -1440,7 +1401,7 @@
         vid_act = action.action_set_vlan_pcp()
         vid_act.vlan_pcp = new_vlan_pcp
 
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
 
 class StripVLANTag(BaseMatchCase):
@@ -1461,7 +1422,7 @@
         exp_pkt = simple_tcp_packet(pktlen=len)
         vid_act = action.action_strip_vlan()
 
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
 
 class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
@@ -1485,7 +1446,7 @@
                      ofp.OFPFW_DL_VLAN_PCP)
         vid_act = action.action_strip_vlan()
 
-        flow_match_test(self, pa_port_map, 
+        flow_match_test(self, config["port_map"], 
                         wildcards=wildcards,
                         pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
@@ -1499,9 +1460,9 @@
 
     dl_vlan_enable=False
     dl_vlan=-1
-    if pa_config["test-params"]["vid"]:
+    if config["test-params"]["vid"]:
         dl_vlan_enable=True
-        dl_vlan = pa_config["test-params"]["vid"]
+        dl_vlan = config["test-params"]["vid"]
 
 # Unpack operator is ** on a dictionary
 
@@ -1519,7 +1480,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyL2Dst(BaseMatchCase):
@@ -1534,7 +1495,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyL3Src(BaseMatchCase):
@@ -1549,7 +1510,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyL3Dst(BaseMatchCase):
@@ -1564,7 +1525,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyL4Src(BaseMatchCase):
@@ -1579,7 +1540,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyL4Dst(BaseMatchCase):
@@ -1594,7 +1555,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2)
 
 class ModifyTOS(BaseMatchCase):
@@ -1609,7 +1570,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
 
 class ModifyL2DstMC(BaseMatchCase):
@@ -1624,7 +1585,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
 
 class ModifyL2DstIngress(BaseMatchCase):
@@ -1639,7 +1600,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=0,
                         ing_port=True)
 
@@ -1655,7 +1616,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1,
                         ing_port=True)
 
@@ -1671,7 +1632,7 @@
 
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
 
 class ModifyL2SrcDstMC(BaseMatchCase):
@@ -1688,7 +1649,7 @@
         mod_fields = ['dl_dst', 'dl_src']
         (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
 
 class ModifyL2DstVIDMC(BaseMatchCase):
@@ -1706,7 +1667,7 @@
         (pkt, exp_pkt, acts) = pkt_action_setup(self, 
              start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
                                                 check_test_params=True)
-        flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt, 
+        flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt, 
                         action_list=acts, max_test=2, egr_count=-1)
 
 class FlowToggle(BaseMatchCase):
@@ -1721,16 +1682,16 @@
     (add, modify, delete +/- strict).
     """
     def runTest(self):
-        flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
-        iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
+        flow_count = test_param_get('ft_flow_count', default=20)
+        iter_count = test_param_get('ft_iter_count', default=10)
 
-        pa_logger.info("Running flow toggle with %d flows, %d iterations" %
+        logging.info("Running flow toggle with %d flows, %d iterations" %
                        (flow_count, iter_count))
         acts = []
         acts.append(action.action_output())
         acts.append(action.action_output())
     
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         if len(of_ports) < 3:
             self.assertTrue(False, "Too few ports for test")
     
@@ -1758,8 +1719,8 @@
                 flows[toggle].append(msg)
 
         # Show two sample flows
-        pa_logger.debug(flows[0][0].show())
-        pa_logger.debug(flows[1][0].show())
+        logging.debug(flows[0][0].show())
+        logging.debug(flows[1][0].show())
 
         # Install the first set of flows
         for f_idx in range(flow_count):
@@ -1767,7 +1728,7 @@
             self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
     
-        pa_logger.info("Installed %d flows" % flow_count)
+        logging.info("Installed %d flows" % flow_count)
     
         # Repeatedly modify all the flows back and forth
         updates = 0
@@ -1776,7 +1737,7 @@
         start = time.time()
         for iter_idx in range(iter_count):
             if not iter_idx % mod_val:
-                pa_logger.info("Flow Toggle: iter %d of %d. " %
+                logging.info("Flow Toggle: iter %d of %d. " %
                                (iter_idx, iter_count) + 
                                "%d updates in %d secs" %
                                (updates, time.time() - start))
@@ -1792,8 +1753,8 @@
 
         end = time.time()
         divisor = end - start or (end - start + 1)
-        pa_logger.info("Flow toggle: %d iterations" % iter_count)
-        pa_logger.info("   %d flow mods in %d secs, %d mods/sec" %
+        logging.info("Flow toggle: %d iterations" % iter_count)
+        logging.info("   %d flow mods in %d secs, %d mods/sec" %
                        (updates, end - start, updates/divisor))
             
 
@@ -1826,14 +1787,16 @@
     The cases come from the list above
     """
 
+    priority = -1
+
     def runTest(self):
-        count = test_param_get(self.config, 'iter_count', default=10)
+        count = test_param_get('iter_count', default=10)
         tests_done = 0
-        pa_logger.info("Running iteration test " + str(count) + " times")
+        logging.info("Running iteration test " + str(count) + " times")
         start = time.time()
         last = start
         for idx in range(count):
-            pa_logger.info("Iteration " + str(idx + 1))
+            logging.info("Iteration " + str(idx + 1))
             for cls in iter_classes:
                 test = cls()
                 test.inheritSetup(self)
@@ -1842,22 +1805,19 @@
                 # Report update about every minute, between tests
                 if time.time() - last > 60:
                     last = time.time()
-                    pa_logger.info(
+                    logging.info(
                         "IterCases: Iter %d of %d; Ran %d tests in %d " %
                         (idx, count, tests_done, last - start) + 
                         "seconds so far")
         stats = all_stats_get(self)
         last = time.time()
-        pa_logger.info("\nIterCases ran %d tests in %d seconds." %
+        logging.info("\nIterCases ran %d tests in %d seconds." %
                        (tests_done, last - start))
-        pa_logger.info("    flows: %d. packets: %d. bytes: %d" %
+        logging.info("    flows: %d. packets: %d. bytes: %d" %
                        (stats["flows"], stats["packets"], stats["bytes"]))
-        pa_logger.info("    active: %d. lookups: %d. matched %d." %
+        logging.info("    active: %d. lookups: %d. matched %d." %
                        (stats["active"], stats["lookups"], stats["matched"]))
 
-# Don't run by default
-test_prio["IterCases"] = -1
-
 #@todo Need to implement tagged versions of the above tests
 #
 #@todo Implement a test case that strips tag 2, adds tag 3
@@ -1887,9 +1847,9 @@
     If only VID 5 distinguishes pkt, this will fail on some platforms
     """   
 
-test_prio["MixedVLAN"] = -1
+    priority = -1
 
-class MatchEach(basic.SimpleDataPlane):
+class MatchEach(base_tests.SimpleDataPlane):
     """
     Check that each match field is actually matched on.
     Installs two flows that differ in one field. The flow that should not
@@ -1899,18 +1859,18 @@
     TODO test UDP, ARP, ICMP, etc.
     """
     def runTest(self):
-        of_ports = pa_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
-        delete_all_flows(self.controller, pa_logger)
+        delete_all_flows(self.controller)
 
         pkt = simple_tcp_packet()
         ingress_port = of_ports[0]
         egress_port = of_ports[1]
 
         def testField(field, mask):
-            pa_logger.info("Testing field %s" % field)
+            logging.info("Testing field %s" % field)
 
             def addFlow(matching, priority, output_port):
                 match = packet_to_flow_match(self, pkt)
@@ -1932,7 +1892,7 @@
                 act = action.action_output()
                 act.port = output_port
                 self.assertTrue(request.actions.add(act), "Could not add action")
-                pa_logger.info("Inserting flow")
+                logging.info("Inserting flow")
                 self.controller.message_send(request)
 
             # This flow should match.
@@ -1942,19 +1902,19 @@
 
             self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
-            pa_logger.info("Sending packet to dp port " + str(ingress_port))
+            logging.info("Sending packet to dp port " + str(ingress_port))
             self.dataplane.send(ingress_port, str(pkt))
 
             exp_pkt_arg = None
             exp_port = None
-            if pa_config["relax"]:
+            if config["relax"]:
                 exp_pkt_arg = pkt
                 exp_port = egress_port
 
             (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
                                                                 exp_pkt=exp_pkt_arg)
             self.assertTrue(rcv_pkt is not None, "Did not receive packet")
-            pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
+            logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
             self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
             self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
 
diff --git a/tests/port_stats.py b/tests/port_stats.py
index 96d3cc5..670e31f 100644
--- a/tests/port_stats.py
+++ b/tests/port_stats.py
@@ -9,25 +9,18 @@
 import unittest
 import random
 
+from oftest import config
 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 basic
+import oftest.base_tests as base_tests
 
 from oftest.testutils import *
 from time import sleep
 
-#@var fs_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-fs_port_map = None
-#@var fs_logger Local logger object
-fs_logger = None
-#@var fs_config Local copy of global configuration data
-fs_config = None
-
 # TODO: ovs has problems with VLAN id?
 WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
                    # (ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP),
@@ -44,33 +37,15 @@
                    ofp.OFPFW_DL_VLAN_PCP,
                    ofp.OFPFW_NW_TOS]
 
-def test_set_init(config):
-    """
-    Set up function for packet action test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    basic.test_set_init(config)
-
-    global fs_port_map
-    global fs_logger
-    global fs_config
-
-    fs_logger = logging.getLogger("flow_stats")
-    fs_logger.info("Initializing test set")
-    fs_port_map = config["port_map"]
-    fs_config = config
-
 def sendPacket(obj, pkt, ingress_port, egress_port, test_timeout):
 
-    fs_logger.info("Sending packet to dp port " + str(ingress_port) +
+    logging.info("Sending packet to dp port " + str(ingress_port) +
                    ", expecting output on " + str(egress_port))
     obj.dataplane.send(ingress_port, str(pkt))
 
     exp_pkt_arg = None
     exp_port = None
-    if fs_config["relax"]:
+    if config["relax"]:
         exp_pkt_arg = pkt
         exp_port = egress_port
 
@@ -78,7 +53,7 @@
                                                        exp_pkt=exp_pkt_arg)
     obj.assertTrue(rcv_pkt is not None,
                    "Packet not received on port " + str(egress_port))
-    fs_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
+    logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + 
                     str(rcv_port))
     obj.assertEqual(rcv_port, egress_port,
                     "Packet received on port " + str(rcv_port) +
@@ -90,17 +65,17 @@
     stat_req = message.port_stats_request()
     stat_req.port_no = port
 
-    fs_logger.info("Sending stats request")
+    logging.info("Sending stats request")
     response, pkt = obj.controller.transact(stat_req, timeout=2)
     obj.assertTrue(response is not None, 
                     "No response to stats request")
     obj.assertTrue(len(response.stats) == 1,
                     "Did not receive port stats reply")
     for item in response.stats:
-        fs_logger.info("Sent " + str(item.tx_packets) + " packets")
+        logging.info("Sent " + str(item.tx_packets) + " packets")
         packet_sent = item.tx_packets
         packet_recv = item.rx_packets
-    fs_logger.info("Port %d stats count: tx %d rx %d" % (port, packet_sent, packet_recv))
+    logging.info("Port %d stats count: tx %d rx %d" % (port, packet_sent, packet_recv))
     return packet_sent, packet_recv
 
 def verifyStats(obj, port, test_timeout, packet_sent, packet_recv):
@@ -111,7 +86,7 @@
     all_packets_sent = 0
     sent = recv = 0
     for i in range(0,test_timeout):
-        fs_logger.info("Sending stats request")
+        logging.info("Sending stats request")
         response, pkt = obj.controller.transact(stat_req,
                                                 timeout=test_timeout)
         obj.assertTrue(response is not None, 
@@ -121,10 +96,10 @@
         for item in response.stats:
             sent = item.tx_packets
             recv = item.rx_packets
-            fs_logger.info("Sent " + str(item.tx_packets) + " packets")
+            logging.info("Sent " + str(item.tx_packets) + " packets")
             if item.tx_packets == packet_sent:
                 all_packets_sent = 1
-            fs_logger.info("Received " + str(item.rx_packets) + " packets")
+            logging.info("Received " + str(item.rx_packets) + " packets")
             if item.rx_packets == packet_recv:
                 all_packets_received = 1
 
@@ -132,14 +107,14 @@
             break
         sleep(1)
 
-    fs_logger.info("Expected port %d stats count: tx %d rx %d" % (port, packet_sent, packet_recv))
-    fs_logger.info("Actual port %d stats count: tx %d rx %d" % (port, sent, recv))
+    logging.info("Expected port %d stats count: tx %d rx %d" % (port, packet_sent, packet_recv))
+    logging.info("Actual port %d stats count: tx %d rx %d" % (port, sent, recv))
     obj.assertTrue(all_packets_sent,
                    "Packet sent does not match number sent")
     obj.assertTrue(all_packets_received,
                    "Packet received does not match number sent")
 
-class SingleFlowStats(basic.SimpleDataPlane):
+class SingleFlowStats(base_tests.SimpleDataPlane):
     """
     Verify flow stats are properly retrieved.
 
@@ -151,16 +126,14 @@
     """
 
     def runTest(self):
-        global fs_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
 
-        rc = delete_all_flows(self.controller, fs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         # build packet
@@ -174,7 +147,7 @@
         # build flow
         ingress_port = of_ports[0];
         egress_port = of_ports[1];
-        fs_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
         match.in_port = ingress_port
         flow_mod_msg = message.flow_mod()
@@ -187,7 +160,7 @@
         self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
        
         # send flow
-        fs_logger.info("Inserting flow")
+        logging.info("Inserting flow")
         rv = self.controller.message_send(flow_mod_msg)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
@@ -198,7 +171,7 @@
 
         # send packet N times
         num_sends = random.randint(10,20)
-        fs_logger.info("Sending " + str(num_sends) + " test packets")
+        logging.info("Sending " + str(num_sends) + " test packets")
         for i in range(0,num_sends):
             sendPacket(self, pkt, ingress_port, egress_port,
                        test_timeout)
@@ -207,7 +180,7 @@
         verifyStats(self, egress_port, test_timeout, initTxOutPort + num_sends, initRxOutPort)
 
 
-class MultiFlowStats(basic.SimpleDataPlane):
+class MultiFlowStats(base_tests.SimpleDataPlane):
     """
     Verify flow stats are properly retrieved.
 
@@ -234,25 +207,23 @@
         act.port = egress_port
         self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
 
-        fs_logger.info("Ingress " + str(ingress_port) + 
+        logging.info("Ingress " + str(ingress_port) + 
                        " to egress " + str(egress_port))
 
         return flow_mod_msg
 
     def runTest(self):
-        global fs_port_map
-
         # TODO: set from command-line parameter
         test_timeout = 60
 
-        of_ports = fs_port_map.keys()
+        of_ports = config["port_map"].keys()
         of_ports.sort()
         self.assertTrue(len(of_ports) >= 3, "Not enough ports for test")
         ingress_port = of_ports[0];
         egress_port1 = of_ports[1];
         egress_port2 = of_ports[2];
 
-        rc = delete_all_flows(self.controller, fs_logger)
+        rc = delete_all_flows(self.controller)
         self.assertEqual(rc, 0, "Failed to delete all flows")
 
         pkt1 = simple_tcp_packet()
@@ -261,10 +232,10 @@
         pkt2 = simple_tcp_packet(dl_src='0:7:7:7:7:7')
         flow_mod_msg2 = self.buildFlowModMsg(pkt2, ingress_port, egress_port2)
        
-        fs_logger.info("Inserting flow1")
+        logging.info("Inserting flow1")
         rv = self.controller.message_send(flow_mod_msg1)
         self.assertTrue(rv != -1, "Error installing flow mod")
-        fs_logger.info("Inserting flow2")
+        logging.info("Inserting flow2")
         rv = self.controller.message_send(flow_mod_msg2)
         self.assertTrue(rv != -1, "Error installing flow mod")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
@@ -275,9 +246,9 @@
         initTxOutPort2, initRxOutPort2 = getStats(self, egress_port2)
 
         num_pkt1s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt1s) + " pkt1s")
+        logging.info("Sending " + str(num_pkt1s) + " pkt1s")
         num_pkt2s = random.randint(10,30)
-        fs_logger.info("Sending " + str(num_pkt2s) + " pkt2s")
+        logging.info("Sending " + str(num_pkt2s) + " pkt2s")
         for i in range(0,num_pkt1s):
             sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
         for i in range(0,num_pkt2s):
diff --git a/tests/serial_failover.py b/tests/serial_failover.py
index 311dde1..ffbbf0a 100644
--- a/tests/serial_failover.py
+++ b/tests/serial_failover.py
@@ -4,13 +4,13 @@
 """
 
 import time
-import signal
 import sys
 import logging
 
 import unittest
 import random
 
+from oftest import config
 import oftest.controller as controller
 import oftest.cstruct as ofp
 import oftest.message as message
@@ -19,32 +19,6 @@
 
 from oftest.testutils import *
 
-#@var serial_failover_port_map Local copy of the configuration map from OF port
-# numbers to OS interfaces
-serial_failover_port_map = None
-#@var serial_failover_logger Local logger object
-serial_failover_logger = None
-#@var serial_failover_config Local copy of global configuration data
-serial_failover_config = None
-
-test_prio = {}
-
-def test_set_init(config):
-    """
-    Set up function for serial failover test classes
-
-    @param config The configuration dictionary; see oft
-    """
-
-    global serial_failover_port_map
-    global serial_failover_logger
-    global serial_failover_config
-
-    serial_failover_logger = logging.getLogger("serial_failover")
-    serial_failover_logger.info("Initializing test set")
-    serial_failover_port_map = config["port_map"]
-    serial_failover_config = config
-
 class SerialFailover(unittest.TestCase):
     """
     Opens a connection that the switch should use as its only controller,
@@ -57,6 +31,8 @@
     --test-params="param1=val1;param2=val2"
     """
 
+    priority = -1
+
     # populated by buildControllerList()
     controller_list = []
     controller_idx = 0
@@ -64,13 +40,6 @@
     test_timeout = 0
     test_iterations = 0
 
-    def sig_handler(self, v1, v2):
-        serial_failover_logger.critical("Received interrupt signal; exiting")
-        print "Received interrupt signal; exiting"
-        self.clean_shutdown = False
-        self.tearDown()
-        sys.exit(1)
-
     def controllerSetup(self, host, port):
         self.controller = controller.Controller(host=host,port=port)
 
@@ -89,7 +58,7 @@
         reply, pkt = self.controller.transact(request, timeout=20)
         self.assertTrue(reply is not None,
                         "Did not complete features_request for handshake")
-        serial_failover_logger.info("Connected " + 
+        logging.info("Connected " + 
                                     str(self.controller.switch_addr))
 
         # send echo request and wait for reply
@@ -103,10 +72,10 @@
 
     def connectionKill(self, kill_method):
         if kill_method == 'controller_shutdown':
-            serial_failover_logger.info("Shutting down controller")
+            logging.info("Shutting down controller")
             self.controller.shutdown()
         elif kill_method == 'no_echo':
-            serial_failover_logger.info("Disabling controller keep alive")
+            logging.info("Disabling controller keep alive")
             self.controller.keep_alive = False
 
             # wait for controller to die
@@ -115,15 +84,14 @@
                 time.sleep(1)
                 count = count + 1
         else:
-            self.assertTrue(false, "Unknown controller kill method")
+            self.assertTrue(False, "Unknown controller kill method")
 
     def buildControllerList(self):
         # controller_list is list of ip/port tuples
-        partial_list = test_param_get(serial_failover_config,
-                                      'controller_list')
-        serial_failover_logger.debug("ctrl list: " + str(partial_list))
-        self.controller_list = [(serial_failover_config["controller_host"],
-                                 serial_failover_config["controller_port"])]
+        partial_list = test_param_get('controller_list')
+        logging.debug("ctrl list: " + str(partial_list))
+        self.controller_list = [(config["controller_host"],
+                                 config["controller_port"])]
         if partial_list is not None:
             for controller in partial_list:
                 ip,portstr = controller.split(':')
@@ -143,20 +111,10 @@
         return self.controller_list[self.controller_idx]
 
     def setUp(self):
-        self.logger = serial_failover_logger
-        self.config = serial_failover_config
-        #@todo Test cases shouldn't monkey with signals; move SIGINT handler
-        # to top-level oft
-        try:
-           signal.signal(signal.SIGINT, self.sig_handler)
-        except ValueError, e:
-           serial_failover_logger.info("Could not set SIGINT handler: %s" % e)
-        serial_failover_logger.info("** START TEST CASE " + str(self))
+        logging.info("** START TEST CASE " + str(self))
 
-        self.test_timeout = test_param_get(serial_failover_config,
-                                           'failover_timeout') or 60
-        self.test_iterations = test_param_get(serial_failover_config,
-                                              'failover_iterations') or 4
+        self.test_timeout = test_param_get('failover_timeout') or 60
+        self.test_iterations = test_param_get('failover_iterations') or 4
 
         self.buildControllerList()
         self.controller_idx = 0
@@ -178,27 +136,25 @@
         the state after the sub_test is run must be taken into account
         by subsequent operations.
         """
-        self.logger = parent.logger
-        self.config = parent.config
-        serial_failover_logger.info("** Setup " + str(self) + 
+        logging.info("** Setup " + str(self) + 
                                     " inheriting from " + str(parent))
         self.controller = parent.controller
         
     def tearDown(self):
-        serial_failover_logger.info("** END TEST CASE " + str(self))
+        logging.info("** END TEST CASE " + str(self))
         self.controller.shutdown()
         if self.clean_shutdown:
             self.controller.join()
 
     def doFailover(self, killmethod):
-        serial_failover_logger.info("Starting serial failover test")
+        logging.info("Starting serial failover test")
         self.assertTrue(self.controller.switch_socket is not None,
                         str(self) + 'No connection to switch')
         # kill controller connection
         self.connectionKill(killmethod)
         # establish new controller connection
         controller = self.getNextController()
-        serial_failover_logger.debug("** Next controller (%u/%u)%s:%u" % 
+        logging.debug("** Next controller (%u/%u)%s:%u" % 
                                      (self.controller_idx,
                                       len(self.controller_list),
                                       controller[0],
@@ -211,17 +167,13 @@
 
     def assertTrue(self, cond, msg):
         if not cond:
-            serial_failover_logger.error("** FAILED ASSERTION: " + msg)
+            logging.error("** FAILED ASSERTION: " + msg)
         unittest.TestCase.assertTrue(self, cond, msg)
 
-test_prio["SerialFailover"] = -1
-
 
 class SerialFailoverNoEcho(SerialFailover):
+    priority = -1
 
     def runTest(self):
         for i in range(0,self.test_iterations):
             self.doFailover('no_echo')
-
-test_prio["SerialFailoverNoEcho"] = -1
-