After discussing the issue with few people,

I think we should keep the old_xcache during the full revalidation.

And in xlate_learn_action(), if may_learn is false, we should check if the
learned rule is in the old_xcache, if it is, we should copy the XC_LEARN
entry
to the new_xcache list (but we do not refresh the learnt rule again, since
may_learn to false).

Thoughts?

Alex Wang,


On Tue, Jun 3, 2014 at 10:39 AM, Alex Wang <al...@nicira.com> wrote:

> 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 <joestrin...@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 <shendri...@vmware.com>
>> Signed-off-by: Joe Stringer <joestrin...@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
>>
>>
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to