On Wed, Apr 30, 2025 at 7:54 AM Ales Musil <amu...@redhat.com> wrote:

> The vector has the same functionality as the x2nrealloc
> for insert. Use vector instead which slightly simplifies
> the final code. There is one exception that wasn't converted
> that's the expr_constant_set.
>
> Signed-off-by: Ales Musil <amu...@redhat.com>
> Acked-by: Mark Michelson <mmich...@redhat.com>
> ---
> v4: Rebase on top of current main.
>     Add ack from Mark.
> v3: Rebase on top of current main.
> v2: Rebase on top of current main.
> ---
>  controller/lflow.c          |  17 +++--
>  controller/ovn-controller.c |   9 ++-
>  include/ovn/expr.h          |   4 +-
>  lib/actions.c               | 115 ++++++++++++++--------------------
>  lib/expr.c                  |  56 ++++++++---------
>  lib/inc-proc-eng.c          | 120 ++++++++++++++++--------------------
>  lib/lb.c                    |  49 ++++++---------
>  lib/lb.h                    |   4 +-
>  northd/lb.c                 |   7 ++-
>  northd/northd.c             |  44 +++++++------
>  tests/test-ovn.c            |   3 +-
>  11 files changed, 187 insertions(+), 241 deletions(-)
>
> diff --git a/controller/lflow.c b/controller/lflow.c
> index c24b2e212..0a3bf1c1c 100644
> --- a/controller/lflow.c
> +++ b/controller/lflow.c
> @@ -925,7 +925,7 @@ add_matches_to_flow_table(const struct
> sbrec_logical_flow *lflow,
>              .ip = m->as_ip,
>              .mask = m->as_mask
>          };
> -        if (!m->n) {
> +        if (vector_is_empty(&m->conjunctions)) {
>              ofctrl_add_flow_metered(l_ctx_out->flow_table, ptable,
>                                      lflow->priority,
>                                      lflow->header_.uuid.parts[0],
> &m->match,
> @@ -933,18 +933,16 @@ add_matches_to_flow_table(const struct
> sbrec_logical_flow *lflow,
>                                      ctrl_meter_id,
>                                      as_info.name ? &as_info : NULL);
>          } else {
> -            if (m->n > 1) {
> +            if (vector_len(&m->conjunctions) > 1) {
>                  ovs_assert(!as_info.name);
>              }
>              uint64_t conj_stubs[64 / 8];
>              struct ofpbuf conj;
>
>              ofpbuf_use_stub(&conj, conj_stubs, sizeof conj_stubs);
> -            for (int i = 0; i < m->n; i++) {
> -                const struct cls_conjunction *src = &m->conjunctions[i];
> -                struct ofpact_conjunction *dst;
> -
> -                dst = ofpact_put_CONJUNCTION(&conj);
> +            const struct cls_conjunction *src;
> +            VECTOR_FOR_EACH_PTR (&m->conjunctions, src) {
> +                struct ofpact_conjunction *dst =
> ofpact_put_CONJUNCTION(&conj);
>                  dst->id = src->id;
>                  dst->clause = src->clause;
>                  dst->n_clauses = src->n_clauses;
> @@ -1941,9 +1939,8 @@ consider_lb_hairpin_flows(const struct
> ovn_controller_lb *lb,
>      for (size_t i = 0; i < lb->n_vips; i++) {
>          struct ovn_lb_vip *lb_vip = &lb->vips[i];
>
> -        for (size_t j = 0; j < lb_vip->n_backends; j++) {
> -            struct ovn_lb_backend *lb_backend = &lb_vip->backends[j];
> -
> +        struct ovn_lb_backend *lb_backend;
> +        VECTOR_FOR_EACH_PTR (&lb_vip->backends, lb_backend) {
>              add_lb_vip_hairpin_flows(lb, lb_vip, lb_backend, flow_table,
>                                       register_consolidation);
>          }
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 75b1ac750..180b8a8d2 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -2683,9 +2683,9 @@ lb_data_removed_five_tuples_add(struct
> ed_type_lb_data *lb_data,
>
>      for (size_t i = 0; i < lb->n_vips; i++) {
>          struct ovn_lb_vip *vip = &lb->vips[i];
> -        for (size_t j = 0; j < vip->n_backends; j++) {
> -            struct ovn_lb_backend *backend = &vip->backends[j];
>
> +        const struct ovn_lb_backend *backend;
> +        VECTOR_FOR_EACH_PTR (&vip->backends, backend) {
>              ovn_lb_5tuple_add(&lb_data->removed_tuples, vip, backend,
>                                lb->proto);
>          }
> @@ -2703,10 +2703,9 @@ lb_data_removed_five_tuples_remove(struct
> ed_type_lb_data *lb_data,
>
>      for (size_t i = 0; i < lb->n_vips; i++) {
>          struct ovn_lb_vip *vip = &lb->vips[i];
> -        for (size_t j = 0; j < vip->n_backends; j++) {
> -            struct ovn_lb_backend *backend = &vip->backends[j];
> -
>
> +        const struct ovn_lb_backend *backend;
> +        VECTOR_FOR_EACH_PTR (&vip->backends, backend) {
>              struct ovn_lb_5tuple tuple;
>              ovn_lb_5tuple_init(&tuple, vip, backend, lb->proto);
>              ovn_lb_5tuple_find_and_delete(&lb_data->removed_tuples,
> &tuple);
> diff --git a/include/ovn/expr.h b/include/ovn/expr.h
> index e54edb5bf..9621a2c09 100644
> --- a/include/ovn/expr.h
> +++ b/include/ovn/expr.h
> @@ -60,6 +60,7 @@
>  #include "openvswitch/meta-flow.h"
>  #include "logical-fields.h"
>  #include "smap.h"
> +#include "vec.h"
>
>  struct ds;
>  struct expr;
> @@ -471,8 +472,7 @@ bool expr_evaluate(const struct expr *, const struct
> flow *uflow,
>  struct expr_match {
>      struct hmap_node hmap_node;
>      struct match match;
> -    struct cls_conjunction *conjunctions;
> -    size_t n, allocated;
> +    struct vector conjunctions; /* Vector of struct cls_conjunction. */
>
>      /* Tracked address set information. */
>      char *as_name;
> diff --git a/lib/actions.c b/lib/actions.c
> index 75d0951fc..cd969c684 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -42,6 +42,7 @@
>  #include "socket-util.h"
>  #include "lib/ovn-util.h"
>  #include "controller/lflow.h"
> +#include "vec.h"
>
>  VLOG_DEFINE_THIS_MODULE(actions);
>
> @@ -1208,9 +1209,7 @@ parse_ct_lb_action(struct action_context *ctx, bool
> ct_lb_mark)
>
>      add_prerequisite(ctx, "ip");
>
> -    struct ovnact_ct_lb_dst *dsts = NULL;
> -    size_t allocated_dsts = 0;
> -    size_t n_dsts = 0;
> +    struct vector dsts = VECTOR_EMPTY_INITIALIZER(struct
> ovnact_ct_lb_dst);
>      char *hash_fields = NULL;
>      enum ovnact_ct_lb_flag ct_flag = OVNACT_CT_LB_FLAG_NONE;
>
> @@ -1229,7 +1228,7 @@ parse_ct_lb_action(struct action_context *ctx, bool
> ct_lb_mark)
>                  /* IPv6 address and port */
>                  if (ctx->lexer->token.type != LEX_T_INTEGER
>                      || ctx->lexer->token.format != LEX_F_IPV6) {
> -                    free(dsts);
> +                    vector_destroy(&dsts);
>                      lexer_syntax_error(ctx->lexer, "expecting IPv6
> address");
>                      return;
>                  }
> @@ -1238,7 +1237,7 @@ parse_ct_lb_action(struct action_context *ctx, bool
> ct_lb_mark)
>
>                  lexer_get(ctx->lexer);
>                  if (!lexer_match(ctx->lexer, LEX_T_RSQUARE)) {
> -                    free(dsts);
> +                    vector_destroy(&dsts);
>                      lexer_syntax_error(ctx->lexer, "no closing square "
>                                                     "bracket");
>                      return;
> @@ -1246,14 +1245,14 @@ parse_ct_lb_action(struct action_context *ctx,
> bool ct_lb_mark)
>                  dst.port = 0;
>                  if (lexer_match(ctx->lexer, LEX_T_COLON)
>                      && !action_parse_uint16(ctx, &dst.port, "port
> number")) {
> -                    free(dsts);
> +                    vector_destroy(&dsts);
>                      return;
>                  }
>              } else {
>                  if (ctx->lexer->token.type != LEX_T_INTEGER
>                      || (ctx->lexer->token.format != LEX_F_IPV4
>                      && ctx->lexer->token.format != LEX_F_IPV6)) {
> -                    free(dsts);
> +                    vector_destroy(&dsts);
>                      lexer_syntax_error(ctx->lexer, "expecting IP
> address");
>                      return;
>                  }
> @@ -1271,31 +1270,27 @@ parse_ct_lb_action(struct action_context *ctx,
> bool ct_lb_mark)
>                  dst.port = 0;
>                  if (lexer_match(ctx->lexer, LEX_T_COLON)) {
>                      if (dst.family == AF_INET6) {
> -                        free(dsts);
> +                        vector_destroy(&dsts);;
>                          lexer_syntax_error(ctx->lexer, "IPv6 address
> needs "
>                                  "square brackets if port is included");
>                          return;
>                      } else if (!action_parse_uint16(ctx, &dst.port,
>                                                      "port number")) {
> -                        free(dsts);
> +                        vector_destroy(&dsts);
>                          return;
>                      }
>                  }
>              }
>              lexer_match(ctx->lexer, LEX_T_COMMA);
>
> -            /* Append to dsts. */
> -            if (n_dsts >= allocated_dsts) {
> -                dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);
> -            }
> -            dsts[n_dsts++] = dst;
> +            vector_push(&dsts, &dst);
>          }
>
>          if (lexer_match_id(ctx->lexer, "hash_fields")) {
>              if (!lexer_match(ctx->lexer, LEX_T_EQUALS) ||
>                  ctx->lexer->token.type != LEX_T_STRING) {
>                  lexer_syntax_error(ctx->lexer, "invalid hash_fields");
> -                free(dsts);
> +                vector_destroy(&dsts);
>                  return;
>              }
>
> @@ -1318,8 +1313,8 @@ parse_ct_lb_action(struct action_context *ctx, bool
> ct_lb_mark)
>      struct ovnact_ct_lb *cl = ct_lb_mark ?
> ovnact_put_CT_LB_MARK(ctx->ovnacts)
>                                           : ovnact_put_CT_LB(ctx->ovnacts);
>      cl->ltable = ctx->pp->cur_ltable + 1;
> -    cl->dsts = dsts;
> -    cl->n_dsts = n_dsts;
> +    cl->n_dsts = vector_len(&dsts);
> +    cl->dsts = vector_steal_array(&dsts);
>      cl->hash_fields = hash_fields;
>      cl->ct_flag = ct_flag;
>  }
> @@ -1542,9 +1537,7 @@ parse_select_action(struct action_context *ctx,
> struct expr_field *res_field)
>          return;
>      }
>
> -    struct ovnact_select_dst *dsts = NULL;
> -    size_t allocated_dsts = 0;
> -    size_t n_dsts = 0;
> +    struct vector dsts = VECTOR_EMPTY_INITIALIZER(struct
> ovnact_select_dst);
>      bool requires_hash_fields = false;
>      char *hash_fields = NULL;
>
> @@ -1560,14 +1553,14 @@ parse_select_action(struct action_context *ctx,
> struct expr_field *res_field)
>      while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
>          struct ovnact_select_dst dst;
>          if (!action_parse_uint16(ctx, &dst.id, "id")) {
> -            free(dsts);
> +            vector_destroy(&dsts);
>              return;
>          }
>
>          dst.weight = 0;
>          if (lexer_match(ctx->lexer, LEX_T_EQUALS)) {
>              if (!action_parse_uint16(ctx, &dst.weight, "weight")) {
> -                free(dsts);
> +                vector_destroy(&dsts);
>                  return;
>              }
>              if (dst.weight == 0) {
> @@ -1581,15 +1574,11 @@ parse_select_action(struct action_context *ctx,
> struct expr_field *res_field)
>
>          lexer_match(ctx->lexer, LEX_T_COMMA);
>
> -        /* Append to dsts. */
> -        if (n_dsts >= allocated_dsts) {
> -            dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);
> -        }
> -        dsts[n_dsts++] = dst;
> +        vector_push(&dsts, &dst);
>      }
> -    if (n_dsts <= 1) {
> +    if (vector_len(&dsts) <= 1) {
>          lexer_syntax_error(ctx->lexer, "expecting at least 2 group
> members");
> -        free(dsts);
> +        vector_destroy(&dsts);
>          return;
>      }
>
> @@ -1597,14 +1586,14 @@ parse_select_action(struct action_context *ctx,
> struct expr_field *res_field)
>          lexer_force_match(ctx->lexer, LEX_T_SEMICOLON);
>          if (!lexer_match_id(ctx->lexer, "hash_fields")) {
>              lexer_syntax_error(ctx->lexer, "expecting hash_fields");
> -            free(dsts);
> +            vector_destroy(&dsts);
>              return;
>          }
>          if (!lexer_match(ctx->lexer, LEX_T_EQUALS) ||
>              ctx->lexer->token.type != LEX_T_STRING ||
>              lexer_lookahead(ctx->lexer) != LEX_T_RPAREN) {
>              lexer_syntax_error(ctx->lexer, "invalid hash_fields");
> -            free(dsts);
> +            vector_destroy(&dsts);
>              return;
>          }
>          hash_fields = xstrdup(ctx->lexer->token.s);
> @@ -1614,8 +1603,8 @@ parse_select_action(struct action_context *ctx,
> struct expr_field *res_field)
>
>      struct ovnact_select *select = ovnact_put_SELECT(ctx->ovnacts);
>      select->ltable = ctx->pp->cur_ltable + 1;
> -    select->dsts = dsts;
> -    select->n_dsts = n_dsts;
> +    select->n_dsts = vector_len(&dsts);
> +    select->dsts = vector_steal_array(&dsts);
>      select->res_field = *res_field;
>      select->hash_fields = hash_fields;
>  }
> @@ -2681,26 +2670,23 @@ parse_trigger_event(struct action_context *ctx,
>
>      lexer_match(ctx->lexer, LEX_T_COMMA);
>
> -    size_t allocated_options = 0;
> +    struct vector options = VECTOR_EMPTY_INITIALIZER(struct
> ovnact_gen_option);
>      while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
> -        if (event->n_options >= allocated_options) {
> -            event->options = x2nrealloc(event->options,
> &allocated_options,
> -                                     sizeof *event->options);
> -        }
> -
> -        struct ovnact_gen_option *o = &event->options[event->n_options++];
> -        memset(o, 0, sizeof *o);
> -        parse_gen_opt(ctx, o,
> +        struct ovnact_gen_option o = {0};
> +        parse_gen_opt(ctx, &o,
>
>  &ctx->pp->controller_event_opts->event_opts[event_type],
>                        event_to_string(event_type));
> +        vector_push(&options, &o);
>
>          if (ctx->lexer->error) {
>              return;
>          }
> -
>          lexer_match(ctx->lexer, LEX_T_COMMA);
>      }
>
> +    event->n_options = vector_len(&options);
> +    event->options = vector_steal_array(&options);
> +
>      switch (event_type) {
>      case OVN_EVENT_EMPTY_LB_BACKENDS:
>          validate_empty_lb_backends(ctx, event->options, event->n_options);
> @@ -2838,22 +2824,21 @@ parse_put_opts(struct action_context *ctx, const
> struct expr_field *dst,
>      }
>      po->dst = *dst;
>
> -    size_t allocated_options = 0;
> +    struct vector options = VECTOR_EMPTY_INITIALIZER(struct
> ovnact_gen_option);
>      while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
> -        if (po->n_options >= allocated_options) {
> -            po->options = x2nrealloc(po->options, &allocated_options,
> -                                     sizeof *po->options);
> -        }
> +        struct ovnact_gen_option o = {0};
> +        parse_gen_opt(ctx, &o, gen_opts, opts_type);
> +        vector_push(&options, &o);
>
> -        struct ovnact_gen_option *o = &po->options[po->n_options++];
> -        memset(o, 0, sizeof *o);
> -        parse_gen_opt(ctx, o, gen_opts, opts_type);
>          if (ctx->lexer->error) {
> -            return;
> +            break;
>          }
>
>          lexer_match(ctx->lexer, LEX_T_COMMA);
>      }
> +
> +    po->n_options = vector_len(&options);
> +    po->options = vector_steal_array(&options);
>  }
>
>  /* Parses the "put_dhcp_opts" and "put_dhcpv6_opts" actions.
> @@ -4134,9 +4119,8 @@ ovnact_handle_svc_check_free(struct
> ovnact_handle_svc_check *sc OVS_UNUSED)
>  static void
>  parse_fwd_group_action(struct action_context *ctx)
>  {
> -    char *child_port, **child_port_list = NULL;
> -    size_t allocated_ports = 0;
> -    size_t n_child_ports = 0;
> +    struct vector child_port_list = VECTOR_EMPTY_INITIALIZER(char *);
> +    char *child_port = NULL;
>      bool liveness = false;
>
>      if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
> @@ -4165,25 +4149,18 @@ parse_fwd_group_action(struct action_context *ctx)
>                  if (ctx->lexer->token.type != LEX_T_STRING) {
>                      lexer_syntax_error(ctx->lexer,
>                                         "expecting logical switch port");
> -                    if (child_port_list) {
> -                        for (int i = 0; i < n_child_ports; i++) {
> -                            free(child_port_list[i]);
> -                        }
> -                        free(child_port_list);
> +                    char *port;
> +                    VECTOR_FOR_EACH (&child_port_list, port) {
> +                            free(port);
>                      }
> +                    vector_destroy(&child_port_list);
>                      return;
>                  }
>                  /* Parse child's logical ports */
>                  child_port = xstrdup(ctx->lexer->token.s);
>                  lexer_get(ctx->lexer);
>                  lexer_match(ctx->lexer, LEX_T_COMMA);
> -
> -                if (n_child_ports >= allocated_ports) {
> -                    child_port_list = x2nrealloc(child_port_list,
> -                                                 &allocated_ports,
> -                                                 sizeof *child_port_list);
> -                }
> -                child_port_list[n_child_ports++] = child_port;
> +                vector_push(&child_port_list, &child_port);
>              }
>          }
>      }
> @@ -4191,8 +4168,8 @@ parse_fwd_group_action(struct action_context *ctx)
>      struct ovnact_fwd_group *fwd_group =
> ovnact_put_FWD_GROUP(ctx->ovnacts);
>      fwd_group->ltable = ctx->pp->cur_ltable + 1;
>      fwd_group->liveness = liveness;
> -    fwd_group->child_ports = child_port_list;
> -    fwd_group->n_child_ports = n_child_ports;
> +    fwd_group->n_child_ports = vector_len(&child_port_list);
> +    fwd_group->child_ports = vector_steal_array(&child_port_list);
>  }
>
>  static void
> diff --git a/lib/expr.c b/lib/expr.c
> index ecf8a6338..937fecb75 100644
> --- a/lib/expr.c
> +++ b/lib/expr.c
> @@ -3141,16 +3141,16 @@ expr_match_new(const struct match *m, uint8_t
> clause, uint8_t n_clauses,
>          match_init_catchall(&match->match);
>      }
>      if (conj_id) {
> -        match->conjunctions = xmalloc(sizeof *match->conjunctions);
> -        match->conjunctions[0].id = conj_id;
> -        match->conjunctions[0].clause = clause;
> -        match->conjunctions[0].n_clauses = n_clauses;
> -        match->n = 1;
> -        match->allocated = 1;
> +        match->conjunctions =
> +            VECTOR_CAPACITY_INITIALIZER(struct cls_conjunction, 1);
> +        struct cls_conjunction conj = (struct cls_conjunction) {
> +            .id = conj_id,
> +            .clause = clause,
> +            .n_clauses = n_clauses,
> +        };
> +        vector_push(&match->conjunctions, &conj);
>      } else {
> -        match->conjunctions = NULL;
> -        match->n = 0;
> -        match->allocated = 0;
> +        match->conjunctions = VECTOR_EMPTY_INITIALIZER(struct
> cls_conjunction);
>      }
>      return match;
>  }
> @@ -3159,7 +3159,7 @@ void
>  expr_match_destroy(struct expr_match *match)
>  {
>      free(match->as_name);
> -    free(match->conjunctions);
> +    vector_destroy(&match->conjunctions);
>      free(match);
>  }
>
> @@ -3176,19 +3176,13 @@ expr_match_add(struct hmap *matches, struct
> expr_match *match)
>
>      HMAP_FOR_EACH_WITH_HASH (m, hmap_node, hash, matches) {
>          if (match_equal(&m->match, &match->match)) {
> -            if (!m->n || !match->n) {
> -                free(m->conjunctions);
> -                m->conjunctions = NULL;
> -                m->n = 0;
> -                m->allocated = 0;
> +            if (vector_is_empty(&m->conjunctions) ||
> +                vector_is_empty(&match->conjunctions)) {
> +                vector_destroy(&m->conjunctions);
>              } else {
> -                ovs_assert(match->n == 1);
> -                if (m->n >= m->allocated) {
> -                    m->conjunctions = x2nrealloc(m->conjunctions,
> -                                                 &m->allocated,
> -                                                 sizeof *m->conjunctions);
> -                }
> -                m->conjunctions[m->n++] = match->conjunctions[0];
> +                ovs_assert(vector_len(&match->conjunctions) == 1);
> +                vector_push(&m->conjunctions,
> +                            vector_get_ptr(&match->conjunctions, 0));
>              }
>              if (m->as_name) {
>                  /* m is combined with match. so untracked the address
> set. */
> @@ -3461,11 +3455,11 @@ expr_matches_prepare(struct hmap *matches,
> uint32_t conj_id_ofs)
>              m->match.flow.conj_id += conj_id_ofs;
>          }
>
> -        for (size_t i = 0; i < m->n; i++) {
> -            struct cls_conjunction *src = &m->conjunctions[i];
> +        struct cls_conjunction *src;
> +        VECTOR_FOR_EACH_PTR (&m->conjunctions, src) {
>              src->id += conj_id_ofs;
>          }
> -        total_size += sizeof *m + m->allocated * sizeof *m->conjunctions;
> +        total_size += sizeof *m + vector_memory_usage(&m->conjunctions);
>      }
>      return total_size;
>  }
> @@ -3503,12 +3497,12 @@ expr_matches_print(const struct hmap *matches,
> FILE *stream)
>          fputs(s, stream);
>          free(s);
>
> -        if (m->n) {
> -            for (int i = 0; i < m->n; i++) {
> -                const struct cls_conjunction *c = &m->conjunctions[i];
> -                fprintf(stream, "%c conjunction(%"PRIu32", %d/%d)",
> -                        i == 0 ? ':' : ',', c->id, c->clause,
> c->n_clauses);
> -            }
> +        bool first = true;
> +        struct cls_conjunction *c;
> +        VECTOR_FOR_EACH_PTR (&m->conjunctions, c) {
> +            fprintf(stream, "%c conjunction(%"PRIu32", %d/%d)",
> +                    first ? ':' : ',', c->id, c->clause, c->n_clauses);
> +            first = false;
>          }
>          putc('\n', stream);
>      }
> diff --git a/lib/inc-proc-eng.c b/lib/inc-proc-eng.c
> index 56dc62c4f..c410af5cd 100644
> --- a/lib/inc-proc-eng.c
> +++ b/lib/inc-proc-eng.c
> @@ -30,6 +30,7 @@
>  #include "inc-proc-eng.h"
>  #include "timeval.h"
>  #include "unixctl.h"
> +#include "vec.h"
>
>  VLOG_DEFINE_THIS_MODULE(inc_proc_eng);
>
> @@ -37,8 +38,8 @@ static bool engine_force_recompute = false;
>  static bool engine_run_canceled = false;
>  static const struct engine_context *engine_context;
>
> -static struct engine_node **engine_nodes;
> -static size_t engine_n_nodes;
> +static struct vector engine_nodes =
> +    VECTOR_EMPTY_INITIALIZER(struct engine_node *);
>
>  static const char *engine_node_state_name[EN_STATE_MAX] = {
>      [EN_STALE]     = "Stale",
> @@ -93,50 +94,32 @@ engine_set_context(const struct engine_context *ctx)
>  /* Builds the topologically sorted 'sorted_nodes' array starting from
>   * 'node'.
>   */
> -static struct engine_node **
> -engine_topo_sort(struct engine_node *node, struct engine_node
> **sorted_nodes,
> -                 size_t *n_count, size_t *n_size)
> +static void
> +engine_topo_sort(struct engine_node *node, struct vector *sorted_nodes)
>  {
>      /* It's not so efficient to walk the array of already sorted nodes but
>       * we know that sorting is done only once at startup so it's ok for
> now.
>       */
> -    for (size_t i = 0; i < *n_count; i++) {
> -        if (sorted_nodes[i] == node) {
> -            return sorted_nodes;
> +    struct engine_node *sorted_node;
> +    VECTOR_FOR_EACH (sorted_nodes, sorted_node) {
> +        if (sorted_node == node) {
> +            return;
>          }
>      }
>
>      for (size_t i = 0; i < node->n_inputs; i++) {
> -        sorted_nodes = engine_topo_sort(node->inputs[i].node,
> sorted_nodes,
> -                                        n_count, n_size);
> -    }
> -    if (*n_count == *n_size) {
> -        sorted_nodes = x2nrealloc(sorted_nodes, n_size, sizeof
> *sorted_nodes);
> +        engine_topo_sort(node->inputs[i].node, sorted_nodes);
>      }
> -    sorted_nodes[(*n_count)] = node;
> -    (*n_count)++;
> -    return sorted_nodes;
> -}
>
> -/* Return the array of topologically sorted nodes when starting from
> - * 'node'. Stores the number of nodes in 'n_count'.
> - */
> -static struct engine_node **
> -engine_get_nodes(struct engine_node *node, size_t *n_count)
> -{
> -    size_t n_size = 0;
> -
> -    *n_count = 0;
> -    return engine_topo_sort(node, NULL, n_count, &n_size);
> +    vector_push(sorted_nodes, &node);
>  }
>
>  static void
>  engine_clear_stats(struct unixctl_conn *conn, int argc OVS_UNUSED,
>                     const char *argv[] OVS_UNUSED, void *arg OVS_UNUSED)
>  {
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        struct engine_node *node = engine_nodes[i];
> -
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
>          memset(&node->stats, 0, sizeof node->stats);
>      }
>      unixctl_command_reply(conn, NULL);
> @@ -150,9 +133,8 @@ engine_dump_stats(struct unixctl_conn *conn, int argc,
>      const char *dump_eng_node_name = (argc > 1 ? argv[1] : NULL);
>      const char *dump_stat_type = (argc > 2 ? argv[2] : NULL);
>
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        struct engine_node *node = engine_nodes[i];
> -
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
>          if (dump_eng_node_name && strcmp(node->name, dump_eng_node_name))
> {
>              continue;
>          }
> @@ -213,14 +195,14 @@ engine_set_log_timeout_cmd(struct unixctl_conn
> *conn, int argc OVS_UNUSED,
>  void
>  engine_init(struct engine_node *node, struct engine_arg *arg)
>  {
> -    engine_nodes = engine_get_nodes(node, &engine_n_nodes);
> +    engine_topo_sort(node, &engine_nodes);
>
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        if (engine_nodes[i]->init) {
> -            engine_nodes[i]->data =
> -                engine_nodes[i]->init(engine_nodes[i], arg);
> +    struct engine_node *sorted_node;
> +    VECTOR_FOR_EACH (&engine_nodes, sorted_node) {
> +        if (sorted_node->init) {
> +            sorted_node->data = sorted_node->init(sorted_node, arg);
>          } else {
> -            engine_nodes[i]->data = NULL;
> +            sorted_node->data = NULL;
>          }
>      }
>
> @@ -237,19 +219,18 @@ engine_init(struct engine_node *node, struct
> engine_arg *arg)
>  void
>  engine_cleanup(void)
>  {
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        if (engine_nodes[i]->clear_tracked_data) {
> -            engine_nodes[i]->clear_tracked_data(engine_nodes[i]->data);
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
> +        if (node->clear_tracked_data) {
> +            node->clear_tracked_data(node->data);
>          }
>
> -        if (engine_nodes[i]->cleanup) {
> -            engine_nodes[i]->cleanup(engine_nodes[i]->data);
> +        if (node->cleanup) {
> +            node->cleanup(node->data);
>          }
> -        free(engine_nodes[i]->data);
> +        free(node->data);
>      }
> -    free(engine_nodes);
> -    engine_nodes = NULL;
> -    engine_n_nodes = 0;
> +    vector_destroy(&engine_nodes);
>  }
>
>  struct engine_node *
> @@ -346,8 +327,9 @@ engine_node_changed(struct engine_node *node)
>  bool
>  engine_has_run(void)
>  {
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        if (engine_nodes[i]->state != EN_STALE) {
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
> +        if (node->state != EN_STALE) {
>              return true;
>          }
>      }
> @@ -357,8 +339,9 @@ engine_has_run(void)
>  bool
>  engine_has_updated(void)
>  {
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        if (engine_nodes[i]->state == EN_UPDATED) {
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
> +        if (node->state == EN_UPDATED) {
>              return true;
>          }
>      }
> @@ -390,11 +373,12 @@ void
>  engine_init_run(void)
>  {
>      VLOG_DBG("Initializing new run");
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        engine_set_node_state(engine_nodes[i], EN_STALE);
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
> +        engine_set_node_state(node, EN_STALE);
>
> -        if (engine_nodes[i]->clear_tracked_data) {
> -            engine_nodes[i]->clear_tracked_data(engine_nodes[i]->data);
> +        if (node->clear_tracked_data) {
> +            node->clear_tracked_data(node->data);
>          }
>      }
>  }
> @@ -539,11 +523,12 @@ engine_run(bool recompute_allowed)
>      }
>
>      engine_run_canceled = false;
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> -        engine_run_node(engine_nodes[i], recompute_allowed);
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
> +        engine_run_node(node, recompute_allowed);
>
> -        if (engine_nodes[i]->state == EN_CANCELED) {
> -            engine_nodes[i]->stats.cancel++;
> +        if (node->state == EN_CANCELED) {
> +            node->stats.cancel++;
>              engine_run_canceled = true;
>              return;
>          }
> @@ -553,17 +538,18 @@ engine_run(bool recompute_allowed)
>  bool
>  engine_need_run(void)
>  {
> -    for (size_t i = 0; i < engine_n_nodes; i++) {
> +    struct engine_node *node;
> +    VECTOR_FOR_EACH (&engine_nodes, node) {
>          /* Check only leaf nodes for updates. */
> -        if (engine_nodes[i]->n_inputs) {
> +        if (node->n_inputs) {
>              continue;
>          }
>
> -        engine_nodes[i]->run(engine_nodes[i], engine_nodes[i]->data);
> -        engine_nodes[i]->stats.recompute++;
> -        VLOG_DBG("input node: %s, state: %s", engine_nodes[i]->name,
> -                 engine_node_state_name[engine_nodes[i]->state]);
> -        if (engine_nodes[i]->state == EN_UPDATED) {
> +        node->run(node, node->data);
> +        node->stats.recompute++;
> +        VLOG_DBG("input node: %s, state: %s", node->name,
> +                 engine_node_state_name[node->state]);
> +        if (node->state == EN_UPDATED) {
>              return true;
>          }
>      }
> diff --git a/lib/lb.c b/lib/lb.c
> index 6e7a4e296..cd234adb8 100644
> --- a/lib/lb.c
> +++ b/lib/lb.c
> @@ -77,27 +77,20 @@ static char *
>  ovn_lb_backends_init_explicit(struct ovn_lb_vip *lb_vip, const char
> *value)
>  {
>      struct ds errors = DS_EMPTY_INITIALIZER;
> -    size_t n_allocated_backends = 0;
>      char *tokstr = xstrdup(value);
>      char *save_ptr = NULL;
> -    lb_vip->n_backends = 0;
> +    lb_vip->backends = VECTOR_EMPTY_INITIALIZER(struct ovn_lb_backend);
>
>      for (char *token = strtok_r(tokstr, ",", &save_ptr);
>          token != NULL;
>          token = strtok_r(NULL, ",", &save_ptr)) {
>
> -        if (lb_vip->n_backends == n_allocated_backends) {
> -            lb_vip->backends = x2nrealloc(lb_vip->backends,
> -                                          &n_allocated_backends,
> -                                          sizeof *lb_vip->backends);
> -        }
> -
> -        struct ovn_lb_backend *backend =
> &lb_vip->backends[lb_vip->n_backends];
> -        if (!ovn_lb_backend_init_explicit(lb_vip, backend, token,
> &errors)) {
> +        struct ovn_lb_backend backend = {0};
> +        if (!ovn_lb_backend_init_explicit(lb_vip, &backend, token,
> &errors)) {
>              continue;
>          }
>
> -        lb_vip->n_backends++;
> +        vector_push(&lb_vip->backends, &backend);
>      }
>      free(tokstr);
>
> @@ -190,31 +183,25 @@ ovn_lb_backends_init_template(struct ovn_lb_vip
> *lb_vip, const char *value_)
>      struct ds errors = DS_EMPTY_INITIALIZER;
>      char *value = xstrdup(value_);
>      char *save_ptr = NULL;
> -    size_t n_allocated_backends = 0;
> -    lb_vip->n_backends = 0;
> +    lb_vip->backends = VECTOR_EMPTY_INITIALIZER(struct ovn_lb_backend);
>
>      for (char *token = strtok_r(value, ",", &save_ptr); token;
>           token = strtok_r(NULL, ",", &save_ptr)) {
>
> -        if (lb_vip->n_backends == n_allocated_backends) {
> -            lb_vip->backends = x2nrealloc(lb_vip->backends,
> -                                          &n_allocated_backends,
> -                                          sizeof *lb_vip->backends);
> -        }
>
> -        struct ovn_lb_backend *backend =
> &lb_vip->backends[lb_vip->n_backends];
> +        struct ovn_lb_backend backend = {0};
>          if (token[0] && token[0] == '^') {
> -            if (!ovn_lb_backend_init_template(backend, token, &errors)) {
> +            if (!ovn_lb_backend_init_template(&backend, token, &errors)) {
>                  continue;
>              }
>          } else {
> -            if (!ovn_lb_backend_init_explicit(lb_vip, backend,
> +            if (!ovn_lb_backend_init_explicit(lb_vip, &backend,
>                                                token, &errors)) {
>                  continue;
>              }
>          }
>
> -        lb_vip->n_backends++;
> +        vector_push(&lb_vip->backends, &backend);
>      }
>
>      free(value);
> @@ -292,11 +279,12 @@ ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const
> char *lb_key,
>  static void
>  ovn_lb_backends_destroy(struct ovn_lb_vip *vip)
>  {
> -    for (size_t i = 0; i < vip->n_backends; i++) {
> -        free(vip->backends[i].ip_str);
> -        free(vip->backends[i].port_str);
> +    struct ovn_lb_backend *backend;
> +    VECTOR_FOR_EACH_PTR (&vip->backends, backend) {
> +        free(backend->ip_str);
> +        free(backend->port_str);
>      }
> -    free(vip->backends);
> +    vector_destroy(&vip->backends);
>  }
>
>  void
> @@ -334,8 +322,8 @@ ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct
> ds *s, bool template)
>  void
>  ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s)
>  {
> -    for (size_t i = 0; i < vip->n_backends; i++) {
> -        struct ovn_lb_backend *backend = &vip->backends[i];
> +    const struct ovn_lb_backend *backend;
> +    VECTOR_FOR_EACH_PTR (&vip->backends, backend) {
>          bool needs_brackets = vip->address_family == AF_INET6 &&
>                                vip->port_str &&
>                                !ipv6_addr_equals(&backend->ip,
> &in6addr_any);
> @@ -349,10 +337,9 @@ ovn_lb_vip_backends_format(const struct ovn_lb_vip
> *vip, struct ds *s)
>          if (backend->port_str) {
>              ds_put_format(s, ":%s", backend->port_str);
>          }
> -        if (i != vip->n_backends - 1) {
> -            ds_put_char(s, ',');
> -        }
> +        ds_put_char(s, ',');
>      }
> +    ds_chomp(s, ',');
>  }
>
>  /* Formats the VIP in the way the ovn-controller expects it, that is,
> diff --git a/lib/lb.h b/lib/lb.h
> index b1a89d63c..ce5ad3580 100644
> --- a/lib/lb.h
> +++ b/lib/lb.h
> @@ -24,6 +24,7 @@
>  #include "ovn-util.h"
>  #include "sset.h"
>  #include "uuid.h"
> +#include "vec.h"
>
>  struct uuid;
>
> @@ -37,8 +38,7 @@ struct ovn_lb_vip {
>                            * in ovn-northd.
>                            */
>      bool template_vips;  /* True if the vips are templates. */
> -    struct ovn_lb_backend *backends;
> -    size_t n_backends;
> +    struct vector backends; /* Vector of struct ovn_lb_backend. */
>
>      bool empty_backend_rej;
>      int address_family;
> diff --git a/northd/lb.c b/northd/lb.c
> index af0c92954..ffd21c5bc 100644
> --- a/northd/lb.c
> +++ b/northd/lb.c
> @@ -93,7 +93,7 @@ void ovn_northd_lb_vip_init(struct ovn_northd_lb_vip
> *lb_vip_nb,
>                              bool template)
>  {
>      lb_vip_nb->backend_ips = xstrdup(backend_ips);
> -    lb_vip_nb->n_backends = lb_vip->n_backends;
> +    lb_vip_nb->n_backends = vector_len(&lb_vip->backends);
>      lb_vip_nb->backends_nb = xcalloc(lb_vip_nb->n_backends,
>                                       sizeof *lb_vip_nb->backends_nb);
>      lb_vip_nb->lb_health_check =
> @@ -107,8 +107,9 @@ ovn_lb_vip_backends_health_check_init(const struct
> ovn_northd_lb *lb,
>  {
>      struct ds key = DS_EMPTY_INITIALIZER;
>
> -    for (size_t j = 0; j < lb_vip->n_backends; j++) {
> -        struct ovn_lb_backend *backend = &lb_vip->backends[j];
> +    for (size_t j = 0; j < vector_len(&lb_vip->backends); j++) {
> +        const struct ovn_lb_backend *backend =
> +            vector_get_ptr(&lb_vip->backends, j);
>          ds_clear(&key);
>          ds_put_format(&key, IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)
>                        ? "%s" : "[%s]", backend->ip_str);
> diff --git a/northd/northd.c b/northd/northd.c
> index 464b3798a..9a49fb8f1 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -3751,8 +3751,9 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn,
>          struct ovn_lb_vip *lb_vip = &lb->vips[i];
>          struct ovn_northd_lb_vip *lb_vip_nb = &lb->vips_nb[i];
>
> -        for (size_t j = 0; j < lb_vip->n_backends; j++) {
> -            struct ovn_lb_backend *backend = &lb_vip->backends[j];
> +        for (size_t j = 0; j < vector_len(&lb_vip->backends); j++) {
> +            const struct ovn_lb_backend *backend =
> +                vector_get_ptr(&lb_vip->backends, j);
>              struct ovn_northd_lb_backend *backend_nb =
>                  &lb_vip_nb->backends_nb[j];
>
> @@ -3826,8 +3827,10 @@ build_lb_vip_actions(const struct ovn_northd_lb *lb,
>                       bool ls_dp,
>                       const struct hmap *svc_monitor_map)
>  {
> -    bool reject = !lb_vip->n_backends && lb_vip->empty_backend_rej;
> -    bool drop = !lb_vip->n_backends && !lb_vip->empty_backend_rej;
> +    bool reject =
> +        vector_is_empty(&lb_vip->backends) && lb_vip->empty_backend_rej;
> +    bool drop =
> +        vector_is_empty(&lb_vip->backends) && !lb_vip->empty_backend_rej;
>
>      if (ls_dp || lb->affinity_timeout) {
>          const char *ip_reg =
> @@ -3842,11 +3845,12 @@ build_lb_vip_actions(const struct ovn_northd_lb
> *lb,
>      if (lb_vip_nb->lb_health_check) {
>          ds_put_cstr(action, "ct_lb_mark(backends=");
>
> +        size_t i = 0;
>          size_t n_active_backends = 0;
> -        for (size_t i = 0; i < lb_vip->n_backends; i++) {
> -            struct ovn_lb_backend *backend = &lb_vip->backends[i];
> +        const struct ovn_lb_backend *backend;
> +        VECTOR_FOR_EACH_PTR (&lb_vip->backends, backend) {
>              struct ovn_northd_lb_backend *backend_nb =
> -                &lb_vip_nb->backends_nb[i];
> +                &lb_vip_nb->backends_nb[i++];
>
>              if (!backend_nb->health_check) {
>                  continue;
> @@ -6373,7 +6377,7 @@ build_empty_lb_event_flow(struct ovn_lb_vip *lb_vip,
>  {
>      bool controller_event = lb->controller_event ||
>                              controller_event_en; /* deprecated */
> -    if (!controller_event || lb_vip->n_backends ||
> +    if (!controller_event || !vector_is_empty(&lb_vip->backends) ||
>          lb_vip->empty_backend_rej) {
>          return false;
>      }
> @@ -8195,9 +8199,8 @@ build_lb_affinity_lr_flows(struct lflow_table
> *lflows,
>      size_t aff_match_learn_len = aff_match_learn.length;
>
>
> -    for (size_t i = 0; i < lb_vip->n_backends; i++) {
> -        struct ovn_lb_backend *backend = &lb_vip->backends[i];
> -
> +    struct ovn_lb_backend *backend;
> +    VECTOR_FOR_EACH_PTR (&lb_vip->backends, backend) {
>          ds_put_cstr(&aff_match_learn, backend->ip_str);
>          ds_put_cstr(&aff_match, backend->ip_str);
>
> @@ -8370,9 +8373,8 @@ build_lb_affinity_ls_flows(struct lflow_table
> *lflows,
>      size_t aff_match_len = aff_match.length;
>      size_t aff_match_learn_len = aff_match_learn.length;
>
> -    for (size_t i = 0; i < lb_vip->n_backends; i++) {
> -        struct ovn_lb_backend *backend = &lb_vip->backends[i];
> -
> +    const struct ovn_lb_backend *backend;
> +    VECTOR_FOR_EACH_PTR (&lb_vip->backends, backend) {
>          ds_put_cstr(&aff_match_learn, backend->ip_str);
>          ds_put_cstr(&aff_match, backend->ip_str);
>
> @@ -12246,8 +12248,9 @@ build_distr_lrouter_nat_flows_for_lb(struct
> lrouter_nat_lb_flows_ctx *ctx,
>       * (created by ct_lb_mark for the first rcv packet in this flow).
>       */
>      if (stateless_nat) {
> -        if (ctx->lb_vip->n_backends) {
> -            struct ovn_lb_backend *backend = &ctx->lb_vip->backends[0];
> +        if (!vector_is_empty(&ctx->lb_vip->backends)) {
> +            const struct ovn_lb_backend *backend =
> +                vector_get_ptr(&ctx->lb_vip->backends, 0);
>              bool ipv6 = !IN6_IS_ADDR_V4MAPPED(&backend->ip);
>              ds_put_format(&dnat_action, "%s.dst = %s; ", ipv6 ? "ip6" :
> "ip4",
>                            backend->ip_str);
> @@ -12261,7 +12264,8 @@ build_distr_lrouter_nat_flows_for_lb(struct
> lrouter_nat_lb_flows_ctx *ctx,
>          meter = copp_meter_get(COPP_REJECT, od->nbr->copp,
> ctx->meter_groups);
>      }
>
> -    if (ctx->lb_vip->n_backends || !ctx->lb_vip->empty_backend_rej) {
> +    if (!vector_is_empty(&ctx->lb_vip->backends) ||
> +        !ctx->lb_vip->empty_backend_rej) {
>          ds_put_format(ctx->new_match, " && is_chassis_resident(%s)",
>                        dgp->cr_port->json_key);
>      }
> @@ -12274,7 +12278,7 @@ build_distr_lrouter_nat_flows_for_lb(struct
> lrouter_nat_lb_flows_ctx *ctx,
>      ds_truncate(ctx->new_match, new_match_len);
>
>      ds_destroy(&dnat_action);
> -    if (!ctx->lb_vip->n_backends) {
> +    if (vector_is_empty(&ctx->lb_vip->backends)) {
>          return;
>      }
>
> @@ -12466,8 +12470,8 @@ build_lrouter_nat_flows_for_lb(
>       */
>      ds_put_format(&undnat_match, "%s && (", ip_match);
>
> -    for (size_t i = 0; i < lb_vip->n_backends; i++) {
> -        struct ovn_lb_backend *backend = &lb_vip->backends[i];
> +    const struct ovn_lb_backend *backend;
> +    VECTOR_FOR_EACH_PTR (&lb_vip->backends, backend) {
>          ds_put_format(&undnat_match, "(%s.src == %s", ip_match,
>                        backend->ip_str);
>
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index c4eb2a7df..1b63c05d2 100644
> --- a/tests/test-ovn.c
> +++ b/tests/test-ovn.c
> @@ -954,7 +954,8 @@ test_tree_shape_exhaustively(struct expr *expr, struct
> shash *symtab,
>                  test_rule = xmalloc(sizeof *test_rule);
>                  cls_rule_init(&test_rule->cr, &m->match, 0);
>                  classifier_insert(&cls, &test_rule->cr, OVS_VERSION_MIN,
> -                                  m->conjunctions, m->n);
> +                                  vector_get_array(&m->conjunctions),
> +                                  vector_len(&m->conjunctions));
>              }
>          }
>          for (int subst = 0; subst < 1 << (n_bits * n_nvars + n_svars);
> --
> 2.49.0
>
>
Recheck-request: github-robot
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to