On Mon, Jul 29, 2024 at 2:41 AM Ales Musil <amu...@redhat.com> wrote: > > Add support for limiting the CT zone usage per Ls, LR or LSP. > When the limit is configured on logical switch it will also implicitly > set limits for all ports in that logical switch. The port configuration > can be overwritten individually and has priority over the whole logical > switch configuration. > > The value 0 means unlimited, when the value is not specified it is > derived from OvS default CT limit specified for given OvS datapath. > > Reported-at: https://bugzilla.redhat.com/2189924 > Signed-off-by: Ales Musil <amu...@redhat.com> > --- > v7: Rebase on top of latest main. > v6: Rebase on top of latest main. > Addressed comments from Mark: > - Fix spelling error in the documenation. > Addressed comments from Numan: > - Avoid looping over all interface and loop over local ones only. > - Do not loop over interfaces when the DP limit didn't change. > v5: Rebase on top of latest main. > Avoid OvS CT zone lookup in every loop of pending commit. > v4: Rebase on top of latest main. > Change naming of the ct_zone_limit_sync to avoid potential confusion as > suggested by Lorenzo. > v3: Rebase on top of latest main. > ---
Thanks for the patch series. I did some very small changes and applied to main. ---- diff --git a/ovn-nb.xml b/ovn-nb.xml index 7087c0cf22..6a2b964ace 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -749,7 +749,8 @@ </column> <column name="other_config" key="ct-zone-limit" - type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967295}'> + type='{"type": "integer", "minInteger": 0, + "maxInteger": 4294967295}'> CT zone <code>limit</code> value for given <ref table="Logical_Switch"/>. This value will be propagated to all <ref table="Logical_Switch_Port"/> when configured, but can be @@ -1160,7 +1161,8 @@ </column> <column name="options" key="ct-zone-limit" - type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967295}'> + type='{"type": "integer", "minInteger": 0, + "maxInteger": 4294967295}'> CT zone <code>limit</code> value for given <ref table="Logical_Switch_Port"/>. This value has priority over limit specified on <ref table="Logical_Switch"/> when configured. @@ -2834,9 +2836,10 @@ or </column> <column name="options" key="ct-zone-limit" - type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967295}'> + type='{"type": "integer", "minInteger": 0, + "maxInteger": 4294967295}'> CT zone <code>limit</code> value for given - <ref table="Logical_Router"/>. The value 0 means unlimited, when the + <ref table="Logical_Router"/>. The value 0 means unlimited. When the option is not present the limit is not set and the zone limit is derived from OvS default datapath limit. ----- Numan > NEWS | 3 + > controller/ct-zone.c | 181 ++++++++++++++++++++++++++++++++---- > controller/ct-zone.h | 15 ++- > controller/ovn-controller.c | 19 ++-- > lib/ovn-util.c | 17 ++++ > lib/ovn-util.h | 3 + > northd/northd.c | 8 ++ > ovn-nb.xml | 29 ++++++ > tests/ovn-controller.at | 99 ++++++++++++++++++++ > 9 files changed, 346 insertions(+), 28 deletions(-) > > diff --git a/NEWS b/NEWS > index 15c4c788a..87e326f21 100644 > --- a/NEWS > +++ b/NEWS > @@ -44,6 +44,9 @@ Post v24.03.0 > localnet port. > - Added support to define boundaries (min and max values) for selected ct > zones. > + - Add support for CT zone limit that can be specified per LR > + (options:ct-zone-limit), LS (other_config:ct-zone-limit) or LSP > + (options:ct-zone-limit). > > OVN v24.03.0 - 01 Mar 2024 > -------------------------- > diff --git a/controller/ct-zone.c b/controller/ct-zone.c > index f19883831..0a5d3d410 100644 > --- a/controller/ct-zone.c > +++ b/controller/ct-zone.c > @@ -16,6 +16,7 @@ > #include <config.h> > #include <errno.h> > > +#include "binding.h" > #include "chassis.h" > #include "ct-zone.h" > #include "local_data.h" > @@ -37,6 +38,16 @@ static bool ct_zone_assign_unused(struct ct_zone_ctx *ctx, > static bool ct_zone_remove(struct ct_zone_ctx *ctx, const char *name); > static void ct_zone_add(struct ct_zone_ctx *ctx, const char *name, > uint16_t zone, bool set_pending); > +static void > +ct_zone_limits_update_per_dp(struct ct_zone_ctx *ctx, > + const struct local_datapath *local_dp, > + const struct shash *local_lports, > + const char *name); > +static bool ct_zone_limit_update(struct ct_zone_ctx *ctx, const char *name, > + int64_t limit); > +static int64_t ct_zone_get_dp_limit(const struct sbrec_datapath_binding *dp); > +static int64_t ct_zone_get_pb_limit(const struct sbrec_port_binding *pb); > +static int64_t ct_zone_limit_normalize(int64_t limit); > > void > ct_zone_ctx_init(struct ct_zone_ctx *ctx) > @@ -265,11 +276,24 @@ ct_zones_update(const struct sset *local_lports, > > void > ct_zones_commit(const struct ovsrec_bridge *br_int, > - struct shash *pending_ct_zones) > + const struct ovsrec_datapath *ovs_dp, > + struct ovsdb_idl_txn *ovs_idl_txn, > + struct ct_zone_ctx *ctx) > { > + if (shash_is_empty(&ctx->pending)) { > + return; > + } > + > + struct ovsrec_ct_zone **all_zones = > + xzalloc(sizeof *all_zones * (MAX_CT_ZONES + 1)); > + for (size_t i = 0; i < ovs_dp->n_ct_zones; i++) { > + all_zones[ovs_dp->key_ct_zones[i]] = ovs_dp->value_ct_zones[i]; > + } > + > struct shash_node *iter; > - SHASH_FOR_EACH (iter, pending_ct_zones) { > + SHASH_FOR_EACH (iter, &ctx->pending) { > struct ct_zone_pending_entry *ctzpe = iter->data; > + struct ct_zone *ct_zone = &ctzpe->ct_zone; > > /* The transaction is open, so any pending entries in the > * CT_ZONE_DB_QUEUED must be sent and any in CT_ZONE_DB_QUEUED > @@ -281,7 +305,7 @@ ct_zones_commit(const struct ovsrec_bridge *br_int, > > char *user_str = xasprintf("ct-zone-%s", iter->name); > if (ctzpe->add) { > - char *zone_str = xasprintf("%"PRIu16, ctzpe->ct_zone.zone); > + char *zone_str = xasprintf("%"PRIu16, ct_zone->zone); > struct smap_node *node = > smap_get_node(&br_int->external_ids, user_str); > if (!node || strcmp(node->value, zone_str)) { > @@ -296,8 +320,22 @@ ct_zones_commit(const struct ovsrec_bridge *br_int, > } > free(user_str); > > + struct ovsrec_ct_zone *ovs_zone = all_zones[ct_zone->zone]; > + if ((!ctzpe->add || ct_zone->limit < 0) && ovs_zone) { > + ovsrec_datapath_update_ct_zones_delkey(ovs_dp, ct_zone->zone); > + } else if (ctzpe->add && ct_zone->limit >= 0) { > + if (!ovs_zone) { > + ovs_zone = ovsrec_ct_zone_insert(ovs_idl_txn); > + ovsrec_datapath_update_ct_zones_setkey(ovs_dp, ct_zone->zone, > + ovs_zone); > + } > + ovsrec_ct_zone_set_limit(ovs_zone, &ct_zone->limit, 1); > + } > + > ctzpe->state = CT_ZONE_DB_SENT; > } > + > + free(all_zones); > } > > void > @@ -316,9 +354,21 @@ ct_zones_pending_clear_commited(struct shash *pending) > /* Returns "true" when there is no need for full recompute. */ > bool > ct_zone_handle_dp_update(struct ct_zone_ctx *ctx, > - const struct sbrec_datapath_binding *dp) > + const struct local_datapath *local_dp, > + const struct shash *local_lports) > { > - int req_snat_zone = ct_zone_get_snat(dp); > + const char *name = smap_get(&local_dp->datapath->external_ids, "name"); > + if (!name) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > + VLOG_ERR_RL(&rl, "Missing name for datapath '"UUID_FMT"' skipping" > + "zone check.", > + UUID_ARGS(&local_dp->datapath->header_.uuid)); > + return true; > + } > + > + ct_zone_limits_update_per_dp(ctx, local_dp, local_lports, name); > + > + int req_snat_zone = ct_zone_get_snat(local_dp->datapath); > if (req_snat_zone == -1) { > /* datapath snat ct zone is not set. This condition will also hit > * when CMS clears the snat-ct-zone for the logical router. > @@ -328,14 +378,6 @@ ct_zone_handle_dp_update(struct ct_zone_ctx *ctx, > return true; > } > > - const char *name = smap_get(&dp->external_ids, "name"); > - if (!name) { > - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > - VLOG_ERR_RL(&rl, "Missing name for datapath '"UUID_FMT"' skipping" > - "zone check.", UUID_ARGS(&dp->header_.uuid)); > - return true; > - } > - > /* Check if the requested snat zone has changed for the datapath > * or not. If so, then fall back to full recompute of > * ct_zone engine. */ > @@ -359,11 +401,12 @@ ct_zone_handle_dp_update(struct ct_zone_ctx *ctx, > > /* Returns "true" if there was an update to the context. */ > bool > -ct_zone_handle_port_update(struct ct_zone_ctx *ctx, const char *name, > +ct_zone_handle_port_update(struct ct_zone_ctx *ctx, > + const struct sbrec_port_binding *pb, > bool updated, int *scan_start, > int min_ct_zone, int max_ct_zone) > { > - struct shash_node *node = shash_find(&ctx->current, name); > + struct shash_node *node = shash_find(&ctx->current, pb->logical_port); > > if (node) { > struct ct_zone *ct_zone = node->data; > @@ -373,10 +416,14 @@ ct_zone_handle_port_update(struct ct_zone_ctx *ctx, > const char *name, > } > } > > - if (updated && !node) { > - ct_zone_assign_unused(ctx, name, scan_start, max_ct_zone); > + if (updated) { > + if (!node) { > + ct_zone_assign_unused(ctx, pb->logical_port, > + scan_start, max_ct_zone); > + } > + ct_zone_limit_update(ctx, pb->logical_port, > ct_zone_get_pb_limit(pb)); > return true; > - } else if (!updated && node && ct_zone_remove(ctx, node->name)) { > + } else if (node && ct_zone_remove(ctx, node->name)) { > return true; > } > > @@ -390,6 +437,25 @@ ct_zone_find_zone(const struct shash *ct_zones, const > char *name) > return ct_zone ? ct_zone->zone : 0; > } > > +void > +ct_zones_limits_sync(struct ct_zone_ctx *ctx, > + const struct hmap *local_datapaths, > + const struct shash *local_lports) > +{ > + const struct local_datapath *ld; > + HMAP_FOR_EACH (ld, hmap_node, local_datapaths) { > + const char *name = smap_get(&ld->datapath->external_ids, "name"); > + if (!name) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > + VLOG_ERR_RL(&rl, "Missing name for datapath '"UUID_FMT"' " > + "skipping zone assignment.", > + UUID_ARGS(&ld->datapath->header_.uuid)); > + continue; > + } > + > + ct_zone_limits_update_per_dp(ctx, ld, local_lports, name); > + } > +} > > static bool > ct_zone_assign_unused(struct ct_zone_ctx *ctx, const char *zone_name, > @@ -442,7 +508,10 @@ ct_zone_add(struct ct_zone_ctx *ctx, const char *name, > uint16_t zone, > shash_add(&ctx->current, name, ct_zone); > } > > - ct_zone->zone = zone; > + *ct_zone = (struct ct_zone) { > + .zone = zone, > + .limit = -1, > + }; > > if (set_pending) { > ct_zone_add_pending(&ctx->pending, CT_ZONE_OF_QUEUED, > @@ -525,6 +594,7 @@ ct_zone_restore(const struct sbrec_datapath_binding_table > *dp_table, > > struct ct_zone ct_zone = { > .zone = zone, > + .limit = -1, > }; > /* Make sure we remove the uuid one in the next OvS DB commit without > * flush. */ > @@ -540,3 +610,76 @@ ct_zone_restore(const struct > sbrec_datapath_binding_table *dp_table, > ct_zone_add(ctx, current_name, zone, false); > free(new_name); > } > + > +static void > +ct_zone_limits_update_per_dp(struct ct_zone_ctx *ctx, > + const struct local_datapath *local_dp, > + const struct shash *local_lports, > + const char *name) > +{ > + > + int64_t dp_limit = ct_zone_get_dp_limit(local_dp->datapath); > + char *dnat = alloc_nat_zone_key(name, "dnat"); > + char *snat = alloc_nat_zone_key(name, "snat"); > + > + bool zone_updated = ct_zone_limit_update(ctx, dnat, dp_limit); > + zone_updated |= ct_zone_limit_update(ctx, snat, dp_limit); > + > + if (local_dp->is_switch && zone_updated) { > + const struct shash_node *node; > + SHASH_FOR_EACH (node, local_lports) { > + const struct binding_lport *lport = node->data; > + > + if (lport->pb->datapath != local_dp->datapath) { > + continue; > + } > + > + ct_zone_limit_update(ctx, lport->name, > + ct_zone_get_pb_limit(lport->pb)); > + } > + } > + > + free(dnat); > + free(snat); > +} > + > +static bool > +ct_zone_limit_update(struct ct_zone_ctx *ctx, const char *name, int64_t > limit) > +{ > + struct ct_zone *ct_zone = shash_find_data(&ctx->current, name); > + > + if (!ct_zone || ct_zone->limit == limit) { > + return false; > + } > + > + ct_zone->limit = limit; > + /* Add pending entry only for DB store to avoid flushing the zone. */ > + ct_zone_add_pending(&ctx->pending, CT_ZONE_DB_QUEUED, ct_zone, true, > name); > + VLOG_DBG("setting ct zone %"PRIu16" limit to %"PRId64, > + ct_zone->zone, ct_zone->limit); > + > + return true; > +} > + > +static int64_t > +ct_zone_get_dp_limit(const struct sbrec_datapath_binding *dp) > +{ > + int64_t limit = ovn_smap_get_llong(&dp->external_ids, "ct-zone-limit", > -1); > + return ct_zone_limit_normalize(limit); > +} > + > +static int64_t > +ct_zone_get_pb_limit(const struct sbrec_port_binding *pb) > +{ > + int64_t dp_limit = ovn_smap_get_llong(&pb->datapath->external_ids, > + "ct-zone-limit", -1); > + int64_t limit = ovn_smap_get_llong(&pb->options, > + "ct-zone-limit", dp_limit); > + return ct_zone_limit_normalize(limit); > +} > + > +static int64_t > +ct_zone_limit_normalize(int64_t limit) > +{ > + return limit >= 0 && limit <= UINT32_MAX ? limit : -1; > +} > diff --git a/controller/ct-zone.h b/controller/ct-zone.h > index 79e894de9..6df03975c 100644 > --- a/controller/ct-zone.h > +++ b/controller/ct-zone.h > @@ -22,6 +22,7 @@ > #include "openvswitch/hmap.h" > #include "openvswitch/shash.h" > #include "openvswitch/types.h" > +#include "local_data.h" > #include "ovn-sb-idl.h" > #include "simap.h" > #include "vswitch-idl.h" > @@ -43,6 +44,7 @@ struct ct_zone_ctx { > > struct ct_zone { > uint16_t zone; > + int64_t limit; > }; > > /* States to move through when a new conntrack zone has been allocated. */ > @@ -73,13 +75,20 @@ void ct_zones_update(const struct sset *local_lports, > const struct hmap *local_datapaths, > struct ct_zone_ctx *ctx); > void ct_zones_commit(const struct ovsrec_bridge *br_int, > - struct shash *pending_ct_zones); > + const struct ovsrec_datapath *ovs_dp, > + struct ovsdb_idl_txn *ovs_idl_txn, > + struct ct_zone_ctx *ctx); > void ct_zones_pending_clear_commited(struct shash *pending); > bool ct_zone_handle_dp_update(struct ct_zone_ctx *ctx, > - const struct sbrec_datapath_binding *dp); > -bool ct_zone_handle_port_update(struct ct_zone_ctx *ctx, const char *name, > + const struct local_datapath *local_dp, > + const struct shash *local_lports); > +bool ct_zone_handle_port_update(struct ct_zone_ctx *ctx, > + const struct sbrec_port_binding *pb, > bool updated, int *scan_start, > int min_ct_zone, int max_ct_zone); > uint16_t ct_zone_find_zone(const struct shash *ct_zones, const char *name); > +void ct_zones_limits_sync(struct ct_zone_ctx *ctx, > + const struct hmap *local_datapaths, > + const struct shash *local_lports); > > #endif /* controller/ct-zone.h */ > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index 4634fc6fe..f5674184a 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -795,6 +795,7 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_private_key); > ovsdb_idl_add_table(ovs_idl, &ovsrec_table_datapath); > ovsdb_idl_add_column(ovs_idl, &ovsrec_datapath_col_capabilities); > + ovsdb_idl_add_column(ovs_idl, &ovsrec_datapath_col_ct_zones); > ovsdb_idl_add_table(ovs_idl, &ovsrec_table_flow_sample_collector_set); > ovsdb_idl_add_table(ovs_idl, &ovsrec_table_qos); > ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_other_config); > @@ -804,6 +805,8 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > ovsdb_idl_add_column(ovs_idl, &ovsrec_queue_col_other_config); > ovsdb_idl_add_column(ovs_idl, &ovsrec_queue_col_external_ids); > ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_link_state); > + ovsdb_idl_add_table(ovs_idl, &ovsrec_table_ct_zone); > + ovsdb_idl_add_column(ovs_idl, &ovsrec_ct_zone_col_limit); > > chassis_register_ovs_idl(ovs_idl); > encaps_register_ovs_idl(ovs_idl); > @@ -2227,6 +2230,8 @@ en_ct_zones_run(struct engine_node *node, void *data) > ct_zones_restore(&ct_zones_data->ctx, ovs_table, dp_table, br_int); > ct_zones_update(&rt_data->local_lports, ovs_table, > &rt_data->local_datapaths, &ct_zones_data->ctx); > + ct_zones_limits_sync(&ct_zones_data->ctx, &rt_data->local_datapaths, > + &rt_data->lbinding_data.lports); > > ct_zones_data->recomputed = true; > engine_set_node_state(node, EN_UPDATED); > @@ -2246,8 +2251,9 @@ ct_zones_datapath_binding_handler(struct engine_node > *node, void *data) > EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node)); > > SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (dp, dp_table) { > - if (!get_local_datapath(&rt_data->local_datapaths, > - dp->tunnel_key)) { > + const struct local_datapath *local_dp= > + get_local_datapath(&rt_data->local_datapaths, > dp->tunnel_key); > + if (!local_dp) { > continue; > } > > @@ -2257,7 +2263,8 @@ ct_zones_datapath_binding_handler(struct engine_node > *node, void *data) > return false; > } > > - if (!ct_zone_handle_dp_update(&ct_zones_data->ctx, dp)) { > + if (!ct_zone_handle_dp_update(&ct_zones_data->ctx, local_dp, > + &rt_data->lbinding_data.lports)) { > return false; > } > } > @@ -2311,7 +2318,7 @@ ct_zones_runtime_data_handler(struct engine_node *node, > void *data) > t_lport->tracked_type == TRACKED_RESOURCE_NEW || > t_lport->tracked_type == TRACKED_RESOURCE_UPDATED; > updated |= ct_zone_handle_port_update(&ct_zones_data->ctx, > - t_lport->pb->logical_port, > + t_lport->pb, > port_updated, &scan_start, > min_ct_zone, max_ct_zone); > } > @@ -5566,8 +5573,8 @@ main(int argc, char *argv[]) > if (ct_zones_data) { > stopwatch_start(CT_ZONE_COMMIT_STOPWATCH_NAME, > time_msec()); > - ct_zones_commit(br_int, > - &ct_zones_data->ctx.pending); > + ct_zones_commit(br_int, br_int_dp, ovs_idl_txn, > + &ct_zones_data->ctx); > stopwatch_stop(CT_ZONE_COMMIT_STOPWATCH_NAME, > time_msec()); > } > diff --git a/lib/ovn-util.c b/lib/ovn-util.c > index 58e941193..1ad347419 100644 > --- a/lib/ovn-util.c > +++ b/lib/ovn-util.c > @@ -816,6 +816,23 @@ str_tolower(const char *orig) > return copy; > } > > +/* This is a wrapper function which get the value associated with 'key' in > + * 'smap' and converts it to a long long. If 'key' is not in 'smap' or a > + * valid unsigned integer can't be parsed from its value, returns 'def'. > + */ > +long long > +ovn_smap_get_llong(const struct smap *smap, const char *key, long long def) > +{ > + const char *value = smap_get(smap, key); > + long long ll_value; > + > + if (!value || !str_to_llong(value, 10, &ll_value)) { > + return def; > + } > + > + return ll_value; > +} > + > /* For a 'key' of the form "IP:port" or just "IP", sets 'port', > * 'ip_address' and 'ip' ('struct in6_addr' IPv6 or IPv4 mapped address). > * The caller must free() the memory allocated for 'ip_address'. > diff --git a/lib/ovn-util.h b/lib/ovn-util.h > index f75b821b6..ae971ce5a 100644 > --- a/lib/ovn-util.h > +++ b/lib/ovn-util.h > @@ -211,6 +211,9 @@ char *normalize_v46_prefix(const struct in6_addr *prefix, > unsigned int plen); > */ > char *str_tolower(const char *orig); > > +long long ovn_smap_get_llong(const struct smap *smap, const char *key, > + long long def); > + > /* OVN daemon options. Taken from ovs/lib/daemon.h. */ > #define OVN_DAEMON_OPTION_ENUMS \ > OVN_OPT_DETACH, \ > diff --git a/northd/northd.c b/northd/northd.c > index 5b50ea191..325b412db 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -741,6 +741,14 @@ ovn_datapath_update_external_ids(struct ovn_datapath *od) > smap_add(&ids, "name2", name2); > } > > + int64_t ct_zone_limit = ovn_smap_get_llong(od->nbs ? > + &od->nbs->other_config : > + &od->nbr->options, > + "ct-zone-limit", -1); > + if (ct_zone_limit > 0) { > + smap_add_format(&ids, "ct-zone-limit", "%"PRId64, ct_zone_limit); > + } > + > /* Set interconn-ts. */ > if (od->nbs) { > const char *ts = smap_get(&od->nbs->other_config, "interconn-ts"); > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 0f9a1005a..7087c0cf2 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -747,6 +747,17 @@ > this timeout will be automatically removed. The value defaults > to 0, which means disabled. > </column> > + > + <column name="other_config" key="ct-zone-limit" > + type='{"type": "integer", "minInteger": 0, "maxInteger": > 4294967295}'> > + CT zone <code>limit</code> value for given > + <ref table="Logical_Switch"/>. This value will be propagated to all > + <ref table="Logical_Switch_Port"/> when configured, but can be > + overwritten individually per <ref table="Logical_Switch_Port"/>. The > + value 0 means unlimited. When the option is not present the limit > + is not set and the zone limit is derived from OvS default datapath > + limit. > + </column> > </group> > > <group title="IP Multicast Snooping Options"> > @@ -1148,6 +1159,16 @@ > <code>false</code>. > </column> > > + <column name="options" key="ct-zone-limit" > + type='{"type": "integer", "minInteger": 0, "maxInteger": > 4294967295}'> > + CT zone <code>limit</code> value for given > + <ref table="Logical_Switch_Port"/>. This value has priority over > + limit specified on <ref table="Logical_Switch"/> when configured. > + The value 0 means unlimited. When the option is not present the > limit > + is not set and the zone limit is derived from OvS default datapath > + limit. > + </column> > + > </group> > > <group title="Options for localnet ports"> > @@ -2811,6 +2832,14 @@ or > </p> > > </column> > + > + <column name="options" key="ct-zone-limit" > + type='{"type": "integer", "minInteger": 0, "maxInteger": > 4294967295}'> > + CT zone <code>limit</code> value for given > + <ref table="Logical_Router"/>. The value 0 means unlimited, when the > + option is not present the limit is not set and the zone limit is > + derived from OvS default datapath limit. > + </column> > </group> > > <group title="Common Columns"> > diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at > index 41a929ffd..bbf9b3c43 100644 > --- a/tests/ovn-controller.at > +++ b/tests/ovn-controller.at > @@ -3194,3 +3194,102 @@ check_ct_zone_max 20 > OVN_CLEANUP([hv1]) > AT_CLEANUP > ]) > + > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([ovn-controller - CT zone limit]) > +ovn_start > + > +net_add n1 > +sim_add hv1 > +as hv1 > +check ovs-vsctl add-br br-phys > +ovn_attach n1 br-phys 192.168.0.1 > + > +check ovn-appctl -t ovn-controller vlog/set dbg:ct_zone > + > +check ovs-vsctl add-port br-int lsp \ > + -- set Interface lsp external-ids:iface-id=lsp > + > +check ovn-nbctl lr-add lr > + > +check ovn-nbctl ls-add ls > +check ovn-nbctl lsp-add ls ls-lr > +check ovn-nbctl lsp-set-type ls-lr router > +check ovn-nbctl lsp-set-addresses ls-lr router > +check ovn-nbctl lrp-add lr lr-ls 00:00:00:00:00:01 10.0.0.1 > + > +check ovn-nbctl lsp-add ls lsp > +check ovn-nbctl lsp-set-addresses lsp "00:00:00:00:00:02 10.0.0.2" > + > +check ovn-nbctl lrp-add lr lrp-gw 01:00:00:00:00:01 172.16.0.1 > +check ovn-nbctl lrp-set-gateway-chassis lrp-gw hv1 > + > +wait_for_ports_up > +check ovn-nbctl --wait=hv sync > + > +get_zone_num() { > + output=$1 > + name=$2 > + > + printf "$output" | grep $name | cut -d ' ' -f 2 > +} > + > +check_ovs_ct_limit() { > + zone=$1 > + limit=$2 > + > + AT_CHECK_UNQUOTED([ovs-appctl dpctl/ct-get-limits zone=$zone | sed > "s/count=.*/count=?/;s/default limit=.*/default limit=?/" | sort], [0], [dnl > +default limit=? > +zone=$zone,limit=$limit,count=? > +]) > +} > + > +wait_ovs_ct_limit_count() { > + count=$1 > + > + OVS_WAIT_UNTIL([test $count -eq $(ovs-vsctl --no-headings --format=table > list CT_Zone | wc -l)]) > +} > + > +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list) > +lr_dnat=$(get_zone_num "$ct_zones" lr_dnat) > +lr_snat=$(get_zone_num "$ct_zones" lr_snat) > + > +ls_dnat=$(get_zone_num "$ct_zones" ls_dnat) > +ls_snat=$(get_zone_num "$ct_zones" ls_snat) > + > +lsp=$(get_zone_num "$ct_zones" lsp) > + > +wait_ovs_ct_limit_count 0 > + > +check ovn-nbctl --wait=hv set Logical_Router lr options:ct-zone-limit=5 > +wait_ovs_ct_limit_count 2 > +check_ovs_ct_limit $lr_dnat 5 > +check_ovs_ct_limit $lr_snat 5 > + > +check ovn-nbctl --wait=hv remove Logical_Router lr options ct-zone-limit > +wait_ovs_ct_limit_count 0 > + > +check ovn-nbctl --wait=hv set Logical_Switch ls other_config:ct-zone-limit=10 > +wait_ovs_ct_limit_count 3 > +check_ovs_ct_limit $ls_dnat 10 > +check_ovs_ct_limit $ls_snat 10 > +check_ovs_ct_limit $lsp 10 > + > +check ovn-nbctl --wait=hv set Logical_Switch_Port lsp options:ct-zone-limit=5 > +wait_ovs_ct_limit_count 3 > +check_ovs_ct_limit $ls_dnat 10 > +check_ovs_ct_limit $ls_snat 10 > +check_ovs_ct_limit $lsp 5 > + > +check ovn-nbctl --wait=hv remove Logical_Switch_Port lsp options > ct-zone-limit > +wait_ovs_ct_limit_count 3 > +check_ovs_ct_limit $ls_dnat 10 > +check_ovs_ct_limit $ls_snat 10 > +check_ovs_ct_limit $lsp 10 > + > +check ovn-nbctl --wait=hv remove Logical_Switch ls other_config ct-zone-limit > +wait_ovs_ct_limit_count 0 > + > +OVN_CLEANUP([hv1]) > +AT_CLEANUP > +]) > -- > 2.45.2 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev