Updated with Argon-isms
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 37f9adc..9183ab2 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -1,7 +1,8 @@
"""
Flow query test case.
-Attempts to fill switch to capacity with randomized flows, and ensure that they all are read back correctly.
+Attempts to fill switch to capacity with randomized flows, and ensure that
+they all are read back correctly.
"""
import math
@@ -55,7 +56,8 @@
# 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.
+ # Disable this test by default, since the flow capacity
+ # reported by OVS is bogus.
test_prio["Flow_Add_6"] = -1
@@ -206,7 +208,8 @@
ofp.OFPFW_TP_DST
]
-# TBD - Need this because there are duplicates in ofp.ofp_flow_wildcards_map -- FIX
+# TBD - Need this because there are duplicates in ofp.ofp_flow_wildcards_map
+# -- FIX
all_wildcard_names = {
1 : 'OFPFW_IN_PORT',
2 : 'OFPFW_DL_VLAN',
@@ -224,9 +227,11 @@
def wildcard_set(x, w, val):
result = x
if w == ofp.OFPFW_NW_SRC_MASK:
- result = (result & ~ofp.OFPFW_NW_SRC_MASK) | (val << ofp.OFPFW_NW_SRC_SHIFT)
+ result = (result & ~ofp.OFPFW_NW_SRC_MASK) \
+ | (val << ofp.OFPFW_NW_SRC_SHIFT)
elif w == ofp.OFPFW_NW_DST_MASK:
- result = (result & ~ofp.OFPFW_NW_DST_MASK) | (val << ofp.OFPFW_NW_DST_SHIFT)
+ result = (result & ~ofp.OFPFW_NW_DST_MASK) \
+ | (val << ofp.OFPFW_NW_DST_SHIFT)
elif val == 0:
result = result & ~w
else:
@@ -344,7 +349,9 @@
if self.hard_timeout != x.hard_timeout:
return False
if test_param_get(pa_config, "dut", "") == "argon":
- # Compare actions lists as unordered, since Argon may re-order action lists.
+ pa_logger.debug("Doing argon-style action comparison")
+ # 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:
@@ -385,9 +392,13 @@
if wildcard_get(self.match.wildcards, ofp.OFPFW_IN_PORT) == 0:
result = result + (", in_port=%d" % (self.match.in_port))
if wildcard_get(self.match.wildcards, ofp.OFPFW_DL_DST) == 0:
- result = result + (", dl_dst=%s" % (dl_addr_to_str(self.match.dl_dst)))
+ result = result + (", dl_dst=%s" \
+ % (dl_addr_to_str(self.match.dl_dst)) \
+ )
if wildcard_get(self.match.wildcards, ofp.OFPFW_DL_SRC) == 0:
- result = result + (", dl_src=%s" % (dl_addr_to_str(self.match.dl_src)))
+ result = result + (", dl_src=%s" \
+ % (dl_addr_to_str(self.match.dl_src)) \
+ )
if wildcard_get(self.match.wildcards, ofp.OFPFW_DL_VLAN) == 0:
result = result + (", dl_vlan=%d" % (self.match.dl_vlan))
if wildcard_get(self.match.wildcards, ofp.OFPFW_DL_VLAN_PCP) == 0:
@@ -400,10 +411,14 @@
result = result + (", nw_proto=%d" % (self.match.nw_proto))
n = wildcard_get(self.match.wildcards, ofp.OFPFW_NW_SRC_MASK)
if n < 32:
- result = result + (", nw_src=%s" % (ip_addr_to_str(self.match.nw_src, 32 - n)))
+ result = result + (", nw_src=%s" % \
+ (ip_addr_to_str(self.match.nw_src, 32 - n)) \
+ )
n = wildcard_get(self.match.wildcards, ofp.OFPFW_NW_DST_MASK)
if n < 32:
- result = result + (", nw_dst=%s" % (ip_addr_to_str(self.match.nw_dst, 32 - n)))
+ result = result + (", nw_dst=%s" % \
+ (ip_addr_to_str(self.match.nw_dst, 32 - n)) \
+ )
if wildcard_get(self.match.wildcards, ofp.OFPFW_TP_SRC) == 0:
result = result + (", tp_src=%d" % self.match.tp_src)
if wildcard_get(self.match.wildcards, ofp.OFPFW_TP_DST) == 0:
@@ -438,10 +453,116 @@
result = result + ("(port=%d,queue=%d)" % (a.port, a.queue_id))
return result
- # Randomize flow data for flow modifies
+ def rand_actions_argon(self, fi, valid_actions, valid_ports):
+ # 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))]
+
+ # The setting of max_len to 65535 is a hack, since that's what's
+ # returned by Argon for all actions (for now...)
+
+ self.actions = action_list.action_list()
+ for a in supported_actions:
+ if a == ofp.OFPAT_OUTPUT:
+ pass # OUTPUT actions must come last
+ elif a == ofp.OFPAT_SET_VLAN_VID:
+ act = action.action_set_vlan_vid()
+ act.vlan_vid = fi.rand_vlan()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_VLAN_PCP:
+ act = action.action_set_vlan_pcp()
+ act.vlan_pcp = random.randint(0, (1 << 3) - 1)
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_STRIP_VLAN:
+ act = action.action_strip_vlan()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_DL_SRC:
+ act = action.action_set_dl_src()
+ act.dl_addr = fi.rand_dl_addr()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_DL_DST:
+ act = action.action_set_dl_dst()
+ act.dl_addr = fi.rand_dl_addr()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_NW_SRC:
+ act = action.action_set_nw_src()
+ act.nw_addr = fi.rand_ip_addr()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_NW_DST:
+ act = action.action_set_nw_dst()
+ act.nw_addr = fi.rand_ip_addr()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_NW_TOS:
+ act = action.action_set_nw_tos()
+ act.nw_tos = fi.rand_ip_tos()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_TP_SRC:
+ act = action.action_set_tp_src()
+ act.tp_port = fi.rand_l4_port()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_SET_TP_DST:
+ act = action.action_set_tp_dst()
+ act.tp_port = fi.rand_l4_port()
+ act.max_len = 65535
+ self.actions.add(act)
+ elif a == ofp.OFPAT_ENQUEUE:
+ pass # Enqueue actions must come last
+
+ p = random.randint(1, 100)
+ if p <= 33:
+ # 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)
+ # TBD - Limits for queue number?
+ act.queue_id = random.randint(0, 7)
+ act.max_len = 65535
+ self.actions.add(act)
+ elif p <= 66:
+ # 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
+ n = 1 if wildcard_get(self.match.wildcards, ofp.OFPFW_IN_PORT) != 0 \
+ else random.randint(1, len(valid_ports))
+ port_idxs = port_idxs[0 : n]
+ for pi in port_idxs:
+ act = action.action_output()
+ act.port = valid_ports[pi]
+ act.max_len = 65535
+ if act.port != ofp.OFPP_IN_PORT \
+ or wildcard_get(self.match.wildcards, ofp.OFPFW_IN_PORT) == 0:
+ # OUTPUT(IN_PORT) only valid if OFPFW_IN_PORT not wildcarded
+ self.actions.add(act)
+ else:
+ # One third of the time, include neither
+ pass
+
+
+ # Randomize flow data for flow modifies (i.e. cookie and actions)
def rand_mod(self, fi, valid_actions, valid_ports):
self.cookie = random.randint(0, (1 << 53) - 1)
+ if test_param_get(pa_config, "dut", "") == "argon":
+ pa_logger.debug("Generating actions for argon")
+ self.rand_actions_argon(fi, valid_actions, valid_ports)
+ return self
+
# Action lists are ordered, so pick an ordered random subset of
# supported actions
supported_actions = []
@@ -469,6 +590,8 @@
self.actions.add(act)
elif a == ofp.OFPAT_SET_VLAN_PCP:
if test_param_get(pa_config, "dut", "") == "indigo":
+ pa_logger.debug("OFPAT_SET_VLAN_PCP broken on indigo")
+ pa_logger.debug("not using")
# Temporaily removed, broken in Indigo
pass
else:
@@ -539,42 +662,60 @@
or flip_coin():
self.match.in_port = rand_pick(valid_ports)
else:
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_IN_PORT, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_IN_PORT, \
+ 1 \
+ )
if 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, ofp.OFPFW_DL_DST, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_DST, \
+ 1 \
+ )
if 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, ofp.OFPFW_DL_SRC, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_SRC, \
+ 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)
+ 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():
self.match.dl_vlan = fi.rand_vlan()
else:
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_VLAN, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_VLAN, \
+ 1 \
+ )
if 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, ofp.OFPFW_DL_TYPE, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_TYPE, \
+ 1 \
+ )
if exact or flip_coin():
n = 0
@@ -583,14 +724,20 @@
if n > 32:
n = 32
n = random.randint(0, n)
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_SRC_MASK, n)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_NW_SRC_MASK, \
+ n \
+ )
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}
if flip_coin():
self.match.dl_type = rand_pick([0x0800, 0x0806])
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_TYPE, \
+ 0 \
+ )
if exact or flip_coin():
n = 0
@@ -599,14 +746,20 @@
if n > 32:
n = 32
n = random.randint(0, n)
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_DST_MASK, n)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_NW_DST_MASK, \
+ n \
+ )
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}
if flip_coin():
self.match.dl_type = rand_pick([0x0800, 0x0806])
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_TYPE, \
+ 0 \
+ )
if wildcard_get(valid_wildcards, ofp.OFPFW_NW_TOS) == 0 \
or exact \
@@ -615,15 +768,26 @@
# Specifying a TOS value 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)
+ 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_TOS, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_NW_TOS, \
+ 1 \
+ )
if test_param_get(pa_config, "dut", "") == "ovs":
+ pa_logger.debug("Flow canonicalization broken")
+ pa_logger.debug("for OFPFW_NW_PROTO on ovs, always wildcarding")
# 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)
+ # 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 \
@@ -632,9 +796,15 @@
# 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)
+ 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)
+ 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\
@@ -644,14 +814,23 @@
# one of {ICMP, TCP, UDP}
if flip_coin():
self.match.nw_proto = rand_pick([1, 6, 17])
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_PROTO, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_NW_PROTO, \
+ 0 \
+ )
# Specifying a L4 port requirues that Ethertype is IP
self.match.dl_type = 0x0800
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_TYPE, \
+ 0 \
+ )
if self.match.nw_proto == 1:
self.match.tp_src = self.match.tp_src & 0xff
else:
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_TP_SRC, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_TP_SRC, \
+ 1 \
+ )
if wildcard_get(valid_wildcards, ofp.OFPFW_TP_DST) == 0 \
or exact \
@@ -661,18 +840,29 @@
# one of {ICMP, TCP, UDP}
if flip_coin():
self.match.nw_proto = rand_pick([1, 6, 17])
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_NW_PROTO, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_NW_PROTO, \
+ 0 \
+ )
# Specifying a L4 port requirues that Ethertype is IP
self.match.dl_type = 0x0800
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_DL_TYPE, 0)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_DL_TYPE, \
+ 0 \
+ )
if self.match.nw_proto == 1:
self.match.tp_dst = self.match.tp_dst & 0xff
else:
- self.match.wildcards = wildcard_set(self.match.wildcards, ofp.OFPFW_TP_DST, 1)
+ self.match.wildcards = wildcard_set(self.match.wildcards, \
+ ofp.OFPFW_TP_DST, \
+ 1 \
+ )
# 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()
+ # (Open vSwitch, for one) *require* that exact flow specs
+ # have priority 65535.
+ self.priority = 65535 if self.match.wildcards == 0 \
+ else fi.rand_priority()
# N.B. Don't make the timeout too short, else the flow might
# disappear before we get a chance to check for it.
@@ -686,30 +876,59 @@
return self
# Return flow cfg in canonical form
- # - There are dependencies between flow qualifiers, e.g. it only makes sense to qualify nw_proto if dl_type is qualified to be 0x0800 (IP).
- # The canonical form of flow match criteria will "wildcard out" all such cases.
+ # - There are dependencies between flow qualifiers, e.g. it only makes
+ # sense to qualify nw_proto if dl_type is qualified to be 0x0800 (IP).
+ # The canonical form of flow match criteria will "wildcard out"
+ # all such cases.
def canonical(self):
result = copy.deepcopy(self)
if wildcard_get(result.match.wildcards, ofp.OFPFW_DL_TYPE) != 0 \
or result.match.dl_type not in [0x0800, 0x0806]:
- # dl_tyoe is wildcarded, or specified as something other than IP or ARP
+ # dl_tyoe is wildcarded, or specified as something other
+ # than IP or ARP
# => nw_src and nw_dst cannot be specified, must be wildcarded
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_NW_SRC_MASK, 32)
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_NW_DST_MASK, 32)
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_NW_SRC_MASK, \
+ 32 \
+ )
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_NW_DST_MASK, \
+ 32 \
+ )
if wildcard_get(result.match.wildcards, ofp.OFPFW_DL_TYPE) != 0 \
or result.match.dl_type != 0x0800:
# dl_type is wildcarded, or specified as something other than IP
- # => nw_proto, nw_tos, tp_src and tp_dst cannot be specified, must be wildcarded
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_NW_PROTO, 1)
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_NW_TOS, 1)
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_TP_SRC, 1)
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_TP_DST, 1)
+ # => nw_proto, nw_tos, tp_src and tp_dst cannot be specified,
+ # must be wildcarded
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_NW_PROTO, \
+ 1 \
+ )
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_NW_TOS, \
+ 1 \
+ )
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_TP_SRC, \
+ 1 \
+ )
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_TP_DST, \
+ 1 \
+ )
if wildcard_get(result.match.wildcards, ofp.OFPFW_NW_PROTO) != 0 \
or result.match.nw_proto not in [1, 6, 17]:
- # nw_proto is wildcarded, or specified as something other than ICMP, TCP or UDP
+ # nw_proto is wildcarded, or specified as something other than ICMP,
+ # TCP or UDP
# => tp_src and tp_dst cannot be specified, must be wildcarded
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_TP_SRC, 1)
- result.match.wildcards = wildcard_set(result.match.wildcards, ofp.OFPFW_TP_DST, 1)
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_TP_SRC, \
+ 1 \
+ )
+ result.match.wildcards = wildcard_set(result.match.wildcards, \
+ ofp.OFPFW_TP_DST, \
+ 1 \
+ )
return result
# Overlap check
@@ -866,6 +1085,23 @@
j = 0
+error_msgs = []
+removed_msgs = []
+
+def error_handler(self, msg, rawmsg):
+ pa_logger.debug("Got an ERROR message, type=%d, code=%d" \
+ % (msg.type, msg.code) \
+ )
+ global error_msgs
+ error_msgs.append(msg)
+ pass
+
+def removed_handler(self, msg, rawmsg):
+ pa_logger.debug("Got a REMOVED message")
+ global removed_msgs
+ removed_msgs.append(msg)
+ pass
+
class Switch:
# Members:
# controller - switch's test controller
@@ -883,6 +1119,14 @@
self.flow_stats = None
self.flow_tbl = Flow_Tbl()
+ def controller_set(self, controller):
+ self.controller = controller
+ # Register error message handler
+ global error_msgs
+ error_msgs = []
+ controller.register(ofp.OFPT_ERROR, error_handler)
+ controller.register(ofp.OFPT_FLOW_REMOVED, removed_handler)
+
def features_get(self):
# Get switch features
request = message.features_request()
@@ -890,6 +1134,19 @@
if self.sw_features is None:
return False
self.valid_ports = map(lambda x: x.port_no, self.sw_features.ports)
+ # TBD - OFPP_LOCAL is returned by OVS is switch features --
+ # is that universal?
+
+ # TBD - There seems to be variability in which switches support which
+ # ports; need to sort that out
+ # TBD - Is it legal to enqueue to a special port? Depends on switch?
+# self.valid_ports.extend([ofp.OFPP_IN_PORT, \
+# ofp.OFPP_NORMAL, \
+# ofp.OFPP_FLOOD, \
+# ofp.OFPP_ALL, \
+# ofp.OFPP_CONTROLLER \
+# ] \
+# )
return True
def tbl_stats_get(self):
@@ -905,8 +1162,25 @@
request.match = query_match
request.table_id = 0xff
request.out_port = ofp.OFPP_NONE;
- (self.flow_stats, pkt) = self.controller.transact(request, timeout=2)
- return (self.flow_stats is not None)
+ if self.controller.message_send(request) == -1:
+ return False
+ # <TBD>
+ # Glue together successive reponse messages for stats reply.
+ # Looking at the "more" flag and performing re-assembly
+ # should be a part of the infrastructure.
+ # </TBD>
+ n = 0
+ while True:
+ # TBD - Check for "more" flag
+ (resp, pkt) = self.controller.poll(ofp.OFPT_STATS_REPLY, 1)
+ if resp is None:
+ break
+ if n == 0:
+ self.flow_stats = resp
+ else:
+ self.flow_stats.stats.extend(resp.stats)
+ n = n + 1
+ return (n > 0)
def flow_add(self, flow_cfg, overlapf = False):
flow_mod_msg = message.flow_mod()
@@ -916,19 +1190,21 @@
if overlapf:
flow_mod_msg.flags = flow_mod_msg.flags | ofp.OFPFF_CHECK_OVERLAP
if flow_cfg.send_rem:
- flow_mod_msg.flags = flow_mod_msg.flags | ofp.OFPFF_SEND_FLOW_REM
+ flow_mod_msg.flags = flow_mod_msg.flags | ofp.OFPFF_SEND_FLOW_REM
return (self.controller.message_send(flow_mod_msg) != -1)
def flow_mod(self, flow_cfg, strictf):
flow_mod_msg = message.flow_mod()
- flow_mod_msg.command = ofp.OFPFC_MODIFY_STRICT if strictf else ofp.OFPFC_MODIFY
+ flow_mod_msg.command = ofp.OFPFC_MODIFY_STRICT if strictf \
+ else ofp.OFPFC_MODIFY
flow_mod_msg.buffer_id = 0xffffffff
flow_cfg.to_flow_mod_msg(flow_mod_msg)
return (self.controller.message_send(flow_mod_msg) != -1)
def flow_del(self, flow_cfg, strictf):
flow_mod_msg = message.flow_mod()
- flow_mod_msg.command = ofp.OFPFC_DELETE_STRICT if strictf else ofp.OFPFC_DELETE
+ flow_mod_msg.command = ofp.OFPFC_DELETE_STRICT if strictf \
+ else ofp.OFPFC_DELETE
flow_mod_msg.buffer_id = 0xffffffff
# TBD - "out_port" filtering of deletes needs to be tested
flow_mod_msg.out_port = ofp.OFPP_NONE
@@ -940,28 +1216,70 @@
(resp, pkt) = self.controller.transact(barrier, 5)
return (resp is not None)
- def errors_verify(self, num, type = 0, code = 0):
- pa_logger.debug("Expecting %d error messages" % (num))
- if num > 0:
- pa_logger.debug("with type=%d code=%d" % (type, code))
+ def errors_verify(self, num_exp, type = 0, code = 0):
result = True
- n = 0
- while True:
- (errmsg, pkt) = self.controller.poll(ofp.OFPT_ERROR, 1)
- if errmsg is None:
- break
- pa_logger.debug("Got error message, type=%d, code=%d" \
- % (errmsg.type, errmsg.code) \
- )
- if num == 0 or errmsg.type != type or errmsg.code != code:
- pa_logger.debug("Unexpected error message")
+ global error_msgs
+ pa_logger.debug("Expecting %d error messages" % (num_exp))
+ num_got = len(error_msgs)
+ pa_logger.debug("Got %d error messages" % (num_got))
+ if num_got != num_exp:
+ pa_logger.error("Incorrect number of error messages received")
+ result = False
+ if num_exp == 0:
+ return result
+ elif num_exp == 1:
+ pa_logger.debug("Expecting error message, type=%d, code=%d" \
+ % (type, code) \
+ )
+ f = False
+ for e in error_msgs:
+ if e.type == type and e.code == code:
+ pa_logger.debug("Got it")
+ f = True
+ if not f:
+ pa_logger.error("Did not get it")
result = False
- n = n + 1
- if n != num:
- pa_logger.error("Received %d error messages" % (n))
+ else:
+ pa_logger.error("Can't expect more than 1 error message type")
result = False
return result
+ def removed_verify(self, num_exp):
+ result = True
+ global removed_msgs
+ pa_logger.debug("Expecting %d removed messages" % (num_exp))
+ num_got = len(removed_msgs)
+ pa_logger.debug("Got %d removed messages" % (num_got))
+ if num_got != num_exp:
+ pa_logger.error("Incorrect number of removed messages received")
+ result = False
+ if num_exp < 2:
+ return result
+ pa_logger.error("Can't expect more than 1 error message type")
+ return False
+
+
+# pa_logger.debug("Expecting %d error messages" % (num))
+# if num > 0:
+# pa_logger.debug("with type=%d code=%d" % (type, code))
+# result = True
+# n = 0
+# while True:
+# (errmsg, pkt) = self.controller.poll(ofp.OFPT_ERROR, 1)
+# if errmsg is None:
+# break
+# pa_logger.debug("Got error message, type=%d, code=%d" \
+# % (errmsg.type, errmsg.code) \
+# )
+# if num == 0 or errmsg.type != type or errmsg.code != code:
+# pa_logger.debug("Unexpected error message")
+# result = False
+# n = n + 1
+# if n != num:
+# pa_logger.error("Received %d error messages" % (n))
+# result = False
+# return result
+
def flow_tbl_verify(self):
result = True
@@ -1039,7 +1357,7 @@
pa_logger.debug("Flow_Add_5 TEST BEGIN")
num_flows = test_param_get(pa_config, "num_flows", 100)
-
+
# Clear all flows from switch
pa_logger.debug("Deleting all flows from switch")
@@ -1050,7 +1368,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1126,7 +1444,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1182,6 +1500,10 @@
pa_logger.debug("Flow_Add_5_1 TEST PASSED")
+# Disabled because of bogus capacity reported by OVS.
+# Should be DUT dependent.
+test_prio["Flow_Add_6"] = -1
+
class Flow_Add_6(basic.SimpleProtocol):
"""
Test FLOW_ADD_6 from draft top-half test plan
@@ -1203,7 +1525,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1308,7 +1630,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1398,7 +1720,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1500,7 +1822,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1592,7 +1914,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1600,7 +1922,8 @@
# random flow parameter generation
fi = Flow_Info()
- fi.rand(int(math.log(num_flows)) / 2) # Shrunk, to increase chance of meta-matches
+ # Shrunk, to increase chance of meta-matches
+ fi.rand(int(math.log(num_flows)) / 2)
# Dream up some flows
@@ -1644,7 +1967,10 @@
if w == ofp.OFPFW_NW_SRC_MASK or w == ofp.OFPFW_NW_DST_MASK:
n = wildcard_get(mfc.match.wildcards, w)
if n < 32:
- mfc.match.wildcards = wildcard_set(mfc.match.wildcards, w, random.randint(n + 1, 32))
+ mfc.match.wildcards = wildcard_set(mfc.match.wildcards, \
+ w, \
+ random.randint(n + 1, 32) \
+ )
else:
continue
else:
@@ -1716,7 +2042,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1787,7 +2113,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1878,7 +2204,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -1886,7 +2212,8 @@
# random flow parameter generation
fi = Flow_Info()
- fi.rand(int(math.log(num_flows)) / 2) # Shrunk, to increase chance of meta-matches
+ # Shrunk, to increase chance of meta-matches
+ fi.rand(int(math.log(num_flows)) / 2)
# Dream up some flows
@@ -1930,7 +2257,10 @@
if w == ofp.OFPFW_NW_SRC_MASK or w == ofp.OFPFW_NW_DST_MASK:
n = wildcard_get(dfc.match.wildcards, w)
if n < 32:
- dfc.match.wildcards = wildcard_set(dfc.match.wildcards, w, random.randint(n + 1, 32))
+ dfc.match.wildcards = wildcard_set(dfc.match.wildcards, \
+ w, \
+ random.randint(n + 1, 32) \
+ )
else:
continue
else:
@@ -1980,9 +2310,6 @@
pa_logger.debug("Flow_Del_2 TEST PASSED")
-# Disable this test by default, there seems to be an issue with error message reporting
-test_prio["Flow_Del_4"] = -1
-
class Flow_Del_4(basic.SimpleProtocol):
"""
Test FLOW_DEL_4 from draft top-half test plan
@@ -2004,7 +2331,7 @@
pa_logger.debug("Getting switch capabilities")
sw = Switch()
- sw.controller = self.controller
+ sw.controller_set(self.controller)
self.assertTrue(sw.features_get(), "Get switch features failed")
self.assertTrue(sw.tbl_stats_get(), "Get table stats failed")
@@ -2059,10 +2386,10 @@
# Check for expected "removed" message
- if not sw.errors_verify(1, \
- ofp.OFPT_FLOW_REMOVED, \
- ofp.OFPRR_DELETE \
- ):
+ if not sw.errors_verify(0):
+ result = False
+
+ if not sw.removed_verify(1):
result = False
# Verify flow table