Added FloodMinusPort routine; use utility routines
FloodMinusPort checks that the no-flood port configuration
works. In addition, use sets of ports passed to receive_pkt_check
in various places for positive and negative packet reception
checking.
diff --git a/tests/basic.py b/tests/basic.py
index b464b5e..8296be3 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -68,7 +68,7 @@
def setUp(self):
signal.signal(signal.SIGINT, self.sig_handler)
- basic_logger.info("Setup for " + str(self))
+ basic_logger.info("** START TEST CASE " + str(self))
self.controller = controller.Controller(
host=basic_config["controller_host"],
port=basic_config["controller_port"])
@@ -84,7 +84,7 @@
basic_logger.info("Connected " + str(self.controller.switch_addr))
def tearDown(self):
- basic_logger.info("Teardown for simple proto test")
+ basic_logger.info("** END TEST CASE " + str(self))
self.controller.shutdown()
#@todo Review if join should be done on clean_shutdown
if self.clean_shutdown:
@@ -96,6 +96,11 @@
self.assertTrue(self.controller.switch_socket is not None,
str(self) + 'No connection to switch')
+ def assertTrue(self, cond, msg):
+ if not cond:
+ basic_logger.error("** FAILED ASSERTION: " + msg)
+ unittest.TestCase.assertTrue(self, cond, msg)
+
class SimpleDataPlane(SimpleProtocol):
"""
Root class that sets up the controller and dataplane
@@ -271,39 +276,34 @@
def runTest(self):
basic_logger.info("Running " + str(self))
- request = message.features_request()
- reply, pkt = self.controller.transact(request, timeout=2)
- self.assertTrue(reply is not None, "Did not get response to ftr req")
- basic_logger.info("Reply has " + str(len(reply.ports)) + " ports")
- #basic_logger.debug(reply.show())
- tport = reply.ports[0]
- basic_logger.info("No flood bit port 0 is now " +
- str(reply.ports[0].config ^ ofp.OFPPC_NO_FLOOD))
+ for of_port, ifname in basic_port_map.items(): # Grab first port
+ break
- mod = message.port_mod()
- mod.port_no = tport.port_no
- mod.hw_addr = tport.hw_addr
- mod.config = tport.config ^ ofp.OFPPC_NO_FLOOD
- mod.mask = ofp.OFPPC_NO_FLOOD
- mod.advertise = tport.advertised
- #basic_logger.debug(mod.show())
- rv = self.controller.message_send(mod)
+ (hw_addr, config, advert) = \
+ port_config_get(self.controller, of_port, basic_logger)
+ self.assertTrue(config is not None, "Did not get port config")
+
+ basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
+ str(config & ofp.OFPPC_NO_FLOOD))
+
+ rv = port_config_set(self.controller, of_port,
+ config ^ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
+ basic_logger)
self.assertTrue(rv != -1, "Error sending port mod")
# Verify change took place with same feature request
- request.header.xid = 0 # Force new XID
- reply2, pkt = self.controller.transact(request, timeout=2)
- self.assertTrue(reply2 is not None, "Did not get response ftr req2")
- #basic_logger.debug(reply2.show())
- self.assertTrue(reply2.ports[0].port_no == tport.port_no,
- "Feature reply port order changed; unhandled")
- self.assertTrue(reply2.ports[0].config & ofp.OFPPC_NO_FLOOD !=
- tport.config & ofp.OFPPC_NO_FLOOD,
- "Bit change did not take")
+ (hw_addr, config2, advert) = \
+ port_config_get(self.controller, of_port, basic_logger)
+ basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
+ str(config2 & ofp.OFPPC_NO_FLOOD))
+ self.assertTrue(config2 is not None, "Did not get port config2")
+ self.assertTrue(config2 & ofp.OFPPC_NO_FLOOD !=
+ config & ofp.OFPPC_NO_FLOOD,
+ "Bit change did not take")
# Set it back
- mod.config ^= ofp.OFPPC_NO_FLOOD
- rv = self.controller.message_send(mod)
- self.assertTrue(rv != -1, "Error sending port mod2")
+ rv = port_config_set(self.controller, of_port, config,
+ ofp.OFPPC_NO_FLOOD, basic_logger)
+ self.assertTrue(rv != -1, "Error sending port mod")
if __name__ == "__main__":
print "Please run through oft script: ./oft --test_spec=basic"
diff --git a/tests/pktact.py b/tests/pktact.py
index 1bedd29..535eea1 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -15,6 +15,8 @@
"""
+import copy
+
import logging
import unittest
@@ -77,8 +79,8 @@
act = action.action_output()
for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
ingress_port = of_ports[idx]
egress_port = of_ports[(idx + 1) % len(of_ports)]
@@ -135,8 +137,8 @@
act = action.action_output()
for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
ingress_port = of_ports[idx]
egress_port1 = of_ports[(idx + 1) % len(of_ports)]
@@ -164,27 +166,11 @@
pa_logger.info("Sending packet to dp port " +
str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- (rcv_port1, rcv_pkt1, pkt_time1) = self.dataplane.poll(timeout=1)
- (rcv_port2, rcv_pkt2, pkt_time2) = self.dataplane.poll(timeout=1)
- self.assertTrue(rcv_pkt1 is not None, "Did not receive packet 1")
- self.assertTrue(rcv_pkt2 is not None, "Did not receive packet 2")
- pa_logger.debug("Packet len " + str(len(rcv_pkt1)) + " in on " +
- str(rcv_port1))
- pa_logger.debug("Packet len " + str(len(rcv_pkt2)) + " in on " +
- str(rcv_port2))
+ yes_ports = set([egress_port1, egress_port2])
+ no_ports = set(of_ports).difference(yes_ports)
- # Check if ports swapped
- if (rcv_port1 == egress_port2 and rcv_port2 == egress_port1):
- (rcv_port2, rcv_port1) = (rcv_port1, rcv_port2)
- (rcv_pkt2, rcv_pkt1) = (rcv_pkt1, rcv_pkt2)
- self.assertEqual(rcv_port1, egress_port1,
- "Unexpected receive port 1")
- self.assertEqual(rcv_port2, egress_port2,
- "Unexpected receive port 2")
- self.assertEqual(str(pkt), str(rcv_pkt1),
- 'Response packet does not match send packet 1')
- self.assertEqual(str(pkt), str(rcv_pkt2),
- 'Response packet does not match send packet 2')
+ receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
+ self, pa_logger)
class DirectMCNonIngress(basic.SimpleDataPlane):
"""
@@ -211,50 +197,36 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) +
" all non-ingress ports")
-
match.in_port = ingress_port
request = message.flow_mod()
request.match = match
request.buffer_id = 0xffffffff
- for egr_idx in range(len(of_ports)):
- if egr_idx == idx:
+ for egress_port in of_ports:
+ if egress_port == ingress_port:
continue
- egress_port = of_ports[egr_idx]
act.port = egress_port
self.assertTrue(request.actions.add(act),
"Could not add output to " + str(egress_port))
- pa_logger.info(request.show())
+ pa_logger.debug(request.show())
pa_logger.info("Inserting flow")
rv = self.controller.message_send(request)
self.assertTrue(rv != -1, "Error installing flow mod")
do_barrier(self.controller)
- pa_logger.info("Sending packet to dp port " +
- str(ingress_port))
+ pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- if egr_idx == idx:
- continue
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
+ yes_ports = set(of_ports).difference([ingress_port])
+ receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
+ self, pa_logger)
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
class DirectMC(basic.SimpleDataPlane):
"""
@@ -281,21 +253,18 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
-
match.in_port = ingress_port
request = message.flow_mod()
request.match = match
request.buffer_id = 0xffffffff
- for egr_idx in range(len(of_ports)):
- egress_port = of_ports[egr_idx]
- if egr_idx == idx:
+ for egress_port in of_ports:
+ if egress_port == ingress_port:
act.port = ofp.OFPP_IN_PORT
else:
act.port = egress_port
@@ -310,18 +279,8 @@
pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
-
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
+ receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
+ pa_logger)
class Flood(basic.SimpleDataPlane):
"""
@@ -346,13 +305,11 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
-
match.in_port = ingress_port
request = message.flow_mod()
@@ -370,20 +327,9 @@
pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- if egr_idx == idx:
- continue
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
-
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
+ yes_ports = set(of_ports).difference([ingress_port])
+ receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
+ self, pa_logger)
class FloodPlusIngress(basic.SimpleDataPlane):
@@ -410,13 +356,11 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
-
match.in_port = ingress_port
request = message.flow_mod()
@@ -437,18 +381,8 @@
pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
-
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
+ receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
+ pa_logger)
class All(basic.SimpleDataPlane):
"""
@@ -473,13 +407,11 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
-
match.in_port = ingress_port
request = message.flow_mod()
@@ -497,20 +429,9 @@
pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- if egr_idx == idx:
- continue
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
-
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
+ yes_ports = set(of_ports).difference([ingress_port])
+ receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
+ self, pa_logger)
class AllPlusIngress(basic.SimpleDataPlane):
"""
@@ -536,13 +457,11 @@
"Could not generate flow match from pkt")
act = action.action_output()
- for idx in range(len(of_ports)):
- rc = delete_all_flows(self.controller, pa_logger)
- self.assertEqual(rc, 0, "Failed to delete all flows")
+ for ingress_port in of_ports:
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
- ingress_port = of_ports[idx]
pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
-
match.in_port = ingress_port
request = message.flow_mod()
@@ -563,15 +482,76 @@
pa_logger.info("Sending packet to dp port " + str(ingress_port))
self.dataplane.send(ingress_port, str(pkt))
- for egr_idx in range(len(of_ports)):
- ofport = of_ports[egr_idx]
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
- port_number=ofport, timeout=1)
- self.assertTrue(rcv_pkt is not None,
- "Did not receive packet port " + str(ofport))
- pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
- + str(rcv_port))
+ receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
+ pa_logger)
+
- self.assertEqual(str(pkt), str(rcv_pkt),
- 'Response packet does not match send packet ' +
- "on port " + str(ofport))
+class FloodMinusPort(basic.SimpleDataPlane):
+ """
+ Config port with No_Flood and test Flood action
+
+ Generate a packet
+ Generate a matching flow
+ Add action to forward to OFPP_ALL
+ Set port to no-flood
+ Send the packet to ingress dataplane port
+ Verify the packet is received at all other ports except
+ the ingress port and the no_flood port
+ """
+ def runTest(self):
+ global pa_port_map
+ of_ports = pa_port_map.keys()
+ of_ports.sort()
+ self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
+
+ pkt = simple_tcp_packet()
+ match = parse.packet_to_flow_match(pkt)
+ match.wildcards &= ~ofp.OFPFW_IN_PORT
+ self.assertTrue(match is not None,
+ "Could not generate flow match from pkt")
+ act = action.action_output()
+
+ for idx in range(len(of_ports)):
+ rv = delete_all_flows(self.controller, pa_logger)
+ self.assertEqual(rv, 0, "Failed to delete all flows")
+
+ ingress_port = of_ports[idx]
+ no_flood_idx = (idx + 1) % len(of_ports)
+ no_flood_port = of_ports[no_flood_idx]
+ rv = port_config_set(self.controller, no_flood_port,
+ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
+ pa_logger)
+ self.assertEqual(rv, 0, "Failed to set port config")
+
+ match.in_port = ingress_port
+
+ request = message.flow_mod()
+ request.match = match
+ request.buffer_id = 0xffffffff
+ act.port = ofp.OFPP_FLOOD
+ self.assertTrue(request.actions.add(act),
+ "Could not add flood port action")
+ pa_logger.info(request.show())
+
+ pa_logger.info("Inserting flow")
+ rv = self.controller.message_send(request)
+ self.assertTrue(rv != -1, "Error installing flow mod")
+ do_barrier(self.controller)
+
+ pa_logger.info("Sending packet to dp port " + str(ingress_port))
+ pa_logger.info("No flood port is " + str(no_flood_port))
+ self.dataplane.send(ingress_port, str(pkt))
+ no_ports = set([ingress_port, no_flood_port])
+ yes_ports = set(of_ports).difference(no_ports)
+ receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
+ pa_logger)
+
+ # Turn no flood off again
+ rv = port_config_set(self.controller, no_flood_port,
+ 0, ofp.OFPPC_NO_FLOOD, pa_logger)
+ self.assertEqual(rv, 0, "Failed to reset port config")
+
+ #@todo Should check no other packets received
+
+if __name__ == "__main__":
+ print "Please run through oft script: ./oft --test_spec=basic"