From 00467f7367deade04c4405e1eb2841581700d519 Mon Sep 17 00:00:00 2001 From: Alexandru Copot Date: Tue, 22 Oct 2013 11:40:03 +0300 Subject: [PATCH] ofproto: Add support for sending OFPTYPE_ROLE_STATUS messages. When a controller changes its role to MASTER, the others are marked as SLAVE. This patch makes it possible to notify the controllers of this change. Signed-off-by: Alexandru Copot Cc: Daniel Baluta Signed-off-by: Ben Pfaff --- include/openflow/openflow-1.4.h | 3 +- lib/ofp-print.c | 65 ++++++++++++++++++++++++++------- lib/ofp-util.c | 45 +++++++++++++++++++++++ lib/ofp-util.h | 12 ++++++ ofproto/connmgr.c | 18 ++++++++- ofproto/connmgr.h | 2 + tests/ofp-print.at | 30 +++++++++++++++ 7 files changed, 159 insertions(+), 16 deletions(-) diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h index 2dc6ef26b..332a0d3ee 100644 --- a/include/openflow/openflow-1.4.h +++ b/include/openflow/openflow-1.4.h @@ -116,7 +116,6 @@ OFP_ASSERT(sizeof(struct ofp14_role_prop_header) == 4); /* Role status event message. */ struct ofp14_role_status { - struct ofp_header header; /* Type OFPT_ROLE_REQUEST/OFPT_ROLE_REPLY. */ ovs_be32 role; /* One of OFPCR_ROLE_*. */ uint8_t reason; /* One of OFPCRR_*. */ uint8_t pad[3]; /* Align to 64 bits. */ @@ -124,7 +123,7 @@ struct ofp14_role_status { /* Followed by a list of struct ofp14_role_prop_header */ }; -OFP_ASSERT(sizeof(struct ofp14_role_status) == 24); +OFP_ASSERT(sizeof(struct ofp14_role_status) == 16); /* What changed about the controller role */ enum ofp14_controller_role_reason { diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 9949a9b0d..1dc459888 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1917,20 +1917,12 @@ ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity) } static void -ofp_print_role_message(struct ds *string, const struct ofp_header *oh) +ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role, + uint64_t generation_id) { - struct ofputil_role_request rr; - enum ofperr error; - - error = ofputil_decode_role_message(oh, &rr); - if (error) { - ofp_print_error(string, error); - return; - } - ds_put_cstr(string, " role="); - switch (rr.role) { + switch (role) { case OFPCR12_ROLE_NOCHANGE: ds_put_cstr(string, "nochange"); break; @@ -1947,8 +1939,54 @@ ofp_print_role_message(struct ds *string, const struct ofp_header *oh) NOT_REACHED(); } - if (rr.have_generation_id) { - ds_put_format(string, " generation_id=%"PRIu64, rr.generation_id); + if (generation_id != UINT64_MAX) { + ds_put_format(string, " generation_id=%"PRIu64, generation_id); + } +} + +static void +ofp_print_role_message(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_role_request rr; + enum ofperr error; + + error = ofputil_decode_role_message(oh, &rr); + if (error) { + ofp_print_error(string, error); + return; + } + + ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX); +} + +static void +ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh) +{ + struct ofputil_role_status rs; + enum ofperr error; + + error = ofputil_decode_role_status(oh, &rs); + if (error) { + ofp_print_error(string, error); + return; + } + + ofp_print_role_generic(string, rs.role, rs.generation_id); + + ds_put_cstr(string, " reason="); + + switch (rs.reason) { + case OFPCRR_MASTER_REQUEST: + ds_put_cstr(string, "master_request"); + break; + case OFPCRR_CONFIG: + ds_put_cstr(string, "configuration_changed"); + break; + case OFPCRR_EXPERIMENTER: + ds_put_cstr(string, "experimenter_data_changed"); + break; + default: + NOT_REACHED(); } } @@ -2566,6 +2604,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, ofp_print_role_message(string, oh); break; case OFPTYPE_ROLE_STATUS: + ofp_print_role_status_message(string, oh); break; case OFPTYPE_METER_STATS_REQUEST: diff --git a/lib/ofp-util.c b/lib/ofp-util.c index e881849e5..d435e9969 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -4186,6 +4186,51 @@ ofputil_encode_role_reply(const struct ofp_header *request, return buf; } +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; +} + +enum ofperr +ofputil_decode_role_status(const struct ofp_header *oh, + struct ofputil_role_status *rs) +{ + struct ofpbuf b; + enum ofpraw raw; + const struct ofp14_role_status *r; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + raw = ofpraw_pull_assert(&b); + ovs_assert(raw == OFPRAW_OFPT14_ROLE_STATUS); + + r = b.l3; + if (r->role != htonl(OFPCR12_ROLE_NOCHANGE) && + r->role != htonl(OFPCR12_ROLE_EQUAL) && + r->role != htonl(OFPCR12_ROLE_MASTER) && + r->role != htonl(OFPCR12_ROLE_SLAVE)) { + return OFPERR_OFPRRFC_BAD_ROLE; + } + + rs->role = ntohl(r->role); + rs->generation_id = ntohll(r->generation_id); + rs->reason = r->reason; + + return 0; +} + /* Table stats. */ static void diff --git a/lib/ofp-util.h b/lib/ofp-util.h index e16124cef..c37ab2bc6 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -692,11 +692,23 @@ struct ofputil_role_request { uint64_t generation_id; }; +struct ofputil_role_status { + enum ofp12_controller_role role; + enum ofp14_controller_role_reason reason; + uint64_t generation_id; +}; + enum ofperr ofputil_decode_role_message(const struct ofp_header *, struct ofputil_role_request *); struct ofpbuf *ofputil_encode_role_reply(const struct ofp_header *, const struct ofputil_role_request *); +struct ofpbuf *ofputil_encode_role_status( + const struct ofputil_role_status *status, + enum ofputil_protocol protocol); + +enum ofperr ofputil_decode_role_status(const struct ofp_header *oh, + struct ofputil_role_status *rs); /* Abstract table stats. * * For now we use ofp12_table_stats as a superset of the other protocol diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index c9feae52d..da2593036 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -912,17 +912,33 @@ ofconn_get_role(const struct ofconn *ofconn) return ofconn->role; } +void +ofconn_send_role_status(struct ofconn *ofconn, uint32_t role, uint8_t reason) +{ + struct ofputil_role_status status; + struct ofpbuf *buf; + + status.reason = reason; + status.role = role; + ofconn_get_master_election_id(ofconn, &status.generation_id); + + buf = ofputil_encode_role_status(&status, ofconn_get_protocol(ofconn)); + + ofconn_send(ofconn, buf, NULL); +} + /* Changes 'ofconn''s role to 'role'. If 'role' is OFPCR12_ROLE_MASTER then * any existing master is demoted to a slave. */ void ofconn_set_role(struct ofconn *ofconn, enum ofp12_controller_role role) { - if (role == OFPCR12_ROLE_MASTER) { + if (role != ofconn->role && role == OFPCR12_ROLE_MASTER) { struct ofconn *other; HMAP_FOR_EACH (other, hmap_node, &ofconn->connmgr->controllers) { if (other->role == OFPCR12_ROLE_MASTER) { other->role = OFPCR12_ROLE_SLAVE; + ofconn_send_role_status(other, OFPCR12_ROLE_SLAVE, OFPCRR_MASTER_REQUEST); } } } diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h index 10caaf4e6..170d8721d 100644 --- a/ofproto/connmgr.h +++ b/ofproto/connmgr.h @@ -153,6 +153,8 @@ void connmgr_send_flow_removed(struct connmgr *, const struct ofputil_flow_removed *); void connmgr_send_packet_in(struct connmgr *, const struct ofproto_packet_in *); +void ofconn_send_role_status(struct ofconn *ofconn, uint32_t role, + uint8_t reason); /* Fail-open settings. */ enum ofproto_fail_mode connmgr_get_fail_mode(const struct connmgr *); diff --git a/tests/ofp-print.at b/tests/ofp-print.at index a0512528c..52e6fef2c 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -2092,6 +2092,36 @@ NXT_ROLE_REPLY (xid=0x2): role=slave ]) AT_CLEANUP +AT_SETUP([OFP_ROLE_STATUS - master, experimenter - OF1.4]) +AT_KEYWORDS([ofp-print]) +AT_CHECK([ovs-ofctl ofp-print "\ +05 1e 00 18 00 00 00 0a \ +00 00 00 02 02 00 00 00 ff ff ff ff ff ff ff ff \ +"], [0], [dnl +OFPT_ROLE_STATUS (OF 0x05) (xid=0xa): role=master reason=experimenter_data_changed +]) +AT_CLEANUP + +AT_SETUP([OFP_ROLE_STATUS - master, config - OF1.4]) +AT_KEYWORDS([ofp-print]) +AT_CHECK([ovs-ofctl ofp-print "\ +05 1e 00 18 00 00 00 0a \ +00 00 00 02 01 00 00 00 ff ff ff ff ff ff ff ff \ +"], [0], [dnl +OFPT_ROLE_STATUS (OF 0x05) (xid=0xa): role=master reason=configuration_changed +]) +AT_CLEANUP + +AT_SETUP([OFP_ROLE_STATUS - master, config,generation - OF1.4]) +AT_KEYWORDS([ofp-print]) +AT_CHECK([ovs-ofctl ofp-print "\ +05 1e 00 18 00 00 00 0a \ +00 00 00 02 01 00 00 00 00 00 00 00 00 00 00 10 \ +"], [0], [dnl +OFPT_ROLE_STATUS (OF 0x05) (xid=0xa): role=master generation_id=16 reason=configuration_changed +]) +AT_CLEANUP + AT_SETUP([NXT_SET_PACKET_IN]) AT_KEYWORDS([ofp-print]) AT_CHECK([ovs-ofctl ofp-print "\ -- 2.43.0