On Mon, Sep 8, 2014 at 5:43 AM, Lori Jakab <loja...@cisco.com> wrote:
> On 8/25/14 3:33 AM, Jesse Gross wrote:
>>
>> On Thu, Aug 21, 2014 at 12:24 PM, Lori Jakab <loja...@cisco.com> wrote:
>>>
>>> On 8/6/14 4:37 AM, Jesse Gross wrote:
>>>>
>>>> Besides the fact that it would be nice to unify things, I'm not sure
>>>> that it is actually correct to pull off VLAN, MPLS, etc. tags that we
>>>> don't understand. Presumably, these are being used to create some kind
>>>> of isolation and dropping all the tags that we don't understand would
>>>> just blindly merge things together. Also, from an implementation
>>>> perspective, we don't really parse beyond what we understand (this is
>>>> not quite true for MPLS but it is for VLANs and any unknown protocols)
>>>> so we wouldn't necessarily actually get to an L3 header. On the other
>>>> hand, if we only deal with tags that we do understand then can't we
>>>> have more atomic instructions that pull them off one-by-one?
>>>
>>>
>>> Atomic instructions make a lot of sense, and we definitely should support
>>> them.  However, if a packet is sent to an L3 port, it should not have any
>>> Ethernet, VLAN or MPLS header. Note that for now these actions are not
>>> user
>>> visible, and cannot be added with OpenFlow, they are added automatically
>>> by
>>> the user space code, when a packet is sent from an L2->L3 port or L3->L2
>>> port.
>>>
>>> I agreed with Ben that this behavior will be changed in the future, based
>>> on
>>> discussions in the ONF's EXT-112 proposal, where the consensus was to
>>> have
>>> explicit push_eth and pop_eth OpenFlow actions.  However, the current
>>> behavior of the LISP code is to add/remove L2 headers automatically, so
>>> we
>>> want to keep that in the first phase, until I implement OpenFlow support.
>>> Once automatic header popping is not used, we can remove the
>>> "extract_l3_packet()" action.
>>>
>>>  From the implementation perspective, this action would rely on the
>>> skb->network_header being set correctly.
>>
>> I'm not sure that this really addresses the concerns that I have from
>> both policy and implementation perspectives.
>>
>>  From the policy perspective: Will a Cisco implementation of LISP
>> accept a packet on an unknown VLAN, throw away the tag when it does L2
>> processing, and then continue on to do L3 processing and LISP? Somehow
>> I doubt it.
>>
>>  From an implementation perspective: There is no mechanism to rely on
>> skb->network_header being set in the general case. It will only be set
>> in situations where OVS can parse the packet. OVS doesn't know about
>> QinQ for example so you the action that you have defined won't
>> actually give you an L3 packet.
>>
>> Finally, from a Linux perspective, removing kernel interfaces isn't
>> something that is OK as a matter of policy.
>>
>> The fact that the OVS kernel module doesn't know how to inherently
>> find the L3 is not as bad as it seems. Conveniently, it means that we
>> can pop off exactly the same headers as we know how to parse so there
>> is no loss of functionality to doing this individually. As bonus,
>> since userspace needs to generate these actions, the policy can be
>> enforced there as well.
>
>
> All compelling arguments, so I agree, let's not add an "extract_l3_packet()"
> action and have pop_eth() only remove an Ethernet header.  VLAN tags, if
> any, should be removed by a previous pop_vlan() action before calling
> pop_eth().  Does this implementation look correct to you?
>
> --- a/datapath/actions.c
> +++ b/datapath/actions.c
> @@ -421,9 +421,9 @@ static int set_eth_addr(struct sk_buff *skb,
>
>  static int pop_eth(struct sk_buff *skb)
>  {
> -       skb_pull_rcsum(skb, skb_network_offset(skb));
> +       skb_pull_rcsum(skb, ETH_HLEN);
>         skb_reset_mac_header(skb);
> -       vlan_set_tci(skb, 0);
> +       skb->mac_len -= ETH_HLEN;
>
>         OVS_CB(skb)->is_layer3 = true;
>
> --- a/datapath/flow_netlink.c
> +++ b/datapath/flow_netlink.c
> @@ -1831,6 +1831,8 @@ static int __ovs_nla_copy_actions(const struct nlattr
> *attr,
>                 case OVS_ACTION_ATTR_POP_ETH:
>                         if (noeth)
>                                 return -EINVAL;
> +                       if (vlan_tci != htons(0))
> +                               return -EINVAL;

I wonder if this check is necessary/correct? It seems like there could
be other equivalent L2 tags that we don't know about, like QinQ.

>
> I think is_layer3 in the control block should not be used on output anymore,
> since we cannot guarantee it is correct.  So another change I suggest is
> removing the check for a packet being layer 2 or layer 3 in the various
> ${vport}-send() functions, and keep its use limited to receiving.

That generally makes sense to me. For things like LISP would you then
check to make sure that this is an IPv4/v6 packet before
encapsulation? If so, could we apply the same mechanism on the receive
side to completely avoid the need for the is_layer3 flag (since I
think it would then only be read in a single place)?

>>>>>>>>> --- a/datapath/actions.c
>>>>>>>>> +++ b/datapath/actions.c
>>>>>>>>> @@ -258,6 +258,7 @@ static void push_eth(struct sk_buff *skb, const
>>>>>>>>> struct
>>>>>>>>> ovs_action_push_eth *ethh
>>>>>>>>>             skb_push(skb, ETH_HLEN);
>>>>>>>>>             skb_reset_mac_header(skb);
>>>>>>>>>             skb_reset_mac_len(skb);
>>>>>>>>> +       vlan_set_tci(skb, 0);
>>>>>>>>
>>>>>>>> I don't think it's right to throw away the vlan tag. My assumption
>>>>>>>> is
>>>>>>>> that it should be placed into the packet before we push on the
>>>>>>>> Ethernet header (this actually should never happen since we disallow
>>>>>>>> pushing multiple Ethernet headers but it still seems like the right
>>>>>>>> thing to do).
>>>>>>>
>>>>>>>
>>>>>>> That's not what I would expect from a simple push_eth() action.  If
>>>>>>> someone
>>>>>>> wanted to push a VLAN tag, that should be an explicit action.  So I
>>>>>>> would
>>>>>>> just throw away whatever there is in skb->vlan_tci.
>>>>>>
>>>>>> The contents of skb->vlan_tci were already pushed explicitly (look at
>>>>>> the implementation of push_vlan()). From a user's perspective, there
>>>>>> is no difference - it is just an internal optimization to pull the tag
>>>>>> out of the packet, so I can't see any justification for throwing away
>>>>>> that tag.
>>>>>
>>>>>
>>>>> OK.  I will remove that line.
>>>>
>>>> But just to be clear, I think we still need to explicitly push the
>>>> vlan tag on the packet. Otherwise, it will migrate from the inner
>>>> Ethernet header to the outer.
>>>
>>>
>>> Still not sure what I need to do here.  If skb->vlan_tci was set by a
>>> push_vlan action, then the vlan tag should already have been pushed on
>>> the
>>> packet, right?
>>
>> Yes, the user has requested that a vlan tag be applied. skb->vlan_tci
>> is a form of offloading that should be transparent and will no longer
>> work in this case, so it needs to be de-offloaded. Please take a look
>> at the OVS vlan operations and other vlan code in the kernel if this
>> isn't clear.
>
>
> I wasn't aware of how hardware offloading of VLAN tags worked.  How about
> the following incremental?

That looks basically right to me although since the code is very
similar to the start of push_vlan(), I would probably pull it out as a
separate function.

>>>>>>> BTW, for a packet with multiple Ethernet headers, is there already
>>>>>>> support
>>>>>>> for matching on anything after the outer header?  Does that need
>>>>>>> recirculation?
>>>>>>
>>>>>> There isn't currently any support on matching on multiple headers but
>>>>>> it seems like a natural possibility if we introduce the capability to
>>>>>> push/pop Ethernet headers. Once those are there, it seems like you
>>>>>> could do it with recirculation.
>>>>>>
>>>>>>>> Somewhat related, what happens if someone specifies just an
>>>>>>>> EtherType
>>>>>>>> but no Ethernet addresses? Maybe we should just reject this?
>>>>>>>
>>>>>>>
>>>>>>> In a flow key?  I don't have a strong opinion on this, but I think I
>>>>>>> wouldn't reject it.
>>>>>>
>>>>>> Is there any situation where it could be used (what meaning would it
>>>>>> have)?
>>>>>
>>>>>
>>>>> Not that I can think of right now.
>>>>>
>>>>>
>>>>>> Normally we reject things that can never make sense.
>>>>>
>>>>>
>>>>> If that's the policy, I'll change the implementation.
>>>>
>>>> OK, I think that probably makes sense (we can loosen it later if we
>>>> come up with a use case and add support for it).
>>>
>>>
>>> I just want to note that the push_eth action has a single struct with all
>>> the data.  So the netlink message will always have the Ethertype AND the
>>> Ethernet addresses.  The only thing I can think of validating here is if
>>> the
>>> Ethernet addresses are not all zero, but I think we should allow even
>>> that.
>>
>> I'm not sure that I understand this comment. When pushing on a new
>> Ethernet header, wouldn't you expect that both the addresses and the
>> EtherType is present?
>>
>> Before I was talking about validating the match, not the action part.
>
>
> Sorry, I got confused in my previous response.  Is this the Right Way(tm) to
> do what you propose?

That looks reasonable to me.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to