On Thu, 2023-05-25 at 08:38 -0500, Dan Williams wrote:
> On Wed, 2023-05-24 at 11:12 +0200, Ihtisham ul Haq via dev wrote:
> > Using cache improves performance of recomputation of lflows(by
> > about 30%)
> > 
> > Exising lflow cache for `matches` and `expressions` is adopted
> > to include `actions` as well.
> > 
> > Co-authored-by: Felix Huettner <[email protected]>
> > Signed-off-by: Felix Huettner <[email protected]>
> > Signed-off-by: Ihtisham ul Haq <[email protected]>
> > ---
> >  controller/lflow-cache.c      | 12 ++++++++--
> >  controller/lflow-cache.h      |  8 +++++--
> >  controller/lflow.c            | 41 +++++++++++++++++++++-------------
> >  controller/test-lflow-cache.c | 42 +++++++++++++++++++++++++++--------
> >  tests/ovn-lflow-cache.at      | 41 ++++++++++++++++++++++++++++++++++
> >  5 files changed, 115 insertions(+), 29 deletions(-)
> > 
> > diff --git a/controller/lflow-cache.c b/controller/lflow-cache.c
> > index f723eab8a..a648d77af 100644
> > --- a/controller/lflow-cache.c
> > +++ b/controller/lflow-cache.c
> > @@ -25,7 +25,9 @@
> >  #include "lflow-cache.h"
> >  #include "lib/uuid.h"
> >  #include "memory-trim.h"
> > +#include "openvswitch/ofpbuf.h"
> >  #include "openvswitch/vlog.h"
> > +#include "ovn/actions.h"
> >  #include "ovn/expr.h"
> > 
> >  VLOG_DEFINE_THIS_MODULE(lflow_cache);
> > @@ -209,7 +211,8 @@ lflow_cache_get_stats(const struct lflow_cache *lc, 
> > struct ds *output)
> > 
> >  void
> >  lflow_cache_add_expr(struct lflow_cache *lc, const struct uuid *lflow_uuid,
> > -                     struct expr *expr, size_t expr_sz)
> > +                     struct expr *expr, size_t expr_sz,
> > +                     struct ofpbuf *actions)
> >  {
> >      struct lflow_cache_value *lcv =
> >          lflow_cache_add__(lc, lflow_uuid, LCACHE_T_EXPR, expr_sz);
> > @@ -220,12 +223,14 @@ lflow_cache_add_expr(struct lflow_cache *lc, const 
> > struct uuid *lflow_uuid,
> >      }
> >      COVERAGE_INC(lflow_cache_add_expr);
> >      lcv->expr = expr;
> > +    lcv->actions = actions;
> 
> Since the function consumes the action, you need to free & uninit the
> actions in the !lcv case above this chunk, like happens for 'expr'.
> 
> >  }
> > 
> >  void
> >  lflow_cache_add_matches(struct lflow_cache *lc, const struct uuid 
> > *lflow_uuid,
> >                          uint32_t conj_id_ofs, uint32_t n_conjs,
> > -                        struct hmap *matches, size_t matches_sz)
> > +                        struct hmap *matches, size_t matches_sz,
> > +                        struct ofpbuf *actions)
> >  {
> >      struct lflow_cache_value *lcv =
> >          lflow_cache_add__(lc, lflow_uuid, LCACHE_T_MATCHES, matches_sz);
> > @@ -239,6 +244,7 @@ lflow_cache_add_matches(struct lflow_cache *lc, const 
> > struct uuid *lflow_uuid,
> >      lcv->expr_matches = matches;
> >      lcv->n_conjs = n_conjs;
> >      lcv->conj_id_ofs = conj_id_ofs;
> > +    lcv->actions = actions;
> 
> Similarly, since the function consumes the action, you need to free &
> uninit the actions in the !lcv case above this chunk, like happens for
> 'matches'.
> 
> >  }
> > 
> >  struct lflow_cache_value *
> > @@ -380,11 +386,13 @@ lflow_cache_delete__(struct lflow_cache *lc, struct 
> > lflow_cache_entry *lce)
> >      case LCACHE_T_EXPR:
> >          COVERAGE_INC(lflow_cache_free_expr);
> >          expr_destroy(lce->value.expr);
> > +        ovnacts_free((*lce->value.actions).data, 
> > (*lce->value.actions).size);
> 
> ovnacts_free(lce->value.actions->data, lce->value.actions->size);
> 
> seems a bit more canonical (eg, actions->data instead of dereferencing 
> actions and using '.')
> 
> >          break;
> >      case LCACHE_T_MATCHES:
> >          COVERAGE_INC(lflow_cache_free_matches);
> >          expr_matches_destroy(lce->value.expr_matches);
> >          free(lce->value.expr_matches);
> > +        ovnacts_free((*lce->value.actions).data, 
> > (*lce->value.actions).size);
> 
> Same here.
> 
> >          break;
> >      }
> > 
> > diff --git a/controller/lflow-cache.h b/controller/lflow-cache.h
> > index 300a56077..9d542beec 100644
> > --- a/controller/lflow-cache.h
> > +++ b/controller/lflow-cache.h
> > @@ -50,6 +50,8 @@ struct lflow_cache_value {
> >      uint32_t n_conjs;
> >      uint32_t conj_id_ofs;
> > 
> > +    struct ofpbuf *actions;
> > +
> >      union {
> >          struct hmap *expr_matches;
> >          struct expr *expr;
> > @@ -66,11 +68,13 @@ bool lflow_cache_is_enabled(const struct lflow_cache *);
> >  void lflow_cache_get_stats(const struct lflow_cache *, struct ds *output);
> > 
> >  void lflow_cache_add_expr(struct lflow_cache *, const struct uuid 
> > *lflow_uuid,
> > -                          struct expr *expr, size_t expr_sz);
> > +                          struct expr *expr, size_t expr_sz,
> > +                          struct ofpbuf *actions);
> >  void lflow_cache_add_matches(struct lflow_cache *,
> >                               const struct uuid *lflow_uuid,
> >                               uint32_t conj_id_ofs, uint32_t n_conjs,
> > -                             struct hmap *matches, size_t matches_sz);
> > +                             struct hmap *matches, size_t matches_sz,
> > +                             struct ofpbuf *actions);
> > 
> >  struct lflow_cache_value *lflow_cache_get(struct lflow_cache *,
> >                                            const struct uuid *lflow_uuid);
> > diff --git a/controller/lflow.c b/controller/lflow.c
> > index 0b071138d..5ca676ee8 100644
> > --- a/controller/lflow.c
> > +++ b/controller/lflow.c
> > @@ -1078,14 +1078,23 @@ consider_logical_flow__(const struct 
> > sbrec_logical_flow *lflow,
> >      struct sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref);
> >      struct expr *prereqs = NULL;
> > 
> > -    if (!lflow_parse_actions(lflow, l_ctx_in, &template_vars_ref,
> > -                             &ovnacts, &prereqs)) {
> > -        ovnacts_free(ovnacts.data, ovnacts.size);
> > -        ofpbuf_uninit(&ovnacts);
> > -        store_lflow_template_refs(l_ctx_out->lflow_deps_mgr,
> > -                                  &template_vars_ref, lflow);
> > -        sset_destroy(&template_vars_ref);
> > -        return;
> > +    struct lflow_cache_value *lcv =
> > +        lflow_cache_get(l_ctx_out->lflow_cache, &lflow->header_.uuid);
> > +    enum lflow_cache_type lcv_type =
> > +        lcv ? lcv->type : LCACHE_T_NONE;
> > +
> > +    if (lcv_type != LCACHE_T_NONE) {
> > +        ovnacts = *ofpbuf_clone(lcv->actions);
> 
> Nothing actually modifies lcv->actions so we can optimize memory usage
> for the cached case by never cloning if we have a cache hit. (we could
> also avoid cloning the uncached actions if it was heap-allocated, but
> that's another patch perhaps).
> 
> Since you'd have to track the cached actions separately to ensure they
> don't get freed, you could:
> 
>     uint64_t ovnacts_stub[1024 / 8];
>     struct ofpbuf ovnacts = OFPBUF_STUB_INITIALIZER(ovnacts_stub);
>     struct ofpbuf *ovnacts_cached = NULL;
>     ...
> 
>     if (lcv_type != LCACHE_T_NONE) {
>         ovnacts_cached = lcv->actions;
>     } else {
>         if (!lflow_parse_actions(lflow, l_ctx_in, &template_vars_ref,
>                                  &ovnacts, &prereqs)) {
>             ovnacts_free(ovnacts.data, ovnacts.size);
>             ofpbuf_uninit(&ovnacts);
>             store_lflow_template_refs(l_ctx_out->lflow_deps_mgr,
>                                     &template_vars_ref, lflow);
>             sset_destroy(&template_vars_ref);
>             return;
>         }
>     }
>     ...
>     if (lcv_type == LCACHE_T_MATCHES
>         && lcv->n_conjs
>         && !lflow_conj_ids_alloc_specified(l_ctx_out->conj_ids,
>                                            &lflow->header_.uuid,
>                                            &dp->header_.uuid,
>                                            lcv->conj_id_ofs, lcv->n_conjs)) {
>         /* This should happen very rarely. */
>         VLOG_DBG("lflow "UUID_FMT" match cached with conjunctions, but the"
>                  " cached ids are not available anymore. Drop the cache.",
>                  UUID_ARGS(&lflow->header_.uuid));
>         /* Clone actions as they'll get freed when the cache entry is deleted 
> */
>         ovnacts_cached = ofpbuf_clone(ovnacts_cached);
>         lflow_cache_delete(l_ctx_out->lflow_cache, &lflow->header_.uuid);
>         lcv_type = LCACHE_T_NONE;
>     }
>     ...
>     add_matches_to_flow_table(lflow, ldp, matches, ptable, output_ptable,
>                               ovnacts_cached ? ovnacts_cached : ovnacts,
>                               ingress, l_ctx_in, l_ctx_out);
>     ...
>         /* Cache new entry if caching is enabled. */
>         if (lflow_cache_is_enabled(l_ctx_out->lflow_cache)) {
>             struct ofpbuf *lcv_actions = ovnacts_cached
>                                          ? ovnacts_cached
>                                          : ofpbuf_clone(&ovnacts);
>     ...
>  done:
>      ovnacts_free(ovnacts_uncached.data, ovnacts_uncached.size);
>      ofpbuf_uninit(&ovnacts_uncached);

These should be just 'ovnacts', not 'ovnacts_uncached'... left-over
from a draft reply.

> 
> You wouldn't need to free the cached actions (since they're still owned
> by the cache), just the ones created by lflow_parse_actions() in
> ovnact_uncached.
> 
> > +    } else {
> > +        if (!lflow_parse_actions(lflow, l_ctx_in, &template_vars_ref,
> > +                                 &ovnacts, &prereqs)) {
> > +            ovnacts_free(ovnacts.data, ovnacts.size);
> > +            ofpbuf_uninit(&ovnacts);
> > +            store_lflow_template_refs(l_ctx_out->lflow_deps_mgr,
> > +                                    &template_vars_ref, lflow);
> > +            sset_destroy(&template_vars_ref);
> > +            return;
> > +        }
> >      }
> > 
> >      struct lookup_port_aux aux = {
> > @@ -1105,11 +1114,6 @@ consider_logical_flow__(const struct 
> > sbrec_logical_flow *lflow,
> >          .deps_mgr = l_ctx_out->lflow_deps_mgr,
> >      };
> > 
> > -    struct lflow_cache_value *lcv =
> > -        lflow_cache_get(l_ctx_out->lflow_cache, &lflow->header_.uuid);
> > -    enum lflow_cache_type lcv_type =
> > -        lcv ? lcv->type : LCACHE_T_NONE;
> > -
> >      struct expr *cached_expr = NULL, *expr = NULL;
> >      struct hmap *matches = NULL;
> >      size_t matches_size = 0;
> > @@ -1211,17 +1215,20 @@ consider_logical_flow__(const struct 
> > sbrec_logical_flow *lflow,
> >      case LCACHE_T_NONE:
> >          /* Cache new entry if caching is enabled. */
> >          if (lflow_cache_is_enabled(l_ctx_out->lflow_cache)) {
> > +            struct ofpbuf *lcv_actions = ofpbuf_clone(&ovnacts);
> 
> If you go with the above suggestion, then we wouldn't need to clone if
> ovnacts_cached != NULL since it was already cloned by the cache drop
> case.
> 
> >              if (cached_expr
> >                  && !objdep_mgr_contains_obj(l_ctx_out->lflow_deps_mgr,
> >                                              &lflow->header_.uuid)) {
> >                  lflow_cache_add_matches(l_ctx_out->lflow_cache,
> >                                          &lflow->header_.uuid, 
> > start_conj_id,
> > -                                        n_conjs, matches, matches_size);
> > +                                        n_conjs, matches, matches_size,
> > +                                        lcv_actions);
> >                  matches = NULL;
> >              } else if (cached_expr) {
> >                  lflow_cache_add_expr(l_ctx_out->lflow_cache,
> >                                       &lflow->header_.uuid,
> > -                                     cached_expr, expr_size(cached_expr));
> > +                                     cached_expr, expr_size(cached_expr),
> > +                                     lcv_actions);
> >                  cached_expr = NULL;
> >              }
> 
> If neither of the if() statements happened the cloned lcv_actions gets
> leaked.
> 
> You could add:
> 
> } else {
>     ovnacts_free(lcv_actions->data, lcv_actions->size);
>     ofpbuf_uninit(lcv_actions);
> }
> 
> >          }
> > @@ -1236,7 +1243,9 @@ consider_logical_flow__(const struct 
> > sbrec_logical_flow *lflow,
> > 
> >  done:
> >      expr_destroy(prereqs);
> > -    ovnacts_free(ovnacts.data, ovnacts.size);
> > +    if (!lflow_cache_is_enabled(l_ctx_out->lflow_cache)) {
> > +        ovnacts_free(ovnacts.data, ovnacts.size);
> 
> Don't we want to always free here? Since it's getting cloned before
> being added to the cache we should still free the original data.
> 
> And we have to clone the uncached ovnacts before caching them, because
> it's a stack buffer. So I think we always want to free here, cached or
> uncached.
> 
> Dan
> 
> > +    }
> >      ofpbuf_uninit(&ovnacts);
> >      expr_destroy(expr);
> >      expr_destroy(cached_expr);
> > diff --git a/controller/test-lflow-cache.c b/controller/test-lflow-cache.c
> > index 7ce999360..03e216290 100644
> > --- a/controller/test-lflow-cache.c
> > +++ b/controller/test-lflow-cache.c
> > @@ -16,6 +16,8 @@
> >  #include <config.h>
> > 
> >  #include "lib/uuid.h"
> > +#include "openvswitch/ofpbuf.h"
> > +#include "ovn/actions.h"
> >  #include "ovn/expr.h"
> >  #include "tests/ovstest.h"
> >  #include "tests/test-utils.h"
> > @@ -39,22 +41,26 @@ test_lflow_cache_add__(struct lflow_cache *lc, const 
> > char *op_type,
> >                         const struct uuid *lflow_uuid,
> >                         unsigned int conj_id_ofs,
> >                         unsigned int n_conjs,
> > -                       struct expr *e)
> > +                       struct expr *e, struct ofpbuf *a)
> >  {
> > +    struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
> > +    ovnacts_format(a->data, a->size, &ovnacts_s);
> > +
> >      printf("ADD %s:\n", op_type);
> >      printf("  conj-id-ofs: %u\n", conj_id_ofs);
> >      printf("  n_conjs: %u\n", n_conjs);
> > +    printf("  action: %s\n", ds_cstr(&ovnacts_s));
> > 
> >      if (!strcmp(op_type, "expr")) {
> >          lflow_cache_add_expr(lc, lflow_uuid, expr_clone(e),
> > -                             TEST_LFLOW_CACHE_VALUE_SIZE);
> > +                             TEST_LFLOW_CACHE_VALUE_SIZE, ofpbuf_clone(a));
> >      } else if (!strcmp(op_type, "matches")) {
> >          struct hmap *matches = xmalloc(sizeof *matches);
> >          ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0);
> >          ovs_assert(hmap_count(matches) == 1);
> >          lflow_cache_add_matches(lc, lflow_uuid,
> >                                  conj_id_ofs, n_conjs, matches,
> > -                                TEST_LFLOW_CACHE_VALUE_SIZE);
> > +                                TEST_LFLOW_CACHE_VALUE_SIZE, 
> > ofpbuf_clone(a));
> >      } else {
> >          OVS_NOT_REACHED();
> >      }
> > @@ -72,8 +78,12 @@ test_lflow_cache_lookup__(struct lflow_cache *lc,
> >          return;
> >      }
> > 
> > +    struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
> > +    ovnacts_format(lcv->actions->data, lcv->actions->size, &ovnacts_s);
> > +
> >      printf("  conj_id_ofs: %"PRIu32"\n", lcv->conj_id_ofs);
> >      printf("  n_conjs: %"PRIu32"\n", lcv->n_conjs);
> > +    printf("  action: %s\n", ds_cstr(&ovnacts_s));
> >      switch (lcv->type) {
> >      case LCACHE_T_EXPR:
> >          printf("  type: expr\n");
> > @@ -110,6 +120,13 @@ test_lflow_cache_operations(struct ovs_cmdl_context 
> > *ctx)
> >  {
> >      struct lflow_cache *lc = lflow_cache_create();
> >      struct expr *e = expr_create_boolean(true);
> > +    struct ofpbuf *a = ofpbuf_new(0);
> > +    struct ovnact_next *next = ovnact_put_NEXT(a);
> > +    next->pipeline = 1;
> > +    next->ltable = 2;
> > +    next->src_pipeline = OVNACT_P_INGRESS;
> > +    next->src_ltable = 3;
> > +
> >      bool enabled = !strcmp(ctx->argv[1], "true");
> >      struct uuid *lflow_uuids = NULL;
> >      size_t n_allocated_lflow_uuids = 0;
> > @@ -160,7 +177,7 @@ test_lflow_cache_operations(struct ovs_cmdl_context 
> > *ctx)
> > 
> >              uuid_generate(lflow_uuid);
> >              test_lflow_cache_add__(lc, op_type, lflow_uuid, conj_id_ofs,
> > -                                   n_conjs, e);
> > +                                   n_conjs, e, a);
> >              test_lflow_cache_lookup__(lc, lflow_uuid);
> >          } else if (!strcmp(op, "add-del")) {
> >              const char *op_type = test_read_value(ctx, shift++, "op_type");
> > @@ -183,7 +200,7 @@ test_lflow_cache_operations(struct ovs_cmdl_context 
> > *ctx)
> >              struct uuid lflow_uuid;
> >              uuid_generate(&lflow_uuid);
> >              test_lflow_cache_add__(lc, op_type, &lflow_uuid, conj_id_ofs,
> > -                                   n_conjs, e);
> > +                                   n_conjs, e, a);
> >              test_lflow_cache_lookup__(lc, &lflow_uuid);
> >              test_lflow_cache_delete__(lc, &lflow_uuid);
> >              test_lflow_cache_lookup__(lc, &lflow_uuid);
> > @@ -264,16 +281,23 @@ test_lflow_cache_negative(struct ovs_cmdl_context 
> > *ctx OVS_UNUSED)
> > 
> >      for (size_t i = 0; i < ARRAY_SIZE(lcs); i++) {
> >          struct expr *e = expr_create_boolean(true);
> > +        struct ofpbuf *a = ofpbuf_new(0);
> > +        struct ovnact_next *next = ovnact_put_NEXT(a);
> > +        next->pipeline = 1;
> > +        next->ltable = 2;
> > +        next->src_pipeline = OVNACT_P_INGRESS;
> > +        next->src_ltable = 3;
> > +
> >          struct hmap *matches = xmalloc(sizeof *matches);
> > 
> >          ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0);
> >          ovs_assert(hmap_count(matches) == 1);
> > 
> > -        lflow_cache_add_expr(lcs[i], NULL, NULL, 0);
> > -        lflow_cache_add_expr(lcs[i], NULL, e, expr_size(e));
> > -        lflow_cache_add_matches(lcs[i], NULL, 0, 0, NULL, 0);
> > +        lflow_cache_add_expr(lcs[i], NULL, NULL, 0, NULL);
> > +        lflow_cache_add_expr(lcs[i], NULL, e, expr_size(e), a);
> > +        lflow_cache_add_matches(lcs[i], NULL, 0, 0, NULL, 0, NULL);
> >          lflow_cache_add_matches(lcs[i], NULL, 0, 0, matches,
> > -                                TEST_LFLOW_CACHE_VALUE_SIZE);
> > +                                TEST_LFLOW_CACHE_VALUE_SIZE, a);
> >          lflow_cache_destroy(lcs[i]);
> >      }
> >  }
> > diff --git a/tests/ovn-lflow-cache.at b/tests/ovn-lflow-cache.at
> > index 593d3eaac..b1f79cb72 100644
> > --- a/tests/ovn-lflow-cache.at
> > +++ b/tests/ovn-lflow-cache.at
> > @@ -19,9 +19,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -32,9 +34,11 @@ trim count      : 0
> >  ADD matches:
> >    conj-id-ofs: 3
> >    n_conjs: 2
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 3
> >    n_conjs: 2
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  Enabled: true
> >  high-watermark  : 2
> > @@ -61,9 +65,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  DELETE
> >  LOOKUP:
> > @@ -77,9 +83,11 @@ trim count      : 0
> >  ADD matches:
> >    conj-id-ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  DELETE
> >  LOOKUP:
> > @@ -109,6 +117,7 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  Enabled: false
> > @@ -120,6 +129,7 @@ trim count      : 0
> >  ADD matches:
> >    conj-id-ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  Enabled: false
> > @@ -154,9 +164,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -167,9 +179,11 @@ trim count      : 0
> >  ADD matches:
> >    conj-id-ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  Enabled: true
> >  high-watermark  : 2
> > @@ -188,6 +202,7 @@ trim count      : 1
> >  ADD expr:
> >    conj-id-ofs: 5
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  Enabled: false
> > @@ -199,6 +214,7 @@ trim count      : 1
> >  ADD matches:
> >    conj-id-ofs: 6
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  Enabled: false
> > @@ -217,9 +233,11 @@ trim count      : 1
> >  ADD expr:
> >    conj-id-ofs: 8
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -230,9 +248,11 @@ trim count      : 1
> >  ADD matches:
> >    conj-id-ofs: 9
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 9
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  Enabled: true
> >  high-watermark  : 2
> > @@ -273,9 +293,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -286,9 +308,11 @@ trim count      : 0
> >  ADD matches:
> >    conj-id-ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  Enabled: true
> >  high-watermark  : 2
> > @@ -309,9 +333,11 @@ trim count      : 1
> >  ADD expr:
> >    conj-id-ofs: 5
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -322,9 +348,11 @@ trim count      : 1
> >  ADD matches:
> >    conj-id-ofs: 6
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 6
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >    type: matches
> >  dnl
> >  dnl Cache is full but we can evict the expr entry because we're adding
> > @@ -339,6 +367,7 @@ trim count      : 1
> >  ADD expr:
> >    conj-id-ofs: 7
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  dnl
> > @@ -365,6 +394,7 @@ trim count      : 2
> >  ADD expr:
> >    conj-id-ofs: 9
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  dnl
> > @@ -380,6 +410,7 @@ trim count      : 2
> >  ADD matches:
> >    conj-id-ofs: 10
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    not found
> >  dnl
> > @@ -428,9 +459,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 1
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 1
> > @@ -441,9 +474,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 2
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 2
> > @@ -454,9 +489,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 3
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 3
> > @@ -467,9 +504,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 4
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 4
> > @@ -480,9 +519,11 @@ trim count      : 0
> >  ADD expr:
> >    conj-id-ofs: 5
> >    n_conjs: 1
> > +  action: next(pipeline=egress, table=2);
> >  LOOKUP:
> >    conj_id_ofs: 0
> >    n_conjs: 0
> > +  action: next(pipeline=egress, table=2);
> >    type: expr
> >  Enabled: true
> >  high-watermark  : 5
> > --
> > 2.34.1
> > 
> > Diese E Mail enthält möglicherweise vertrauliche Inhalte und ist nur für 
> > die Verwertung durch den vorgesehenen Empfänger bestimmt.
> > Sollten Sie nicht der vorgesehene Empfänger sein, setzen Sie den Absender 
> > bitte unverzüglich in Kenntnis und löschen diese E Mail.
> > 
> > Hinweise zum Datenschutz finden Sie hier<https://www.datenschutz.schwarz>.
> > 
> > 
> > This e-mail may contain confidential content and is intended only for the 
> > specified recipient/s.
> > If you are not the intended recipient, please inform the sender immediately 
> > and delete this e-mail.
> > 
> > Information on data protection can be found 
> > here<https://www.datenschutz.schwarz>.
> > _______________________________________________
> > dev mailing list
> > [email protected]
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> 

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

Reply via email to