On Tue, Jan 9, 2024 at 2:29 PM Mohammad Heib <mh...@redhat.com> wrote:
> This patch implements a basic sequence number protocol > that can be used by CMS to determine if the changes > applied to INB are successfully propagated to ISB. > > The implementation of this patch relies on OVN-ICs > instances to update the ISB by adding a per AZ a nb_ic_cfg > counter that will be updated by the OVN-IC once it is done > and commit all needed changes to the ISB, and according to this > AZ:nb_ic_cfg the ISB and INB will be updating about the status > of the changes. > > Signed-off-by: Mohammad Heib <mh...@redhat.com> > --- > Hi Mohammad, there is one small nit see down below. > ic/ovn-ic.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 91 insertions(+), 5 deletions(-) > > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c > index 8ceb34d7c..ba393e910 100644 > --- a/ic/ovn-ic.c > +++ b/ic/ovn-ic.c > @@ -1782,16 +1782,96 @@ route_run(struct ic_context *ctx, > hmap_destroy(&ic_lrs); > } > > +/* > + * This function implements a sequence number protocol that can be used by > + * the INB end user to verify that ISB is synced with all the changes that > + * are done be the user/AZs-controllers: > + * > + * Since we have multiple IC instances running in different regions > + * we can't rely on one of them to update the ISB and sync that update > + * to INB since other ICs can make changes in parallel. > + * So to have a sequence number protocol working properly we must > + * make sure that all the IC instances are synced with the ISB first > + * and then update the INB. > + * > + * To guarantee that all instances are synced with ISB first, each IC > + * will do the following steps: > + * > + * 1. when local ovn-ic sees that INB:nb_ic_cfg has updated we will set > + * the ic_sb_loop->next_cfg to match the INB:nb_ic_cfg and increment > + * the value of AZ:nb_ic_cfg and wait until we get confirmation from > + * the server. > + * > + * 2. once this IC instance changes for ISB are committed successfully > + * (next loop), the value of cur_cfg will be updated to match > + * the INB:nb_ic_cfg that indicate that our local instance is up to > date > + * and no more changes need to be done for ISB. > + * > + * 3. validate that the AZ:nb_ic_cfg to match the INB:nb_ic_cfg. > + * > + * 4. Go through all the AZs and check if all have the same value of > + * AZ:nb_ic_cfg that means all the AZs are done with ISB changes and > ISB are > + * up to date with INB, so we can set the values of ISB:nb_ic_cfg to > + * INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. > + */ > static void > -ovn_db_run(struct ic_context *ctx) > +update_sequence_numbers(const struct icsbrec_availability_zone *az, > + struct ic_context *ctx, > + struct ovsdb_idl_loop *ic_sb_loop) > { > - const struct icsbrec_availability_zone *az = az_run(ctx); > - VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet."); > + bool azs_cfg_equals = true; > + if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { > + return; > + } > > - if (!az) { > + const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( > + ctx->ovninb_idl); > + if (!ic_nb) { > + ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); > + } > + const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( > + ctx->ovnisb_idl); > + if (!ic_sb) { > + ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); > + } > + > + if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && > + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { > + /* Deal with potential overflows. */ > + if (az->nb_ic_cfg == LLONG_MAX) { > + icsbrec_availability_zone_set_nb_ic_cfg(az, 0); > + } > + ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; > + ovsdb_idl_txn_increment(ctx->ovnisb_txn, &az->header_, > + &icsbrec_availability_zone_col_nb_ic_cfg, > true); > return; > } > > + /* handle cases where accidentally AZ:ic_nb_cfg exceeds > + * the INB:ic_nb_cfg. > + */ > + if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { > + icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); > + return; > + } > + > + const struct icsbrec_availability_zone *other_az; > + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { > + if (other_az->nb_ic_cfg != az->nb_ic_cfg) { > + azs_cfg_equals = false; > If one of those doesn't equal we can just stop the iteration, we can even scratch the whole "azs_cfg_equals" variable and return here instead. Once all are equal it will proceed to the if below WDYT? > + } > + } > + > + if (azs_cfg_equals && (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg)) { > + icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); > + icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); > + } > +} > + > +static void > +ovn_db_run(struct ic_context *ctx, > + const struct icsbrec_availability_zone *az) > +{ > ts_run(ctx); > gateway_run(ctx, az); > port_binding_run(ctx, az); > @@ -2218,7 +2298,13 @@ main(int argc, char *argv[]) > ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && > ovsdb_idl_has_ever_connected(ctx.ovninb_idl) && > ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) { > - ovn_db_run(&ctx); > + const struct icsbrec_availability_zone *az = az_run(&ctx); > + VLOG_DBG("Availability zone: %s", az ? az->name : > + "not created yet."); > + if (az) { > + ovn_db_run(&ctx, az); > + update_sequence_numbers(az, &ctx, &ovnisb_idl_loop); > + } > } > > int rc1 = ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop); > -- > 2.34.3 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > Thanks, Ales -- Ales Musil Senior Software Engineer - OVN Core Red Hat EMEA <https://www.redhat.com> amu...@redhat.com <https://red.ht/sig> _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev