diff --git a/ofproto/bond.c b/ofproto/bond.c
index f06cf20c9..a3cc795bf 100644
--- a/ofproto/bond.c
+++ b/ofproto/bond.c
@@ -187,10 +187,15 @@ static struct bond_member *choose_output_member(const struct bond *,
                                                 uint16_t vlan)
     OVS_REQ_RDLOCK(rwlock);
 static void update_recirc_rules__(struct bond *);
+static bool bond_may_recirc(const struct bond *bond);
+static void bond_update_post_recirc_rules__(struct bond *bond,
+                                            const bool force)
+    OVS_REQ_WRLOCK(rwlock);
 static bool bond_is_falling_back_to_ab(const struct bond *);
 static void bond_add_lb_output_buckets(const struct bond *);
 static void bond_del_lb_output_buckets(const struct bond *);
 
+
 /* Attempts to parse 's' as the name of a bond balancing mode.  If successful,
  * stores the mode in '*balance' and returns true.  Otherwise returns false
  * without modifying '*balance'. */
@@ -515,6 +520,12 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
         bond_entry_reset(bond);
     }
 
+    if (bond->ofproto->backer->rt_support.odp.recirc
+        && bond_may_recirc(bond)) {
+        /* Update rules to reflect possible recirc_id changes. */
+        update_recirc_rules(bond);
+    }
+
     ovs_rwlock_unlock(&rwlock);
     return revalidate;
 }
@@ -728,6 +739,12 @@ bond_run(struct bond *bond, enum lacp_status lacp_status)
         bond_choose_active_member(bond);
     }
 
+    if (bond->ofproto->backer->rt_support.odp.recirc
+        && bond_may_recirc(bond)) {
+        /* Update rules to reflect possible link state changes. */
+        bond_update_post_recirc_rules__(bond, false);
+    }
+
     revalidate = bond->bond_revalidate;
     bond->bond_revalidate = false;
     ovs_rwlock_unlock(&rwlock);
@@ -1091,6 +1108,19 @@ bond_update_post_recirc_rules(struct bond *bond, uint32_t *recirc_id,
     }
 }
 
+void
+bond_get_recirc_id_and_hash_basis(struct bond *bond, uint32_t *recirc_id,
+                                  uint32_t *hash_basis)
+{
+    ovs_rwlock_rdlock(&rwlock);
+    if (bond_may_recirc(bond)) {
+        *recirc_id = bond->recirc_id;
+        *hash_basis = bond->basis;
+    } else {
+        *recirc_id = *hash_basis = 0;
+    }
+    ovs_rwlock_unlock(&rwlock);
+}
 
 /* Rebalancing. */
 
diff --git a/ofproto/bond.h b/ofproto/bond.h
index 2eb0c95a7..9c2b994c6 100644
--- a/ofproto/bond.h
+++ b/ofproto/bond.h
@@ -131,6 +131,9 @@ void bond_rebalance(struct bond *);
 void bond_update_post_recirc_rules(struct bond *, uint32_t *recirc_id,
                                    uint32_t *hash_basis);
 
+void bond_get_recirc_id_and_hash_basis(struct bond *bond, uint32_t *recirc_id,
+                                       uint32_t *hash_basis);
+
 bool bond_use_lb_output_action(const struct bond *bond);
 
 #endif /* bond.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index fda802e83..60ce7bb5b 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2466,9 +2466,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
             /* In case recirculation is not actually in use, 'xr.recirc_id'
              * will be set to '0', since a valid 'recirc_id' can
              * not be zero.  */
-            bond_update_post_recirc_rules(out_xbundle->bond,
-                                          &xr.recirc_id,
-                                          &xr.hash_basis);
+            if (ctx->xin->allow_side_effects) {
+                bond_update_post_recirc_rules(out_xbundle->bond,
+                                              &xr.recirc_id,
+                                              &xr.hash_basis);
+            } else {
+                /* If side effects are not allowed, only getting the bond
+                 * configuration.  Rule updates will be handled by the
+                 * main thread later. */
+                bond_get_recirc_id_and_hash_basis(out_xbundle->bond,
+                                                  &xr.recirc_id,
+                                                  &xr.hash_basis);
+            }
             if (xr.recirc_id) {
                 /* Use recirculation instead of output. */
                 use_recirc = true;
