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,
> 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.
> 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) {
> + 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.
> {
> - 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);
}
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);
Should we also add a new command to list the engines? E.g.:
$ ovn-appctl inc-engine/list-engines
flow-engine
meter-engine
etc.
> + 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)
> {
> - 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);
> - free(engine_nodes);
> - engine_nodes = NULL;
> - engine_n_nodes = 0;
> + e->engine_n_nodes = 0;
This is not needed.
> + 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.
> + /* 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.
> + 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
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev