On Dec 20, Dumitru Ceara wrote:
> On 12/9/21 17:47, Lorenzo Bianconi wrote:
> > Remove global state variable and move move inc-proc code in an isolated
> > strucuture. This is a preliminary patch to add the capability to run
> > multiple inc-proc engines.
> > 
> > Signed-off-by: Lorenzo Bianconi <[email protected]>
> > ---
> 
> Hi Lorenzo,

Hi Dumitru,

thx for the review.

> 
> > Changes since v1:
> > - fix unixctl commands for IP engine.
> > ---
> >  controller/ovn-controller.c |  65 ++++++------
> >  lib/inc-proc-eng.c          | 199 ++++++++++++++++++++++--------------
> >  lib/inc-proc-eng.h          |  40 ++++++--
> >  northd/en-lflow.c           |   2 +-
> >  northd/en-northd.c          |   2 +-
> >  northd/inc-proc-northd.c    |  28 ++---
> >  6 files changed, 202 insertions(+), 134 deletions(-)
> > 
> > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> > index 5069aedfc..9f5e55bac 100644
> > --- a/controller/ovn-controller.c
> > +++ b/controller/ovn-controller.c
> 
> [...]
> 
> > @@ -4152,9 +4157,11 @@ inject_pkt(struct unixctl_conn *conn, int argc 
> > OVS_UNUSED,
> >  
> >  static void
> >  engine_recompute_cmd(struct unixctl_conn *conn OVS_UNUSED, int argc 
> > OVS_UNUSED,
> > -                     const char *argv[] OVS_UNUSED, void *arg OVS_UNUSED)
> > +                     const char *argv[] OVS_UNUSED, void *arg)
> >  {
> > -    engine_trigger_recompute();
> > +    struct engine *e = arg;
> > +
> > +    engine_trigger_recompute(e);
> 
> Nit: This can be engine_trigger_recompute(arg) directly.

ack, I will fix it in v3.

> 
> >      unixctl_command_reply(conn, NULL);
> >  }
> >  
> > @@ -4166,7 +4173,7 @@ lflow_cache_flush_cmd(struct unixctl_conn *conn 
> > OVS_UNUSED,
> >      VLOG_INFO("User triggered lflow cache flush.");
> >      struct lflow_output_persistent_data *fo_pd = arg_;
> >      lflow_cache_flush(fo_pd->lflow_cache);
> > -    engine_set_force_recompute(true);
> > +    engine_set_force_recompute(flow_engine, true);
> >      poll_immediate_wake();
> >      unixctl_command_reply(conn, NULL);
> >  }
> > diff --git a/lib/inc-proc-eng.c b/lib/inc-proc-eng.c
> > index 2958a55e3..e7b3e9d2d 100644
> > --- a/lib/inc-proc-eng.c
> > +++ b/lib/inc-proc-eng.c
> > @@ -33,12 +33,7 @@
> >  
> >  VLOG_DEFINE_THIS_MODULE(inc_proc_eng);
> >  
> > -static bool engine_force_recompute = false;
> > -static bool engine_run_aborted = false;
> > -static const struct engine_context *engine_context;
> > -
> > -static struct engine_node **engine_nodes;
> > -static size_t engine_n_nodes;
> > +static struct ovs_list engines = OVS_LIST_INITIALIZER(&engines);
> >  
> >  static const char *engine_node_state_name[EN_STATE_MAX] = {
> >      [EN_STALE]     = "Stale",
> > @@ -52,21 +47,21 @@ engine_recompute(struct engine_node *node, bool allowed,
> >                   const char *reason_fmt, ...) OVS_PRINTF_FORMAT(3, 4);
> >  
> >  void
> > -engine_set_force_recompute(bool val)
> > +engine_set_force_recompute(struct engine *e, bool val)
> >  {
> > -    engine_force_recompute = val;
> > +    e->engine_force_recompute = val;
> >  }
> >  
> >  const struct engine_context *
> > -engine_get_context(void)
> > +engine_get_context(struct engine *e)
> >  {
> > -    return engine_context;
> > +    return e->engine_context;
> >  }
> >  
> >  void
> > -engine_set_context(const struct engine_context *ctx)
> > +engine_set_context(struct engine *e, const struct engine_context *ctx)
> >  {
> > -    engine_context = ctx;
> > +    e->engine_context = ctx;
> >  }
> >  
> >  /* Builds the topologically sorted 'sorted_nodes' array starting from
> > @@ -113,30 +108,53 @@ 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];
> > +    const char *target = argc == 2 ? argv[1] : NULL;
> > +    struct ds reply = DS_EMPTY_INITIALIZER;
> > +    struct engine *e;
> > +
> > +    ds_put_format(&reply, "no %s engine found", target ? target : "");
> > +    LIST_FOR_EACH (e, node, &engines) {
> > +        for (size_t i = 0; i < e->engine_n_nodes; i++) {
> > +            struct engine_node *node = e->engine_nodes[i];
> >  
> > -        memset(&node->stats, 0, sizeof node->stats);
> > +            if (target && strcmp(target, e->name)) {
> > +                continue;
> > +            }
> > +            memset(&node->stats, 0, sizeof node->stats);
> > +            ds_clear(&reply);
> > +        }
> >      }
> > -    unixctl_command_reply(conn, NULL);
> > +
> > +    unixctl_command_reply(conn, ds_cstr(&reply));
> > +    ds_destroy(&reply);
> >  }
> >  
> >  static void
> > -engine_dump_stats(struct unixctl_conn *conn, int argc OVS_UNUSED,
> > +engine_dump_stats(struct unixctl_conn *conn, int argc,
> >                    const char *argv[] OVS_UNUSED, void *arg OVS_UNUSED)
> >  {
> > +    const char *target = argc == 2 ? argv[1] : NULL;
> >      struct ds dump = DS_EMPTY_INITIALIZER;
> > +    struct engine *e;
> >  
> > -    for (size_t i = 0; i < engine_n_nodes; i++) {
> > -        struct engine_node *node = engine_nodes[i];
> > +    LIST_FOR_EACH (e, node, &engines) {
> > +        for (size_t i = 0; i < e->engine_n_nodes; i++) {
> > +            struct engine_node *node = e->engine_nodes[i];
> >  
> > -        ds_put_format(&dump,
> > -                      "Node: %s\n"
> > -                      "- recompute: %12"PRIu64"\n"
> > -                      "- compute:   %12"PRIu64"\n"
> > -                      "- abort:     %12"PRIu64"\n",
> > -                      node->name, node->stats.recompute,
> > -                      node->stats.compute, node->stats.abort);
> > +            if (target && strcmp(target, e->name)) {
> > +                continue;
> > +            }
> > +            ds_put_format(&dump,
> > +                          "Node: %s\n"
> > +                          "- recompute: %12"PRIu64"\n"
> > +                          "- compute:   %12"PRIu64"\n"
> > +                          "- abort:     %12"PRIu64"\n",
> > +                          node->name, node->stats.recompute,
> > +                          node->stats.compute, node->stats.abort);
> > +        }
> > +    }
> > +    if (!dump.length) {
> 
> It's probably better to not use dynamic string internals.  I'd rewrite
> this as:
> 
> if (ds_last(&dump) == EOF) {

ack, I will fix it in v3.
> 
> > +        ds_put_format(&dump, "no %s engine found", target ? target : "");
> >      }
> >      unixctl_command_reply(conn, ds_cstr(&dump));
> >  
> > @@ -148,48 +166,69 @@ engine_trigger_recompute_cmd(struct unixctl_conn 
> > *conn, int argc OVS_UNUSED,
> >                               const char *argv[] OVS_UNUSED,
> >                               void *arg OVS_UNUSED)
> >  {
> > -    engine_trigger_recompute();
> > -    unixctl_command_reply(conn, NULL);
> > +    const char *target = argc == 2 ? argv[1] : NULL;
> > +    struct ds reply = DS_EMPTY_INITIALIZER;
> > +    struct engine *e;
> > +
> > +    ds_put_format(&reply, "no %s engine found", target ? target : "");
> > +    LIST_FOR_EACH (e, node, &engines) {
> > +        if (target && strcmp(target, e->name)) {
> > +            continue;
> > +        }
> > +        engine_trigger_recompute(e);
> > +        ds_clear(&reply);
> > +    }
> > +
> > +    unixctl_command_reply(conn, ds_cstr(&reply));
> > +    ds_destroy(&reply);
> >  }
> >  
> > -void
> > -engine_init(struct engine_node *node, struct engine_arg *arg)
> > +void engine_init(struct engine **pe, struct engine_node *node,
> > +                 struct engine_arg *arg, const char *name)
> 
> It's probably more clear if we return "struct engine *" from this
> function instead of passing "struct **pe".  We could also rename it to
> engine_new(..), I think.

ack, I will fix it in v3.

> 
> >  {
> > -    engine_nodes = engine_get_nodes(node, &engine_n_nodes);
> > +    struct engine *e = xzalloc(sizeof *e);
> > +
> > +    e->engine_nodes = engine_get_nodes(node, &e->engine_n_nodes);
> > +    e->name = name;
> >  
> > -    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);
> > +    for (size_t i = 0; i < e->engine_n_nodes; i++) {
> > +        if (e->engine_nodes[i]->init) {
> > +            e->engine_nodes[i]->data =
> > +                e->engine_nodes[i]->init(e->engine_nodes[i], arg);
> >          } else {
> > -            engine_nodes[i]->data = NULL;
> > +            e->engine_nodes[i]->data = NULL;
> >          }
> > +        e->engine_nodes[i]->e = e;
> >      }
> >  
> > -    unixctl_command_register("inc-engine/show-stats", "", 0, 0,
> > +    unixctl_command_register("inc-engine/show-stats", "", 0, 1,
> >                               engine_dump_stats, NULL);
> > -    unixctl_command_register("inc-engine/clear-stats", "", 0, 0,
> > +    unixctl_command_register("inc-engine/clear-stats", "", 0, 1,
> >                               engine_clear_stats, NULL);
> > -    unixctl_command_register("inc-engine/recompute", "", 0, 0,
> > +    unixctl_command_register("inc-engine/recompute", "", 0, 1,
> >                               engine_trigger_recompute_cmd, NULL);
> 
> It's a bit confusing to call unixctl_command_register() here now.
> It will not do anything except the first time an engine is added.  We
> should probably use a constructor and move this part to a separate function:
> 
> OVS_CONSTRUCTOR(inc_proc_eng_init)
> {
>     unixctl_command_register("inc-engine/show-stats", "", 0, 1,
>                              engine_dump_stats, NULL);
>     unixctl_command_register("inc-engine/clear-stats", "", 0, 1,
>                              engine_clear_stats, NULL);
>     unixctl_command_register("inc-engine/recompute", "", 0, 1,
>                              engine_trigger_recompute_cmd, NULL);
> }

ack, I will fix it in v3.

> 
> We also need to update the usage strings for these commands, e.g.:
> 
>     unixctl_command_register("inc-engine/show-stats",
>                            "[engine]", 0, 1,
>                              engine_dump_stats, NULL);

ack, I will fix it in v3.

> 
> Should we also add a new command to list the engines?  E.g.:
> 
> $ ovn-appctl inc-engine/list-engines
> flow-engine
> meter-engine
> etc.

ack, I will add it in v3.

> 
> > +    ovs_list_push_back(&engines, &e->node);
> > +    *pe = e;
> >  }
> >  
> >  void
> > -engine_cleanup(void)
> > +engine_cleanup(struct engine **pe)
> 
> If we change engine_init() to return the new engine then we should also
> change this to:
> 
> void
> engine_cleanup(struct engine *pe)

ack, I will fix it in v3.

> 
> >  {
> > -    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 *e = *pe;
> > +    for (size_t i = 0; i < e->engine_n_nodes; i++) {
> > +        if (e->engine_nodes[i]->clear_tracked_data) {
> > +            e->engine_nodes[i]->clear_tracked_data(
> > +                    e->engine_nodes[i]->data);
> >          }
> >  
> > -        if (engine_nodes[i]->cleanup) {
> > -            engine_nodes[i]->cleanup(engine_nodes[i]->data);
> > +        if (e->engine_nodes[i]->cleanup) {
> > +            e->engine_nodes[i]->cleanup(e->engine_nodes[i]->data);
> >          }
> > -        free(engine_nodes[i]->data);
> > +        free(e->engine_nodes[i]->data);
> >      }
> 
> We need to remove the engine from the list of engines:
> 
> ovs_list_remove(&e->node);

ditto.
> 
> > -    free(engine_nodes);
> > -    engine_nodes = NULL;
> > -    engine_n_nodes = 0;
> > +    e->engine_n_nodes = 0;
> 
> This is not needed.
ditto.
> 
> > +    free(e->engine_nodes);
> > +    *pe = NULL;
> >  }
> >  
> 
> [...]
> 
> > diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
> > index 9bfab1f7c..7f59dfa63 100644
> > --- a/lib/inc-proc-eng.h
> > +++ b/lib/inc-proc-eng.h
> > @@ -67,6 +67,7 @@
> >  #include <stdint.h>
> >  
> >  #include "compiler.h"
> > +#include "openvswitch/list.h"
> >  
> >  struct engine_context {
> >      struct ovsdb_idl_txn *ovs_idl_txn;
> > @@ -122,6 +123,8 @@ struct engine_stats {
> >  };
> >  
> >  struct engine_node {
> > +    struct engine *e;
> > +
> >      /* A unique name for each node. */
> >      char *name;
> >  
> > @@ -173,30 +176,45 @@ struct engine_node {
> >      struct engine_stats stats;
> >  };
> >  
> > +struct engine {
> > +    struct ovs_list node;
> 
> Nit: Please add an empty line.
ditto.
> 
> > +    /* A unique name for each node. */
> 
> Nit: or remove this comment, seems a bit redundant and it's actually the
> engine's name, not the node's.
ditto.
> 
> > +    const char *name;
> > +
> > +    struct engine_node **engine_nodes;
> > +    size_t engine_n_nodes;
> > +
> > +    bool engine_force_recompute;
> > +    bool engine_run_aborted;
> > +
> > +    const struct engine_context *engine_context;
> > +};
> 
> Thanks,
> Dumitru

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

Reply via email to