Added some more test parameters, for:
(1) overriding the list of valid ports returned by the switch,
(2) forcing certain wildcards to be used, and
(3) forcing certain actions to be used.
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 0538365..a79c9f9 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -13,12 +13,30 @@
 # Overrides bitmap of supported wildcards reported by switch
 # Default: none
 #
+# Name: wildcards_force
+# Type: number
+# Description:
+# Bitmap of wildcards to always be set
+# Default: none
+#
 # Name: actions
 # Type: number
 # Description:
 # Overrides bitmap of supported actions reported by switch
 # Default: none
 #
+# Name: actions_force
+# Type: number
+# Description:
+# Bitmap of actions to always be used
+# Default: none
+#
+# Name: ports
+# Type: list of OF port numbers
+# Description:
+# Override list of OF port numbers reported by switch
+# Default: none
+#
 # Name: conservative_ordered_actions
 # Type: boolean (True or False)
 # Description:
@@ -469,18 +487,26 @@
     def rand_actions_ordered(self, fi, valid_actions, valid_ports):
         # Action lists are ordered, so pick an ordered random subset of
         # supported actions
+
+        actions_force = test_param_get(fq_config, "actions_force", 0)
+
         ACTION_MAX_LEN = 65535 # @fixme Should be test param?
         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))]
+        actions \
+            = shuffle(supported_actions)[0 : random.randint(1, len(supported_actions))]
+
+        for a in all_actions_list:
+            if ((1 << a) & actions_force) != 0:
+                actions.append(a)
+
+        actions = shuffle(actions)
 
         self.actions = action_list.action_list()
-        for a in supported_actions:
+        for a in actions:
             act = None
             if a == ofp.OFPAT_OUTPUT:
                 pass                    # OUTPUT actions must come last
@@ -520,8 +546,10 @@
                 self.actions.add(act)
                 
         p = random.randint(1, 100)
-        if p <= 33 and ofp.OFPAT_ENQUEUE in supported_actions:
-            # One third of the time, include ENQUEUE actions at end of list
+        if (((1 << ofp.OFPAT_ENQUEUE) & actions_force) != 0 or p <= 33) \
+               and ofp.OFPAT_ENQUEUE in actions:
+            # In not forecd, one third of the time, include ENQUEUE actions
+            # at end of list
             # At most 1 ENQUEUE action
             act = action.action_enqueue()
             act.port = rand_pick(valid_ports)
@@ -529,7 +557,10 @@
             act.queue_id = random.randint(0, 7)
             act.max_len = ACTION_MAX_LEN
             self.actions.add(act)
-        if p > 33 and p <= 66 and ofp.OFPAT_OUTPUT in supported_actions:
+        if (((1 << ofp.OFPAT_OUTPUT) & actions_force) != 0 \
+            or (p > 33 and p <= 66) \
+            ) \
+            and ofp.OFPAT_OUTPUT in actions:
             # One third of the time, include OUTPUT actions at end of list
             port_idxs = shuffle(range(len(valid_ports)))
             # Only 1 output action allowed if IN_PORT wildcarded
@@ -559,19 +590,25 @@
             self.rand_actions_ordered(fi, valid_actions, valid_ports)
             return self
 
-        # Action lists are ordered, so pick an ordered random subset of
-        # supported actions
+        actions_force = test_param_get(fq_config, "actions_force", 0)
+
+        ACTION_MAX_LEN = 65535 # @fixme Should be test param?
         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))]
+        actions \
+            = shuffle(supported_actions)[0 : random.randint(1, len(supported_actions))]
+
+        for a in all_actions_list:
+            if ((1 << a) & actions_force) != 0:
+                actions.append(a)
+
+        actions = shuffle(actions)
 
         self.actions = action_list.action_list()
-        for a in supported_actions:
+        for a in actions:
             if a == ofp.OFPAT_OUTPUT:
                 # TBD - Output actions are clustered in list, spread them out?
                 port_idxs = shuffle(range(len(valid_ports)))
@@ -633,11 +670,16 @@
 
     # Randomize flow cfg
     def rand(self, fi, valid_wildcards, valid_actions, valid_ports):
+        wildcards_force = test_param_get(fq_config, "wildcards_force", 0)
+        
         # Start with no wildcards, i.e. everything specified
         self.match.wildcards = 0
-        
-        # Make approx. 5% of flows exact
-        exact = (random.randint(1, 100) <= 5)
+
+        if wildcards_force != 0:
+            exact = False
+        else:
+            # Make approx. 5% of flows exact
+            exact = (random.randint(1, 100) <= 5)
 
         # For each qualifier Q,
         #   if (wildcarding is not supported for Q,
@@ -647,9 +689,11 @@
         #   else
         #      wildcard Q
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_IN_PORT) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_IN_PORT) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_IN_PORT) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.in_port = rand_pick(valid_ports)
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, \
@@ -657,9 +701,11 @@
                                                 1 \
                                                 )
             
-        if wildcard_get(valid_wildcards, ofp.OFPFW_DL_DST) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_DL_DST) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_DL_DST) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.dl_dst = fi.rand_dl_addr()
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, \
@@ -667,9 +713,11 @@
                                                 1 \
                                                 )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_DL_SRC) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_DL_SRC) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_DL_SRC) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.dl_src = fi.rand_dl_addr()
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, \
@@ -677,19 +725,11 @@
                                                 1 \
                                                 )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_DL_VLAN_PCP) == 0 \
-           or exact \
-           or flip_coin():
-            self.match.dl_vlan_pcp = random.randint(0, (1 << 3) - 1)
-        else:
-            self.match.wildcards = wildcard_set(self.match.wildcards, \
-                                                ofp.OFPFW_DL_VLAN_PCP, \
-                                                1 \
-                                                )
-
-        if wildcard_get(valid_wildcards, ofp.OFPFW_DL_VLAN) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_DL_VLAN) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_DL_VLAN) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.dl_vlan = fi.rand_vlan()
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, \
@@ -697,9 +737,23 @@
                                                 1 \
                                                 )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_DL_TYPE) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_DL_VLAN_PCP) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_DL_VLAN_PCP) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
+            self.match.dl_vlan_pcp = random.randint(0, (1 << 3) - 1)
+        else:
+            self.match.wildcards = wildcard_set(self.match.wildcards, \
+                                                ofp.OFPFW_DL_VLAN_PCP, \
+                                                1 \
+                                                )
+
+        if wildcard_get(wildcards_force, ofp.OFPFW_DL_TYPE) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_DL_TYPE) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.dl_type = fi.rand_ethertype()
         else:
             self.match.wildcards = wildcard_set(self.match.wildcards, \
@@ -707,13 +761,15 @@
                                                 1 \
                                                 )
 
-        if exact or flip_coin():
-            n = 0
-        else:
-            n = wildcard_get(valid_wildcards, ofp.OFPFW_NW_SRC_MASK)
-            if n > 32:
-                n = 32
-            n = random.randint(0, n)
+        n = wildcard_get(wildcards_force, ofp.OFPFW_NW_SRC_MASK)
+        if n == 0:
+            if exact or flip_coin():
+                n = 0
+            else:
+                n = wildcard_get(valid_wildcards, ofp.OFPFW_NW_SRC_MASK)
+                if n > 32:
+                    n = 32
+                n = random.randint(0, n)
         self.match.wildcards = wildcard_set(self.match.wildcards, \
                                             ofp.OFPFW_NW_SRC_MASK, \
                                             n \
@@ -729,13 +785,15 @@
                                                     0 \
                                                     )
 
-        if exact or flip_coin():
-            n = 0
-        else:
-            n = wildcard_get(valid_wildcards, ofp.OFPFW_NW_DST_MASK)
-            if n > 32:
-                n = 32
-            n = random.randint(0, n)
+        n = wildcard_get(wildcards_force, ofp.OFPFW_NW_DST_MASK)
+        if n == 0:
+            if exact or flip_coin():
+                n = 0
+            else:
+                n = wildcard_get(valid_wildcards, ofp.OFPFW_NW_DST_MASK)
+                if n > 32:
+                    n = 32
+                n = random.randint(0, n)
         self.match.wildcards = wildcard_set(self.match.wildcards, \
                                             ofp.OFPFW_NW_DST_MASK, \
                                             n \
@@ -751,9 +809,11 @@
                                                     0 \
                                                     )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_NW_TOS) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_NW_TOS) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_NW_TOS) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.nw_tos = fi.rand_ip_tos()
             # Specifying a TOS value requires that Ethertype is IP
             if flip_coin():
@@ -769,9 +829,11 @@
                                                 )
 
         # Known issue on OVS with specifying nw_proto w/o dl_type as IP
-        if wildcard_get(valid_wildcards, ofp.OFPFW_NW_PROTO) == 0 \
-               or exact \
-               or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_NW_PROTO) == 0 \
+               and (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():
@@ -786,9 +848,11 @@
                                                 1 \
                                                 )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_TP_SRC) == 0 \
-           or exact\
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_TP_SRC) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_TP_SRC) == 0 \
+                    or exact\
+                    or flip_coin() \
+                    ):
             self.match.tp_src = fi.rand_l4_port()
             # Specifying a L4 port requires that IP protcol is
             # one of {ICMP, TCP, UDP}
@@ -812,9 +876,11 @@
                                                 1 \
                                                 )
 
-        if wildcard_get(valid_wildcards, ofp.OFPFW_TP_DST) == 0 \
-           or exact \
-           or flip_coin():
+        if wildcard_get(wildcards_force, ofp.OFPFW_TP_DST) == 0 \
+               and (wildcard_get(valid_wildcards, ofp.OFPFW_TP_DST) == 0 \
+                    or exact \
+                    or flip_coin() \
+                    ):
             self.match.tp_dst = fi.rand_l4_port()
             # Specifying a L4 port requires that IP protcol is
             # one of {ICMP, TCP, UDP}
@@ -1156,6 +1222,9 @@
         actions_override = test_param_get(fq_config, "actions", -1)
         if actions_override != -1:
             self.sw_features.actions = actions_override
+        ports_override = test_param_get(fq_config, "ports", [])
+        if ports_override != []:
+            self.valid_ports = ports_override
 
         return True
 
@@ -1171,7 +1240,7 @@
                 ts.wildcards = wildcards_override
         return True
 
-    def flow_stats_get(self):
+    def flow_stats_get(self, limit = 10000):
         request = message.flow_stats_request()
         query_match           = ofp.ofp_match()
         query_match.wildcards = ofp.OFPFW_ALL
@@ -1187,15 +1256,19 @@
         # </TBD>
         n = 0
         while True:
-            # TBD - Check for "more" flag
             (resp, pkt) = self.controller.poll(ofp.OFPT_STATS_REPLY, 4)
             if resp is None:
-                break
+                return False            # Did not get expected response
             if n == 0:
                 self.flow_stats = resp
             else:
                 self.flow_stats.stats.extend(resp.stats)
             n = n + 1
+            if len(self.flow_stats.stats) > limit:
+                fq_logger.error("Too many flows returned")
+                return False
+            if (resp.flags & 1) == 0:
+                break                   # No more responses expected
         return (n > 0)
 
     def flow_add(self, flow_cfg, overlapf = False):
@@ -1208,7 +1281,9 @@
         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.debug("Sending flow_mod(add), xid=%d" % (flow_mod_msg.header.xid))
+        fq_logger.debug("Sending flow_mod(add), xid=%d"
+                        % (flow_mod_msg.header.xid)
+                        )
         return (self.controller.message_send(flow_mod_msg) != -1)
 
     def flow_mod(self, flow_cfg, strictf):
@@ -1218,7 +1293,9 @@
         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.debug("Sending flow_mod(mod), xid=%d" % (flow_mod_msg.header.xid))
+        fq_logger.debug("Sending flow_mod(mod), xid=%d"
+                        % (flow_mod_msg.header.xid)
+                        )
         return (self.controller.message_send(flow_mod_msg) != -1)
 
     def flow_del(self, flow_cfg, strictf):
@@ -1230,7 +1307,9 @@
         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.debug("Sending flow_mod(del), xid=%d" % (flow_mod_msg.header.xid))
+        fq_logger.debug("Sending flow_mod(del), xid=%d"
+                        % (flow_mod_msg.header.xid)
+                        )
         return (self.controller.message_send(flow_mod_msg) != -1)
 
     def barrier(self):
diff --git a/tests/pktact.py b/tests/pktact.py
index 74c0bad..222317f 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -1048,6 +1048,27 @@
         flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
                         action_list=[vid_act])
 
+class ModifyVlanPcp(BaseMatchCase):
+    """
+    Modify the priority field of the VLAN tag of a tagged packet
+    """
+    def runTest(self):
+        vid          = 123
+        old_vlan_pcp = 2
+        new_vlan_pcp = 3
+        sup_acts = supported_actions_get(self)
+        if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
+            skip_message_emit(self, "Modify VLAN tag test")
+            return
+
+        pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
+        exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
+        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,
+                        action_list=[vid_act])
+
 class StripVLANTag(BaseMatchCase):
     """
     Strip the VLAN tag from a tagged packet