[ovs-dev] [PATCH 1/2] ofproto-dpif-xlate: Cache full flowmod for learning.

Alex Wang alexw at nicira.com
Tue Jun 3 17:39:40 UTC 2014


I confirm this patch fix the bug, but have a high level concern,


Assume another learnt flow with hard_timeout=10 and was never hit after
install, now, if there is frequent change to the flow table and
need_revalidate
is constantly 'true', this learnt flow will never timeout...  since we
always
redo the flow_mod during revalidation,

Let's discuss further on this scenario, I'm thinking about solutions,

Thanks,
Alex Wang,




On Tue, Jun 3, 2014 at 2:59 AM, Joe Stringer <joestringer at nicira.com> wrote:

> Caching the results of xlate_learn was previously dependent on the state
> of the 'may_learn' flag. This meant that if the caller did not specify
> that this flow may learn, then a learn entry would not be cached.
> However, the xlate_cache tends to be used on a recurring basis, so
> failing to cache the learn entry can provide unexpected behaviour later
> on, particularly in corner cases.
>
> Such a corner case occurred previously:-
> * Revalidation was requested.
> * A flow with a learn action was dumped.
> * The flow had no packets.
> * The flow's corresponding xcache was cleared, and the flow revalidated.
> * The flow went on to receive packets after the xcache is re-created.
>
> In this case, the xcache would be re-created, but would not refresh the
> timeouts on the learnt flow until the next time it was cleared, even if
> it received more traffic. This would cause flows to time out sooner than
> expected. Symptoms of this bug may include unexpected forwarding
> behaviour or extraneous statistics being attributed to the wrong flow.
>
> This patch fixes the issue by caching the entire flow_mod, including
> actions, upon translating an xlate_learn action. This is used to perform
> a flow_mod from scratch with the original flow, rather than simply
> refreshing the rule that was created during the creation of the xcache.
>
> Bug #1252997.
>
> Reported-by: Scott Hendricks <shendricks at vmware.com>
> Signed-off-by: Joe Stringer <joestringer at nicira.com>
> ---
>  ofproto/ofproto-dpif-xlate.c |   58
> ++++++++++++++++++++++--------------------
>  1 file changed, 30 insertions(+), 28 deletions(-)
>
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 068d54f..e8f3dbf 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -265,7 +265,9 @@ struct xc_entry {
>              uint16_t vid;
>          } bond;
>          struct {
> -            struct rule_dpif *rule;
> +            struct ofproto_dpif *ofproto;
> +            struct ofputil_flow_mod *fm;
> +            struct ofpbuf *ofpacts;
>          } learn;
>          struct {
>              struct ofproto_dpif *ofproto;
> @@ -2977,34 +2979,38 @@ xlate_bundle_action(struct xlate_ctx *ctx,
>  }
>
>  static void
> -xlate_learn_action(struct xlate_ctx *ctx,
> -                   const struct ofpact_learn *learn)
> +xlate_learn_action__(struct xlate_ctx *ctx, const struct ofpact_learn
> *learn,
> +                     struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts)
>  {
> -    uint64_t ofpacts_stub[1024 / 8];
> -    struct ofputil_flow_mod fm;
> -    struct ofpbuf ofpacts;
> +    learn_execute(learn, &ctx->xin->flow, fm, ofpacts);
> +    if (ctx->xin->may_learn) {
> +        ofproto_dpif_flow_mod(ctx->xbridge->ofproto, fm);
> +    }
> +}
>
> +static void
> +xlate_learn_action(struct xlate_ctx *ctx, const struct ofpact_learn
> *learn)
> +{
>      ctx->xout->has_learn = true;
> -
>      learn_mask(learn, &ctx->xout->wc);
>
> -    if (!ctx->xin->may_learn) {
> -        return;
> -    }
> -
> -    ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
> -    learn_execute(learn, &ctx->xin->flow, &fm, &ofpacts);
> -    ofproto_dpif_flow_mod(ctx->xbridge->ofproto, &fm);
> -    ofpbuf_uninit(&ofpacts);
> -
>      if (ctx->xin->xcache) {
>          struct xc_entry *entry;
>
>          entry = xlate_cache_add_entry(ctx->xin->xcache, XC_LEARN);
> -        /* Lookup the learned rule, taking a reference on it.  The
> reference
> -         * is released when this cache entry is deleted. */
> -        rule_dpif_lookup(ctx->xbridge->ofproto, &ctx->xin->flow, NULL,
> -                         &entry->u.learn.rule, true, NULL);
> +        entry->u.learn.ofproto = ctx->xbridge->ofproto;
> +        entry->u.learn.fm = xmalloc(sizeof *entry->u.learn.fm);
> +        entry->u.learn.ofpacts = ofpbuf_new(1024);
> +        xlate_learn_action__(ctx, learn, entry->u.learn.fm,
> +                             entry->u.learn.ofpacts);
> +    } else if (ctx->xin->may_learn) {
> +        uint64_t ofpacts_stub[1024 / 8];
> +        struct ofputil_flow_mod fm;
> +        struct ofpbuf ofpacts;
> +
> +        ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
> +        xlate_learn_action__(ctx, learn, &fm, &ofpacts);
> +        ofpbuf_uninit(&ofpacts);
>      }
>  }
>
> @@ -3911,12 +3917,8 @@ xlate_push_stats(struct xlate_cache *xcache, bool
> may_learn,
>              break;
>          case XC_LEARN:
>              if (may_learn) {
> -                struct rule_dpif *rule = entry->u.learn.rule;
> -
> -                /* Reset the modified time for a rule that is equivalent
> to
> -                 * the currently cached rule.  If the rule is not the
> exact
> -                 * rule we have cached, update the reference that we
> have. */
> -                entry->u.learn.rule = ofproto_dpif_refresh_rule(rule);
> +                ofproto_dpif_flow_mod(entry->u.learn.ofproto,
> +                                      entry->u.learn.fm);
>              }
>              break;
>          case XC_NORMAL:
> @@ -3989,8 +3991,8 @@ xlate_cache_clear(struct xlate_cache *xcache)
>              mbridge_unref(entry->u.mirror.mbridge);
>              break;
>          case XC_LEARN:
> -            /* 'u.learn.rule' is the learned rule. */
> -            rule_dpif_unref(entry->u.learn.rule);
> +            free(entry->u.learn.fm);
> +            ofpbuf_delete(entry->u.learn.ofpacts);
>              break;
>          case XC_NORMAL:
>              free(entry->u.normal.flow);
> --
> 1.7.10.4
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20140603/cdcb07e4/attachment-0005.html>


More information about the dev mailing list