[ovs-dev] [PATCH] bridge: Add controller status to Controller table.

Andrew Evans aevans at nicira.com
Sun Jan 23 02:07:52 UTC 2011


Get status information for controller(s) attached to each bridge and store in
Controller table every 5 seconds.
---
 ofproto/ofproto.c          |   56 ++++++++++++++++++++++++++++++++++++++++++++
 ofproto/ofproto.h          |   20 +++++++++++++++
 vswitchd/bridge.c          |   37 +++++++++++++++++++++++++++++
 vswitchd/vswitch.ovsschema |   15 ++++++++++-
 vswitchd/vswitch.xml       |   33 ++++++++++++++++++++++++++
 5 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 7df8600..1678892 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1354,6 +1354,62 @@ ofproto_is_alive(const struct ofproto *p)
     return !hmap_is_empty(&p->controllers);
 }
 
+void
+ofproto_get_ofproto_controller_info(const struct ofproto * const ofproto,
+                                    struct shash *info)
+{
+    const struct ofconn *ofconn;
+
+    shash_init(info);
+
+    HMAP_FOR_EACH (ofconn, hmap_node, &ofproto->controllers) {
+        static const char *keys[] = { "last_error", "state", "time_in_state" };
+        static const size_t n_keys = ARRAY_SIZE(keys);
+        const struct rconn *rconn = ofconn->rconn;
+        const int last_error = rconn_get_last_error(rconn);
+        const char *last_error_str;
+        struct ofproto_controller_info *cinfo = xmalloc(sizeof *cinfo);
+
+        shash_add(info, rconn_get_target(rconn), cinfo);
+
+        cinfo->is_connected = rconn_is_connected(rconn);
+        cinfo->role = ofconn->role;
+
+        cinfo->pairs.keys = keys;
+
+        if (last_error == EOF) {
+            last_error_str = "EOF";
+        } else if (last_error > 0) {
+            last_error_str = strerror(last_error);
+        } else {
+            last_error_str = "";
+        }
+
+        cinfo->pairs.values = xmalloc(sizeof *cinfo->pairs.values * n_keys);
+        cinfo->pairs.values[CONTROLLER_INFO_KEY_LAST_ERROR] = last_error_str;
+        cinfo->pairs.values[CONTROLLER_INFO_KEY_STATE]
+            = rconn_get_state(rconn);
+        cinfo->pairs.values[CONTROLLER_INFO_KEY_TIME_IN_STATE] =
+            xasprintf("%u", rconn_get_state_elapsed(rconn));
+
+        cinfo->pairs.count = n_keys;
+    }
+}
+
+void
+ofproto_free_ofproto_controller_info(struct shash *info)
+{
+    struct shash_node *node;
+
+    SHASH_FOR_EACH (node, info) {
+        struct ofproto_controller_info *cinfo = node->data;
+        free((char *) cinfo->pairs.values[CONTROLLER_INFO_KEY_TIME_IN_STATE]);
+        free(cinfo->pairs.values);
+        free(cinfo);
+    }
+    shash_destroy(info);
+}
+
 /* Deletes port number 'odp_port' from the datapath for 'ofproto'.
  *
  * This is almost the same as calling dpif_port_del() directly on the
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index eeaeb6f..b03ad7e 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -34,8 +34,25 @@ struct cls_rule;
 struct nlattr;
 struct ofhooks;
 struct ofproto;
+struct shash;
 struct svec;
 
+struct ofproto_controller_info {
+    bool is_connected;
+    enum nx_role role;
+    struct {
+        const char **keys;
+        const char **values;
+        size_t count;
+    } pairs;
+};
+
+enum ofproto_controller_info_key_indices {
+    CONTROLLER_INFO_KEY_LAST_ERROR,
+    CONTROLLER_INFO_KEY_STATE,
+    CONTROLLER_INFO_KEY_TIME_IN_STATE
+};
+
 struct ofexpired {
     struct flow flow;
     uint64_t packet_count;      /* Packets from subrules. */
@@ -147,6 +164,9 @@ struct ofhooks {
 void ofproto_revalidate(struct ofproto *, tag_type);
 struct tag_set *ofproto_get_revalidate_set(struct ofproto *);
 
+void ofproto_get_ofproto_controller_info(const struct ofproto * const, struct shash *);
+void ofproto_free_ofproto_controller_info(struct shash *);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 680c1ad..4b43918 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -1318,6 +1318,42 @@ refresh_system_stats(const struct ovsrec_open_vswitch *cfg)
                         &datum);
 }
 
+static inline const char *
+nx_role_to_str(enum nx_role role)
+{
+    switch (role) {
+    case NX_ROLE_OTHER:
+        return "other";
+    case NX_ROLE_MASTER:
+        return "master";
+    case NX_ROLE_SLAVE:
+        return "slave";
+    default:
+        return "*** INVALID ROLE ***";
+    }
+}
+
+static void
+bridge_refresh_controller_status(const struct bridge *br)
+{
+    struct shash info;
+    const struct ovsrec_controller *cfg;
+
+    ofproto_get_ofproto_controller_info(br->ofproto, &info);
+
+    OVSREC_CONTROLLER_FOR_EACH(cfg, idl) {
+        struct ofproto_controller_info *cinfo = shash_find_data(&info, cfg->target);
+
+        ovsrec_controller_set_is_connected(cfg, cinfo->is_connected);
+        ovsrec_controller_set_role(cfg, nx_role_to_str(cinfo->role));
+        ovsrec_controller_set_status(cfg, (char **) cinfo->pairs.keys,
+                                     (char **) cinfo->pairs.values,
+                                     cinfo->pairs.count);
+    }
+
+    ofproto_free_ofproto_controller_info(&info);
+}
+
 void
 bridge_run(void)
 {
@@ -1393,6 +1429,7 @@ bridge_run(void)
                         iface_refresh_status(iface);
                     }
                 }
+                bridge_refresh_controller_status(br);
             }
             refresh_system_stats(cfg);
             ovsdb_idl_txn_commit(txn);
diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
index 75c4326..c62353c 100644
--- a/vswitchd/vswitch.ovsschema
+++ b/vswitchd/vswitch.ovsschema
@@ -1,5 +1,5 @@
 {"name": "Open_vSwitch",
- "version": "1.0.6",
+ "version": "99.99.99",
  "cksum": "2256400918 14940",
  "tables": {
    "Open_vSwitch": {
@@ -384,7 +384,18 @@
                   "min": 0, "max": 1}},
        "external_ids": {
          "type": {"key": "string", "value": "string",
-                  "min": 0, "max": "unlimited"}}}},
+                  "min": 0, "max": "unlimited"}},
+       "is_connected": {
+         "type": "boolean",
+         "ephemeral": true},
+       "role": {
+         "type": {"key": {"type": "string",
+                          "enum": ["set", ["other", "master", "slave"]]},
+                  "min": 0, "max": 1},
+         "ephemeral": true},
+       "status": {
+         "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"},
+         "ephemeral": true}}},
    "Manager": {
      "columns": {
        "target": {
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index dfa3f20..0b839c7 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -1844,6 +1844,39 @@
         unique.  No common key-value pairs are currently defined.
       </column>
     </group>
+
+    <group title="Controller Status">
+      <column name="is_connected">
+        <code>true</code> if currently connected to this controller,
+        <code>false</code> otherwise.
+      </column>
+
+      <column name="role">
+        The level of authority this controller has on the associated bridge.
+      </column>
+
+      <column name="status">
+        <p>Key-value pairs that report controller status.</p>
+        <dl>
+          <dt><code>state</code></dt>
+          <dd>The state of the connection to the controller.  Possible values
+            are: <code>VOID</code>, <code>BACKOFF</code>,
+            <code>CONNECTING</code>, <code>ACTIVE</code> and
+            <code>IDLE</code>.</dd>
+        </dl>
+        <dl>
+          <dt><code>last_error</code></dt>
+          <dd>The last error on this connection, if any, in human-readable
+            form.  Possible values are empty, <code>EOF</code> and UNIX system
+            call error strings; i.e. <code>strerror(errno)</code>.</dd>
+        </dl>
+        <dl>
+          <dt><code>time_disconnected</code></dt>
+          <dd>Seconds since disconnecting from controller, if previously
+            connected.</dd>
+        </dl>
+      </column>
+    </group>
   </table>
 
   <table name="Manager" title="OVSDB management connection.">
-- 
1.7.2.3





More information about the dev mailing list