add bsn_role_status testcase
diff --git a/tests-1.3/bsn_role_status.py b/tests-1.3/bsn_role_status.py
new file mode 100644
index 0000000..957738a
--- /dev/null
+++ b/tests-1.3/bsn_role_status.py
@@ -0,0 +1,92 @@
+"""
+Test the BSN role status message
+
+This is a backport of the OpenFlow 1.4 functionality.
+"""
+import struct
+import unittest
+import logging
+
+import oftest
+from oftest import config
+import oftest.controller as controller
+import ofp
+import oftest.base_tests as base_tests
+
+from oftest.testutils import *
+
+def simple_role_request(test, role, gen=None, con=None):
+ """
+ Send a role request we expect to succeed
+ """
+ if con == None:
+ con = test.controller
+ request = ofp.message.role_request(role=role, generation_id=gen)
+ response, _ = con.transact(request)
+ test.assertTrue(isinstance(response, ofp.message.role_reply), "Expected a role reply")
+ if role != ofp.OFPCR_ROLE_NOCHANGE:
+ test.assertEquals(response.role, role)
+ if gen != None:
+ test.assertEquals(response.generation_id, gen)
+ return response.role, response.generation_id
+
+@disabled
+@nonstandard
+class RoleStatus(unittest.TestCase):
+ """
+ Verify that when a connection becomes a master the existing master is
+ downgraded to slave and receives a role-status message.
+
+ Requires the switch to attempt to connect in parallel to ports 6653
+ and 6753 on the configured IP.
+ """
+
+ def setUp(self):
+ host = config["controller_host"]
+ self.controllers = [
+ controller.Controller(host=host,port=6653),
+ controller.Controller(host=host,port=6753)
+ ]
+
+ def runTest(self):
+ # Connect and handshake with both controllers
+ for con in self.controllers:
+ con.start()
+ if not con.connect():
+ raise AssertionError("failed to connect controller %s" % str(con))
+ reply, _ = con.transact(ofp.message.features_request())
+ self.assertTrue(isinstance(reply, ofp.message.features_reply))
+
+ # Assert initial role and get generation IDs
+ role, gen0 = simple_role_request(self, ofp.OFPCR_ROLE_NOCHANGE, con=self.controllers[0])
+ self.assertEqual(role, ofp.OFPCR_ROLE_EQUAL)
+ role, gen1 = simple_role_request(self, ofp.OFPCR_ROLE_NOCHANGE, con=self.controllers[1])
+ self.assertEqual(role, ofp.OFPCR_ROLE_EQUAL)
+
+ # Initial role assignment: controller 0 is master, controller 1 is slave
+ simple_role_request(self, ofp.OFPCR_ROLE_MASTER, gen0, con=self.controllers[0])
+ simple_role_request(self, ofp.OFPCR_ROLE_SLAVE, gen1, con=self.controllers[1])
+ self.verify_role(self.controllers[0], ofp.OFPCR_ROLE_MASTER)
+ self.verify_role(self.controllers[1], ofp.OFPCR_ROLE_SLAVE)
+
+ # Controller 1 requests master
+ # Controller 0 becomes slave
+ simple_role_request(self, ofp.OFPCR_ROLE_MASTER, gen1, con=self.controllers[1])
+ self.verify_role(self.controllers[0], ofp.OFPCR_ROLE_SLAVE)
+ self.verify_role(self.controllers[1], ofp.OFPCR_ROLE_MASTER)
+
+ # Controller 0 should receive a bsn_role_status message
+ msg, _ = self.controllers[0].poll(ofp.OFPT_EXPERIMENTER)
+ self.assertIsInstance(msg, ofp.message.bsn_role_status)
+ self.assertEqual(msg.role, ofp.OFPCR_ROLE_SLAVE)
+ self.assertEqual(msg.reason, ofp.OFP_BSN_CONTROLLER_ROLE_REASON_MASTER_REQUEST)
+ self.assertEqual(msg.generation_id, gen1)
+
+ def verify_role(self, con, role):
+ rcv_role, _ = simple_role_request(self, ofp.OFPCR_ROLE_NOCHANGE, con=con)
+ self.assertEqual(rcv_role, role)
+
+ def tearDown(self):
+ for con in self.controllers:
+ con.shutdown()
+