On Mon, Nov 4, 2013 at 10:03 AM, Ben Pfaff <b...@nicira.com> wrote:
> On Sun, Nov 03, 2013 at 06:56:05PM -0800, Gurucharan Shetty wrote:
>> On Fri, Nov 1, 2013 at 1:21 PM, Ben Pfaff <b...@nicira.com> wrote:
>> > On Fri, Nov 01, 2013 at 02:15:13AM -0700, Gurucharan Shetty wrote:
>> >> Instead of an exact match flow table, we introduce a classifier.
>> >> This enables mega-flows in userspace datapath.
>> >>
>> >> Signed-off-by: Gurucharan Shetty <gshe...@nicira.com>
>> >
>> > I know why struct dp_netdev_flow needs 'flow' in addition to a
>> > cls_rule: because a cls_rule always zeros out the bits in the flow,
>> > and dpif-netdev needs to be able to report the original values of
>> > those bits.  But why does struct dp_netdev_flow need another copy of
>> > the mask?
>> I suppose you mean that we can just get back the mask from the 'cls_rule'
>> through minimask_expand() function? I did not know about this function.
>> I am using this in V2.
>
> That's what I meant.  Thanks.
>
>> > I don't really understand dp_netdev_lookup_flow().  It is being called
>> > in two different and conflicting contexts.  dp_netdev_port_input()
>> > uses it to determine how to handle an incoming packet, which correctly
>> > would just call classifier_lookup().  The other functions that call
>> > dp_netdev_lookup_flow() should just call
>> > classifier_find_rule_exactly().  (Or am I missing something
>> > important?)
>>
>> I spoke with Ben about this offline.
>> The other functions that call dp_netdev_lookup_flow() are:
>> 1) dpif_netdev_flow_get().
>> 2) dpif_netdev_flow_put().
>> 3) dpif_netdev_flow_del().
>>
>> For V2, I am changing the logic as follows.
>> For 1) and 3), I will do a classifier_lookup() for the supplied 'flow'
>> and then verify it against the flow stored in the hmap for an exact
>> match. Only return success if there is an exact match, else return
>> ENOENT. The assumption is that userspace will not send a overlapping
>> flow to delete/get a mega-flow in the datapath but rather send the
>> same flow that was used to create the mega-flow in the first place.
>>
>> For 2),
>> Do a classifier_lookup() for the flow. If there is a match and the
>> 'flow' used to create the original entry is the same as the one being
>> supplied again, return a EEXIST. If they are not the same, then there
>> is an overlapping flow. We should return an error to indicate that. I
>> am using EINVAL for a lack of better alternative.
>
> OK.
>
> I hope that these errors match what the kernel datapath uses.  (Did you
> check?)
I spoke to Andy and checked the kernel datapath. Kernel datapath does
it slightly different for dpif_netdev_flow_put()
It does the following.
* If the flow look up is a success and the put flow was with the
CREATE flag, return a EXIST (irrespective of whether it is a exact
flow or overlap flow)
* If the flow lookup was a success and the put flow was with modify
flag, only modify if the flows are equal. Else, return a EINVAL.

I will change the userspace datapath do the same too.
>
>> > Also in dpif_netdev_flow_mask_from_nlattrs(), should we now only check
>> > that the in_port is valid, if the in_port is not wildcarded?
>> Okay. I think I made a general assumption that in_port is not
>> wildcarded. But I don't see
>> any reason why that assumption should be true. So I will add the
>> following incremental.
>
> OK.  Another option is to force the in_port not be wildcarded.  (I think
> that the kernel does that.)  That might be a better option because I am
> not sure how one would implement a partially masked in_port.
Okay. I will do that. I guess, now I will have to check the in_port's
validity irrespective of whether it was originally masked or not.

>
> I think that the conditions below could be simplified a little, from:
>>      in_port = flow->in_port.odp_port;
>> -    if (!is_valid_port_number(in_port) && in_port != ODPP_NONE) {
>> +    if (mask_key) {
>> +        if (odp_to_u32(mask->in_port.odp_port) == UINT32_MAX
>> +            && !is_valid_port_number(in_port) && in_port != ODPP_NONE) {
>> +            return EINVAL;
>> +        }
>> +    } else if (!is_valid_port_number(in_port) && in_port != ODPP_NONE) {
>>          return EINVAL;
>>      }
>
> to:
>
>     if ((!mask_key || odp_to_u32(mask->in_port.odp_port) == UINT32_MAX)
>         && !is_valid_port_number(in_port) && in_port != ODPP_NONE)
>
>> > In dp_netdev_flow_add(), copying the mask into a flow_wildcards
>> > structure seems wasteful.  I think that the caller can easily provide
>> > the mask in that form, without copying.
>> You mean do a pointer cast like this?
>> match_init(&match, flow, (struct flow_wildcards *)mask);
>>
>> I suppose that would be a problem if eventually 'struct
>> flow_wildcards' has one more member? Or did you have something else in
>> mind?
>
> No cast should be needed.  I mean that the caller can declare a "struct
> flow_wildcards" and fill in the struct flow member, then pass the
> address of the flow_wildcards container.

Thanks. I will send a V2.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to