[{"id":3675689,"web_url":"http://patchwork.ozlabs.org/comment/3675689/","msgid":"<CALVEqe7iU6+eLj-KQpg1uurtWanFfbhgGufWg4GEL_cD=W7qRA@mail.gmail.com>","list_archive_url":null,"date":"2026-04-10T07:14:19","subject":"Re: [ovs-dev] [PATCH ovn v3] ovn-ic: Use dual IC-SB connections to\n prevent constraint violations.","submitter":{"id":83634,"url":"http://patchwork.ozlabs.org/api/people/83634/","name":"Ales Musil","email":"amusil@redhat.com"},"content":"On Mon, Feb 23, 2026 at 6:47 PM Tiago Matos via dev <ovs-dev@openvswitch.org>\nwrote:\n\n> When multiple Availability Zones (AZs) are connected via OVN-IC,\n> certain events trigger all AZs to attempt writing the same data to the\n> IC-SB simultaneously. This race condition leads to constraint\n> violations, causing transaction failures and forcing expensive full\n> recomputes.\n>\n> To mitigate this, this patch introduces a write-segregation mechanism\n> employing two distinct connections to IC-SB:\n> 1. Locked Connection: Acquires a lock to handle data that only a\n>    single AZ should write (e.g., creating a new datapath_binding for a\n>    transit switch/router).\n>\n> 2. Lockless Connections: Used for data that multiple AZs can safely\n>    insert concurrently (e.g., creating a new port_binding).\n>\n> Signed-off-by: Tiago Matos <tiago.reis@luizalabs.com>\n> ---\n>\n\nHi Tiago,\n\nsorry for the delay and thank you for the patch. I have a few comments down\nbelow.\n\n\n>  ic/inc-proc-ic.c |   6 +-\n>  ic/inc-proc-ic.h |   1 +\n>  ic/ovn-ic.c      | 186 +++++++++++++++++++++++++++++++++++------------\n>  ic/ovn-ic.h      |   2 +\n>  4 files changed, 145 insertions(+), 50 deletions(-)\n>\n> diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\n> index 995f23433..2c0420292 100644\n> --- a/ic/inc-proc-ic.c\n> +++ b/ic/inc-proc-ic.c\n> @@ -27,6 +27,7 @@\n>  #include \"openvswitch/vlog.h\"\n>  #include \"inc-proc-ic.h\"\n>  #include \"en-ic.h\"\n> +#include \"ovn-util.h\"\n>  #include \"unixctl.h\"\n>  #include \"util.h\"\n>\n> @@ -214,7 +215,7 @@ inc_proc_ic_run(struct ic_context *ctx,\n>                  struct ic_engine_context *ic_eng_ctx)\n>  {\n>      ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn &&\n> -               ctx->ovninb_txn && ctx->ovnisb_txn);\n> +               ctx->ovninb_txn && ctx->ovnisb_unlocked_txn);\n>\n>      int64_t start = time_msec();\n>      engine_init_run();\n> @@ -262,7 +263,8 @@ inc_proc_ic_can_run(struct ic_engine_context *ctx)\n>          ctx->nb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n>          ctx->sb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n>          ctx->inb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n> -        ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) {\n> +        ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n> +        ctx->isb_unlock_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) {\n>          return true;\n>      }\n>\n> diff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h\n> index 9af147fb3..36464564d 100644\n> --- a/ic/inc-proc-ic.h\n> +++ b/ic/inc-proc-ic.h\n> @@ -13,6 +13,7 @@ struct ic_engine_context {\n>      uint64_t sb_idl_duration_ms;\n>      uint64_t inb_idl_duration_ms;\n>      uint64_t isb_idl_duration_ms;\n> +    uint64_t isb_unlock_idl_duration_ms;\n>      uint32_t backoff_ms;\n>  };\n>\n> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\n> index 95d73cb4b..0adf637c8 100644\n> --- a/ic/ovn-ic.c\n> +++ b/ic/ovn-ic.c\n> @@ -115,8 +115,9 @@ az_run(struct ic_context *ctx)\n>       * \"ovn-ic-sbctl destroy avail <az>\". */\n>      static char *az_name;\n>      const struct icsbrec_availability_zone *az;\n> -    if (ctx->ovnisb_txn && az_name && strcmp(az_name, nb_global->name)) {\n> -        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {\n> +    if (ctx->ovnisb_unlocked_txn && az_name\n> +        && strcmp(az_name, nb_global->name)) {\n> +        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_idl)\n> {\n>              /* AZ name update locally need to update az in ISB. */\n>              if (nb_global->name[0] && !strcmp(az->name, az_name)) {\n>                  icsbrec_availability_zone_set_name(az, nb_global->name);\n> @@ -138,11 +139,11 @@ az_run(struct ic_context *ctx)\n>          az_name = xstrdup(nb_global->name);\n>      }\n>\n> -    if (ctx->ovnisb_txn) {\n> -        ovsdb_idl_txn_add_comment(ctx->ovnisb_txn, \"AZ %s\", az_name);\n> +    if (ctx->ovnisb_unlocked_txn) {\n> +        ovsdb_idl_txn_add_comment(ctx->ovnisb_unlocked_txn, \"AZ %s\",\n> az_name);\n>      }\n>\n> -    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {\n> +    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_idl) {\n>          if (!strcmp(az->name, az_name)) {\n>              ctx->runned_az = az;\n>              return az;\n> @@ -150,9 +151,9 @@ az_run(struct ic_context *ctx)\n>      }\n>\n>      /* Create AZ in ISB */\n> -    if (ctx->ovnisb_txn) {\n> +    if (ctx->ovnisb_unlocked_txn) {\n>          VLOG_INFO(\"Register AZ %s to interconnection DB.\", az_name);\n> -        az = icsbrec_availability_zone_insert(ctx->ovnisb_txn);\n> +        az = icsbrec_availability_zone_insert(ctx->ovnisb_unlocked_txn);\n>          icsbrec_availability_zone_set_name(az, az_name);\n>          ctx->runned_az = az;\n>          return az;\n> @@ -195,7 +196,7 @@ enumerate_datapaths(struct ic_context *ctx, struct\n> hmap *dp_tnlids,\n>                      struct shash *isb_ts_dps, struct shash *isb_tr_dps)\n>  {\n>      const struct icsbrec_datapath_binding *isb_dp;\n> -    ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) {\n> +    ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_unlocked_idl) {\n>          ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key);\n>\n>          enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp);\n> @@ -209,6 +210,20 @@ enumerate_datapaths(struct ic_context *ctx, struct\n> hmap *dp_tnlids,\n>      }\n>  }\n>\n> +/*\n> + * Check if the AZ is the leader by checking the lock.\n> + */\n> +static bool\n> +is_az_leader(struct ovsdb_idl_txn *txn)\n> +{\n> +    struct ovsdb_idl *idl = ovsdb_idl_txn_get_idl(txn);\n> +    if (idl && ovsdb_idl_has_lock(idl)) {\n> +        return true;\n> +    }\n> +\n> +    return false;\n>\n\nnit: \"return idl && ovsdb_idl_has_lock(idl)\".\n\n+}\n> +\n>  static void\n>  ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n>         struct shash *isb_ts_dps)\n> @@ -221,7 +236,7 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n>\n>      if (ic_nb && smap_get_bool(&ic_nb->options, \"vxlan_mode\", false)) {\n>          const struct icsbrec_encap *encap;\n> -        ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_idl) {\n> +        ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_unlocked_idl) {\n>              if (!strcmp(encap->type, \"vxlan\")) {\n>                  vxlan_mode = true;\n>                  break;\n> @@ -294,7 +309,8 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n>      /* Sync TS between INB and ISB.  This is performed after syncing with\n> AZ\n>       * SB, to avoid uncommitted ISB datapath tunnel key to be synced back\n> to\n>       * AZ. */\n> -    if (ctx->ovnisb_txn) {\n> +    if (ctx->ovnisb_txn &&\n> +        is_az_leader(ctx->ovnisb_txn)) {\n>          /* Create ISB Datapath_Binding */\n>          ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {\n>              const struct icsbrec_datapath_binding *isb_dp =\n> @@ -383,7 +399,8 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n>      /* Sync TR between INB and ISB.  This is performed after syncing with\n> AZ\n>       * SB, to avoid uncommitted ISB datapath tunnel key to be synced back\n> to\n>       * AZ. */\n> -    if (ctx->ovnisb_txn) {\n> +    if (ctx->ovnisb_txn &&\n> +        is_az_leader(ctx->ovnisb_txn)) {\n>\n\nWe need to be careful that we don't take any pointer\nfrom the unlocked IDL for the insertion. This is not the\ncase now, but maybe we should add a comment to\nemphasize that.\n\n         /* Create ISB Datapath_Binding */\n>          const struct icnbrec_transit_router *tr;\n>          ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {\n> @@ -488,7 +505,7 @@ sync_sb_gw_to_isb(struct ic_context *ctx,\n>      struct icsbrec_encap **isb_encaps =\n>          xmalloc(chassis->n_encaps * sizeof *isb_encaps);\n>      for (int i = 0; i < chassis->n_encaps; i++) {\n> -        isb_encap = icsbrec_encap_insert(ctx->ovnisb_txn);\n> +        isb_encap = icsbrec_encap_insert(ctx->ovnisb_unlocked_txn);\n\n         icsbrec_encap_set_gateway_name(isb_encap,\n>                                        chassis->name);\n>          icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);\n> @@ -506,14 +523,14 @@ sync_sb_gw_to_isb(struct ic_context *ctx,\n>  static void\n>  gateway_run(struct ic_context *ctx)\n>  {\n> -    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n> +    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {\n>          return;\n>      }\n>\n>      struct shash local_gws = SHASH_INITIALIZER(&local_gws);\n>      struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);\n>      const struct icsbrec_gateway *gw;\n> -    ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_idl) {\n> +    ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) {\n>          if (gw->availability_zone == ctx->runned_az) {\n>              shash_add(&local_gws, gw->name, gw);\n>          } else {\n> @@ -526,7 +543,7 @@ gateway_run(struct ic_context *ctx)\n>          if (smap_get_bool(&chassis->other_config, \"is-interconn\", false))\n> {\n>              gw = shash_find_and_delete(&local_gws, chassis->name);\n>              if (!gw) {\n> -                gw = icsbrec_gateway_insert(ctx->ovnisb_txn);\n> +                gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn);\n>                  icsbrec_gateway_set_availability_zone(gw, ctx->runned_az);\n>                  icsbrec_gateway_set_name(gw, chassis->name);\n>                  sync_sb_gw_to_isb(ctx, chassis, gw);\n> @@ -980,7 +997,7 @@ create_isb_pb(struct ic_context *ctx, const char\n> *logical_port,\n>      }\n>\n>      const struct icsbrec_port_binding *isb_pb =\n> -        icsbrec_port_binding_insert(ctx->ovnisb_txn);\n> +        icsbrec_port_binding_insert(ctx->ovnisb_unlocked_txn);\n>      icsbrec_port_binding_set_availability_zone(isb_pb, az);\n>      icsbrec_port_binding_set_transit_switch(isb_pb, ts_name);\n>      icsbrec_port_binding_set_logical_port(isb_pb, logical_port);\n> @@ -1068,7 +1085,7 @@ find_lsp_in_sb(struct ic_context *ctx,\n>  static void\n>  port_binding_run(struct ic_context *ctx)\n>  {\n> -    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n> +    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n>          return;\n>      }\n>\n> @@ -2252,7 +2269,7 @@ advertise_routes(struct ic_context *ctx,\n>                   const char *ts_name,\n>                   struct hmap *routes_ad)\n>  {\n> -    ovs_assert(ctx->ovnisb_txn);\n> +    ovs_assert(ctx->ovnisb_unlocked_txn);\n>      const struct icsbrec_route *isb_route;\n>      const struct icsbrec_route *isb_route_key =\n>          icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts_az);\n> @@ -2294,7 +2311,7 @@ advertise_routes(struct ic_context *ctx,\n>      /* Create the missing routes in IC-SB */\n>      struct ic_route_info *route_adv;\n>      HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) {\n> -        isb_route = icsbrec_route_insert(ctx->ovnisb_txn);\n> +        isb_route = icsbrec_route_insert(ctx->ovnisb_unlocked_txn);\n>          icsbrec_route_set_transit_switch(isb_route, ts_name);\n>          icsbrec_route_set_availability_zone(isb_route, az);\n>\n> @@ -2526,7 +2543,7 @@ delete_orphan_ic_routes(struct ic_context *ctx,\n>  static void\n>  route_run(struct ic_context *ctx)\n>  {\n> -    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n> +    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n>          return;\n>      }\n>\n> @@ -2958,7 +2975,7 @@ destroy_service_monitor_data(struct\n> sync_service_monitor_data *sync_data)\n>  static void\n>  sync_service_monitor(struct ic_context *ctx)\n>  {\n> -    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n> +    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {\n>          return;\n>      }\n>\n> @@ -2980,7 +2997,7 @@ sync_service_monitor(struct ic_context *ctx)\n>          if (ic_rec) {\n>              sbrec_service_monitor_set_status(db_rec, ic_rec->status);\n>          } else {\n> -            ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn);\n> +            ic_rec =\n> icsbrec_service_monitor_insert(ctx->ovnisb_unlocked_txn);\n>              icsbrec_service_monitor_set_type(ic_rec, db_rec->type);\n>              icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip);\n>              icsbrec_service_monitor_set_port(ic_rec, db_rec->port);\n> @@ -3085,7 +3102,7 @@ static void\n>  update_sequence_numbers(struct ic_context *ctx,\n>                          struct ovsdb_idl_loop *ic_sb_loop)\n>  {\n> -    if (!ctx->ovnisb_txn || !ctx->ovninb_txn) {\n> +    if (!ctx->ovnisb_unlocked_txn || !ctx->ovninb_txn) {\n>          return;\n>      }\n>\n> @@ -3095,9 +3112,9 @@ update_sequence_numbers(struct ic_context *ctx,\n>          ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn);\n>      }\n>      const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first(\n> -                                               ctx->ovnisb_idl);\n> +                                               ctx->ovnisb_unlocked_idl);\n>      if (!ic_sb) {\n> -        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn);\n> +        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_unlocked_txn);\n>      }\n>\n>      if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) &&\n> @@ -3107,7 +3124,8 @@ update_sequence_numbers(struct ic_context *ctx,\n>              icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, 0);\n>          }\n>          ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg;\n> -        ovsdb_idl_txn_increment(ctx->ovnisb_txn, &ctx->runned_az->header_,\n> +        ovsdb_idl_txn_increment(ctx->ovnisb_unlocked_txn,\n> +                                &ctx->runned_az->header_,\n>              &icsbrec_availability_zone_col_nb_ic_cfg, true);\n>          return;\n>      }\n> @@ -3122,7 +3140,7 @@ update_sequence_numbers(struct ic_context *ctx,\n>      }\n>\n>      const struct icsbrec_availability_zone *other_az;\n> -    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) {\n> +    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az,\n> ctx->ovnisb_unlocked_idl) {\n>          if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) {\n>              return;\n>          }\n> @@ -3331,6 +3349,7 @@ static void\n>  update_idl_probe_interval(struct ovsdb_idl *ovn_sb_idl,\n>                            struct ovsdb_idl *ovn_nb_idl,\n>                            struct ovsdb_idl *ovn_icsb_idl,\n> +                          struct ovsdb_idl *ovn_icsb_unlocked_idl,\n>                            struct ovsdb_idl *ovn_icnb_idl)\n>  {\n>      const struct nbrec_nb_global *nb = nbrec_nb_global_first(ovn_nb_idl);\n> @@ -3349,6 +3368,7 @@ update_idl_probe_interval(struct ovsdb_idl\n> *ovn_sb_idl,\n>                                     ic_interval);\n>      }\n>      set_idl_probe_interval(ovn_icsb_idl, ovn_ic_sb_db, ic_interval);\n> +    set_idl_probe_interval(ovn_icsb_unlocked_idl, ovn_ic_sb_db,\n> ic_interval);\n>      set_idl_probe_interval(ovn_icnb_idl, ovn_ic_nb_db, ic_interval);\n>  }\n>\n> @@ -3389,7 +3409,27 @@ main(int argc, char *argv[])\n>          ovsdb_idl_create(ovn_ic_nb_db, &icnbrec_idl_class, true, true));\n>      ovsdb_idl_track_add_all(ovninb_idl_loop.idl);\n>\n> -    /* ovn-ic-sb db. */\n> +    /*\n> +     * Each ovn-ic instance maintains two connections to the IC-SB\n> database:\n> +     * 1. Locked Connection: Competes for a global lock on IC-SB. Used for\n> +     * writes that must be performed by only one active instance\n> +     * (e.g., inserting a datapath_binding for a transit switch/router).\n> +     *\n> +     * 2. Unlocked Connection: Does not hold a lock. Used for writes that\n> +     * can be safely performed by multiple instances simultaneously\n> +     * (e.g., inserting a port_binding).\n> +     *\n> +     * This segregation prevents constraint violations and a full\n> recompute\n> +     * when writing to IC-SB.\n> +     */\n> +    /* ovn-ic-sb db without lock. */\n> +    struct ovsdb_idl_loop ovnisb_unlocked_idl_loop =\n> +        OVSDB_IDL_LOOP_INITIALIZER(ovsdb_idl_create(ovn_ic_sb_db,\n> +                                                    &icsbrec_idl_class,\n> +                                                    true, true));\n> +    ovsdb_idl_track_add_all(ovnisb_unlocked_idl_loop.idl);\n> +\n> +    /* ovn-ic-sb db with lock. */\n>      struct ovsdb_idl_loop ovnisb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n>          ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true));\n>      ovsdb_idl_track_add_all(ovnisb_idl_loop.idl);\n> @@ -3614,41 +3654,41 @@ main(int argc, char *argv[])\n>                                    &icnbrec_transit_switch_col_name);\n>\n>      struct ovsdb_idl_index *icsbrec_port_binding_by_az\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>\n>  &icsbrec_port_binding_col_availability_zone);\n>\n>      struct ovsdb_idl_index *icsbrec_port_binding_by_ts\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>\n>  &icsbrec_port_binding_col_transit_switch);\n>\n>      struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az\n> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl,\n>\n>  &icsbrec_port_binding_col_transit_switch,\n>\n>  &icsbrec_port_binding_col_availability_zone);\n>\n>      struct ovsdb_idl_index *icsbrec_route_by_az\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>                                    &icsbrec_route_col_availability_zone);\n>\n>      struct ovsdb_idl_index *icsbrec_route_by_ts\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>                                    &icsbrec_route_col_transit_switch);\n>\n>      struct ovsdb_idl_index *icsbrec_route_by_ts_az\n> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl,\n>                                    &icsbrec_route_col_transit_switch,\n>                                    &icsbrec_route_col_availability_zone);\n>\n>      struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>              &icsbrec_service_monitor_col_source_availability_zone);\n>\n>      struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az\n> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create1(ovnisb_unlocked_idl_loop.idl,\n>              &icsbrec_service_monitor_col_target_availability_zone);\n>\n>      struct ovsdb_idl_index\n> *icsbrec_service_monitor_by_target_az_logical_port\n> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n> +        = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl,\n>              &icsbrec_service_monitor_col_target_availability_zone,\n>              &icsbrec_service_monitor_col_logical_port);\n>\n> @@ -3661,14 +3701,26 @@ main(int argc, char *argv[])\n>      unixctl_command_register(\"ic-sb-connection-status\", \"\", 0, 0,\n>                               ovn_conn_show, ovnisb_idl_loop.idl);\n>\n> +    if (!ovsdb_idl_has_lock(ovnisb_idl_loop.idl) &&\n> +        !ovsdb_idl_is_lock_contended(ovnisb_idl_loop.idl)) {\n> +        /*\n> +         * Ensure that only a single ovn-ic has the permission to\n> +         * write to IC-SB.\n> +         */\n> +        VLOG_INFO(\"OVN ISB lock acquired. \"\n> +                  \"This ovn-ic instance is now active.\");\n> +        ovsdb_idl_set_lock(ovnisb_idl_loop.idl, \"ovn_ic_sb\");\n> +    }\n>\n\nThis block should be at the same place as the SB lock,\nbecause otherwise we won't attempt to take it again\nafter reconnecting. Also we don't release the lock when\novn-ic is paused, which would cause \"deadlock\".\n\n+\n>      /* Initialize incremental processing engine for ovn-northd */\n>      inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop,\n> -                     &ovninb_idl_loop, &ovnisb_idl_loop);\n> +                     &ovninb_idl_loop, &ovnisb_unlocked_idl_loop);\n>\n>      unsigned int ovnnb_cond_seqno = UINT_MAX;\n>      unsigned int ovnsb_cond_seqno = UINT_MAX;\n>      unsigned int ovninb_cond_seqno = UINT_MAX;\n>      unsigned int ovnisb_cond_seqno = UINT_MAX;\n> +    unsigned int ovnisb_unlocked_cond_seqno = UINT_MAX;\n>\n>      /* Main loop. */\n>      struct ic_engine_context  eng_ctx = {0};\n> @@ -3680,7 +3732,9 @@ main(int argc, char *argv[])\n>      while (!exiting) {\n>          update_ssl_config();\n>          update_idl_probe_interval(ovnsb_idl_loop.idl, ovnnb_idl_loop.idl,\n> -                                  ovnisb_idl_loop.idl,\n> ovninb_idl_loop.idl);\n> +                                  ovnisb_idl_loop.idl,\n> +                                  ovnisb_unlocked_idl_loop.idl,\n> +                                  ovninb_idl_loop.idl);\n>          memory_run();\n>          if (memory_should_report()) {\n>              struct simap usage = SIMAP_INITIALIZER(&usage);\n> @@ -3754,6 +3808,20 @@ main(int argc, char *argv[])\n>                  ovnisb_cond_seqno = new_ovnisb_cond_seqno;\n>              }\n>\n> +            struct ovsdb_idl_txn *ovnisb_unlocked_txn =\n> +                run_idl_loop(&ovnisb_unlocked_idl_loop,\n> \"OVN_IC_Southbound\",\n> +                             &eng_ctx.isb_unlock_idl_duration_ms);\n> +            unsigned int new_ovnisb_unlocked_cond_seqno =\n> +\n> ovsdb_idl_get_condition_seqno(ovnisb_unlocked_idl_loop.idl);\n> +            if (new_ovnisb_unlocked_cond_seqno !=\n> ovnisb_unlocked_cond_seqno) {\n> +                if (!new_ovnisb_unlocked_cond_seqno) {\n> +                    VLOG_INFO(\"OVN ISB IDL Unlocked reconnected,\"\n>\n\nnit: Missing space after \",\".\n\n+                              \"force recompute.\");\n> +                    inc_proc_ic_force_recompute();\n> +                }\n> +                ovnisb_unlocked_cond_seqno =\n> new_ovnisb_unlocked_cond_seqno;\n> +            }\n> +\n>              struct ic_context ctx = {\n>                  .ovnnb_idl = ovnnb_idl_loop.idl,\n>                  .ovnnb_txn = ovnnb_txn,\n> @@ -3763,6 +3831,8 @@ main(int argc, char *argv[])\n>                  .ovninb_txn = ovninb_txn,\n>                  .ovnisb_idl = ovnisb_idl_loop.idl,\n>                  .ovnisb_txn = ovnisb_txn,\n> +                .ovnisb_unlocked_idl = ovnisb_unlocked_idl_loop.idl,\n> +                .ovnisb_unlocked_txn = ovnisb_unlocked_txn,\n>                  .nbrec_ls_by_name = nbrec_ls_by_name,\n>                  .nbrec_lr_by_name = nbrec_lr_by_name,\n>                  .nbrec_lrp_by_name = nbrec_lrp_by_name,\n> @@ -3810,15 +3880,17 @@ main(int argc, char *argv[])\n>                  ovsdb_idl_has_ever_connected(ctx.ovnnb_idl) &&\n>                  ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) &&\n>                  ovsdb_idl_has_ever_connected(ctx.ovninb_idl) &&\n> -                ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) {\n> +                ovsdb_idl_has_ever_connected(ctx.ovnisb_idl) &&\n> +\n> ovsdb_idl_has_ever_connected(ovnisb_unlocked_idl_loop.idl)) {\n>\n\nnit: We should use ctx.ovnisb_unlocked_idlhere too for consistency.\n\n                 if (ctx.ovnnb_txn && ctx.ovnsb_txn && ctx.ovninb_txn &&\n> -                    ctx.ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) {\n> +                    ctx.ovnisb_unlocked_txn &&\n> inc_proc_ic_can_run(&eng_ctx)) {\n>                      ctx.runned_az = az_run(&ctx);\n>                      VLOG_DBG(\"Availability zone: %s\", ctx.runned_az ?\n>                               ctx.runned_az->name : \"not created yet.\");\n>                      if (ctx.runned_az) {\n>                          (void) inc_proc_ic_run(&ctx, &eng_ctx);\n> -                        update_sequence_numbers(&ctx, &ovnisb_idl_loop);\n> +                        update_sequence_numbers(&ctx,\n> +\n> &ovnisb_unlocked_idl_loop);\n>                      }\n>                  } else if (!inc_proc_ic_get_force_recompute()) {\n>                      clear_idl_track = false;\n> @@ -3842,22 +3914,36 @@ main(int argc, char *argv[])\n>                                  \"force recompute next time.\");\n>                      inc_proc_ic_force_recompute_immediate();\n>                  }\n> -\n> -                if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop)) {\n> -                    VLOG_INFO(\"OVNISB commit failed, \"\n> +                if (!ovsdb_idl_loop_commit_and_wait(\n> +                                          &ovnisb_unlocked_idl_loop)) {\n> +                    VLOG_INFO(\"OVNISB Unlocked commit failed, \"\n>                                  \"force recompute next time.\");\n>                      inc_proc_ic_force_recompute_immediate();\n>                  }\n> +\n> +                /*\n> +                 * ovn-ic will only try to recompute a failed transaction\n> from\n> +                 * the locked connection IF the AZ has the lock.\n> +                 */\n> +                if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop) &&\n> +                    ovsdb_idl_has_lock(ovnisb_idl_loop.idl)) {\n> +                    VLOG_INFO(\"OVNISB commit failed, \"\n> +                              \"force recompute next time.\");\n> +                        inc_proc_ic_force_recompute_immediate();\n>\n\nnit: Wrong indentation.\n\n\n> +                }\n>              } else {\n>                  /* Make sure we send any pending requests, e.g., lock. */\n>                  int rc1 = ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop);\n>                  int rc2 = ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);\n>                  int rc3 =\n> ovsdb_idl_loop_commit_and_wait(&ovninb_idl_loop);\n>                  int rc4 =\n> ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop);\n> -                if (!rc1 || !rc2 || !rc3 || !rc4) {\n> -                    VLOG_DBG(\" a transaction failed in: %s %s %s %s\",\n> +                int rc5 =\n> +\n> ovsdb_idl_loop_commit_and_wait(&ovnisb_unlocked_idl_loop);\n> +                                if (!rc1 || !rc2 || !rc3 || !rc4 || !rc5)\n> {\n>\n\nnit: Wrong indentation.\n\n\n> +                    VLOG_DBG(\" a transaction failed in: %s %s %s %s %s\",\n>                              !rc1 ? \"nb\" : \"\", !rc2 ? \"sb\" : \"\",\n> -                            !rc3 ? \"ic_nb\" : \"\", !rc4 ? \"ic_sb\" : \"\");\n> +                             !rc3 ? \"ic_nb\" : \"\", !rc4 ? \"ic_sb\" : \"\",\n> +                             !rc5 ? \"ic_sb_unlocked\" : \"\");\n>                      /* A transaction failed. Wake up immediately to give\n>                      * opportunity to send the proper transaction\n>                      */\n> @@ -3885,10 +3971,12 @@ main(int argc, char *argv[])\n>              ovsdb_idl_run(ovnsb_idl_loop.idl);\n>              ovsdb_idl_run(ovninb_idl_loop.idl);\n>              ovsdb_idl_run(ovnisb_idl_loop.idl);\n> +            ovsdb_idl_run(ovnisb_unlocked_idl_loop.idl);\n>              ovsdb_idl_wait(ovnnb_idl_loop.idl);\n>              ovsdb_idl_wait(ovnsb_idl_loop.idl);\n>              ovsdb_idl_wait(ovninb_idl_loop.idl);\n>              ovsdb_idl_wait(ovnisb_idl_loop.idl);\n> +            ovsdb_idl_wait(ovnisb_unlocked_idl_loop.idl);\n>\n>              /* Force a full recompute next time we become active. */\n>              inc_proc_ic_force_recompute_immediate();\n> @@ -3899,6 +3987,7 @@ main(int argc, char *argv[])\n>              ovsdb_idl_track_clear(ovnsb_idl_loop.idl);\n>              ovsdb_idl_track_clear(ovninb_idl_loop.idl);\n>              ovsdb_idl_track_clear(ovnisb_idl_loop.idl);\n> +            ovsdb_idl_track_clear(ovnisb_unlocked_idl_loop.idl);\n>          }\n>\n>          unixctl_server_run(unixctl);\n> @@ -3920,6 +4009,7 @@ main(int argc, char *argv[])\n>      ovsdb_idl_loop_destroy(&ovnsb_idl_loop);\n>      ovsdb_idl_loop_destroy(&ovninb_idl_loop);\n>      ovsdb_idl_loop_destroy(&ovnisb_idl_loop);\n> +    ovsdb_idl_loop_destroy(&ovnisb_unlocked_idl_loop);\n>      service_stop();\n>\n>      exit(res);\n> diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h\n> index 7391a19d4..9f52bb0f9 100644\n> --- a/ic/ovn-ic.h\n> +++ b/ic/ovn-ic.h\n> @@ -22,10 +22,12 @@ struct ic_context {\n>      struct ovsdb_idl *ovnsb_idl;\n>      struct ovsdb_idl *ovninb_idl;\n>      struct ovsdb_idl *ovnisb_idl;\n> +    struct ovsdb_idl *ovnisb_unlocked_idl;\n>      struct ovsdb_idl_txn *ovnnb_txn;\n>      struct ovsdb_idl_txn *ovnsb_txn;\n>      struct ovsdb_idl_txn *ovninb_txn;\n>      struct ovsdb_idl_txn *ovnisb_txn;\n> +    struct ovsdb_idl_txn *ovnisb_unlocked_txn;\n>      const struct icsbrec_availability_zone *runned_az;\n>      struct ovsdb_idl_index *nbrec_ls_by_name;\n>      struct ovsdb_idl_index *nbrec_lr_by_name;\n> --\n> 2.53.0\n>\n>\n> --\n>\n>\n>\n>\n> _'Esta mensagem é direcionada apenas para os endereços constantes no\n> cabeçalho inicial. Se você não está listado nos endereços constantes no\n> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa\n> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas\n> estão\n> imediatamente anuladas e proibidas'._\n>\n>\n> * **'Apesar do Magazine Luiza tomar\n> todas as precauções razoáveis para assegurar que nenhum vírus esteja\n> presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por\n> quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.*\n>\n>\n>\n> _______________________________________________\n> dev mailing list\n> dev@openvswitch.org\n> https://mail.openvswitch.org/mailman/listinfo/ovs-dev\n>\n>\nWe should probably add a test that will excecise\nthe locking a bit e.g. two ovn-ic and moving the lock\nby pausing while making sure that both actually can\nwrite TS/TR.\n\nRegards,\nAles","headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ovs-dev@lists.linuxfoundation.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=ZgomDsqx;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp3.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=ZgomDsqx","smtp4.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp4.osuosl.org; dkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=ZgomDsqx"],"Received":["from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fsSjc2PkJz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 10 Apr 2026 17:14:44 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id E90616085F;\n\tFri, 10 Apr 2026 07:14:41 +0000 (UTC)","from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 2Jcgfrty9WZi; Fri, 10 Apr 2026 07:14:40 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 13049607A7;\n\tFri, 10 Apr 2026 07:14:40 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id DE9E4C054A;\n\tFri, 10 Apr 2026 07:14:39 +0000 (UTC)","from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 62FDEC0549\n for <dev@openvswitch.org>; Fri, 10 Apr 2026 07:14:39 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id 4A34A40CD9\n for <dev@openvswitch.org>; Fri, 10 Apr 2026 07:14:39 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id keEwIz7-1F82 for <dev@openvswitch.org>;\n Fri, 10 Apr 2026 07:14:37 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp4.osuosl.org (Postfix) with ESMTPS id 890FD40BE8\n for <dev@openvswitch.org>; Fri, 10 Apr 2026 07:14:35 +0000 (UTC)","from mail-yw1-f198.google.com (mail-yw1-f198.google.com\n [209.85.128.198]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-495-5NI8iwLcN0eCx7429I9MRQ-1; Fri, 10 Apr 2026 03:14:32 -0400","by mail-yw1-f198.google.com with SMTP id\n 00721157ae682-794c39ea759so33177557b3.1\n for <dev@openvswitch.org>; Fri, 10 Apr 2026 00:14:32 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp3.osuosl.org 13049607A7","OpenDKIM Filter v2.11.0 smtp4.osuosl.org 890FD40BE8"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp4.osuosl.org 890FD40BE8","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775805274;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=Zxd/zfhZAmm2QYV/Pf652NxXA2osZVyFZGOaSt6V4iI=;\n b=ZgomDsqxWbaqqQMSFYgUlecTgOI9JDoNCWN28NIMOyZ0JqAnwPpCD3W8YAK4U/lfsznl87\n f2XYwESOBL+obcOA1tYA7m9wQWeqjToLQXCScNtUjxjhGjLJbVhSAIYss1rnbzQP3jCXCp\n gx2faECeGWvwjt3fT55BTG7DrGTk4Tw=","X-MC-Unique":"5NI8iwLcN0eCx7429I9MRQ-1","X-Mimecast-MFC-AGG-ID":"5NI8iwLcN0eCx7429I9MRQ_1775805272","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775805272; x=1776410072;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=Zxd/zfhZAmm2QYV/Pf652NxXA2osZVyFZGOaSt6V4iI=;\n b=EbNMly0J9ALFoV12LHKShrjzgxzEHJGJSZ05LedHTYjnhBuJ34HCw3EVWPm1DMu6LN\n UDLN8P7xfly93Du55gpRG6fFGDCH7B7Hgy1Bo7A8cFloLEdlrqbqWhha5fKUBfEpWzs6\n RR3wZ9WilWDLhD3Nj8VclwN6ETeiJ4F96I/K3YG+winX4VYgMxB2BlFRr2GDvBJYCyeF\n NCURQiWbBfER/o4PU5tZ3IG6RA1MfLJ5Xy4jhvUGEATC7Z81OPZczHHJcj/8gsl+w8K7\n v9HRjtsw/qXFUn8HH2gVdKRCTwwpE++MLUGyLWg2H42b7ObkgLWi3ElH9E7iZxDJBd3m\n yeBg==","X-Gm-Message-State":"AOJu0Yyyw+W6RAGnwBsDsl8WAh8tuwFFuGHUL8TvJ8In3vE9hh66MvcY\n Ep81B4Mt5vm6ndoddrvd/HF1fb5FMYQm29tbiDstTog1NcmsUgNtpDMZKn1yQJJic9hG5FaWLjg\n HgJT5p9wkZoCSIatuAIGrmYZ3eYmPaDmASk8//NKv9fklE7sqw3j/iGvib9r+W6VR8+BqD1JN99\n F1wX245XmcQAW/K7fniunvlIzIPItwBbfD+5GCOEs=","X-Gm-Gg":"AeBDiesgr4oSLFhD9y8y2bX00qYlv/KSIFyfLZRoQuwyBk0FmppK2U4liYt/E7j9PPp\n hpY2HSg+yPKXDCvXoOwF3t0ihQpL4nI7eVF9WrP2ZCbuJT+CSqYINOE0WgOtY4/h7a1QUqLJYLQ\n zALMUlBc1S91eGgpRZN3m5IkN4vnzdhoCwxEsABbzPu8LcO910Fc10IbNt20P1tdICXhZmUF2kc\n IIt6qZdU1rVjY0p5+44hw9KGVwJjpFkvJQHBaykdnUS0tpZqJ9PjP52t/ETkZb4jVKA9sCbASKX\n Yzo9MA2LXaFF/0SIzkiQzDncFRE6O845fw/8tcYeP0YpIbL3lOrOAPXPRCcPb4jRpUC6V2hjsaq\n UHiVLhNRyBKylG31gwfI29OdWcMYrS53GilIme0dXAPehklA=","X-Received":["by 2002:a05:690c:7681:b0:79e:d0e5:4069 with SMTP id\n 00721157ae682-7af7128890cmr16559537b3.26.1775805271662;\n Fri, 10 Apr 2026 00:14:31 -0700 (PDT)","by 2002:a05:690c:7681:b0:79e:d0e5:4069 with SMTP id\n 00721157ae682-7af7128890cmr16559397b3.26.1775805271010; Fri, 10 Apr 2026\n 00:14:31 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260223174615.65626-1-tiago.reis@luizalabs.com>","In-Reply-To":"<20260223174615.65626-1-tiago.reis@luizalabs.com>","Date":"Fri, 10 Apr 2026 09:14:19 +0200","X-Gm-Features":"AQROBzDq4eF80xGp9wSEkrP4BG5p7T5P2BULlyx90SDGEyc7laaRrdxkvsUbxH8","Message-ID":"\n <CALVEqe7iU6+eLj-KQpg1uurtWanFfbhgGufWg4GEL_cD=W7qRA@mail.gmail.com>","To":"Tiago Matos <tiago.reis@luizalabs.com>","Cc":"dev@openvswitch.org","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"49-CVnNSV8t15Zb6DAzNMBGUpRPGYF-n9JFCJFl4-Xo_1775805272","X-Mimecast-Originator":"redhat.com","X-Content-Filtered-By":"Mailman/MimeDel 2.1.30","Subject":"Re: [ovs-dev] [PATCH ovn v3] ovn-ic: Use dual IC-SB connections to\n prevent constraint violations.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","From":"Ales Musil via dev <ovs-dev@openvswitch.org>","Reply-To":"Ales Musil <amusil@redhat.com>","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}}]