Thanks Ales,

Acked-by: Mark Michelson <mmich...@redhat.com>

On 4/11/25 06:50, Ales Musil via dev wrote:
The virtual port binding requests were commited twice in case there
was a failure in between them. That unfortunately doesn't solve the
issue for very rare case when the commit fails multiple times in
a row. To make sure we remove only really commited requests use
the next_cfg and cur_cfg mechanism of idl_loop. We can store
the cur_cfg and check against the next loop cur_cfg to see
if the commit was successful. This mechanism is exposed to
the whole pinctrl so it can be used by any other SB transaction
if needed.

Signed-off-by: Ales Musil <amu...@redhat.com>
---
  controller/ovn-controller.c | 16 ++++++-
  controller/pinctrl.c        | 87 +++++++++++++------------------------
  controller/pinctrl.h        |  3 +-
  3 files changed, 47 insertions(+), 59 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 440c76ca1..a42e21c5c 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -6326,7 +6326,8 @@ main(int argc, char *argv[])
                                      &runtime_data->local_active_ports_ipv6_pd,
                                      &runtime_data->local_active_ports_ras,
                                      ovsrec_open_vswitch_table_get(
-                                            ovs_idl_loop.idl));
+                                            ovs_idl_loop.idl),
+                                    ovnsb_idl_loop.cur_cfg);
                          stopwatch_stop(PINCTRL_RUN_STOPWATCH_NAME,
                                         time_msec());
                          mirror_run(ovs_idl_txn,
@@ -6490,9 +6491,20 @@ main(int argc, char *argv[])
              poll_immediate_wake();
          }
- if (!ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop)) {
+        int ovnsb_txn_status = ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
+        if (!ovnsb_txn_status) {
              VLOG_INFO("OVNSB commit failed, force recompute next time.");
              engine_set_force_recompute_immediate();
+        } else if (ovnsb_txn_status == 1) {
+            if (ovnsb_idl_loop.next_cfg == INT64_MAX) {
+                ovnsb_idl_loop.next_cfg = 0;
+            } else {
+                ovnsb_idl_loop.next_cfg++;
+            }
+        } else if (ovnsb_txn_status == -1) {
+            /* The commit is still in progress */
+        } else {
+            OVS_NOT_REACHED();
          }
int ovs_txn_status = ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index bdb619b4d..436e5d487 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -184,6 +184,7 @@ struct pinctrl {
static struct pinctrl pinctrl; +static bool pinctrl_is_sb_commited(int64_t commit_cfg, int64_t cur_cfg);
  static void init_buffered_packets_ctx(void);
  static void destroy_buffered_packets_ctx(void);
  static void
@@ -321,7 +322,7 @@ static void run_put_vport_bindings(
      struct ovsdb_idl_txn *ovnsb_idl_txn,
      struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
      struct ovsdb_idl_index *sbrec_port_binding_by_key,
-    const struct sbrec_chassis *chassis)
+    const struct sbrec_chassis *chassis, int64_t cur_cfg)
      OVS_REQUIRES(pinctrl_mutex);
  static void wait_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn);
  static void pinctrl_handle_bind_vport(const struct flow *md,
@@ -4084,14 +4085,15 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
              const struct sset *active_tunnels,
              const struct shash *local_active_ports_ipv6_pd,
              const struct shash *local_active_ports_ras,
-            const struct ovsrec_open_vswitch_table *ovs_table)
+            const struct ovsrec_open_vswitch_table *ovs_table,
+            int64_t cur_cfg)
  {
      ovs_mutex_lock(&pinctrl_mutex);
      run_put_mac_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
                           sbrec_port_binding_by_key,
                           sbrec_mac_binding_by_lport_ip);
      run_put_vport_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
-                           sbrec_port_binding_by_key, chassis);
+                           sbrec_port_binding_by_key, chassis, cur_cfg);
      send_garp_rarp_prepare(ovnsb_idl_txn, sbrec_port_binding_by_datapath,
                             sbrec_port_binding_by_name,
                             sbrec_mac_binding_by_lport_ip, ecmp_nh_table,
@@ -4629,6 +4631,15 @@ pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn)
      ovs_mutex_unlock(&pinctrl_mutex);
  }
+#define PINCTRL_CFG_INTERVAL 100
+
+static bool
+pinctrl_is_sb_commited(int64_t commit_cfg, int64_t cur_cfg)
+{
+    return (INT64_MAX - commit_cfg < PINCTRL_CFG_INTERVAL &&
+            cur_cfg < PINCTRL_CFG_INTERVAL) || cur_cfg > commit_cfg;
+}
+
  /* Called by ovn-controller. */
  void
  pinctrl_destroy(void)
@@ -7280,45 +7291,13 @@ struct put_vport_binding {
uint32_t vport_parent_key; - /* This vport record Only relevant if "new_record" is true. */
-    bool new_record;
+    /* Current commit cfg number. */
+    int64_t cfg;
  };
/* Contains "struct put_vport_binding"s. */
  static struct hmap put_vport_bindings;
-/*
- * Validate if the vport_binding record that was added
- * by the pinctrl thread is still relevant and needs
- * to be updated in the SBDB or not.
- *
- * vport_binding record is only relevant and needs to be updated in SB if:
- *   2. The put_vport_binding:new_record is true:
- *       The new_record will be set to "true" when this vport record is created
- *       by function "pinctrl_handle_bind_vport".
- *
- *       After the first attempt to bind this vport to the chassis and
- *       virtual_parent by function "run_put_vport_bindings" we will set the
- *       value of vpb:new_record to "false" and keep it in "put_vport_bindings"
- *
- *       After the second attempt of binding the vpb it will be removed by
- *       this function.
- *
- *       The above guarantees that we will try to bind the vport twice in
- *       a certain amount of time.
- *
-*/
-static bool
-is_vport_binding_relevant(struct put_vport_binding *vpb)
-{
-
-    if (vpb->new_record) {
-        vpb->new_record = false;
-        return true;
-    }
-    return false;
-}
-
  static void
  init_put_vport_bindings(void)
  {
@@ -7326,21 +7305,13 @@ init_put_vport_bindings(void)
  }
static void
-flush_put_vport_bindings(bool force_flush)
+destroy_put_vport_bindings(void)
  {
      struct put_vport_binding *vport_b;
      HMAP_FOR_EACH_SAFE (vport_b, hmap_node, &put_vport_bindings) {
-        if (!is_vport_binding_relevant(vport_b) || force_flush) {
-            hmap_remove(&put_vport_bindings, &vport_b->hmap_node);
-            free(vport_b);
-        }
+        hmap_remove(&put_vport_bindings, &vport_b->hmap_node);
+        free(vport_b);
      }
-}
-
-static void
-destroy_put_vport_bindings(void)
-{
-    flush_put_vport_bindings(true);
      hmap_destroy(&put_vport_bindings);
  }
@@ -7405,20 +7376,24 @@ static void
  run_put_vport_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn,
                        struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
                        struct ovsdb_idl_index *sbrec_port_binding_by_key,
-                      const struct sbrec_chassis *chassis)
+                      const struct sbrec_chassis *chassis, int64_t cur_cfg)
      OVS_REQUIRES(pinctrl_mutex)
  {
      if (!ovnsb_idl_txn) {
          return;
      }
- const struct put_vport_binding *vpb;
-    HMAP_FOR_EACH (vpb, hmap_node, &put_vport_bindings) {
-        run_put_vport_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
-                              sbrec_port_binding_by_key, chassis, vpb);
+    struct put_vport_binding *vpb;
+    HMAP_FOR_EACH_SAFE (vpb, hmap_node, &put_vport_bindings) {
+        if (vpb->cfg >= 0 && pinctrl_is_sb_commited(vpb->cfg, cur_cfg)) {
+            hmap_remove(&put_vport_bindings, &vpb->hmap_node);
+            free(vpb);
+        } else {
+            run_put_vport_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
+                                  sbrec_port_binding_by_key, chassis, vpb);
+            vpb->cfg = cur_cfg;
+        }
      }
-
-    flush_put_vport_bindings(false);
  }
/* Called with in the pinctrl_handler thread context. */
@@ -7456,7 +7431,7 @@ pinctrl_handle_bind_vport(
      vpb->dp_key = dp_key;
      vpb->vport_key = vport_key;
      vpb->vport_parent_key = vport_parent_key;
-    vpb->new_record = true;
+    vpb->cfg = -1;
      notify_pinctrl_main();
  }
diff --git a/controller/pinctrl.h b/controller/pinctrl.h
index e33d7cbf5..d3d5d8831 100644
--- a/controller/pinctrl.h
+++ b/controller/pinctrl.h
@@ -61,7 +61,8 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
                   const struct sset *active_tunnels,
                   const struct shash *local_active_ports_ipv6_pd,
                   const struct shash *local_active_ports_ras,
-                 const struct ovsrec_open_vswitch_table *ovs_table);
+                 const struct ovsrec_open_vswitch_table *ovs_table,
+                 int64_t cur_cfg);
  void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
  void pinctrl_destroy(void);

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to