diff mbox

[ovs-dev] datapath: geneve: Handle vlan tag

Message ID 1477976454-83179-1-git-send-email-pshelar@ovn.org
State Accepted
Headers show

Commit Message

Pravin Shelar Nov. 1, 2016, 5 a.m. UTC
The compat vlan code ignores vlan tag for inner packet
on egress path. Following patch fixes this by inserting the
tag for inner packet before tunnel encapsulation.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
---
 datapath/linux/compat/geneve.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

Comments

Joe Stringer Nov. 1, 2016, 5:30 p.m. UTC | #1
On 31 October 2016 at 22:00, Pravin B Shelar <pshelar@ovn.org> wrote:
> The compat vlan code ignores vlan tag for inner packet
> on egress path. Following patch fixes this by inserting the
> tag for inner packet before tunnel encapsulation.
>
> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>

Is this a problem upstream and for other tunnels too?

> ---
>  datapath/linux/compat/geneve.c | 26 ++++++++++++++++++++++++--
>  1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
> index 7f2b192..6cce5ca 100644
> --- a/datapath/linux/compat/geneve.c
> +++ b/datapath/linux/compat/geneve.c
> @@ -750,11 +750,22 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
>         skb_scrub_packet(skb, xnet);
>
>         min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
> -                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
> +                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
> +                       + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
> +
>         err = skb_cow_head(skb, min_headroom);
>         if (unlikely(err))
>                 goto free_rt;
>
> +       if (skb_vlan_tag_present(skb)) {
> +               err = __vlan_insert_tag(skb, skb->vlan_proto,
> +                                       skb_vlan_tag_get(skb));

Does the proto need to be set? I see that the equivalent vxlan code
upstream uses vlan_hwaccel_push_inside() instead.

> +
> +               if (unlikely(err))
> +                       goto free_rt;
> +               skb->vlan_tci = 0;
> +       }
> +
>         err = udp_tunnel_handle_offloads(skb, udp_sum);
>         if (err)
>                 goto free_rt;
> @@ -783,11 +794,22 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
>         skb_scrub_packet(skb, xnet);
>
>         min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
> -                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
> +                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr)
> +                       + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
> +
>         err = skb_cow_head(skb, min_headroom);
>         if (unlikely(err))
>                 goto free_dst;
>
> +       if (skb_vlan_tag_present(skb)) {
> +               err = __vlan_insert_tag(skb, skb->vlan_proto,
> +                                       skb_vlan_tag_get(skb));
> +
> +               if (unlikely(err))
> +                       goto free_dst;
> +               skb->vlan_tci = 0;
> +       }
> +
>         err = udp_tunnel_handle_offloads(skb, udp_sum);
>         if (err)
>                 goto free_dst;
> --
> 2.5.5
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
Pravin Shelar Nov. 1, 2016, 5:48 p.m. UTC | #2
On Tue, Nov 1, 2016 at 10:30 AM, Joe Stringer <joe@ovn.org> wrote:
> On 31 October 2016 at 22:00, Pravin B Shelar <pshelar@ovn.org> wrote:
>> The compat vlan code ignores vlan tag for inner packet
>> on egress path. Following patch fixes this by inserting the
>> tag for inner packet before tunnel encapsulation.
>>
>> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
>
> Is this a problem upstream and for other tunnels too?
>
upstream does not has this issue since networking stack would handle
vlan tag for geneve device.

>> ---
>>  datapath/linux/compat/geneve.c | 26 ++++++++++++++++++++++++--
>>  1 file changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
>> index 7f2b192..6cce5ca 100644
>> --- a/datapath/linux/compat/geneve.c
>> +++ b/datapath/linux/compat/geneve.c
>> @@ -750,11 +750,22 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
>>         skb_scrub_packet(skb, xnet);
>>
>>         min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
>> -                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
>> +                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
>> +                       + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
>> +
>>         err = skb_cow_head(skb, min_headroom);
>>         if (unlikely(err))
>>                 goto free_rt;
>>
>> +       if (skb_vlan_tag_present(skb)) {
>> +               err = __vlan_insert_tag(skb, skb->vlan_proto,
>> +                                       skb_vlan_tag_get(skb));
>
> Does the proto need to be set? I see that the equivalent vxlan code
> upstream uses vlan_hwaccel_push_inside() instead.
>
We can use vlan_hwaccel_push_inside(), but it frees the skb, thats why
I prefer __vlan_insert_tag(). It allows us to write simple error
handling code.
Joe Stringer Nov. 1, 2016, 6:06 p.m. UTC | #3
On 1 November 2016 at 10:48, Pravin Shelar <pshelar@ovn.org> wrote:
> On Tue, Nov 1, 2016 at 10:30 AM, Joe Stringer <joe@ovn.org> wrote:
>> On 31 October 2016 at 22:00, Pravin B Shelar <pshelar@ovn.org> wrote:
>>> The compat vlan code ignores vlan tag for inner packet
>>> on egress path. Following patch fixes this by inserting the
>>> tag for inner packet before tunnel encapsulation.
>>>
>>> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
>>
>> Is this a problem upstream and for other tunnels too?
>>
> upstream does not has this issue since networking stack would handle
> vlan tag for geneve device.

Bear with me, but why does upstream vxlan do something like this but
upstream geneve doesn't?

>>> ---
>>>  datapath/linux/compat/geneve.c | 26 ++++++++++++++++++++++++--
>>>  1 file changed, 24 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
>>> index 7f2b192..6cce5ca 100644
>>> --- a/datapath/linux/compat/geneve.c
>>> +++ b/datapath/linux/compat/geneve.c
>>> @@ -750,11 +750,22 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
>>>         skb_scrub_packet(skb, xnet);
>>>
>>>         min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
>>> -                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
>>> +                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
>>> +                       + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
>>> +
>>>         err = skb_cow_head(skb, min_headroom);
>>>         if (unlikely(err))
>>>                 goto free_rt;
>>>
>>> +       if (skb_vlan_tag_present(skb)) {
>>> +               err = __vlan_insert_tag(skb, skb->vlan_proto,
>>> +                                       skb_vlan_tag_get(skb));
>>
>> Does the proto need to be set? I see that the equivalent vxlan code
>> upstream uses vlan_hwaccel_push_inside() instead.
>>
> We can use vlan_hwaccel_push_inside(), but it frees the skb, thats why
> I prefer __vlan_insert_tag(). It allows us to write simple error
> handling code.

OK, so skb->proto doesn't need to be set to the vlan proto?
Pravin Shelar Nov. 1, 2016, 6:17 p.m. UTC | #4
On Tue, Nov 1, 2016 at 11:06 AM, Joe Stringer <joe@ovn.org> wrote:
> On 1 November 2016 at 10:48, Pravin Shelar <pshelar@ovn.org> wrote:
>> On Tue, Nov 1, 2016 at 10:30 AM, Joe Stringer <joe@ovn.org> wrote:
>>> On 31 October 2016 at 22:00, Pravin B Shelar <pshelar@ovn.org> wrote:
>>>> The compat vlan code ignores vlan tag for inner packet
>>>> on egress path. Following patch fixes this by inserting the
>>>> tag for inner packet before tunnel encapsulation.
>>>>
>>>> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
>>>
>>> Is this a problem upstream and for other tunnels too?
>>>
>> upstream does not has this issue since networking stack would handle
>> vlan tag for geneve device.
>
> Bear with me, but why does upstream vxlan do something like this but
> upstream geneve doesn't?
>
Because Geneve device does not expose VLAN offload features. Btw I
have patch to handle this discrepancy between geneve and vxlan.

>>>> ---
>>>>  datapath/linux/compat/geneve.c | 26 ++++++++++++++++++++++++--
>>>>  1 file changed, 24 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
>>>> index 7f2b192..6cce5ca 100644
>>>> --- a/datapath/linux/compat/geneve.c
>>>> +++ b/datapath/linux/compat/geneve.c
>>>> @@ -750,11 +750,22 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
>>>>         skb_scrub_packet(skb, xnet);
>>>>
>>>>         min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
>>>> -                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
>>>> +                       + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
>>>> +                       + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
>>>> +
>>>>         err = skb_cow_head(skb, min_headroom);
>>>>         if (unlikely(err))
>>>>                 goto free_rt;
>>>>
>>>> +       if (skb_vlan_tag_present(skb)) {
>>>> +               err = __vlan_insert_tag(skb, skb->vlan_proto,
>>>> +                                       skb_vlan_tag_get(skb));
>>>
>>> Does the proto need to be set? I see that the equivalent vxlan code
>>> upstream uses vlan_hwaccel_push_inside() instead.
>>>
>> We can use vlan_hwaccel_push_inside(), but it frees the skb, thats why
>> I prefer __vlan_insert_tag(). It allows us to write simple error
>> handling code.
>
> OK, so skb->proto doesn't need to be set to the vlan proto?

OIC, you meant skb->protocol, Yes I need to set it.
__vlan_insert_tag() does not do it for us.
diff mbox

Patch

diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 7f2b192..6cce5ca 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -750,11 +750,22 @@  static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
 	skb_scrub_packet(skb, xnet);
 
 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
-			+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
+			+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
+			+ (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
+
 	err = skb_cow_head(skb, min_headroom);
 	if (unlikely(err))
 		goto free_rt;
 
+	if (skb_vlan_tag_present(skb)) {
+		err = __vlan_insert_tag(skb, skb->vlan_proto,
+					skb_vlan_tag_get(skb));
+
+		if (unlikely(err))
+			goto free_rt;
+		skb->vlan_tci = 0;
+	}
+
 	err = udp_tunnel_handle_offloads(skb, udp_sum);
 	if (err)
 		goto free_rt;
@@ -783,11 +794,22 @@  static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
 	skb_scrub_packet(skb, xnet);
 
 	min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
-			+ GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
+			+ GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr)
+			+ (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
+
 	err = skb_cow_head(skb, min_headroom);
 	if (unlikely(err))
 		goto free_dst;
 
+	if (skb_vlan_tag_present(skb)) {
+		err = __vlan_insert_tag(skb, skb->vlan_proto,
+					skb_vlan_tag_get(skb));
+
+		if (unlikely(err))
+			goto free_dst;
+		skb->vlan_tci = 0;
+	}
+
 	err = udp_tunnel_handle_offloads(skb, udp_sum);
 	if (err)
 		goto free_dst;