This commit adds logic that marks the 'struct iface's when their
status need to be updated but the current status update transaction
fails.  So, the main thread can re-try the update in the next run.

Bug #1256577

Signed-off-by: Alex Wang <al...@nicira.com>
---
 vswitchd/bridge.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 835de0f..1682992 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -77,11 +77,18 @@ struct iface {
     char *name;                 /* Host network device name. */
     struct netdev *netdev;      /* Network device. */
     ofp_port_t ofp_port;        /* OpenFlow port number. */
-    uint64_t change_seq;
+    uint64_t netdev_change_seq;
 
     /* These members are valid only within bridge_reconfigure(). */
     const char *type;           /* Usually same as cfg->type. */
     const struct ovsrec_interface *cfg;
+
+    /* 'status_update_try_again' is set when iface's status needs to be
+     * be updated to database but the update transaction fails.  It is
+     * marked so that the next run will try updating it again. */
+    struct list try_again_node; /* Element in "may_try_again_ifaces" list. */
+    bool try_again_inserted;    /* Guarantee iface is inserted only once. */
+    bool status_update_try_again;
 };
 
 struct mirror {
@@ -190,6 +197,12 @@ static bool status_txn_try_again;
 static int stats_timer_interval;
 static long long int stats_timer = LLONG_MIN;
 
+/* List of 'struct iface's that may be checked again for status
+ * update, if the update transaction fails.  The list should be
+ * cleared at the end of bridge_run(). */
+static struct list may_try_again_ifaces =
+    LIST_INITIALIZER(&may_try_again_ifaces);
+
 /* In some datapaths, creating and destroying OpenFlow ports can be extremely
  * expensive.  This can cause bridge_reconfigure() to take a long time during
  * which no other work can be done.  To deal with this problem, we limit port
@@ -290,6 +303,7 @@ static bool iface_is_synthetic(const struct iface *);
 static ofp_port_t iface_get_requested_ofp_port(
     const struct ovsrec_interface *);
 static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *);
+static void iface_register_status_update_try_again(struct iface *);
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
  *
@@ -1547,6 +1561,8 @@ iface_create(struct bridge *br, const struct 
ovsrec_interface *iface_cfg,
     iface->netdev = netdev;
     iface->type = iface_get_type(iface_cfg, br->cfg);
     iface->cfg = iface_cfg;
+    /* Sets the try-again flag to force re-check of initial status. */
+    iface->status_update_try_again = true;
     hmap_insert(&br->ifaces, &iface->ofp_port_node,
                 hash_ofp_port(ofp_port));
 
@@ -1825,11 +1841,13 @@ iface_refresh_netdev_status(struct iface *iface)
         return;
     }
 
-    if (iface->change_seq == netdev_get_change_seq(iface->netdev)) {
+    if (iface->netdev_change_seq == netdev_get_change_seq(iface->netdev)
+        && !iface->status_update_try_again) {
         return;
     }
 
-    iface->change_seq = netdev_get_change_seq(iface->netdev);
+    iface->netdev_change_seq = netdev_get_change_seq(iface->netdev);
+    iface_register_status_update_try_again(iface);
 
     smap_init(&smap);
 
@@ -1914,14 +1932,20 @@ iface_refresh_ofproto_status(struct iface *iface)
     }
 
     if (ofproto_port_cfm_status_changed(iface->port->bridge->ofproto,
-                                        iface->ofp_port)) {
+                                        iface->ofp_port)
+        || iface->status_update_try_again) {
+
+        iface_register_status_update_try_again(iface);
         iface_refresh_cfm_stats(iface);
     }
 
     if (ofproto_port_bfd_status_changed(iface->port->bridge->ofproto,
-                                        iface->ofp_port)) {
+                                        iface->ofp_port)
+        || iface->status_update_try_again) {
         struct smap smap;
 
+        iface_register_status_update_try_again(iface);
+
         smap_init(&smap);
         ofproto_port_get_bfd_status(iface->port->bridge->ofproto,
                                     iface->ofp_port, &smap);
@@ -2354,6 +2378,9 @@ bridge_run(void)
         if (initial_config_done) {
             ovsdb_idl_txn_commit(txn);
             ovsdb_idl_txn_destroy(txn);
+            /* Always sets the 'status_txn_try_again' to check again,
+             * in case that this transaction fails. */
+            status_txn_try_again = true;
         } else {
             initial_config_done = true;
             daemonize_txn = txn;
@@ -2450,6 +2477,7 @@ bridge_run(void)
 
     if (status_txn) {
         enum ovsdb_idl_txn_status status;
+        struct iface *iface, *next;
 
         status = ovsdb_idl_txn_commit(status_txn);
         /* Do not destroy "status_txn" if the transaction is
@@ -2466,6 +2494,16 @@ bridge_run(void)
         } else {
             status_txn_try_again = true;
         }
+
+        /* Unregisters all 'iface's from 'may_try_again_faces' list,
+         * and sets the 'iface->status_update_try_again' to
+         * 'status_txn_try_again'. */
+        LIST_FOR_EACH_SAFE (iface, next, try_again_node,
+                            &may_try_again_ifaces) {
+            iface->try_again_inserted = false;
+            iface->status_update_try_again = status_txn_try_again;
+            list_remove(&iface->try_again_node);
+        }
     }
 
     run_system_stats();
@@ -3800,6 +3838,15 @@ iface_pick_ofport(const struct ovsrec_interface *cfg)
             ? requested_ofport
             : iface_validate_ofport__(cfg->n_ofport, cfg->ofport));
 }
+
+static void
+iface_register_status_update_try_again(struct iface *iface)
+{
+    if (!iface->try_again_inserted) {
+        iface->try_again_inserted = true;
+        list_insert(&may_try_again_ifaces, &iface->try_again_node);
+    }
+}
 
 /* Port mirroring. */
 
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to