ofproto: Store time since last connect and disconnect in Controller table.
authorAndrew Evans <aevans@nicira.com>
Mon, 14 Mar 2011 20:19:20 +0000 (13:19 -0700)
committerAndrew Evans <aevans@nicira.com>
Mon, 14 Mar 2011 20:19:26 +0000 (13:19 -0700)
ovs-vswitchd writes only the duration of its connection to or disconnection
from each controller to the database. This changes that behavior to write the
time since both the last connection and disconnection events regardless of
connection state. This mirrors the new behavior for reporting database manager
connection status.

Requested-by: Peter Balland <peter@nicira.com>
Bug #4833.

lib/rconn.c
lib/rconn.h
ofproto/ofproto.c
ofproto/ofproto.h
vswitchd/vswitch.xml

index 443690b..6a86de6 100644 (file)
@@ -81,6 +81,7 @@ struct rconn {
     time_t backoff_deadline;
     time_t last_received;
     time_t last_connected;
+    time_t last_disconnected;
     unsigned int packets_sent;
     unsigned int seqno;
     int last_error;
@@ -188,7 +189,8 @@ rconn_create(int probe_interval, int max_backoff)
     rc->max_backoff = max_backoff ? max_backoff : 8;
     rc->backoff_deadline = TIME_MIN;
     rc->last_received = time_now();
-    rc->last_connected = time_now();
+    rc->last_connected = TIME_MIN;
+    rc->last_disconnected = TIME_MIN;
     rc->seqno = 0;
 
     rc->packets_sent = 0;
@@ -792,13 +794,21 @@ rconn_get_successful_connections(const struct rconn *rc)
 }
 
 /* Returns the time at which the last successful connection was made by
- * 'rc'. */
+ * 'rc'. Returns TIME_MIN if never connected. */
 time_t
 rconn_get_last_connection(const struct rconn *rc)
 {
     return rc->last_connected;
 }
 
+/* Returns the time at which 'rc' was last disconnected. Returns TIME_MIN
+ * if never disconnected. */
+time_t
+rconn_get_last_disconnect(const struct rconn *rc)
+{
+    return rc->last_disconnected;
+}
+
 /* Returns the time at which the last OpenFlow message was received by 'rc'.
  * If no packets have been received on 'rc', returns the time at which 'rc'
  * was created. */
@@ -980,6 +990,7 @@ disconnect(struct rconn *rc, int error)
         time_t now = time_now();
 
         if (rc->state & (S_CONNECTING | S_ACTIVE | S_IDLE)) {
+            rc->last_disconnected = now;
             vconn_close(rc->vconn);
             rc->vconn = NULL;
             flush_queue(rc);
@@ -1005,6 +1016,7 @@ disconnect(struct rconn *rc, int error)
             question_connectivity(rc);
         }
     } else {
+        rc->last_disconnected = time_now();
         rconn_disconnect(rc);
     }
 }
index 47b211b..8579399 100644 (file)
@@ -81,6 +81,7 @@ const char *rconn_get_state(const struct rconn *);
 unsigned int rconn_get_attempted_connections(const struct rconn *);
 unsigned int rconn_get_successful_connections(const struct rconn *);
 time_t rconn_get_last_connection(const struct rconn *);
+time_t rconn_get_last_disconnect(const struct rconn *);
 time_t rconn_get_last_received(const struct rconn *);
 time_t rconn_get_creation_time(const struct rconn *);
 unsigned long int rconn_get_total_time_connected(const struct rconn *);
index c7872ba..147ade3 100644 (file)
@@ -1367,7 +1367,7 @@ ofproto_is_alive(const struct ofproto *p)
 }
 
 void
-ofproto_get_ofproto_controller_info(const struct ofproto * ofproto,
+ofproto_get_ofproto_controller_info(const struct ofproto *ofproto,
                                     struct shash *info)
 {
     const struct ofconn *ofconn;
@@ -1376,6 +1376,9 @@ ofproto_get_ofproto_controller_info(const struct ofproto * ofproto,
 
     HMAP_FOR_EACH (ofconn, hmap_node, &ofproto->controllers) {
         const struct rconn *rconn = ofconn->rconn;
+        time_t now = time_now();
+        time_t last_connection = rconn_get_last_connection(rconn);
+        time_t last_disconnect = rconn_get_last_disconnect(rconn);
         const int last_error = rconn_get_last_error(rconn);
         struct ofproto_controller_info *cinfo = xmalloc(sizeof *cinfo);
 
@@ -1396,14 +1399,16 @@ ofproto_get_ofproto_controller_info(const struct ofproto * ofproto,
         cinfo->pairs.values[cinfo->pairs.n++] =
             xstrdup(rconn_get_state(rconn));
 
-        if (rconn_is_admitted(rconn)) {
-            cinfo->pairs.keys[cinfo->pairs.n] = "time_connected";
-            cinfo->pairs.values[cinfo->pairs.n++] =
-                xasprintf("%ld", time_now() - rconn_get_last_connection(rconn));
-        } else {
-            cinfo->pairs.keys[cinfo->pairs.n] = "time_disconnected";
-            cinfo->pairs.values[cinfo->pairs.n++] =
-                xasprintf("%d", rconn_failure_duration(rconn));
+        if (last_connection != TIME_MIN) {
+            cinfo->pairs.keys[cinfo->pairs.n] = "sec_since_connect";
+            cinfo->pairs.values[cinfo->pairs.n++]
+                = xasprintf("%ld", (long int) (now - last_connection));
+        }
+
+        if (last_disconnect != TIME_MIN) {
+            cinfo->pairs.keys[cinfo->pairs.n] = "sec_since_disconnect";
+            cinfo->pairs.values[cinfo->pairs.n++]
+                = xasprintf("%ld", (long int) (now - last_disconnect));
         }
     }
 }
index 2828c64..a32b9b9 100644 (file)
@@ -41,8 +41,8 @@ struct ofproto_controller_info {
     bool is_connected;
     enum nx_role role;
     struct {
-        const char *keys[3];
-        const char *values[3];
+        const char *keys[4];
+        const char *values[4];
         size_t n;
     } pairs;
 };
index b084884..244b24e 100644 (file)
         <dl>
           <dt><code>other</code></dt>
           <dd>Allows the controller access to all OpenFlow features.</dd>
-        </dl>
-        <dl>
           <dt><code>master</code></dt>
           <dd>Equivalent to <code>other</code>, except that there may be at
             most one master controller at a time.  When a controller configures
             itself as <code>master</code>, any existing master is demoted to
             the <code>slave</code>role.</dd>
-        </dl>
-        <dl>
           <dt><code>slave</code></dt>
           <dd>Allows the controller read-only access to OpenFlow features.
             Attempts to modify the flow table will be rejected with an
           <dd>A human-readable description of the last error on the connection
             to the controller; i.e. <code>strerror(errno)</code>.  This key
             will exist only if an error has occurred.</dd>
-        </dl>
-        <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>time_in_state</code></dt>
-          <dd>Seconds since connecting to (if currently connected) or
-            disconnecting from (if currently disconnected) this
-            controller.</dd>
+            are: <code>VOID</code> (connection is disabled),
+            <code>BACKOFF</code> (attempting to reconnect at an increasing
+            period), <code>CONNECTING</code> (attempting to connect),
+            <code>ACTIVE</code> (connected, remote host responsive), and
+            <code>IDLE</code> (remote host idle, sending keep-alive).  These
+            values may change in the future.  They are provided only for human
+            consumption.</dd>
+          <dt><code>sec_since_connect</code></dt>
+          <dd>The amount of time since this controller last successfully
+            connected to the switch (in seconds). Value is empty if controller
+            has never successfully connected.</dd>
+          <dt><code>sec_since_disconnect</code></dt>
+          <dd>The amount of time since this controller last disconnected from
+            the switch (in seconds). Value is empty if controller has never
+            disconnected.</dd>
         </dl>
       </column>
     </group>