Goofed last minute change about action comparison for modifies, modify does not change timeouts -- fixed
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index 7495dc7..e7051ee 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -208,8 +208,9 @@
             self.expect_msg_cv.acquire()
             if self.expect_msg:
                 if not self.expect_msg_type or (self.expect_msg_type == hdr.type):
-                    self.logger.debug("Matched expected msg type "
-                                       + ofp_type_map[hdr.type])
+                    self.logger.debug("Matched msg; type %s. expected %s " %
+                                      (ofp_type_map[hdr.type], 
+                                       ofp_type_map[self.expect_msg_type]))
                     self.expect_msg_response = (msg, rawmsg)
                     self.expect_msg = False
                     self.expect_msg_cv.notify()
@@ -485,13 +486,14 @@
         # Careful of race condition releasing sync before message cv
         # Also, this style is ripe for a lockup.
         self.expect_msg_cv.acquire()
-        self.sync.release()
         self.expect_msg_response = None
         self.expect_msg = True
         self.expect_msg_type = exp_msg
+        self.sync.release()
         self.expect_msg_cv.wait(timeout)
         if self.expect_msg_response is not None:
             (msg, pkt) = self.expect_msg_response
+        self.expect_msg = False # Check this -- only 1 thread?
         self.expect_msg_cv.release()
 
         if msg is None:
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 8d29213..37f9adc 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -53,6 +53,11 @@
     pa_port_map = config["port_map"]
     pa_config = config
 
+    # TBD - Doesn't seem to take effect at the right time...
+    if test_param_get(pa_config, "dut", "") == "ovs":
+        # Disable this test by default, since the flow capacity reported by OVS is bogus.
+        test_prio["Flow_Add_6"] = -1
+
 
 def flip_coin():
     return random.randint(1, 100) <= 50
@@ -338,23 +343,25 @@
             return False
         if self.hard_timeout != x.hard_timeout:
             return False
-        # Compare actions lists as unordered, since Argon may re-order action lists.
-        # This is in apparent violation of the spec.
-        # TBD - Verify, or create option in test to check ordered/unordered
-        aa = copy.deepcopy(x.actions.actions)
-        for a in self.actions.actions:
-            i = 0
-            while i < len(aa):
-                if a == aa[i]:
-                    break
-                i = i + 1
-            if i < len(aa):
-                aa.pop(i)
-            else:
-                return False
-        return aa == []
+        if test_param_get(pa_config, "dut", "") == "argon":
+            # Compare actions lists as unordered, since Argon may re-order action lists.
+            # This is in apparent violation of the spec.
+            aa = copy.deepcopy(x.actions.actions)
+            for a in self.actions.actions:
+                i = 0
+                while i < len(aa):
+                    if a == aa[i]:
+                        break
+                    i = i + 1
+                if i < len(aa):
+                    aa.pop(i)
+                else:
+                    return False
+            return aa == []
+        else:
+            return self.actions == x.actions
         
-    def flow_key_str(self):
+    def key_str(self):
         result = "priority=%d" % self.priority
         # TBD - Would be nice if ofp_match.show() was better behaved
         # (no newlines), and more intuitive (things in hex where approprate), etc.
@@ -407,7 +414,8 @@
         return (self.key_equal(x) and self.non_key_equal(x))
 
     def __str__(self):
-        result = self.flow_key_str()
+        result = self.key_str()
+        result = result + (", cookie=%d" % self.cookie)
         result = result + (", idle_timeout=%d" % self.idle_timeout)
         result = result + (", hard_timeout=%d" % self.hard_timeout)
         for a in self.actions.actions:
@@ -460,10 +468,12 @@
                 act.vlan_vid = fi.rand_vlan()
                 self.actions.add(act)
             elif a == ofp.OFPAT_SET_VLAN_PCP:
-                # TBD - Temporaily removed, broken in Indigo
-                #act = action.action_set_vlan_pcp()
-                #act.vlan_pcp = random.randint(0, (1 << 3) - 1)
-                pass
+                if test_param_get(pa_config, "dut", "") == "indigo":
+                    # Temporaily removed, broken in Indigo
+                    pass
+                else:
+                    act = action.action_set_vlan_pcp()
+                    act.vlan_pcp = random.randint(0, (1 << 3) - 1)
             elif a == ofp.OFPAT_STRIP_VLAN:
                 act = action.action_strip_vlan()
                 self.actions.add(act)
@@ -609,22 +619,22 @@
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_TOS, 1)
 
-# <TBD>
-# Due to a bug in OVS, don't specify nw_proto on it's own.
-# OVS will allow specifying a value for nw_proto, even if dl_type is not
-# specified as IP.
-# REMOVE FOR ARGON TESTING, AND BE SURE ABOUT INDENTATION
-# </TBD>
-#         if wildcard_get(valid_wildcards, ofp.OFPFW_NW_PROTO) == 0 \
-#            or exact \
-#            or flip_coin():
-#             self.match.nw_proto = fi.rand_ip_proto()
-#             # Specifying an IP protocol requires that Ethertype is IP
-#             if flip_coin():
-#                 self.match.dl_type   = 0x0800
-#                 self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
-#         else:            
-        self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_PROTO, 1)
+        if test_param_get(pa_config, "dut", "") == "ovs":
+            # Due to a bug in OVS, don't specify nw_proto on it's own.
+            # OVS will allow specifying a value for nw_proto, even if dl_type is not
+            # specified as IP.
+            self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_PROTO, 1)
+        else:
+            if wildcard_get(valid_wildcards, ofp.OFPFW_NW_PROTO) == 0 \
+                   or exact \
+                   or flip_coin():
+                self.match.nw_proto = fi.rand_ip_proto()
+                # Specifying an IP protocol requires that Ethertype is IP
+                if flip_coin():
+                    self.match.dl_type   = 0x0800
+                    self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
+            else:            
+                self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_PROTO, 1)
             
         if wildcard_get(valid_wildcards, ofp.OFPFW_TP_SRC) == 0 \
            or exact\
@@ -818,13 +828,13 @@
         self.clear()
 
     def find(self, f):
-        return self.dict.get(f.flow_key_str(), None)
+        return self.dict.get(f.key_str(), None)
 
     def insert(self, f):
-        self.dict[f.flow_key_str()] = f
+        self.dict[f.key_str()] = f
 
     def delete(self, f):
-        del self.dict[f.flow_key_str()]
+        del self.dict[f.key_str()]
 
     def values(self):
         return self.dict.values()
@@ -1172,9 +1182,6 @@
         pa_logger.debug("Flow_Add_5_1 TEST PASSED")
 
 
-# Disable this test by default, since the flow capacity reported by OVS is bogus.
-test_prio["Flow_Add_6"] = -1
-
 class Flow_Add_6(basic.SimpleProtocol):
     """
     Test FLOW_ADD_6 from draft top-half test plan
@@ -1200,6 +1207,7 @@
         self.assertTrue(sw.features_get(), "Get switch features failed")
         self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
 
+        num_flows = 0
         for ts in sw.tbl_stats.stats:
             num_flows = num_flows + ts.max_entries
 
@@ -1674,9 +1682,8 @@
 
         for fc in ft.values():
             if mfc.overlaps(fc, True):
-                fc.idle_timeout = mfc.idle_timeout
-                fc.hard_timeout = mfc.hard_timeout
-                fc.actions      = mfc.actions
+                fc.cookie  = mfc.cookie
+                fc.actions = mfc.actions
 
         # Verify flow table
 
diff --git a/tests/flow_query2.py b/tests/flow_query2.py
deleted file mode 100644
index a09b886..0000000
--- a/tests/flow_query2.py
+++ /dev/null
@@ -1,1210 +0,0 @@
-"""
-Flow query test case.
-
-Attempts to fill switch to capacity with randomized flows, and ensure that they all are read back correctly.
-"""
-import math
-
-import logging
-
-import unittest
-import random
-
-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.action_list as action_list
-import oftest.parse       as parse
-import pktact
-import basic
-
-from testutils import *
-from time import sleep
-
-#@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
-
-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
-
-
-def shuffle(list):
-    n = len(list)
-    lim = n * n
-    i = 0
-    while i < lim:
-        a = random.randint(0, n - 1)
-        b = random.randint(0, n - 1)
-        temp = list[a]
-        list[a] = list[b]
-        list[b] = temp
-        i = i + 1
-    return list
-
-
-def rand_pick(list):
-    return list[random.randint(0, len(list) - 1)]
-
-def rand_dl_addr():
-    return [random.randint(0, 255) & ~1,
-            random.randint(0, 255),
-            random.randint(0, 255),
-            random.randint(0, 255),
-            random.randint(0, 255),
-            random.randint(0, 255)
-            ]
-
-def rand_nw_addr():
-    return random.randint(0, (1 << 32) - 1)
-
-
-class flow_info:
-    # Members:
-    # priorities - list of flow priorities
-    # dl_addrs   - list of MAC addresses
-    # vlans      - list of VLAN ids
-    # ethertypes - list of Ethertypes
-    # ip_addrs   - list of IP addresses
-    # ip_tos     - list of IP TOS values
-    # ip_protos  - list of IP protocols
-    # l4_ports   - list of L4 ports
-
-    def __init__(self):
-        priorities = []
-        dl_addrs   = []
-        vlans      = []
-        ethertypes = []
-        ip_addrs   = []
-        ip_tos     = []
-        ip_protos  = []
-        l4_ports   = []
-
-    def rand(self, n):
-        self.priorities = []
-        i = 0
-        while i < n:
-            self.priorities.append(random.randint(1, 65534))
-            i = i + 1
-    
-        self.dl_addrs = []
-        i = 0
-        while i < n:
-            self.dl_addrs.append(rand_dl_addr())
-            i = i + 1
-    
-        self.vlans = []
-        i = 0
-        while i < n:
-            self.vlans.append(random.randint(1, 4094))
-            i = i + 1
-    
-        self.ethertypes = []
-        i = 0
-        while i < n:
-            self.ethertypes.append(random.randint(0, (1 << 16) - 1))
-            i = i + 1
-    
-        self.ip_addrs = []
-        i = 0
-        while i < n:
-            self.ip_addrs.append(rand_nw_addr())
-            i = i + 1
-    
-        self.ip_tos = []
-        i = 0
-        while i < n:
-            self.ip_tos.append(random.randint(0, (1 << 8) - 1) & ~3)
-            i = i + 1
-    
-        self.ip_protos = []
-        i = 0
-        while i < n:
-            self.ip_protos.append(random.randint(0, (1 << 8) - 1))
-            i = i + 1
-    
-        self.l4_ports = []
-        i = 0
-        while i < n:
-            self.l4_ports.append(random.randint(0, (1 << 16) - 1))
-            i = i + 1
-
-    def rand_priority(self):
-        return rand_pick(self.priorities)
-
-    def rand_dl_addr(self):
-        return rand_pick(self.dl_addrs)
-
-    def rand_vlan(self):
-        return rand_pick(self.vlans)
-
-    def rand_ethertype(self):
-        return rand_pick(self.ethertypes)
-
-    def rand_ip_addr(self):
-        return rand_pick(self.ip_addrs)
-
-    def rand_ip_tos(self):
-        return rand_pick(self.ip_tos)
-
-    def rand_ip_proto(self):
-        return rand_pick(self.ip_protos)
-
-    def rand_l4_port(self):
-        return rand_pick(self.l4_ports)
-
-
-# TBD - These don't belong here
-
-all_wildcards_list = [ofp.OFPFW_IN_PORT,
-                      ofp.OFPFW_DL_VLAN,
-                      ofp.OFPFW_DL_SRC,
-                      ofp.OFPFW_DL_DST,
-                      ofp.OFPFW_DL_TYPE,
-                      ofp.OFPFW_NW_PROTO,
-                      ofp.OFPFW_TP_SRC,
-                      ofp.OFPFW_TP_DST,
-                      ofp.OFPFW_NW_SRC_MASK,
-                      ofp.OFPFW_NW_DST_MASK,
-                      ofp.OFPFW_DL_VLAN_PCP,
-                      ofp.OFPFW_NW_TOS
-                      ]
-
-
-all_actions_list = [ofp.OFPAT_OUTPUT,
-                    ofp.OFPAT_SET_VLAN_VID,
-                    ofp.OFPAT_SET_VLAN_PCP,
-                    ofp.OFPAT_STRIP_VLAN,
-                    ofp.OFPAT_SET_DL_SRC,
-                    ofp.OFPAT_SET_DL_DST,
-                    ofp.OFPAT_SET_NW_SRC,
-                    ofp.OFPAT_SET_NW_DST,
-                    ofp.OFPAT_SET_NW_TOS,
-                    ofp.OFPAT_SET_TP_SRC,
-                    ofp.OFPAT_SET_TP_DST,
-                    ofp.OFPAT_ENQUEUE
-                    ]
-
-def dl_addr_to_str(a):
-    return "%x:%x:%x:%x:%x:%x" % tuple(a)
-
-def ip_addr_to_str(a, n):
-    result = "%d.%d.%d.%d" % (a >> 24, \
-                              (a >> 16) & 0xff, \
-                              (a >> 8) & 0xff, \
-                              a & 0xff \
-                              )
-    if n is not None:
-        result = result + ("/%d" % (n))
-    return result
-    
-
-class flow_cfg:
-    # Members:
-    # - match
-    # - idle_timeout
-    # - hard_timeout
-    # - priority
-    # - action_list
-
-    def __init__(self):
-        self.priority        = 0
-        self.match           = parse.ofp_match()
-        self.match.wildcards = ofp.OFPFW_ALL
-        self.idle_timeout    = 0
-        self.hard_timeout    = 0
-        self.actions         = action_list.action_list()
-
-    def __eq__(self, x):
-        if self.priority != x.priority:
-            return False
-        # TBD - Should this logic be moved to ofp_match.__eq__()?
-        if self.match.wildcards != x.match.wildcards:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_IN_PORT) == 0 \
-           and self.match.in_port != x.match.in_port:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_DL_SRC) == 0 \
-           and self.match.dl_src != x.match.dl_src:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_DL_DST) == 0 \
-           and self.match.dl_dst != x.match.dl_dst:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN) == 0 \
-           and self.match.dl_vlan != x.match.dl_vlan:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN_PCP) == 0 \
-           and self.match.dl_vlan_pcp != x.match.dl_vlan_pcp:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_DL_TYPE) == 0 \
-           and self.match.dl_type != x.match.dl_type:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_NW_TOS) == 0 \
-           and self.match.nw_tos != x.match.nw_tos:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_NW_PROTO) == 0 \
-           and self.match.nw_proto != x.match.nw_proto:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_NW_SRC_MASK) \
-               < ofp.OFPFW_NW_SRC_ALL:
-            m = ~((1 << ((self.match.wildcards & ofp.OFPFW_NW_SRC_MASK) \
-                         >> ofp.OFPFW_NW_SRC_SHIFT)) - 1)
-            if (self.match.nw_src & m) != (x.match.nw_src & m):
-                return False
-        if (self.match.wildcards & ofp.OFPFW_NW_DST_MASK) \
-               < ofp.OFPFW_NW_DST_ALL:
-            m = ~((1 << ((self.match.wildcards & ofp.OFPFW_NW_DST_MASK) \
-                         >> ofp.OFPFW_NW_DST_SHIFT)) - 1)
-            if (self.match.nw_dst & m) != (x.match.nw_dst & m):
-                return False
-        if (self.match.wildcards & ofp.OFPFW_TP_SRC) == 0 \
-           and self.match.tp_src != x.match.tp_src:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_TP_DST) == 0 \
-           and self.match.tp_dst != x.match.tp_dst:
-            return False
-        if self.idle_timeout != x.idle_timeout:
-            return False
-        if self.hard_timeout != x.hard_timeout:
-            return False
-        return self.actions == x.actions  # N.B. Action lists are ordered
-
-    def __str__(self):
-        result = "priority=%d" % self.priority
-        # TBD - Would be nice if ofp_match.show() was better behaved
-        # (no newlines), and more intuitive (things in hex where approprate), etc.
-        result = result + ", wildcards={"
-        sep = ""
-        for w in ofp.ofp_flow_wildcards_map:
-            if w == ofp.OFPFW_NW_SRC_SHIFT \
-               or w == ofp.OFPFW_NW_SRC_BITS \
-               or w == ofp.OFPFW_NW_SRC_ALL \
-               or w == ofp.OFPFW_NW_DST_SHIFT \
-               or w == ofp.OFPFW_NW_DST_BITS \
-               or w == ofp.OFPFW_NW_DST_ALL \
-               or w == ofp.OFPFW_ALL \
-               or self.match.wildcards & w == 0:
-                continue
-            if w == ofp.OFPFW_NW_SRC_MASK:
-                result = result + sep + "OFPFW_NW_SRC"
-            elif w == ofp.OFPFW_NW_DST_MASK:
-                result = result + sep + "OFPFW_NW_DST"
-            else:
-                result = result + sep + ofp.ofp_flow_wildcards_map[w]
-            sep = ", "
-        result = result +"}"
-        if (self.match.wildcards & ofp.OFPFW_IN_PORT) == 0:
-            result = result + (", in_port=%d" % (self.match.in_port))
-        if (self.match.wildcards & ofp.OFPFW_DL_SRC) == 0:
-            result = result + (", dl_src=%s" % (dl_addr_to_str(self.match.dl_src)))
-        if (self.match.wildcards & ofp.OFPFW_DL_DST) == 0:
-            result = result + (", dl_dst=%s" % (dl_addr_to_str(self.match.dl_dst)))
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN) == 0:
-            result = result + (", dl_vlan=%d" % (self.match.dl_vlan))
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN_PCP) == 0:
-            result = result + (", dl_vlan_pcp=%d" % (self.match.dl_vlan_pcp))
-        if (self.match.wildcards & ofp.OFPFW_DL_TYPE) == 0:
-            result = result + (", dl_type=0x%x" % (self.match.dl_type))
-        if (self.match.wildcards & ofp.OFPFW_NW_TOS) == 0:
-            result = result + (", nw_tos=0x%x" % (self.match.nw_tos))
-        if (self.match.wildcards & ofp.OFPFW_NW_PROTO) == 0:
-            result = result + (", nw_proto=%d" % (self.match.nw_proto))
-        n = (self.match.wildcards & ofp.OFPFW_NW_SRC_MASK) >> ofp.OFPFW_NW_SRC_SHIFT
-        if n < 32:
-            result = result + (", nw_src=%s" % (ip_addr_to_str(self.match.nw_src, n)))
-        n = (self.match.wildcards & ofp.OFPFW_NW_DST_MASK) >> ofp.OFPFW_NW_DST_SHIFT
-        if n < 32:
-            result = result + (", nw_dst=%s" % (ip_addr_to_str(self.match.nw_dst, n)))
-        if (self.match.wildcards & ofp.OFPFW_TP_SRC) == 0:
-            result = result + (", tp_src=%d" % self.match.tp_src)
-        if (self.match.wildcards & ofp.OFPFW_TP_DST) == 0:
-            result = result + (", tp_dst=%d" % self.match.tp_dst)
-        result = result + (", idle_timeout=%d" % self.idle_timeout)
-        result = result + (", hard_timeout=%d" % self.hard_timeout)
-        result = result + (", hard_timeout=%d" % self.hard_timeout)
-        for a in self.actions.actions:
-            result = result + (", action=%s" % ofp.ofp_action_type_map[a.type])
-            if a.type == ofp.OFPAT_OUTPUT:
-                result = result + ("(%d)" % (a.port))
-            elif a.type == ofp.OFPAT_SET_VLAN_VID:
-                result = result + ("(%d)" % (a.vlan_vid))
-            elif a.type == ofp.OFPAT_SET_VLAN_PCP:
-                result = result + ("(%d)" % (a.vlan_pcp))
-            elif a.type == ofp.OFPAT_SET_DL_SRC or a.type == ofp.OFPAT_SET_DL_DST:
-                result = result + ("(%s)" % (dl_addr_to_str(a.dl_addr)))
-            elif a.type == ofp.OFPAT_SET_NW_SRC or a.type == ofp.OFPAT_SET_NW_DST:
-                result = result + ("(%s)" % (ip_addr_to_str(a.nw_addr, None)))
-            elif a.type == ofp.OFPAT_SET_NW_TOS:
-                result = result + ("(0x%x)" % (a.nw_tos))
-            elif a.type == ofp.OFPAT_SET_TP_SRC or a.type == ofp.OFPAT_SET_TP_DST:
-                result = result + ("(%d)" % (a.tp_port))
-            elif a.type == ofp.OFPAT_ENQUEUE:
-                result = result + ("(port=%d,queue=%d)" % (a.port, a.queue_id))
-        return result
-
-    def rand(self, fi, valid_wildcards, valid_actions, valid_ports):
-        # Start with no wildcards, i.e. everything specified
-        self.match.wildcards = 0
-        
-        # Make approx. 1% of flows exact
-        exact = True if random.randint(1, 100) == 1 else False
-
-        # For each qualifier Q,
-        #   if (wildcarding is not supported for Q,
-        #       or an exact flow is specified
-        #       or a coin toss comes up heads), 
-        #      specify Q
-        #   else
-        #      wildcard Q
-
-        if (ofp.OFPFW_IN_PORT & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.in_port = rand_pick(valid_ports)
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_IN_PORT
-            
-        if (ofp.OFPFW_DL_DST & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.dl_dst = fi.rand_dl_addr()
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_DL_DST
-
-        if (ofp.OFPFW_DL_SRC & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.dl_src = fi.rand_dl_addr()
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_DL_SRC
-
-        if (ofp.OFPFW_DL_VLAN_PCP & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.dl_vlan_pcp = random.randint(0, (1 << 3) - 1)
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_DL_VLAN_PCP
-
-        if (ofp.OFPFW_DL_VLAN & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.dl_vlan = fi.rand_vlan()
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_DL_VLAN
-
-        if (ofp.OFPFW_DL_TYPE & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.dl_type = fi.rand_ethertype()
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_DL_TYPE
-
-        if exact:
-            n = 0
-        else:
-            n = (valid_wildcards & ofp.OFPFW_NW_SRC_MASK) \
-                >> ofp.OFPFW_NW_SRC_SHIFT
-            if n > 32:
-                n = 32
-            n = random.randint(0, n)
-        self.match.wildcards = self.match.wildcards \
-                               | (n << ofp.OFPFW_NW_SRC_SHIFT)
-        if n < 32:
-            self.match.nw_src    = fi.rand_ip_addr() & ~((1 << n) - 1)
-            # Specifying any IP address match other than all bits
-            # don't care requires that Ethertype is one of {IP, ARP}
-            self.match.dl_type   = rand_pick([0x0800, 0x0806])
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-
-        if exact:
-            n = 0
-        else:
-            n = (valid_wildcards & ofp.OFPFW_NW_DST_MASK) \
-                >> ofp.OFPFW_NW_DST_SHIFT
-            if n > 32:
-                n = 32
-            n = random.randint(0, n)
-        self.match.wildcards = self.match.wildcards \
-                               | (n << ofp.OFPFW_NW_DST_SHIFT)
-        if n < 32:
-            self.match.nw_dst    = fi.rand_ip_addr() & ~((1 << n) - 1)
-            # Specifying any IP address match other than all bits
-            # don't care requires that Ethertype is one of {IP, ARP}
-            self.match.dl_type   = rand_pick([0x0800, 0x0806])
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-
-        if (ofp.OFPFW_NW_TOS & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.nw_tos = fi.rand_ip_tos()
-            # Specifying a TOS value requires that Ethertype is IP
-            self.match.dl_type   = 0x0800
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_NW_TOS
-
-        if (ofp.OFPFW_NW_PROTO & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.nw_proto = fi.rand_ip_proto()
-            # Specifying an IP protocol requires that Ethertype is IP
-            self.match.dl_type   = 0x0800
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-        else:            
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_NW_PROTO
-            
-        if (ofp.OFPFW_TP_SRC & valid_wildcards) == 0 \
-           or exact\
-           or random.randint(1, 100) <= 50:
-            self.match.tp_src = fi.rand_l4_port()
-            # Specifying a L4 port requires that IP protcol is
-            # one of {ICMP, TCP, UDP}
-            self.match.nw_proto = rand_pick([1, 6, 17])
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_NW_PROTO
-            # Specifying a L4 port requirues that Ethertype is IP
-            self.match.dl_type   = 0x0800
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_TP_SRC
-
-        if (ofp.OFPFW_TP_DST & valid_wildcards) == 0 \
-           or exact \
-           or random.randint(1, 100) <= 50:
-            self.match.tp_dst = fi.rand_l4_port()
-            # Specifying a L4 port requires that IP protcol is
-            # one of {ICMP, TCP, UDP}
-            self.match.nw_proto = rand_pick([1, 6, 17])
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_NW_PROTO
-            # Specifying a L4 port requirues that Ethertype is IP
-            self.match.dl_type   = 0x0800
-            self.match.wildcards = self.match.wildcards & ~ofp.OFPFW_DL_TYPE
-        else:
-            self.match.wildcards = self.match.wildcards | ofp.OFPFW_TP_DST
-
-        # N.B. Don't make the timeout too short, else the flow might
-        # disappear before we get a chance to check for it.
-        t = random.randint(0, 65535)
-        self.idle_timeout = 0 if t < 60 else t
-        t = random.randint(0, 65535)
-        self.hard_timeout = 0 if t < 60 else t
-
-        # If nothing is wildcarded, it is an exact flow spec -- some switches
-        # (Open vSwitch, for one) *require* that exact flow specs have priority 65535.
-        self.priority = 65535 if self.match.wildcards == 0 else fi.rand_priority()
-
-        # Action lists are ordered, so pick an ordered random subset of
-        # supported actions
-        supported_actions = []
-        for a in all_actions_list:
-            if ((1 << a) & valid_actions) != 0:
-                supported_actions.append(a)
-
-        supported_actions = shuffle(supported_actions)
-        supported_actions \
-            = supported_actions[0 : random.randint(1, len(supported_actions))]
-
-        self.actions = action_list.action_list()
-        for a in supported_actions:
-            if a == ofp.OFPAT_OUTPUT:
-                # TBD - Output actions are clustered in list, spread them out?
-                port_idxs = shuffle(range(len(valid_ports)))
-                port_idxs = port_idxs[0 : random.randint(1, len(valid_ports))]
-                for pi in port_idxs:
-                    act = action.action_output()
-                    act.port = valid_ports[pi]
-                    self.actions.add(act)
-            elif a == ofp.OFPAT_SET_VLAN_VID:
-                act = action.action_set_vlan_vid()
-                act.vlan_vid = fi.rand_vlan()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_VLAN_PCP:
-                # TBD - Temporaily removed, broken in Indigo
-                #act = action.action_set_vlan_pcp()
-                #act.vlan_pcp = random.randint(0, (1 << 3) - 1)
-                pass
-            elif a == ofp.OFPAT_STRIP_VLAN:
-                act = action.action_strip_vlan()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_DL_SRC:
-                act = action.action_set_dl_src()
-                act.dl_addr = fi.rand_dl_addr()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_DL_DST:
-                act = action.action_set_dl_dst()
-                act.dl_addr = fi.rand_dl_addr()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_NW_SRC:
-                act = action.action_set_nw_src()
-                act.nw_addr = fi.rand_ip_addr()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_NW_DST:
-                act = action.action_set_nw_dst()
-                act.nw_addr = fi.rand_ip_addr()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_NW_TOS:
-                act = action.action_set_nw_tos()
-                act.nw_tos = fi.rand_ip_tos()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_TP_SRC:
-                act = action.action_set_tp_src()
-                act.tp_port = fi.rand_l4_port()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_SET_TP_DST:
-                act = action.action_set_tp_dst()
-                act.tp_port = fi.rand_l4_port()
-                self.actions.add(act)
-            elif a == ofp.OFPAT_ENQUEUE:
-                # TBD - Enqueue actions are clustered in list, spread them out?
-                port_idxs = shuffle(range(len(valid_ports)))
-                port_idxs = port_idxs[0 : random.randint(1, len(valid_ports))]
-                for pi in port_idxs:
-                    act = action.action_enqueue()
-                    act.port = valid_ports[pi]
-                    # TBD - Limits for queue number?
-                    act.queue_id = random.randint(0, 7)
-                    self.actions.add(act)
-
-        return self
-
-    # Overlap check
-    # delf == True <=> Check for delete overlap, else add overlap
-    # "Add overlap" is defined as there exists a packet that could match both the
-    # receiver and argument flowspecs
-    # "Delete overlap" is defined as the specificity of the argument flowspec
-    # is greater than or equal to the specificity of the receiver flowspec
-    def overlaps(self, x, delf):
-        if self.priority != x.priority:
-            return False
-        if (self.match.wildcards & ofp.OFPFW_IN_PORT) == 0:
-            if (x.match.wildcards & ofp.OFPFW_IN_PORT) == 0:
-                if self.match.in_port != x.match.in_port:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN) == 0:
-            if (x.match.wildcards & ofp.OFPFW_DL_VLAN) == 0:
-                if self.match.dl_vlan != x.match.dl_vlan:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_DL_SRC) == 0:
-            if (x.match.wildcards & ofp.OFPFW_DL_SRC) == 0:
-                if self.match.dl_src != x.match.dl_src:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_DL_DST) == 0:
-            if (x.match.wildcards & ofp.OFPFW_DL_DST) == 0:
-                if self.match.dl_dst != x.match.dl_dst:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_DL_TYPE) == 0:
-            if (x.match.wildcards & ofp.OFPFW_DL_TYPE) == 0:
-                if self.match.dl_type != x.match.dl_type:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Recevier more specific
-        if (self.match.wildcards & ofp.OFPFW_NW_PROTO) == 0:
-            if (x.match.wildcards & ofp.OFPFW_NW_PROTO) == 0:
-                if self.match.nw_proto != x.match.nw_proto:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_TP_SRC) == 0:
-            if (x.match.wildcards & ofp.OFPFW_TP_SRC) == 0:
-                if self.match.tp_src != x.match.tp_src:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_TP_DST) == 0:
-            if (x.match.wildcards & ofp.OFPFW_TP_DST) == 0:
-                if self.match.tp_dst != x.match.tp_dst:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        na = (self.match.wildcards & ofp.OFPFW_NW_SRC_MASK) \
-             >> ofp.OFPFW_NW_SRC_SHIFT
-        nb = (x.match.wildcards & ofp.OFPFW_NW_SRC_MASK) \
-             >> ofp.OFPFW_NW_SRC_SHIFT
-        if delf and na < nb:
-            return False                # Receiver more specific
-        if (na < 32 and nb < 32):
-            m = ~((1 << na) - 1) & ~((1 << nb) - 1)
-            if (self.match.nw_src & m) != (x.match.nw_src & m):
-                return False            # Overlapping bits not equal
-        na = (self.match.wildcards & ofp.OFPFW_NW_DST_MASK) \
-             >> ofp.OFPFW_NW_DST_SHIFT
-        nb = (x.match.wildcards & ofp.OFPFW_NW_DST_MASK) \
-             >> ofp.OFPFW_NW_DST_SHIFT
-        if delf and na < nb:
-            return False                # Receiver more specific
-        if (na < 32 and nb < 32):
-            m = ~((1 << na) - 1) & ~((1 << nb) - 1)
-            if (self.match.nw_dst & m) != (x.match.nw_dst & m):
-                return False            # Overlapping bit not equal
-        if (self.match.wildcards & ofp.OFPFW_DL_VLAN_PCP) == 0:
-            if (x.match.wildcards & ofp.OFPFW_DL_VLAN_PCP) == 0:
-                if self.match.dl_vlan_pcp != x.match.dl_vlan_pcp:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        if (self.match.wildcards & ofp.OFPFW_NW_TOS) == 0:
-            if (x.match.wildcards & ofp.OFPFW_NW_TOS) == 0:
-                if self.match.nw_tos != x.match.nw_tos:
-                    return False        # Both specified, and not equal
-            elif delf:
-                return False            # Receiver more specific
-        return True                     # Flows overlap
-
-    def to_flow_mod_msg(self, msg):
-        msg.match        = self.match
-        msg.idle_timeout = self.idle_timeout
-        msg.hard_timeout = self.hard_timeout
-        msg.priority     = self.priority
-        msg.actions      = self.actions
-        return msg
-
-    def from_flow_stat(self, msg):
-        self.match        = msg.match
-        self.idle_timeout = msg.idle_timeout
-        self.hard_timeout = msg.hard_timeout
-        self.priority     = msg.priority
-        self.actions      = msg.actions
-
-
-class FlowQuery(basic.SimpleProtocol):
-    """
-    """
-
-    def do_barrier(self):
-        barrier = message.barrier_request()
-        (resp, pkt) = self.controller.transact(barrier, 5)
-        self.assertTrue(resp is not None,
-                        "Did not receive response to barrier request"
-                        )
-    
-
-    def verify_flows(self,
-                     sw_features,
-                     tbl_flows,
-                     num_flows,
-                     overlapf,
-                     num_overlaps
-                     ):
-        result = True
-        
-        # Check number of flows reported in table stats
-
-        self.logger.debug("Verifying table stats reports correct number of")
-        self.logger.debug("  active flows")
-        request = message.table_stats_request()
-        (tbl_stats_after, pkt) = self.controller.transact(request, timeout=2)
-        self.assertTrue(tbl_stats_after is not None,
-                        "No reply to table_stats_request"
-                        )
-
-        num_flows_reported = 0
-        for ts in tbl_stats_after.stats:
-            num_flows_reported = num_flows_reported + ts.active_count
-
-        num_flows_expected = num_flows
-        if overlapf:
-            num_flows_expected = num_flows_expected - num_overlaps
-
-        self.logger.debug("Number of flows reported = "
-                          + str(num_flows_reported)
-                          )
-        self.logger.debug("Numer of flows expected = "
-                          + str(num_flows_expected)
-                          )
-        if num_flows_reported != num_flows_expected:
-            self.logger.error("Incorrect number of flows returned by table stats")
-            result = False
-
-        # Retrieve all flows from switch
-
-        self.logger.debug("Retrieving all flows from switch")
-        stat_req = message.flow_stats_request()
-        query_match           = ofp.ofp_match()
-        query_match.wildcards = ofp.OFPFW_ALL
-        stat_req.match    = query_match
-        stat_req.table_id = 0xff
-        stat_req.out_port = ofp.OFPP_NONE;
-        flow_stats, pkt = self.controller.transact(stat_req, timeout=2)
-        self.assertTrue(flow_stats is not None, "Get all flow stats failed")
-
-        # Verify retrieved flows
-
-        self.logger.debug("Verifying retrieved flows")
-
-        self.assertEqual(flow_stats.type,
-                         ofp.OFPST_FLOW,
-                         "Unexpected type of response message"
-                         )
-
-        num_flows_reported = len(flow_stats.stats)
-
-        self.logger.debug("Number of flows reported = "
-                          + str(num_flows_reported)
-                          )
-        self.logger.debug("Numer of flows expected = "
-                          + str(num_flows_expected)
-                          )
-        if num_flows_reported != num_flows_expected:
-            self.logger.error("Incorrect number of flows returned by table stats")
-            result = False
-
-        for f in tbl_flows:
-            f.resp_matched = False
-
-        num_resp_flows_matched = 0
-        for flow_stat in flow_stats.stats:
-            flow_in = flow_cfg()
-            flow_in.from_flow_stat(flow_stat)
-
-            matched = False
-            for f in tbl_flows:
-                if f.deleted:
-                    continue
-                if not f.resp_matched \
-                   and (not overlapf or not f.overlap) \
-                   and f == flow_in:
-                    f.resp_matched = True
-                    num_resp_flows_matched = num_resp_flows_matched + 1
-                    matched = True
-                    break
-            if not matched:
-                self.logger.error("Response flow")
-                self.logger.error(str(flow_in))
-                self.logger.error("does not match any configured flow")
-                result = False
-
-        self.logger.debug("Number of flows matched in response = "
-                          + str(num_resp_flows_matched)
-                          )
-        self.logger.debug("Number of flows expected = "
-                          + str(num_flows_expected)
-                          )
-        if num_resp_flows_matched != num_flows_expected:
-            for f in tbl_flows:
-                if not f.resp_matched:
-                    self.logger.error("Configured flow")
-                    self.logger.error("tbl_idx=%d, flow_idx=%d, %s" % (f.tbl_idx, f.flow_idx, str(f)))
-                    self.logger.error("missing in flow response")
-                    result = False
-
-        self.assertTrue(result, "Flow verification failed")
-
-    def flow_add(self, flow, overlapf):
-        flow_mod_msg = message.flow_mod()
-        flow_mod_msg.command     = ofp.OFPFC_ADD
-        flow_mod_msg.buffer_id   = 0xffffffff
-        flow_mod_msg.cookie      = random.randint(0, (1 << 53) - 1)
-        flow.to_flow_mod_msg(flow_mod_msg)
-        if overlapf:
-            flow_mod_msg.flags = flow_mod_msg.flags | ofp.OFPFF_CHECK_OVERLAP
-        self.logger.debug("Sending flow_mod(add) request to switch")
-        rv = self.controller.message_send(flow_mod_msg)
-        self.assertTrue(rv != -1, "Error installing flow mod")
-
-        # TBD - Don't poll for each error message
-        if flow.overlap:
-            self.logger.debug("Flow overlaps with tbl_idx=%d flow_idx=%d"
-                              % (flow.overlaps_with[0], flow.overlaps_with[1])
-                              )
-        else:
-            self.logger.debug("Flow does not overlap")
-        self.logger.debug("Checking for error response from switch")
-        (errmsg, pkt) = self.controller.poll(ofp.OFPT_ERROR, 1)
-        if errmsg is not None:
-            # Got ERROR message
-            self.logger.debug("Got ERROR message, type = "
-                              + str(errmsg.type)
-                              + ", code = "
-                              + str(errmsg.code)
-                              )
-            
-            if errmsg.type == ofp.OFPET_FLOW_MOD_FAILED \
-               and errmsg.code == ofp.OFPFMFC_OVERLAP:
-                # Got "overlap" ERROR message
-                self.logger.debug("ERROR is overlap")
-                
-                self.assertTrue(overlapf and flow.overlap,
-                                "Overlap not expected"
-                                )
-            else:
-                self.logger.debug("ERROR is not overlap")
-                self.assertTrue(False,
-                                "Unexpected error message")
-
-        else:
-            # Did not get ERROR message
-            self.logger.debug("No ERROR message received")
-            self.assertTrue(not (overlapf and flow.overlap),
-                            "Did not get expected OVERLAP"
-                            )
-
-
-    def flow_del(self, flow, strictf):
-        flow_mod_msg = message.flow_mod()
-        flow_mod_msg.command     = ofp.OFPFC_DELETE_STRICT \
-            if strictf else ofp.OFPFC_DELETE
-        flow_mod_msg.buffer_id   = 0xffffffff
-        flow_mod_msg.cookie      = random.randint(0, (1 << 53) - 1)
-        # TBD - Needs to be a test variable
-        flow_mod_msg.out_port    = ofp.OFPP_NONE
-        flow.to_flow_mod_msg(flow_mod_msg)
-        rv = self.controller.message_send(flow_mod_msg)
-        self.assertTrue(rv != -1, "Error installing flow mod")
-        # TBD - Don't poll for each error message
-        (errmsg, pkt) = self.controller.poll(ofp.OFPT_ERROR, 1)
-        if errmsg is not None:
-            # Got ERROR message
-            self.logger.debug("Got ERROR message, type = "
-                              + str(errmsg.type)
-                              + ", code = "
-                              + str(errmsg.code)
-                              )
-            self.assertTrue(False,
-                            "Unexpected error message"
-                            )
-
-
-    # Add flows to capacity, make sure they can be read back, and delete them
-
-    def test1(self,
-              overlapf,                 # True <=> When sending flow adds to
-                                        # switch, include the "check for
-                                        # overlap" flag, and verify that an
-                                        # error message is received
-                                        # if an overlapping flow is defined
-              strictf                   # True <=> When deleting flows, delete
-                                        # them strictly
-              ):
-        """
-        """
-
-        # Clear all flows from switch
-        self.logger.debug("Deleting all flows from switch")
-        rc = delete_all_flows(self.controller, pa_logger)
-        self.assertEqual(rc, 0, "Failed to delete all flows")
-
-        # Get valid port numbers
-        # Get number of tables supported
-        # Get actions supported by switch
-
-        self.logger.debug("Retrieving features from switch")
-        request = message.features_request()
-        (sw_features, pkt) = self.controller.transact(request, timeout=2)
-        self.assertTrue(sw_features is not None, "No reply to features_request")
-        self.logger.debug("Switch features -")
-        self.logger.debug("Number of tables: " + str(sw_features.n_tables))
-        self.logger.debug("Supported actions: " + hex(sw_features.actions))
-        self.logger.debug("Ports: "
-                          + str(map(lambda x: x.port_no, sw_features.ports))
-                          )
-
-        # For each table, get wildcards supported maximum number of flows
-
-        self.logger.debug("Retrieving table stats from switch")
-        request = message.table_stats_request()
-        (tbl_stats, pkt) = self.controller.transact(request, timeout=2)
-        self.assertTrue(tbl_stats is not None,
-                        "No reply to table_stats_request"
-                        )
-        active_count = 0
-        max_entries  = 0
-        tbl_idx = 0
-        while tbl_idx < sw_features.n_tables:
-            self.logger.debug("Table " + str(tbl_idx) + " - ")
-            self.logger.debug("Supported wildcards: "
-                              + hex(tbl_stats.stats[tbl_idx].wildcards)
-                              )
-            self.logger.debug("Max entries: "
-                              + str(tbl_stats.stats[tbl_idx].max_entries)
-                              )
-            self.logger.debug("Active count: "
-                              + str(tbl_stats.stats[tbl_idx].active_count)
-                              )
-            max_entries  = max_entries + tbl_stats.stats[tbl_idx].max_entries
-            active_count = active_count + tbl_stats.stats[tbl_idx].active_count
-            tbl_idx = tbl_idx + 1
-
-        self.logger.debug("Total active entries = "
-                          + str(active_count)
-                          )
-        self.assertEqual(active_count,
-                         0,
-                         "Delete all flows failed"
-                         )
-
-        # TBD - For testing only, since Open vSWitch reports
-        # ridiculously large capacity; remove
-        sw_features.n_tables = 1
-        tbl_stats.stats[0].max_entries = 10
-        max_entries = tbl_stats.stats[0].max_entries
-
-        # Dream up some flow information, i.e. space to chose from for
-        # random flow parameter generation
-        fi = flow_info()
-        n = int(math.log(max_entries))
-        if not overlapf:
-            # Generated space smaller when testing overlaps,
-            # to increase likelihood of some
-            n = 2 * n
-        fi.rand(n)
-
-        # For each table, think up flows to fill it
-
-        self.logger.debug("Creating flows")
-        num_flows = 0
-        num_overlaps = 0
-        tbl_flows = []
-        tbl_idx = 0
-
-        while tbl_idx < sw_features.n_tables:
-            flow_idx = 0
-            while flow_idx < tbl_stats.stats[tbl_idx].max_entries:
-                flow_out = flow_cfg()
-                if overlapf and num_flows == 1:
-                    # Make 2nd flow a copy of the first,
-                    # to guarantee at least 1 overlap
-                    flow_out = copy.deepcopy(tbl_flows[0])
-                    flow_out.overlap = True
-                    flow_out.overlaps_with = [0, 0]
-                    num_overlaps = num_overlaps + 1
-                else:
-                    flow_out.rand(fi,
-                                  tbl_stats.stats[tbl_idx].wildcards,
-                                  sw_features.actions,
-                                  map(lambda x: x.port_no, sw_features.ports)
-                                  )
-                    flow_out.overlap  = False
-                    
-                    for f in tbl_flows:
-                        if (not overlapf or not f.overlap) \
-                           and flow_out.overlaps(f, False):
-                            flow_out.overlap = True
-                            flow_out.overlaps_with = [f.tbl_idx, f.flow_idx]
-                            num_overlaps = num_overlaps + 1
-
-                flow_out.tbl_idx  = tbl_idx
-                flow_out.flow_idx = flow_idx
-
-                self.logger.debug("tbl_idx=%d, flow_idx=%d, %s" % (tbl_idx, flow_idx, str(flow_out)))
-
-                tbl_flows.append(flow_out)
-
-                num_flows = num_flows + 1
-                flow_idx = flow_idx + 1
-            tbl_idx = tbl_idx + 1
-
-        self.logger.debug("Created " + str(num_flows)
-                          + " flows, with " + str(num_overlaps)
-                          + " overlaps"
-                          )
-
-        # Send all flows to switch
-
-        self.logger.debug("Sending flows to switch")
-        for f in tbl_flows:
-            self.flow_add(f, overlapf)
-            f.deleted = False
-
-        # Send barrier, to make sure all flows are in
-        self.do_barrier()               
-
-        # Red back all flows from switch, and verify
-
-        self.verify_flows(sw_features,
-                          tbl_flows,
-                          num_flows,
-                          overlapf,
-                          num_overlaps
-                          )
-
-        # Delete a flows from switch
-
-        if strictf:
-            # Strict delete
-            
-            # Delete a few flows, in random order, individually (i.e. strictly)
-            
-            del_flow_idxs = shuffle(range(len(tbl_flows)))
-            # TBD - Limited, for testing only; remove
-            del_flow_idxs = del_flow_idxs[0 : random.randint(3, 3)]
-            for di in del_flow_idxs:
-                f = tbl_flows[di]
-                tbl_idx  = f.tbl_idx
-                flow_idx = f.flow_idx
-                if (overlapf and f.overlap):
-                    self.logger.debug("Flow tbl_idx = " + str(tbl_idx)
-                                      + ", flow_idx = " + str(flow_idx)
-                                      + " was an overlap, skipping delete"
-                                      )
-                else:
-                    self.logger.debug("Deleting flow, tbl_idx = "
-                                      + str(tbl_idx) + ", flow_idx = "
-                                      + str(flow_idx)
-                                      )
-                    self.flow_del(f, True)
-                    f.deleted = True
-                    num_flows = num_flows - 1
-
-            # Send barrier, to make sure all flows are deleted
-            self.do_barrier();
-
-            # Red back all flows from switch, and verify
-
-            self.verify_flows(sw_features,
-                              tbl_flows,
-                              num_flows,
-                              overlapf,
-                              num_overlaps
-                              )
-
-            # Delete all remaining flows, in random order,
-            # individually (i.e. strictly)
-            
-            del_flow_idxs = shuffle(range(len(tbl_flows)))
-            for di in del_flow_idxs:
-                f = tbl_flows[di]
-                if f.deleted:
-                    continue
-                tbl_idx  = f.tbl_idx
-                flow_idx = f.flow_idx
-                if (overlapf and f.overlap):
-                    self.logger.debug("Flow tbl_idx = "
-                                      + str(tbl_idx)
-                                      + ", flow_idx = "
-                                      + str(flow_idx)
-                                      + " was an overlap, skipping delete"
-                                      )
-                else:
-                    self.logger.debug("Deleting flow, tbl_idx = "
-                                      + str(tbl_idx)
-                                      + ", flow_idx = "
-                                      + str(flow_idx)
-                                      )
-                    self.flow_del(f, True)
-                    f.deleted = True
-                    num_flows = num_flows - 1
-
-            # Send barrier, to make sure all flows are deleted
-            self.do_barrier()
-            
-            # Red back all flows from switch (i.e. none), and verify
-            
-            self.verify_flows(sw_features,
-                              tbl_flows,
-                              num_flows,
-                              overlapf,
-                              num_overlaps
-                              )
-
-        else:
-            # Non-strict delete
-
-            # Pick a flow at random that had at least 1 qualifier specified,
-            # wildcard a qualifier that was specified,
-            # and do a non-strict delete
-            # Keep wildcarding specified qualifiers, one by one, and deleteing,
-            # until everything is wildcarded,
-            # and hence all flows should be deleted
-
-            while True:
-                f = tbl_flows[random.randint(0, len(tbl_flows) - 1)]
-                if f.match.wildcards != tbl_stats.stats[f.tbl_idx].wildcards:
-                    self.logger.debug("Choosing flow for basis of non-strict delete")
-                    self.logger.debug("  tbl_idx=%d flow_idx=%d" % (f.tbl_idx, f.flow_idx))
-                    self.logger.debug("  " + str(f))
-                    break
-
-            # For each qualifier, in random order, if it was specified,
-            # wildcard it, do a delete, and check the results
-                
-            wildcard_idxs = shuffle(range(len(all_wildcards_list)))
-            for wi in wildcard_idxs:
-                w = all_wildcards_list[wi]
-                if (f.match.wildcards & w) != 0:
-                    continue
-
-                if w ==  ofp.OFPFW_NW_SRC_MASK:
-                    f.match.wildcards = (f.match.wildcards
-                                         & ~ofp.OFPFW_NW_SRC_MASK
-                                         ) \
-                                        | ofp.OFPFW_NW_SRC_ALL
-                    wn = "OFPFW_NW_SRC"
-                elif w ==  ofp.OFPFW_NW_DST_MASK:
-                    f.match.wildcards = (f.match.wildcards
-                                         & ~ofp.OFPFW_NW_DST_MASK
-                                         ) \
-                                        | ofp.OFPFW_NW_DST_ALL
-                    wn = "OFPFW_NW_DST"
-                else:
-                    f.match.wildcards = f.match.wildcards | w
-                    wn = ofp.ofp_flow_wildcards_map[w]
-
-                self.logger.debug("Adding wildcard %s" % (wn))
-                self.logger.debug(str(f))
-
-                # Mark all flows which would be deleted by this
-                # non-strict delete
-                
-                for ff in tbl_flows:
-                    if not ff.deleted and f.overlaps(ff, True):
-                        self.logger.debug("Deleting flow, tbl_idx = "
-                                          + str(ff.tbl_idx) + ", flow_idx = "
-                                          + str(ff.flow_idx)
-                                          )
-                        ff.deleted = True
-                        num_flows = num_flows - 1
-                        
-                self.flow_del(f, False)
-                
-                # Send barrier, to make sure all flows are deleted
-                self.do_barrier()
-                
-                # Red back all flows from switch, and verify
-                
-                self.verify_flows(sw_features,
-                                  tbl_flows,
-                                  num_flows,
-                                  overlapf,
-                                  num_overlaps
-                                  )
-
-
-
-    def runTest(self):
-        """
-        Run all tests
-        """
-
-        self.test1(False, True)         # Test with no overlaps, strict delete
-        self.test1(True,  True)         # Test with overlaps, strict delete
-#        self.test1(False, False)        # Test with no overlaps, non-strict delete
-#        self.test1(True,  False)        # Test with overlaps, non-strict delete
-