When multiple Availability Zones (AZs) are connected via OVN-IC, certain events trigger all AZs to attempt writing the same data to the IC-SB simultaneously. This race condition leads to constraint violations, causing transaction failures and forcing expensive full recomputes.
To mitigate this, this patch introduces a write-segregation mechanism employing two distinct connections to IC-SB: 1. Locked Connection: Acquires a lock to handle data that only a single AZ should write (e.g., creating a new datapath_binding for a transit switch/router). 2. Lockless Connections: Used for data that multiple AZs can safely insert concurrently (e.g., creating a new port_binding). Signed-off-by: Tiago Matos <[email protected]> --- ic/inc-proc-ic.c | 6 +- ic/inc-proc-ic.h | 1 + ic/ovn-ic.c | 181 ++++++++++++++++++++++++++++++++++------------- ic/ovn-ic.h | 2 + 4 files changed, 140 insertions(+), 50 deletions(-) diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 995f23433..2c0420292 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -27,6 +27,7 @@ #include "openvswitch/vlog.h" #include "inc-proc-ic.h" #include "en-ic.h" +#include "ovn-util.h" #include "unixctl.h" #include "util.h" @@ -214,7 +215,7 @@ inc_proc_ic_run(struct ic_context *ctx, struct ic_engine_context *ic_eng_ctx) { ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn && - ctx->ovninb_txn && ctx->ovnisb_txn); + ctx->ovninb_txn && ctx->ovnisb_unlocked_txn); int64_t start = time_msec(); engine_init_run(); @@ -262,7 +263,8 @@ inc_proc_ic_can_run(struct ic_engine_context *ctx) ctx->nb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS || ctx->sb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS || ctx->inb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS || - ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) { + ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS || + ctx->isb_unlock_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) { return true; } diff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h index 9af147fb3..36464564d 100644 --- a/ic/inc-proc-ic.h +++ b/ic/inc-proc-ic.h @@ -13,6 +13,7 @@ struct ic_engine_context { uint64_t sb_idl_duration_ms; uint64_t inb_idl_duration_ms; uint64_t isb_idl_duration_ms; + uint64_t isb_unlock_idl_duration_ms; uint32_t backoff_ms; }; diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 95d73cb4b..eb60596b0 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -115,8 +115,8 @@ az_run(struct ic_context *ctx) * "ovn-ic-sbctl destroy avail <az>". */ static char *az_name; const struct icsbrec_availability_zone *az; - if (ctx->ovnisb_txn && az_name && strcmp(az_name, nb_global->name)) { - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { + if (ctx->ovnisb_unlocked_txn && az_name && strcmp(az_name, nb_global->name)) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_idl) { /* AZ name update locally need to update az in ISB. */ if (nb_global->name[0] && !strcmp(az->name, az_name)) { icsbrec_availability_zone_set_name(az, nb_global->name); @@ -138,11 +138,11 @@ az_run(struct ic_context *ctx) az_name = xstrdup(nb_global->name); } - if (ctx->ovnisb_txn) { - ovsdb_idl_txn_add_comment(ctx->ovnisb_txn, "AZ %s", az_name); + if (ctx->ovnisb_unlocked_txn) { + ovsdb_idl_txn_add_comment(ctx->ovnisb_unlocked_txn, "AZ %s", az_name); } - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_idl) { if (!strcmp(az->name, az_name)) { ctx->runned_az = az; return az; @@ -150,9 +150,9 @@ az_run(struct ic_context *ctx) } /* Create AZ in ISB */ - if (ctx->ovnisb_txn) { + if (ctx->ovnisb_unlocked_txn) { VLOG_INFO("Register AZ %s to interconnection DB.", az_name); - az = icsbrec_availability_zone_insert(ctx->ovnisb_txn); + az = icsbrec_availability_zone_insert(ctx->ovnisb_unlocked_txn); icsbrec_availability_zone_set_name(az, az_name); ctx->runned_az = az; return az; @@ -195,7 +195,7 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids, struct shash *isb_ts_dps, struct shash *isb_tr_dps) { const struct icsbrec_datapath_binding *isb_dp; - ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) { + ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_unlocked_idl) { ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key); enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp); @@ -209,6 +209,20 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids, } } +/* + * Check if the AZ is the leader by checking the lock. + */ +static bool +is_az_leader(struct ovsdb_idl_txn* txn) +{ + struct ovsdb_idl *idl = ovsdb_idl_txn_get_idl(txn); + if (idl && ovsdb_idl_has_lock(idl)) { + return true; + } + + return false; +} + static void ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, struct shash *isb_ts_dps) @@ -221,7 +235,7 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, if (ic_nb && smap_get_bool(&ic_nb->options, "vxlan_mode", false)) { const struct icsbrec_encap *encap; - ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_idl) { + ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_unlocked_idl) { if (!strcmp(encap->type, "vxlan")) { vxlan_mode = true; break; @@ -294,7 +308,8 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, /* Sync TS between INB and ISB. This is performed after syncing with AZ * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to * AZ. */ - if (ctx->ovnisb_txn) { + if (ctx->ovnisb_txn && + is_az_leader(ctx->ovnisb_txn)) { /* Create ISB Datapath_Binding */ ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) { const struct icsbrec_datapath_binding *isb_dp = @@ -383,7 +398,8 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids, /* Sync TR between INB and ISB. This is performed after syncing with AZ * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to * AZ. */ - if (ctx->ovnisb_txn) { + if (ctx->ovnisb_txn && + is_az_leader(ctx->ovnisb_txn)) { /* Create ISB Datapath_Binding */ const struct icnbrec_transit_router *tr; ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) { @@ -488,7 +504,7 @@ sync_sb_gw_to_isb(struct ic_context *ctx, struct icsbrec_encap **isb_encaps = xmalloc(chassis->n_encaps * sizeof *isb_encaps); for (int i = 0; i < chassis->n_encaps; i++) { - isb_encap = icsbrec_encap_insert(ctx->ovnisb_txn); + isb_encap = icsbrec_encap_insert(ctx->ovnisb_unlocked_txn); icsbrec_encap_set_gateway_name(isb_encap, chassis->name); icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip); @@ -506,14 +522,14 @@ sync_sb_gw_to_isb(struct ic_context *ctx, static void gateway_run(struct ic_context *ctx) { - if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) { return; } struct shash local_gws = SHASH_INITIALIZER(&local_gws); struct shash remote_gws = SHASH_INITIALIZER(&remote_gws); const struct icsbrec_gateway *gw; - ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_idl) { + ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) { if (gw->availability_zone == ctx->runned_az) { shash_add(&local_gws, gw->name, gw); } else { @@ -526,7 +542,7 @@ gateway_run(struct ic_context *ctx) if (smap_get_bool(&chassis->other_config, "is-interconn", false)) { gw = shash_find_and_delete(&local_gws, chassis->name); if (!gw) { - gw = icsbrec_gateway_insert(ctx->ovnisb_txn); + gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn); icsbrec_gateway_set_availability_zone(gw, ctx->runned_az); icsbrec_gateway_set_name(gw, chassis->name); sync_sb_gw_to_isb(ctx, chassis, gw); @@ -980,7 +996,7 @@ create_isb_pb(struct ic_context *ctx, const char *logical_port, } const struct icsbrec_port_binding *isb_pb = - icsbrec_port_binding_insert(ctx->ovnisb_txn); + icsbrec_port_binding_insert(ctx->ovnisb_unlocked_txn); icsbrec_port_binding_set_availability_zone(isb_pb, az); icsbrec_port_binding_set_transit_switch(isb_pb, ts_name); icsbrec_port_binding_set_logical_port(isb_pb, logical_port); @@ -1068,7 +1084,7 @@ find_lsp_in_sb(struct ic_context *ctx, static void port_binding_run(struct ic_context *ctx) { - if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) { return; } @@ -2252,7 +2268,7 @@ advertise_routes(struct ic_context *ctx, const char *ts_name, struct hmap *routes_ad) { - ovs_assert(ctx->ovnisb_txn); + ovs_assert(ctx->ovnisb_unlocked_txn); const struct icsbrec_route *isb_route; const struct icsbrec_route *isb_route_key = icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts_az); @@ -2294,7 +2310,7 @@ advertise_routes(struct ic_context *ctx, /* Create the missing routes in IC-SB */ struct ic_route_info *route_adv; HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) { - isb_route = icsbrec_route_insert(ctx->ovnisb_txn); + isb_route = icsbrec_route_insert(ctx->ovnisb_unlocked_txn); icsbrec_route_set_transit_switch(isb_route, ts_name); icsbrec_route_set_availability_zone(isb_route, az); @@ -2526,7 +2542,7 @@ delete_orphan_ic_routes(struct ic_context *ctx, static void route_run(struct ic_context *ctx) { - if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) { return; } @@ -2958,7 +2974,7 @@ destroy_service_monitor_data(struct sync_service_monitor_data *sync_data) static void sync_service_monitor(struct ic_context *ctx) { - if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) { return; } @@ -2980,7 +2996,7 @@ sync_service_monitor(struct ic_context *ctx) if (ic_rec) { sbrec_service_monitor_set_status(db_rec, ic_rec->status); } else { - ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn); + ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_unlocked_txn); icsbrec_service_monitor_set_type(ic_rec, db_rec->type); icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip); icsbrec_service_monitor_set_port(ic_rec, db_rec->port); @@ -3085,7 +3101,7 @@ static void update_sequence_numbers(struct ic_context *ctx, struct ovsdb_idl_loop *ic_sb_loop) { - if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { + if (!ctx->ovnisb_unlocked_txn || !ctx->ovninb_txn) { return; } @@ -3095,9 +3111,9 @@ update_sequence_numbers(struct ic_context *ctx, 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); + ctx->ovnisb_unlocked_idl); if (!ic_sb) { - ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); + ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_unlocked_txn); } if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && @@ -3107,7 +3123,8 @@ update_sequence_numbers(struct ic_context *ctx, icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, 0); } ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; - ovsdb_idl_txn_increment(ctx->ovnisb_txn, &ctx->runned_az->header_, + ovsdb_idl_txn_increment(ctx->ovnisb_unlocked_txn, + &ctx->runned_az->header_, &icsbrec_availability_zone_col_nb_ic_cfg, true); return; } @@ -3122,7 +3139,7 @@ update_sequence_numbers(struct ic_context *ctx, } const struct icsbrec_availability_zone *other_az; - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_unlocked_idl) { if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) { return; } @@ -3331,6 +3348,7 @@ static void update_idl_probe_interval(struct ovsdb_idl *ovn_sb_idl, struct ovsdb_idl *ovn_nb_idl, struct ovsdb_idl *ovn_icsb_idl, + struct ovsdb_idl *ovn_icsb_unlocked_idl, struct ovsdb_idl *ovn_icnb_idl) { const struct nbrec_nb_global *nb = nbrec_nb_global_first(ovn_nb_idl); @@ -3349,6 +3367,7 @@ update_idl_probe_interval(struct ovsdb_idl *ovn_sb_idl, ic_interval); } set_idl_probe_interval(ovn_icsb_idl, ovn_ic_sb_db, ic_interval); + set_idl_probe_interval(ovn_icsb_unlocked_idl, ovn_ic_sb_db, ic_interval); set_idl_probe_interval(ovn_icnb_idl, ovn_ic_nb_db, ic_interval); } @@ -3389,7 +3408,25 @@ main(int argc, char *argv[]) ovsdb_idl_create(ovn_ic_nb_db, &icnbrec_idl_class, true, true)); ovsdb_idl_track_add_all(ovninb_idl_loop.idl); - /* ovn-ic-sb db. */ + /* + * Each ovn-ic instance maintains two connections to the IC-SB database: + * 1. Locked Connection: Competes for a global lock on IC-SB. Used for + * writes that must be performed by only one active instance + * (e.g., inserting a datapath_binding for a transit switch/router). + * + * 2. Unlocked Connection: Does not hold a lock. Used for writes that + * can be safely performed by multiple instances simultaneously + * (e.g., inserting a port_binding). + * + * This segregation prevents constraint violations and a full recompute + * when writing to IC-SB. + */ + /* ovn-ic-sb db without lock. */ + struct ovsdb_idl_loop ovnisb_unlocked_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( + ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true)); + ovsdb_idl_track_add_all(ovnisb_unlocked_idl_loop.idl); + + /* ovn-ic-sb db with lock. */ struct ovsdb_idl_loop ovnisb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true)); ovsdb_idl_track_add_all(ovnisb_idl_loop.idl); @@ -3614,41 +3651,41 @@ main(int argc, char *argv[]) &icnbrec_transit_switch_col_name); struct ovsdb_idl_index *icsbrec_port_binding_by_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_port_binding_col_availability_zone); struct ovsdb_idl_index *icsbrec_port_binding_by_ts - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_port_binding_col_transit_switch); struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl, &icsbrec_port_binding_col_transit_switch, &icsbrec_port_binding_col_availability_zone); struct ovsdb_idl_index *icsbrec_route_by_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_route_col_availability_zone); struct ovsdb_idl_index *icsbrec_route_by_ts - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_route_col_transit_switch); struct ovsdb_idl_index *icsbrec_route_by_ts_az - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl, &icsbrec_route_col_transit_switch, &icsbrec_route_col_availability_zone); struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_service_monitor_col_source_availability_zone); struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl, &icsbrec_service_monitor_col_target_availability_zone); struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, + = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl, &icsbrec_service_monitor_col_target_availability_zone, &icsbrec_service_monitor_col_logical_port); @@ -3661,14 +3698,26 @@ main(int argc, char *argv[]) unixctl_command_register("ic-sb-connection-status", "", 0, 0, ovn_conn_show, ovnisb_idl_loop.idl); + if (!ovsdb_idl_has_lock(ovnisb_idl_loop.idl) && + !ovsdb_idl_is_lock_contended(ovnisb_idl_loop.idl)) { + /* + * Ensure that only a single ovn-ic has the permission to + * write to IC-SB. + */ + VLOG_INFO("OVN ISB lock acquired. " + "This ovn-ic instance is now active."); + ovsdb_idl_set_lock(ovnisb_idl_loop.idl, "ovn_ic_sb"); + } + /* Initialize incremental processing engine for ovn-northd */ inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop, - &ovninb_idl_loop, &ovnisb_idl_loop); + &ovninb_idl_loop, &ovnisb_unlocked_idl_loop); unsigned int ovnnb_cond_seqno = UINT_MAX; unsigned int ovnsb_cond_seqno = UINT_MAX; unsigned int ovninb_cond_seqno = UINT_MAX; unsigned int ovnisb_cond_seqno = UINT_MAX; + unsigned int ovnisb_unlocked_cond_seqno = UINT_MAX; /* Main loop. */ struct ic_engine_context eng_ctx = {0}; @@ -3680,7 +3729,9 @@ main(int argc, char *argv[]) while (!exiting) { update_ssl_config(); update_idl_probe_interval(ovnsb_idl_loop.idl, ovnnb_idl_loop.idl, - ovnisb_idl_loop.idl, ovninb_idl_loop.idl); + ovnisb_idl_loop.idl, + ovnisb_unlocked_idl_loop.idl, + ovninb_idl_loop.idl); memory_run(); if (memory_should_report()) { struct simap usage = SIMAP_INITIALIZER(&usage); @@ -3754,6 +3805,19 @@ main(int argc, char *argv[]) ovnisb_cond_seqno = new_ovnisb_cond_seqno; } + struct ovsdb_idl_txn *ovnisb_unlocked_txn = + run_idl_loop(&ovnisb_unlocked_idl_loop, "OVN_IC_Southbound", + &eng_ctx.isb_unlock_idl_duration_ms); + unsigned int new_ovnisb_unlocked_cond_seqno = + ovsdb_idl_get_condition_seqno(ovnisb_unlocked_idl_loop.idl); + if (new_ovnisb_unlocked_cond_seqno != ovnisb_unlocked_cond_seqno) { + if (!new_ovnisb_unlocked_cond_seqno) { + VLOG_INFO("OVN ISB IDL Unlocked reconnected, force recompute."); + inc_proc_ic_force_recompute(); + } + ovnisb_unlocked_cond_seqno = new_ovnisb_unlocked_cond_seqno; + } + struct ic_context ctx = { .ovnnb_idl = ovnnb_idl_loop.idl, .ovnnb_txn = ovnnb_txn, @@ -3763,6 +3827,8 @@ main(int argc, char *argv[]) .ovninb_txn = ovninb_txn, .ovnisb_idl = ovnisb_idl_loop.idl, .ovnisb_txn = ovnisb_txn, + .ovnisb_unlocked_idl = ovnisb_unlocked_idl_loop.idl, + .ovnisb_unlocked_txn = ovnisb_unlocked_txn, .nbrec_ls_by_name = nbrec_ls_by_name, .nbrec_lr_by_name = nbrec_lr_by_name, .nbrec_lrp_by_name = nbrec_lrp_by_name, @@ -3810,15 +3876,17 @@ main(int argc, char *argv[]) ovsdb_idl_has_ever_connected(ctx.ovnnb_idl) && ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && ovsdb_idl_has_ever_connected(ctx.ovninb_idl) && - ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) { + ovsdb_idl_has_ever_connected(ctx.ovnisb_idl) && + ovsdb_idl_has_ever_connected(ovnisb_unlocked_idl_loop.idl)) { if (ctx.ovnnb_txn && ctx.ovnsb_txn && ctx.ovninb_txn && - ctx.ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) { + ctx.ovnisb_unlocked_txn && inc_proc_ic_can_run(&eng_ctx)) { ctx.runned_az = az_run(&ctx); VLOG_DBG("Availability zone: %s", ctx.runned_az ? ctx.runned_az->name : "not created yet."); if (ctx.runned_az) { (void) inc_proc_ic_run(&ctx, &eng_ctx); - update_sequence_numbers(&ctx, &ovnisb_idl_loop); + update_sequence_numbers(&ctx, + &ovnisb_unlocked_idl_loop); } } else if (!inc_proc_ic_get_force_recompute()) { clear_idl_track = false; @@ -3842,22 +3910,35 @@ main(int argc, char *argv[]) "force recompute next time."); inc_proc_ic_force_recompute_immediate(); } - - if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop)) { - VLOG_INFO("OVNISB commit failed, " + if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_unlocked_idl_loop)) { + VLOG_INFO("OVNISB Unlocked commit failed, " "force recompute next time."); inc_proc_ic_force_recompute_immediate(); } + + /* + * ovn-ic will only try to recompute a failed transaction from + * the locked connection IF the AZ has the lock. + */ + if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop) && + ovsdb_idl_has_lock(ovnisb_idl_loop.idl)) { + VLOG_INFO("OVNISB commit failed, " + "force recompute next time."); + inc_proc_ic_force_recompute_immediate(); + } } else { /* Make sure we send any pending requests, e.g., lock. */ int rc1 = ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop); int rc2 = ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop); int rc3 = ovsdb_idl_loop_commit_and_wait(&ovninb_idl_loop); int rc4 = ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop); - if (!rc1 || !rc2 || !rc3 || !rc4) { - VLOG_DBG(" a transaction failed in: %s %s %s %s", + int rc5 = + ovsdb_idl_loop_commit_and_wait(&ovnisb_unlocked_idl_loop); + if (!rc1 || !rc2 || !rc3 || !rc4 || !rc5) { + VLOG_DBG(" a transaction failed in: %s %s %s %s %s", !rc1 ? "nb" : "", !rc2 ? "sb" : "", - !rc3 ? "ic_nb" : "", !rc4 ? "ic_sb" : ""); + !rc3 ? "ic_nb" : "", !rc4 ? "ic_sb" : "", + !rc5 ? "ic_sb_unlocked" : ""); /* A transaction failed. Wake up immediately to give * opportunity to send the proper transaction */ @@ -3885,10 +3966,12 @@ main(int argc, char *argv[]) ovsdb_idl_run(ovnsb_idl_loop.idl); ovsdb_idl_run(ovninb_idl_loop.idl); ovsdb_idl_run(ovnisb_idl_loop.idl); + ovsdb_idl_run(ovnisb_unlocked_idl_loop.idl); ovsdb_idl_wait(ovnnb_idl_loop.idl); ovsdb_idl_wait(ovnsb_idl_loop.idl); ovsdb_idl_wait(ovninb_idl_loop.idl); ovsdb_idl_wait(ovnisb_idl_loop.idl); + ovsdb_idl_wait(ovnisb_unlocked_idl_loop.idl); /* Force a full recompute next time we become active. */ inc_proc_ic_force_recompute_immediate(); @@ -3899,6 +3982,7 @@ main(int argc, char *argv[]) ovsdb_idl_track_clear(ovnsb_idl_loop.idl); ovsdb_idl_track_clear(ovninb_idl_loop.idl); ovsdb_idl_track_clear(ovnisb_idl_loop.idl); + ovsdb_idl_track_clear(ovnisb_unlocked_idl_loop.idl); } unixctl_server_run(unixctl); @@ -3920,6 +4004,7 @@ main(int argc, char *argv[]) ovsdb_idl_loop_destroy(&ovnsb_idl_loop); ovsdb_idl_loop_destroy(&ovninb_idl_loop); ovsdb_idl_loop_destroy(&ovnisb_idl_loop); + ovsdb_idl_loop_destroy(&ovnisb_unlocked_idl_loop); service_stop(); exit(res); diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h index 7391a19d4..9f52bb0f9 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -22,10 +22,12 @@ struct ic_context { struct ovsdb_idl *ovnsb_idl; struct ovsdb_idl *ovninb_idl; struct ovsdb_idl *ovnisb_idl; + struct ovsdb_idl *ovnisb_unlocked_idl; struct ovsdb_idl_txn *ovnnb_txn; struct ovsdb_idl_txn *ovnsb_txn; struct ovsdb_idl_txn *ovninb_txn; struct ovsdb_idl_txn *ovnisb_txn; + struct ovsdb_idl_txn *ovnisb_unlocked_txn; const struct icsbrec_availability_zone *runned_az; struct ovsdb_idl_index *nbrec_ls_by_name; struct ovsdb_idl_index *nbrec_lr_by_name; -- 2.53.0 -- _'Esta mensagem é direcionada apenas para os endereços constantes no cabeçalho inicial. Se você não está listado nos endereços constantes no cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão imediatamente anuladas e proibidas'._ * **'Apesar do Magazine Luiza tomar todas as precauções razoáveis para assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.* _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
