[firefly] [PATCH 2/2] add support for sending OFPTYPE_ROLE_STATUS messages

Alexandru Copot alex.mihai.c at gmail.com
Tue Oct 22 10:31:11 EEST 2013


Signed-off-by: Alexandru Copot <alex.mihai.c at gmail.com>
Cc: Daniel Baluta <dbaluta at ixiacom.com>
---
 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 77fdb57..d71f74f 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 8bd7eef..f17eddc 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1852,20 +1852,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;
@@ -1882,8 +1874,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();
     }
 }
 
@@ -2495,6 +2533,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 2bf595a..6e75a6a 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -3906,6 +3906,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 937423e..7d4ad86 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -679,11 +679,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 8bb96f0..a5fcc65 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 505a757..d2bce8c 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -143,6 +143,8 @@ void connmgr_send_flow_removed(struct connmgr *,
 void connmgr_send_packet_in(struct connmgr *,
                             const struct ofputil_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 *);
 void connmgr_set_fail_mode(struct connmgr *, enum ofproto_fail_mode);
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index 87d5da8..c0150e2 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -2048,6 +2048,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 "\
-- 
1.8.4.1



More information about the firefly mailing list