Just sent out the v2,

  Jarno

> On Feb 4, 2016, at 3:25 PM, Jarno Rajahalme <ja...@ovn.org> wrote:
> 
> 
>> On Feb 4, 2016, at 3:22 PM, Ben Pfaff <b...@ovn.org> wrote:
>> 
>> On Thu, Feb 04, 2016 at 03:08:48PM -0800, Jarno Rajahalme wrote:
>>> 
>>>> On Feb 4, 2016, at 3:00 PM, Ben Pfaff <b...@ovn.org> wrote:
>>>> 
>>>> On Wed, Feb 03, 2016 at 12:33:01PM -0800, Jarno Rajahalme wrote:
>>>>> From: Ethan Jackson <et...@nicira.com>
>>>>> 
>>>>> There are certain use cases (such as bond rebalancing) where a
>>>>> datapath flow's actions may change, while it's wildcard pattern
>>>>> remains the same.  Before this patch, revalidators would note the
>>>>> change, delete the flow, and wait for the handlers to install an
>>>>> updated version.  This is inefficient, as many packets could get
>>>>> punted to userspace before the new flow is finally installed.
>>>>> 
>>>>> To improve the situation, this patch implements in place modification
>>>>> of datapath flows.  If the revalidators detect the only change to a
>>>>> given ukey is its actions, instead of deleting it, it does a put with
>>>>> the MODIFY flag set.
>>>>> 
>>>>> This patch is a backport of commit 43b2f13 to branch-2.3.
>>>>> 
>>>>> Signed-off-by: Ethan J. Jackson <et...@nicira.com>
>>>>> Signed-off-by: Jarno Rajahalme <ja...@ovn.org>
>>>> 
>>>> The buffer management in modify_op_init() really bothers me.  It is
>>>> brittle and confusing.  It has an unstated assumption that, if 'buf' is
>>>> nonnull, then it contains 'key' and 'mask' and that, if 'buf' is null,
>>>> then 'key' and 'mask' are elsewhere.  I am not sure that this assumption
>>>> is correct, because in revalidator_sweep__() the 'key' argument to
>>>> modify_op_init() seems to come from a ukey whereas the 'mask' argument
>>>> seems to come from an ofpbuf allocated by dpif_flow_get().
>>>> 
>>>> Either way, it's really weird and hard to understand and maintain.  Can
>>>> we do it another way?
>>> 
>>> This is why I asked you (offline) to pay attention to the buffer 
>>> management.. Adjusting the ‘key’ is just wrong, and even if fixed (i.e., 
>>> left unadjusted) it is likely better to solve the buffering here in some 
>>> other way.
>> 
>> How about making the caller responsible for buffer management, like
>> this:
>> 
> 
> This is cleaner, I’ll apply this for the v2, thanks!
> 
>  Jarno
> 
>> diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
>> index 03b4afa..41a51cc 100644
>> --- a/ofproto/ofproto-dpif-upcall.c
>> +++ b/ofproto/ofproto-dpif-upcall.c
>> @@ -1,4 +1,4 @@
>> -/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
>> +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
>> *
>> * Licensed under the Apache License, Version 2.0 (the "License");
>> * you may not use this file except in compliance with the License.
>> @@ -1384,23 +1384,17 @@ modify_op_init(struct dump_op *op, const struct 
>> nlattr *key, size_t key_len,
>>               const struct nlattr *actions, size_t actions_len,
>>               struct udpif_key *ukey, struct ofpbuf *buf)
>> {
>> -    struct nlattr *old_data;
>> -    intptr_t nlattr_delta;
>> -
>>    op->ukey = ukey;
>> -    op->buf = buf ? buf : ofpbuf_new(actions_len);
>> +    op->buf = buf;
>>    op->op.type = DPIF_OP_FLOW_PUT;
>>    op->op.u.flow_put.flags = DPIF_FP_MODIFY;
>> 
>> -    old_data = ofpbuf_data(op->buf);
>> -    op->op.u.flow_put.actions = ofpbuf_put(op->buf, actions, actions_len);
>> +    op->op.u.flow_put.actions = actions;
>>    op->op.u.flow_put.actions_len = actions_len;
>> -    /* 'op->buf's data may have been reallocated by the ofpbuf_put() above. 
>> */
>> -    nlattr_delta = (struct nlattr *)ofpbuf_data(op->buf) - old_data;
>> 
>> -    op->op.u.flow_put.key = key + nlattr_delta;
>> +    op->op.u.flow_put.key = key;
>>    op->op.u.flow_put.key_len = key_len;
>> -    op->op.u.flow_put.mask = mask + nlattr_delta;
>> +    op->op.u.flow_put.mask = mask;
>>    op->op.u.flow_put.mask_len = mask_len;
>>    op->op.u.flow_put.stats = NULL;
>> }
>> @@ -1580,9 +1574,10 @@ revalidate(struct revalidator *revalidator)
>>        if (result == UKEY_DELETE) {
>>            delete_op_init(&ops[n_ops++], key, key_len, ukey);
>>        } else if (result == UKEY_MODIFY) {
>> +            struct ofpbuf *actions_copy = ofpbuf_clone(&odp_actions);
>>            modify_op_init(&ops[n_ops++], key, key_len, mask, mask_len,
>> -                           ofpbuf_data(&odp_actions),
>> -                           ofpbuf_size(&odp_actions), ukey, NULL);
>> +                           ofpbuf_data(actions_copy),
>> +                           ofpbuf_size(actions_copy), ukey, actions_copy);
>>        }
>>        ovs_mutex_unlock(&ukey->mutex);
>> 
>> @@ -1661,10 +1656,18 @@ revalidator_sweep__(struct revalidator *revalidator, 
>> bool purge)
>>            if (result == UKEY_DELETE) {
>>                delete_op_init(&ops[n_ops++], ukey->key, ukey->key_len, ukey);
>>            } else if (result == UKEY_MODIFY) {
>> +                /* Append 'actions' to 'buf', properly adjusting 'mask' in
>> +                 * case this expands 'buf'. */
>> +                struct nlattr *actions;
>> +                buf->frame = mask;
>> +                actions = ofpbuf_put(buf, ofpbuf_data(&odp_actions),
>> +                                     ofpbuf_size(&odp_actions));
>> +                mask = buf->frame;
>> +
>>                /* Takes ownership of 'buf'. */
>>                modify_op_init(&ops[n_ops++], ukey->key, ukey->key_len, mask,
>> -                               mask_len, ofpbuf_data(&odp_actions),
>> -                               ofpbuf_size(&odp_actions), ukey, buf);
>> +                               mask_len, actions, ofpbuf_size(&odp_actions),
>> +                               ukey, buf);
>>                buf = NULL;
>>            }
>>            ofpbuf_delete(buf);
>> 
>> 
>>> 
>>> Jarno
>>> 
> 

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to