Only OpenFlow 1.4 and later support role status messages, but this code tried to send them to all controllers, which caused an assertion failure.
Also, add tests to check that role status messages work, and that they don't cause trouble with OF1.2. Reported-by: Anup Khadka <khadka...@gmail.com> Signed-off-by: Ben Pfaff <b...@nicira.com> --- AUTHORS | 1 + lib/ofp-util.c | 27 ++++++---- ofproto/connmgr.c | 5 +- tests/ofproto.at | 147 ++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 139 insertions(+), 41 deletions(-) diff --git a/AUTHORS b/AUTHORS index 3e97bbe..b505a07 100644 --- a/AUTHORS +++ b/AUTHORS @@ -161,6 +161,7 @@ Andreas Beckmann deb...@abeckmann.de Andrei Andone andrei.and...@softvision.ro Anshuman Manral anshuman.man...@outlook.com Anton Matsiuk anton.mats...@gmail.com +Anup Khadka khadka...@gmail.com Anuprem Chalvadi achalv...@vmware.com Ariel Tubaltsev atubalt...@vmware.com Atzm Watanabe a...@stratosphere.co.jp diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 912def9..a91031c 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -4977,22 +4977,31 @@ ofputil_encode_role_reply(const struct ofp_header *request, return buf; } +/* Encodes "role status" message 'status' for sending in the given + * 'protocol'. Returns the role status message, if 'protocol' supports them, + * otherwise a null pointer. */ struct ofpbuf * ofputil_encode_role_status(const struct ofputil_role_status *status, enum ofputil_protocol protocol) { - struct ofpbuf *buf; enum ofp_version version; - struct ofp14_role_status *rstatus; version = ofputil_protocol_to_ofp_version(protocol); - buf = ofpraw_alloc_xid(OFPRAW_OFPT14_ROLE_STATUS, version, htonl(0), 0); - rstatus = ofpbuf_put_zeros(buf, sizeof *rstatus); - rstatus->role = htonl(status->role); - rstatus->reason = status->reason; - rstatus->generation_id = htonll(status->generation_id); - - return buf; + if (version >= OFP14_VERSION) { + struct ofp14_role_status *rstatus; + struct ofpbuf *buf; + + buf = ofpraw_alloc_xid(OFPRAW_OFPT14_ROLE_STATUS, version, htonl(0), + 0); + rstatus = ofpbuf_put_zeros(buf, sizeof *rstatus); + rstatus->role = htonl(status->role); + rstatus->reason = status->reason; + rstatus->generation_id = htonll(status->generation_id); + + return buf; + } else { + return NULL; + } } enum ofperr diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index be99529..05fe0c4 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -920,8 +920,9 @@ ofconn_send_role_status(struct ofconn *ofconn, uint32_t role, uint8_t reason) ofconn_get_master_election_id(ofconn, &status.generation_id); buf = ofputil_encode_role_status(&status, ofconn_get_protocol(ofconn)); - - ofconn_send(ofconn, buf, NULL); + if (buf) { + ofconn_send(ofconn, buf, NULL); + } } /* Changes 'ofconn''s role to 'role'. If 'role' is OFPCR12_ROLE_MASTER then diff --git a/tests/ofproto.at b/tests/ofproto.at index 729ef7b..3a55ce3 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -1875,41 +1875,128 @@ dnl This test checks that the role request/response messaging works dnl and that generation_id is handled properly. AT_SETUP([ofproto - controller role (OpenFlow 1.2)]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl -O OpenFlow12 monitor br0 --detach --no-chdir --pidfile]) - -ovs-appctl -t ovs-ofctl ofctl/barrier -ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log -: > expout -: > experr +ON_EXIT([kill `cat c1.pid c2.pid`]) + +# Start two ovs-ofctl controller processes. +AT_CAPTURE_FILE([monitor1.log]) +AT_CAPTURE_FILE([expout1]) +AT_CAPTURE_FILE([experr1]) +AT_CAPTURE_FILE([monitor2.log]) +AT_CAPTURE_FILE([expout2]) +AT_CAPTURE_FILE([experr2]) +for i in 1 2; do + AT_CHECK([ovs-ofctl -O OpenFlow12 monitor br0 --detach --no-chdir --pidfile=`pwd`/c$i.pid --unixctl=`pwd`/c$i]) + ovs-appctl -t `pwd`/c$i ofctl/barrier + ovs-appctl -t `pwd`/c$i ofctl/set-output-file monitor$i.log + : > expout$i + : > experr$i + + # find out current role + ovs-appctl -t `pwd`/c$i ofctl/send 031800180000000200000000000000000000000000000000 + echo >>experr$i "send: OFPT_ROLE_REQUEST (OF1.2): role=nochange" + echo >>expout$i "OFPT_ROLE_REPLY (OF1.2): role=equal" +done -# find out current role -ovs-appctl -t ovs-ofctl ofctl/send 031800180000000200000000000000000000000000000000 -echo >>experr "send: OFPT_ROLE_REQUEST (OF1.2) (xid=0x2): role=nochange" -echo >>expout "OFPT_ROLE_REPLY (OF1.2) (xid=0x2): role=equal" +# controller 1: Become slave (generation_id is initially undefined, so +# 2^63+2 should not be stale) +ovs-appctl -t `pwd`/c1 ofctl/send 031800180000000300000003000000008000000000000002 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.2): role=slave generation_id=9223372036854775810" +echo >>expout1 "OFPT_ROLE_REPLY (OF1.2): role=slave generation_id=9223372036854775810" + +# controller 2: Become master. +ovs-appctl -t `pwd`/c2 ofctl/send 031800180000000300000002000000008000000000000003 +echo >>experr2 "send: OFPT_ROLE_REQUEST (OF1.2): role=master generation_id=9223372036854775811" +echo >>expout2 "OFPT_ROLE_REPLY (OF1.2): role=master generation_id=9223372036854775811" + +# controller 1: Try to become the master using a stale generation ID +ovs-appctl -t `pwd`/c1 ofctl/send 031800180000000400000002000000000000000000000003 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.2): role=master generation_id=3" +echo >>expout1 "OFPT_ERROR (OF1.2): OFPRRFC_STALE" +echo >>expout1 "OFPT_ROLE_REQUEST (OF1.2): role=master generation_id=3" + +# controller 1: Become master using a valid generation ID +ovs-appctl -t `pwd`/c1 ofctl/send 031800180000000500000002000000000000000000000001 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.2): role=master generation_id=1" +echo >>expout1 "OFPT_ROLE_REPLY (OF1.2): role=master generation_id=1" + +for i in 1 2; do + ovs-appctl -t `pwd`/c$i ofctl/barrier + echo >>expout$i "OFPT_BARRIER_REPLY (OF1.2):" +done -# Become slave (generation_id is initially undefined, so 2^63+2 should not be stale) -ovs-appctl -t ovs-ofctl ofctl/send 031800180000000300000003000000008000000000000002 -echo >>experr "send: OFPT_ROLE_REQUEST (OF1.2) (xid=0x3): role=slave generation_id=9223372036854775810" -echo >>expout "OFPT_ROLE_REPLY (OF1.2) (xid=0x3): role=slave generation_id=9223372036854775810" +# Check output. +for i in 1 2; do + cp expout$i expout + AT_CHECK([grep -v '^send:' monitor$i.log | STRIP_XIDS], [0], [expout]) + cp experr$i expout + AT_CHECK([grep '^send:' monitor$i.log | STRIP_XIDS], [0], [expout]) +done +OVS_VSWITCHD_STOP +AT_CLEANUP -# Try to become the master using a stale generation ID -ovs-appctl -t ovs-ofctl ofctl/send 031800180000000400000002000000000000000000000002 -echo >>experr "send: OFPT_ROLE_REQUEST (OF1.2) (xid=0x4): role=master generation_id=2" -echo >>expout "OFPT_ERROR (OF1.2) (xid=0x4): OFPRRFC_STALE" -echo >>expout "OFPT_ROLE_REQUEST (OF1.2) (xid=0x4): role=master generation_id=2" - -# Become master using a valid generation ID -ovs-appctl -t ovs-ofctl ofctl/send 031800180000000500000002000000000000000000000001 -echo >>experr "send: OFPT_ROLE_REQUEST (OF1.2) (xid=0x5): role=master generation_id=1" -echo >>expout "OFPT_ROLE_REPLY (OF1.2) (xid=0x5): role=master generation_id=1" -ovs-appctl -t ovs-ofctl ofctl/barrier -echo >>expout "OFPT_BARRIER_REPLY (OF1.2) (xid=0x3):" +dnl This test checks that the role request/response messaging works, +dnl that generation_id is handled properly, and that role status update +dnl messages are sent when a controller's role gets changed from master +dnl to slave. +AT_SETUP([ofproto - controller role (OpenFlow 1.4)]) +OVS_VSWITCHD_START +ON_EXIT([kill `cat c1.pid c2.pid`]) + +# Start two ovs-ofctl controller processes. +AT_CAPTURE_FILE([monitor1.log]) +AT_CAPTURE_FILE([expout1]) +AT_CAPTURE_FILE([experr1]) +AT_CAPTURE_FILE([monitor2.log]) +AT_CAPTURE_FILE([expout2]) +AT_CAPTURE_FILE([experr2]) +for i in 1 2; do + AT_CHECK([ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile=`pwd`/c$i.pid --unixctl=`pwd`/c$i]) + ovs-appctl -t `pwd`/c$i ofctl/barrier + ovs-appctl -t `pwd`/c$i ofctl/set-output-file monitor$i.log + : > expout$i + : > experr$i + + # find out current role + ovs-appctl -t `pwd`/c$i ofctl/send 051800180000000200000000000000000000000000000000 + echo >>experr$i "send: OFPT_ROLE_REQUEST (OF1.4): role=nochange" + echo >>expout$i "OFPT_ROLE_REPLY (OF1.4): role=equal" +done -AT_CHECK([grep -v '^send:' monitor.log], [0], [expout]) -mv experr expout -AT_CHECK([grep '^send:' monitor.log], [0], [expout]) +# controller 1: Become slave (generation_id is initially undefined, so +# 2^63+2 should not be stale) +ovs-appctl -t `pwd`/c1 ofctl/send 051800180000000300000003000000008000000000000002 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.4): role=slave generation_id=9223372036854775810" +echo >>expout1 "OFPT_ROLE_REPLY (OF1.4): role=slave generation_id=9223372036854775810" + +# controller 2: Become master. +ovs-appctl -t `pwd`/c2 ofctl/send 051800180000000300000002000000008000000000000003 +echo >>experr2 "send: OFPT_ROLE_REQUEST (OF1.4): role=master generation_id=9223372036854775811" +echo >>expout2 "OFPT_ROLE_REPLY (OF1.4): role=master generation_id=9223372036854775811" + +# controller 1: Try to become the master using a stale generation ID +ovs-appctl -t `pwd`/c1 ofctl/send 051800180000000400000002000000000000000000000003 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.4): role=master generation_id=3" +echo >>expout1 "OFPT_ERROR (OF1.4): OFPRRFC_STALE" +echo >>expout1 "OFPT_ROLE_REQUEST (OF1.4): role=master generation_id=3" + +# controller 1: Become master using a valid generation ID +ovs-appctl -t `pwd`/c1 ofctl/send 051800180000000500000002000000000000000000000001 +echo >>experr1 "send: OFPT_ROLE_REQUEST (OF1.4): role=master generation_id=1" +echo >>expout1 "OFPT_ROLE_REPLY (OF1.4): role=master generation_id=1" +echo >>expout2 "OFPT_ROLE_STATUS (OF1.4): role=slave generation_id=1 reason=master_request" + +for i in 1 2; do + ovs-appctl -t `pwd`/c$i ofctl/barrier + echo >>expout$i "OFPT_BARRIER_REPLY (OF1.4):" +done -ovs-appctl -t ovs-ofctl exit +# Check output. +for i in 1 2; do + cp expout$i expout + AT_CHECK([grep -v '^send:' monitor$i.log | STRIP_XIDS], [0], [expout]) + cp experr$i expout + AT_CHECK([grep '^send:' monitor$i.log | STRIP_XIDS], [0], [expout]) +done OVS_VSWITCHD_STOP AT_CLEANUP -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev