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); -- 2.49.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev