On Thu, Jan 23, 2025 at 4:03 PM Dumitru Ceara <[email protected]> wrote:

> On 1/17/25 2:03 PM, Ilya Maximets wrote:
> > On 1/17/25 11:03, Ales Musil wrote:
> >> On Tue, Jan 7, 2025 at 10:46 PM Ilya Maximets <[email protected]>
> wrote:
> >>
> >>> OVS allows enabling prefix match optimizations per flow table.  This
> >>> enables masked matches whenever possible on fields that otherwise would
> >>> be exact matched in the datapath flow.
> >>>
> >>> By default, however, only nw_src and nw_dst are enabled (L4 ports are
> >>> also always enabled, but this is not configurable).  OVN is using mixed
> >>> flow tables that match on both IPv4 and IPv6 addresses, meaning that
> >>> IPv6 traffic generates exact match datapath flows where IPv4 generates
> >>> masked matches, causing datapath flow explosion under heavy IPv6 load.
> >>>
> >>> OVN owns the "br-int" bridge and the flow tables, so it should enable
> >>> appropriate fields per flow table to avoid flow explosion and achieve
> >>> better performance overall.
> >>>
> >>> Example on how the prefixes can be configured manually:
> >>>
> >>>  for i in $(seq 0 254); do
> >>>    ovs-vsctl set Bridge br-int flow_tables:${i}=@N -- \
> >>>      --id=@N create Flow_Table name=t${i} \
> >>>                 prefixes=nw_src,nw_dst,ipv6_dst,ipv6_src;
> >>>  done
> >>>
> >>> Until recently, OVS only supported up to 3 prefixes per flow table, but
> >>> now the limit will be increased to 4 in OVS 3.5 and some newer minor
> >>> releases of older versions down to 3.3.
> >>> Unfortunately, that means that ovn-controller needs to check and choose
> >>> the appropriate number of prefixes.  For the 3 we may just add ipv6_src
> >>> and leave ipv6_dst unoptimized.
> >>>
> >>> OVS 3.5 will have all 4 prefixes enabled by default, but OVN will be
> >>> paired with older versions of OVS for a long time, so it's better to
> >>> set these config options to better support older setups.
> >>>
> >>> Unfortunately, IDL doesn't provide a way today to get the type of the
> >>> column from the server side, so it's hard to tell how many prefixes
> >>> are actually supported.  A few approaches:
> >>>
> >>> 1. Try 3 and 4 and check if transaction fails.
> >>> 2. Try to get and parse the schema from the server.
> >>> 3. Enhance IDL to provide server column type information.
> >>>
> >>> While the first approach seems simpler, it's actually not trivial to
> >>> figure out why exactly the transaction failed from the application
> >>> level.  IDL only has the string representation of the error and doesn't
> >>> provide it to the application.
> >>>
> >>> The third approach is the most clean one, but it requires modifications
> >>> of the IDL and CS layers in order to get this information.  This would
> >>> significantly complicate the process of getting this change backported
> >>> to OVN 24.03 LTS, for example.
> >>>
> >>> The second approach is taken by this commit with intention to replace
> >>> the schema parsing with the enhanced IDL API, once it is available.
> >>> This allows for easier backports today with a cleaner solution in the
> >>> future.
> >>>
> >>> IMO, the backportability is important due to increasing importance of
> >>> IPv6 in OVN clusters and the cloud environments in general.
> >>>
> >>> Reported-at: https://issues.redhat.com/browse/FDP-1024
> >>> Signed-off-by: Ilya Maximets <[email protected]>
> >>> ---
> >>>
> >>
> >>
> >> Hi Ilya,
> >>
> >> thank you for the patch, we have briefly discussed that offline,
> >> but I would to hear opinion of others especially maintainers (cced)
> >> whether we should wait a bit for the IDL API enhancement and proceed
> >> without the need for parsing inside ovn-controller.
> >>
>
> Hi Ilya, Ales,
>
> I didn't review the patch thoroughly yet but given that from what I see
> the parsing part is rather small and contained, I'd personally be OK
> with taking the patch as-is (after thorough review of course) instead of
> waiting for the IDL API enhancement.
>
> Once the IDL has the support we need we can easily remove the custom
> parsing code and use the proper API.
>

That's fair, I won't block this in any way.


> Regards,
> Dumitru
>
> >>
> >>
> >>>
> >>> Posting this version as a continuation to internal discussion with
> >>> Dumitru and Ales on how to detect server-side database types.
> >>>
> >>> However, this version is fully functional and is ready for review if we
> >>> agree on the approach.
> >>>
> >>> Note: For backpotrs, OVS submodules on older OVN branches will need to
> >>> be moved to latest commits on corresponding OVS branches.
> >>>
> >>>  NEWS                        |   3 ++
> >>>  TODO.rst                    |   3 ++
> >>>  controller/ovn-controller.c |  79 ++++++++++++++++++++++++++-
> >>>  include/ovn/features.h      |   4 +-
> >>>  lib/features.c              | 105 +++++++++++++++++++++++++++++++++++-
> >>>  lib/test-ovn-features.c     |   6 +--
> >>>  tests/ovn-controller.at     |  50 +++++++++++++++++
> >>>  7 files changed, 244 insertions(+), 6 deletions(-)
> >>>
> >>> diff --git a/NEWS b/NEWS
> >>> index 72c5a6339..3bd57784b 100644
> >>> --- a/NEWS
> >>> +++ b/NEWS
> >>> @@ -28,6 +28,9 @@ Post v24.09.0
> >>>         this option was not set).  TLS ciphersuites for TLSv1.3 and
> later
> >>> can
> >>>         be configured via --ssl-ciphersuites (--ssl-ciphers only
> applies to
> >>>         TLSv1.2 and earlier).
> >>> +   - Improved handling of IPv6 traffic by enabling address prefix
> tracking
> >>> +     in OVS for both IPv4 and IPv6 addresses, whenever possible,
> reducing
> >>> +     the amount of IPv6 datapath flows.
> >>>
> >>>  OVN v24.09.0 - 13 Sep 2024
> >>>  --------------------------
> >>> diff --git a/TODO.rst b/TODO.rst
> >>> index 3426497a7..2e004b0b1 100644
> >>> --- a/TODO.rst
> >>> +++ b/TODO.rst
> >>> @@ -136,3 +136,6 @@ OVN To-do List
> >>>
> >>>  * Remove ssl_ciphersuites workaround for clustered databases from
> ovn-ctl
> >>>    after 26.03 release, assuming it will be an LTS release.
> >>> +
> >>> +* Remove OVS database schema parsing from features.c once server side
> >>> column
> >>> +  types are available through IDL.
> >>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> >>> index d875ecc1e..fa87d9450 100644
> >>> --- a/controller/ovn-controller.c
> >>> +++ b/controller/ovn-controller.c
> >>> @@ -497,6 +497,77 @@ create_br_datapath(struct ovsdb_idl_txn
> *ovs_idl_txn,
> >>>      return dp;
> >>>  }
> >>>
> >>> +
> >>> +#define N_FLOW_TABLES 255
> >>> +
> >>> +static void
> >>> +update_flow_table_prefixes(struct ovsdb_idl_txn *ovs_idl_txn,
> >>> +                           const struct ovsrec_bridge *br_int)
> >>> +{
> >>> +    size_t max_prefixes = ovs_features_max_flow_table_prefixes_get();
> >>> +    struct ds ds = DS_EMPTY_INITIALIZER;
> >>> +    const char *prefixes[] = {
> >>> +        "ip_src", "ip_dst", "ipv6_src", "ipv6_dst",
> >>> +    };
> >>> +    struct ovsrec_flow_table *ft;
> >>> +    size_t i;
> >>> +
> >>> +    /* We must not attempt setting more prefixes than our IDL
> supports.
> >>> +     * Note: This should be a build time assertion, but IDL structures
> >>> +     * are not defined as constants. */
> >>> +    ovs_assert(
> >>> +        ARRAY_SIZE(prefixes) <=
> >>> +
> >>> ovsrec_flow_table_columns[OVSREC_FLOW_TABLE_COL_PREFIXES].type.n_max);
> >>> +
> >>> +    if (!max_prefixes) {
> >>> +        /* Not discovered yet. */
> >>> +        return;
> >>> +    }
> >>> +
> >>> +    max_prefixes = MIN(max_prefixes, ARRAY_SIZE(prefixes));
> >>> +    if (br_int->n_flow_tables == N_FLOW_TABLES &&
> >>> +        br_int->value_flow_tables[0]->n_prefixes == max_prefixes) {
> >>> +        /* Already up to date.  Ideally, we would check every table,
> >>> +         * but it seems excessive. */
> >>> +        return;
> >>> +    }
> >>>
> >>
> >> By moving this after we figure out if all flow tables point to the
> >> same row we can check that row and have definite proof that it is
> >> actually correct, WDYT?
> >
> > I didn't want to check all the tables to avoid burning CPU cycles for
> > nothing.  It may not be a big deal, but it felt excessive to check 255
> > tabes every time ovn-controller wakes up.  Chances that all the tables
> > are set, one of them is configured properly, but others are not, should
> > be negligeable, unless done intentionally by the user.
>

Fair point, I suppose we don't expect users messing with
the configuration.


> >
> >>
> >> +
> >>> +    for (i = 1; i < br_int->n_flow_tables; i++) {
> >>> +        if (br_int->value_flow_tables[i] !=
> br_int->value_flow_tables[0])
> >>> {
> >>> +            break;
> >>> +        }
> >>> +    }
> >>> +    if (i == N_FLOW_TABLES) {
> >>> +        /* Correct number of flow tables and all pointing to the same
> >>> row. */
> >>> +        ft = br_int->value_flow_tables[0];
> >>> +    } else {
> >>> +        /* Unexpected configuration.  Let's create a new flow table
> row.
> >>> +         * Old ones will be garbage collected by the database. */
> >>> +        struct ovsrec_flow_table *values[N_FLOW_TABLES];
> >>> +        int64_t keys[N_FLOW_TABLES];
> >>> +
> >>> +        ft = ovsrec_flow_table_insert(ovs_idl_txn);
> >>> +        for (i = 0; i < ARRAY_SIZE(values); i++) {
> >>> +            keys[i] = i;
> >>> +            values[i] = ft;
> >>> +        }
> >>> +        ovsrec_bridge_set_flow_tables(br_int, keys, values,
> >>> +                                      ARRAY_SIZE(values));
> >>> +    }
> >>> +
> >>> +    ds_put_cstr(&ds, "Setting flow table prefixes:");
> >>> +    for (i = 0 ; i < max_prefixes; i++) {
> >>> +        ds_put_char(&ds, ' ');
> >>> +        ds_put_cstr(&ds, prefixes[i]);
> >>> +        ds_put_char(&ds, ',');
> >>> +    }
> >>> +    ds_chomp(&ds, ',');
> >>> +    VLOG_INFO("%s.", ds_cstr_ro(&ds));
> >>> +    ds_destroy(&ds);
> >>> +
> >>> +    ovsrec_flow_table_set_prefixes(ft, prefixes, max_prefixes);
> >>> +}
> >>> +
> >>>  static const struct ovsrec_bridge *
> >>>  get_br_int(const struct ovsrec_bridge_table *bridge_table,
> >>>             const struct ovsrec_open_vswitch_table *ovs_table)
> >>> @@ -573,6 +644,8 @@ process_br_int(struct ovsdb_idl_txn *ovs_idl_txn,
> >>>                                                      datapath_type);
> >>>                  }
> >>>              }
> >>> +
> >>> +            update_flow_table_prefixes(ovs_idl_txn, br_int);
> >>>          }
> >>>      }
> >>>      *br_int_ = br_int;
> >>> @@ -793,8 +866,11 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_fail_mode);
> >>> +    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_flow_tables);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_other_config);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_external_ids);
> >>> +    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_flow_table);
> >>> +    ovsdb_idl_add_column(ovs_idl, &ovsrec_flow_table_col_prefixes);
> >>>      ovsdb_idl_add_table(ovs_idl, &ovsrec_table_ssl);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_bootstrap_ca_cert);
> >>>      ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_ca_cert);
> >>> @@ -5593,7 +5669,8 @@ main(int argc, char *argv[])
> >>>                  && ovs_feature_support_run(br_int_dp ?
> >>>                                             &br_int_dp->capabilities :
> >>> NULL,
> >>>                                             br_int_remote.target,
> >>> -
>  br_int_remote.probe_interval))
> >>> {
> >>> +
>  br_int_remote.probe_interval,
> >>> +                                           ovs_remote)) {
> >>>                  VLOG_INFO("OVS feature set changed, force
> recompute.");
> >>>                  engine_set_force_recompute();
> >>>
> >>> diff --git a/include/ovn/features.h b/include/ovn/features.h
> >>> index 3566ab60f..95f3704ca 100644
> >>> --- a/include/ovn/features.h
> >>> +++ b/include/ovn/features.h
> >>> @@ -56,9 +56,11 @@ enum ovs_feature_value {
> >>>  void ovs_feature_support_destroy(void);
> >>>  bool ovs_feature_is_supported(enum ovs_feature_value feature);
> >>>  bool ovs_feature_support_run(const struct smap *ovs_capabilities,
> >>> -                             const char *conn_target, int
> probe_interval);
> >>> +                             const char *conn_target, int
> probe_interval,
> >>> +                             const char *db_target);
> >>>  bool ovs_feature_set_discovered(void);
> >>>  uint32_t ovs_feature_max_meters_get(void);
> >>>  uint32_t ovs_feature_max_select_groups_get(void);
> >>> +size_t ovs_features_max_flow_table_prefixes_get(void);
> >>>
> >>>  #endif
> >>> diff --git a/lib/features.c b/lib/features.c
> >>> index 98d56602c..7302599ac 100644
> >>> --- a/lib/features.c
> >>> +++ b/lib/features.c
> >>> @@ -20,6 +20,9 @@
> >>>  #include "lib/util.h"
> >>>  #include "lib/dirs.h"
> >>>  #include "socket-util.h"
> >>> +#include "lib/ovsdb-cs.h"
> >>> +#include "lib/ovsdb-error.h"
> >>> +#include "lib/ovsdb-types.h"
> >>>  #include "lib/vswitch-idl.h"
> >>>  #include "odp-netlink.h"
> >>>  #include "openvswitch/vlog.h"
> >>> @@ -418,17 +421,99 @@ ovs_feature_get_openflow_cap(void)
> >>>      return ret;
> >>>  }
> >>>
> >>> +/* Monitoring how many prefixes flow tables can have.
> >>> + * TODO: Remove this code once the server column type is available via
> >>> IDL. */
> >>> +static struct ovsdb_cs *vswitch_cs;
> >>> +static size_t max_flow_table_prefixes;
> >>> +
> >>> +static struct json *
> >>> +vswitch_schema_prefixes_find(const struct json *schema_json,
> >>> +                             void *ctx OVS_UNUSED)
> >>> +{
> >>> +    /* We must return a monitor request object, but we do not actually
> >>> want
> >>> +     * to monitor the data, so returning an empty one. */
> >>> +    struct json *monitor_request = json_object_create();
> >>> +    struct ovsdb_idl_column *prefixes_col;
> >>> +
> >>> +    prefixes_col =
> >>> &ovsrec_flow_table_columns[OVSREC_FLOW_TABLE_COL_PREFIXES];
> >>> +
> >>> +    if (schema_json->type != JSON_OBJECT) {
> >>> +        VLOG_WARN_RL(&rl, "OVS database schema is not a JSON object");
> >>> +        return monitor_request;
> >>> +    }
> >>> +
> >>> +    const char *ft_name =
> >>> ovsrec_table_classes[OVSREC_TABLE_FLOW_TABLE].name;
> >>> +    const char *nested_objects[] = {
> >>> +        "tables", ft_name, "columns", prefixes_col->name, "type",
> >>> +    };
> >>> +    const struct json *nested = schema_json;
> >>> +
> >>> +    for (size_t i = 0; i < ARRAY_SIZE(nested_objects); i++) {
> >>> +        nested = shash_find_data(json_object(nested),
> nested_objects[i]);
> >>> +        if (!nested || nested->type != JSON_OBJECT) {
> >>> +            VLOG_WARN_RL(&rl, "OVS database schema has no valid
> '%s'.",
> >>> +                         nested_objects[i]);
> >>> +            return monitor_request;
> >>> +        }
> >>> +    }
> >>> +
> >>> +    struct ovsdb_type server_type;
> >>> +    struct ovsdb_error *error;
> >>> +
> >>> +    error = ovsdb_type_from_json(&server_type, nested);
> >>> +    if (error) {
> >>> +        char *msg = ovsdb_error_to_string_free(error);
> >>> +
> >>> +        VLOG_WARN_RL(&rl, "Failed to parse type of %s column in %s
> table:
> >>> %s",
> >>> +                     prefixes_col->name, ft_name, msg);
> >>> +        free(msg);
> >>> +        return monitor_request;
> >>> +    }
> >>> +
> >>> +    if (max_flow_table_prefixes != server_type.n_max) {
> >>> +        VLOG_INFO_RL(&rl, "OVS DB schema supports %d flow table
> prefixes,
> >>> "
> >>> +                          "our IDL supports: %d",
> >>> +                     server_type.n_max, prefixes_col->type.n_max);
> >>> +        max_flow_table_prefixes = server_type.n_max;
> >>> +    }
> >>> +
> >>> +    return monitor_request;
> >>> +}
> >>> +
> >>> +static struct ovsdb_cs_ops feature_cs_ops = {
> >>> +    .compose_monitor_requests = vswitch_schema_prefixes_find,
> >>> +};
> >>> +
> >>> +static void
> >>> +vswitch_schema_prefixes_run(void)
> >>> +{
> >>> +    struct ovsdb_cs_event *event;
> >>> +    struct ovs_list events;
> >>> +
> >>> +    ovsdb_cs_run(vswitch_cs, &events);
> >>> +    LIST_FOR_EACH_POP (event, list_node, &events) {
> >>> +        /* We're not really interested in events.  We only care about
> the
> >>> +         * monitor request callback being invoked on re-connections or
> >>> +         * schema changes. */
> >>> +        ovsdb_cs_event_destroy(event);
> >>> +    }
> >>> +    ovsdb_cs_wait(vswitch_cs);
> >>> +}
> >>> +
> >>>  void
> >>>  ovs_feature_support_destroy(void)
> >>>  {
> >>>      rconn_destroy(swconn);
> >>>      swconn = NULL;
> >>> +    ovsdb_cs_destroy(vswitch_cs);
> >>> +    vswitch_cs = NULL;
> >>>  }
> >>>
> >>>  /* Returns 'true' if the set of tracked OVS features has been
> updated. */
> >>>  bool
> >>>  ovs_feature_support_run(const struct smap *ovs_capabilities,
> >>> -                        const char *conn_target, int probe_interval)
> >>> +                        const char *conn_target, int probe_interval,
> >>> +                        const char *db_target)
> >>>  {
> >>>      static struct smap empty_caps = SMAP_INITIALIZER(&empty_caps);
> >>>
> >>> @@ -449,6 +534,16 @@ ovs_feature_support_run(const struct smap
> >>> *ovs_capabilities,
> >>>          updated |= handle_feature_state_update(new_value,
> feature->value,
> >>>                                                 feature->name);
> >>>      }
> >>> +
> >>> +    if (!vswitch_cs) {
> >>> +        vswitch_cs = ovsdb_cs_create(ovsrec_idl_class.database, 3,
> >>> +                                     &feature_cs_ops, NULL);
> >>> +    }
> >>> +    ovsdb_cs_set_remote(vswitch_cs, db_target, true);
> >>> +    /* This feature doesn't affect OpenFlow rules, so not touching
> >>> 'updated'
> >>> +     * even if changed. */
> >>> +    vswitch_schema_prefixes_run();
> >>> +
> >>>      return updated;
> >>>  }
> >>>
> >>> @@ -479,3 +574,11 @@ ovs_feature_max_select_groups_get(void)
> >>>  {
> >>>      return ovs_group_features.max_groups[OFPGT11_SELECT];
> >>>  }
> >>> +
> >>> +/* Returns the number of flow table prefixes that can be configured in
> >>> + * the OVS database. */
> >>> +size_t
> >>> +ovs_features_max_flow_table_prefixes_get(void)
> >>> +{
> >>> +    return max_flow_table_prefixes;
> >>> +}
> >>> diff --git a/lib/test-ovn-features.c b/lib/test-ovn-features.c
> >>> index cddeae779..40fba6a43 100644
> >>> --- a/lib/test-ovn-features.c
> >>> +++ b/lib/test-ovn-features.c
> >>> @@ -26,15 +26,15 @@ test_ovn_features(struct ovs_cmdl_context *ctx
> >>> OVS_UNUSED)
> >>>      struct smap features = SMAP_INITIALIZER(&features);
> >>>
> >>>      smap_add(&features, "ct_zero_snat", "false");
> >>> -    ovs_assert(!ovs_feature_support_run(&features, NULL, 0));
> >>> +    ovs_assert(!ovs_feature_support_run(&features, NULL, 0, NULL));
> >>>      ovs_assert(!ovs_feature_is_supported(OVS_CT_ZERO_SNAT_SUPPORT));
> >>>
> >>>      smap_replace(&features, "ct_zero_snat", "true");
> >>> -    ovs_assert(ovs_feature_support_run(&features, NULL, 0));
> >>> +    ovs_assert(ovs_feature_support_run(&features, NULL, 0, NULL));
> >>>      ovs_assert(ovs_feature_is_supported(OVS_CT_ZERO_SNAT_SUPPORT));
> >>>
> >>>      smap_add(&features, "unknown_feature", "true");
> >>> -    ovs_assert(!ovs_feature_support_run(&features, NULL, 0));
> >>> +    ovs_assert(!ovs_feature_support_run(&features, NULL, 0, NULL));
> >>>
> >>>      smap_destroy(&features);
> >>>  }
> >>> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
> >>> index 2bf8b53d0..de86ced1c 100644
> >>> --- a/tests/ovn-controller.at
> >>> +++ b/tests/ovn-controller.at
> >>> @@ -3134,6 +3134,56 @@ OVS_WAIT_UNTIL([grep -q 'tcp:127.0.0.1:1235:
> >>> connected' hv1/ovn-controller.log])
> >>>  OVN_CLEANUP([hv1])
> >>>  AT_CLEANUP
> >>>
> >>> +AT_SETUP([ovn-controller - br-int flow table prefixes])
> >>> +AT_KEYWORDS([ovn-controller prefixes])
> >>> +ovn_start
> >>> +
> >>> +net_add n1
> >>> +sim_add hv1
> >>> +ovs-vsctl add-br br-phys
> >>> +
> >>> +dnl Stop the database server before starting ovn-controller and
> convert
> >>> the
> >>> +dnl schema to support only 3 prefixes.
> >>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>> +AT_CHECK([sed 's/"max": 4}/"max": 3}/'
> >>> $ovs_srcdir/vswitchd/vswitch.ovsschema > new_schema])
> >>> +AT_CHECK([ovsdb-tool convert hv1/conf.db new_schema])
> >>> +start_daemon ovsdb-server --remote=punix:db.sock
> >>> +
> >>> +dnl Start ovn-controller.
> >>> +ovn_attach n1 br-phys 192.168.0.20
> >>> +
> >>> +dnl Wait for exactly 3 prefixes to be configured.
> >>> +OVS_WAIT_UNTIL(
> >>> +    [grep -q 'Setting flow table prefixes: ip_src, ip_dst, ipv6_src.'
> \
> >>> +             hv1/ovn-controller.log])
> >>> +OVS_WAIT_FOR_OUTPUT([ovs-vsctl --columns=prefixes --bare list
> >>> Flow_Table], [0], [dnl
> >>> +ip_dst ip_src ipv6_src
> >>> +])
> >>> +
> >>> +dnl Remember the row UUID.
> >>> +uuid=$(ovs-vsctl --columns=_uuid --bare list Flow_Table)
> >>> +
> >>> +dnl Stop the database server again and convert the schema back to
> support
> >>> +dnl up to 4 prefixes.
> >>> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> >>> +AT_CHECK([cat $ovs_srcdir/vswitchd/vswitch.ovsschema > new_schema])
> >>> +AT_CHECK([ovsdb-tool convert hv1/conf.db new_schema])
> >>> +start_daemon ovsdb-server --remote=punix:db.sock
> >>> +
> >>> +dnl Wait for exactly 4 prefixes to be configured.
> >>> +OVS_WAIT_FOR_OUTPUT(
> >>> +    [grep -q 'Setting flow table prefixes: ip_src, ip_dst, ipv6_src,
> >>> ipv6_dst.' \
> >>> +             hv1/ovn-controller.log])
> >>> +OVS_WAIT_FOR_OUTPUT([ovs-vsctl --columns=prefixes --bare list
> >>> Flow_Table], [0], [dnl
> >>> +ip_dst ip_src ipv6_dst ipv6_src
> >>> +])
> >>> +
> >>> +dnl Check that the record was updated and not replaced.
> >>> +AT_CHECK([test "$(ovs-vsctl --columns=_uuid --bare list Flow_Table)" =
> >>> "${uuid}"])
> >>> +
> >>> +OVN_CLEANUP([hv1])
> >>> +AT_CLEANUP
> >>> +
> >>>  OVN_FOR_EACH_NORTHD([
> >>>  AT_SETUP([ovn-controller - CT zone min/max boundaries])
> >>>  ovn_start
> >>> --
> >>> 2.47.0
> >>>
> >>>
> >> Thanks,
> >> Ales
> >> _______________________________________________
> >> dev mailing list
> >> [email protected]
> >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>
>
Reviewed-by: Ales Musil <[email protected]>

Thanks,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to