[ovs-dev] [MASTER 3/3] bridge: Make ovs-vswitchd run again if status_txn commit fails.

Alex Wang alexw at nicira.com
Tue Jun 10 17:03:52 UTC 2014


This commit adds logic that checks the return value of status_txn
transaction and runs the update again if the transaction fails
(transaction status is not 'TXN_SUCCESS', 'TXN_UNCHANGED', or
'TXN_INCOMPLETE').

To keep the code simple, the re-run of update on transaction failure
will extracts the status from all interfaces, rather than just those
that have status change.  Since the transaction failure is considered
to be very rare, such overhead is deemed to be affordable.

Bug #1256577

Signed-off-by: Alex Wang <alexw at nicira.com>
---
 vswitchd/bridge.c |   37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index eee4869..2df82f2 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -173,8 +173,13 @@ static uint64_t connectivity_seqno = LLONG_MIN;
  * update if the previous transaction status is 'TXN_INCOMPLETE'.
  *
  * 'statux_txn' is NULL if there is no ongoing status update.
+ *
+ * If the previous database transaction was failed (is not 'TXN_SUCCESS',
+ * 'TXN_UNCHANGED' or 'TXN_INCOMPLETE'), 'status_txn_try_again' is set to true,
+ * which will cause the main thread wake up soon and retry the status update.
  */
 static struct ovsdb_idl_txn *status_txn;
+static bool status_txn_try_again;
 
 /* When the status update transaction returns 'TXN_INCOMPLETE', should register a
  * timeout in 'STATUS_CHECK_AGAIN_MSEC' to check again. */
@@ -1820,7 +1825,8 @@ iface_refresh_netdev_status(struct iface *iface)
         return;
     }
 
-    if (iface->change_seq == netdev_get_change_seq(iface->netdev)) {
+    if (iface->change_seq == netdev_get_change_seq(iface->netdev)
+        && !status_txn_try_again) {
         return;
     }
 
@@ -1909,12 +1915,14 @@ iface_refresh_ofproto_status(struct iface *iface)
     }
 
     if (ofproto_port_cfm_status_changed(iface->port->bridge->ofproto,
-                                        iface->ofp_port)) {
+                                        iface->ofp_port)
+        || status_txn_try_again) {
         iface_refresh_cfm_stats(iface);
     }
 
     if (ofproto_port_bfd_status_changed(iface->port->bridge->ofproto,
-                                        iface->ofp_port)) {
+                                        iface->ofp_port)
+        || status_txn_try_again) {
         struct smap smap;
 
         smap_init(&smap);
@@ -2347,6 +2355,9 @@ bridge_run(void)
          * of ovs-vswitchd, then keep the transaction around to monitor
          * it for completion. */
         if (initial_config_done) {
+            /* Always sets the 'status_txn_try_again' to check again,
+             * in case that this transaction fails. */
+            status_txn_try_again = true;
             ovsdb_idl_txn_commit(txn);
             ovsdb_idl_txn_destroy(txn);
         } else {
@@ -2423,7 +2434,7 @@ bridge_run(void)
 
         /* Check the need to update status. */
         seq = seq_read(connectivity_seq_get());
-        if (seq != connectivity_seqno) {
+        if (seq != connectivity_seqno || status_txn_try_again) {
             connectivity_seqno = seq;
             status_txn = ovsdb_idl_txn_create(idl);
             HMAP_FOR_EACH (br, node, &all_bridges) {
@@ -2452,6 +2463,13 @@ bridge_run(void)
         if (status != TXN_INCOMPLETE) {
             ovsdb_idl_txn_destroy(status_txn);
             status_txn = NULL;
+
+            /* Sets the 'status_txn_try_again' if the transaction fails. */
+            if (status == TXN_SUCCESS || status == TXN_UNCOMMITTED) {
+                status_txn_try_again = false;
+            } else {
+                status_txn_try_again = true;
+            }
         }
     }
 
@@ -2486,11 +2504,14 @@ bridge_wait(void)
         poll_timer_wait_until(stats_timer);
     }
 
-    /* If the status database transaction is 'TXN_INCOMPLETE' in this run,
-     * register a timeout in 'STATUS_CHECK_AGAIN_MSEC'.  Else, wait on the
-     * global connectivity sequence number.  Note, this also helps batch
-     * multiple status changes into one transaction. */
+    /* If the 'status_txn' is non-null (transaction incomplete), waits for the
+     * transaction to complete.  If the status update to database needs to be
+     * run again (transaction fails), registers a timeout in
+     * 'STATUS_CHECK_AGAIN_MSEC'.  Otherwise, waits on the global connectivity
+     * sequence number. */
     if (status_txn) {
+        ovsdb_idl_txn_wait(status_txn);
+    } else if (status_txn_try_again) {
         poll_timer_wait_until(time_msec() + STATUS_CHECK_AGAIN_MSEC);
     } else {
         seq_wait(connectivity_seq_get(), connectivity_seqno);
-- 
1.7.9.5




More information about the dev mailing list