cfm: Notify connectivity_seq on remote maintenance points change.
[cascardo/ovs.git] / ofproto / connmgr.c
index c9feae5..2350c33 100644 (file)
@@ -637,12 +637,13 @@ connmgr_set_controllers(struct connmgr *mgr,
 
     shash_destroy(&new_controllers);
 
+    ovs_mutex_unlock(&ofproto_mutex);
+
     update_in_band_remotes(mgr);
     update_fail_open(mgr);
     if (had_controllers != connmgr_has_controllers(mgr)) {
         ofproto_flush_flows(mgr->ofproto);
     }
-    ovs_mutex_unlock(&ofproto_mutex);
 }
 
 /* Drops the connections between 'mgr' and all of its primary and secondary
@@ -912,17 +913,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);
             }
         }
     }
@@ -1949,7 +1966,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
 
     default:
     case NXFME_ABBREV:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
 
     LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {