From: David Ahern <hidden> Date: 2016-08-19 17:15:50
This series fixes mtu and fragmentation for tunnels using lwtunnel
output redirect, and fixes GSO for MPLS for locally originated traffic
reported by Lennert Buytenhek.
A follow on series will address fragmentation and GSO for forwarded
MPLS traffic. Hardware offload of GSO with MPLS also needs to be
addressed.
v3
- updates to mpls_gso_segment per Alex's comments
- dropped skb->encapsulation = 1 from mpls_xmit per Alex's comment
v2
- consistent use of network_header in skb to fix GSO for MPLS
- update MPLS code in OVS to network_header and inner_network_header
David Ahern (2):
net: mpls: Fixups for GSO
net: veth: Set features for MPLS
Roopa Prabhu (1):
net: lwtunnel: Handle fragmentation
drivers/net/veth.c | 1 +
include/net/lwtunnel.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
net/core/lwtunnel.c | 35 +++++++++++++++++++++++++++++++++++
net/ipv4/ip_output.c | 8 ++++++++
net/ipv4/route.c | 4 +++-
net/ipv6/ip6_output.c | 8 ++++++++
net/ipv6/route.c | 4 +++-
net/mpls/mpls_gso.c | 38 +++++++++++++++++++++++++++-----------
net/mpls/mpls_iptunnel.c | 13 +++++++++----
net/openvswitch/actions.c | 6 ++++++
10 files changed, 144 insertions(+), 17 deletions(-)
--
2.1.4
From: David Ahern <hidden> Date: 2016-08-19 17:15:51
veth does not really transmit packets only moves the skb from one
netdev to another so gso and checksum is not really needed. Add
the features to mpls_features to get the same benefit and performance
with MPLS as without it.
Reported-by: Lennert Buytenhek <redacted>
Signed-off-by: David Ahern <redacted>
---
drivers/net/veth.c | 1 +
1 file changed, 1 insertion(+)
From: David Ahern <hidden> Date: 2016-08-19 17:16:07
From: Roopa Prabhu <redacted>
Today mpls iptunnel lwtunnel_output redirect expects the tunnel
output function to handle fragmentation. This is ok but can be
avoided if we did not do the mpls output redirect too early.
ie we could wait until ip fragmentation is done and then call
mpls output for each ip fragment.
To make this work we will need,
1) the lwtunnel state to carry encap headroom
2) and do the redirect to the encap output handler on the ip fragment
(essentially do the output redirect after fragmentation)
This patch adds tunnel headroom in lwtstate to make sure we
account for tunnel data in mtu calculations during fragmentation
and adds new xmit redirect handler to redirect to lwtunnel xmit func
after ip fragmentation.
This includes IPV6 and some mtu fixes and testing from David Ahern.
Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: David Ahern <redacted>
---
include/net/lwtunnel.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
net/core/lwtunnel.c | 35 +++++++++++++++++++++++++++++++++++
net/ipv4/ip_output.c | 8 ++++++++
net/ipv4/route.c | 4 +++-
net/ipv6/ip6_output.c | 8 ++++++++
net/ipv6/route.c | 4 +++-
net/mpls/mpls_iptunnel.c | 9 +++++----
7 files changed, 106 insertions(+), 6 deletions(-)
From: David Ahern <hidden> Date: 2016-08-19 17:17:49
As reported by Lennert the MPLS GSO code is failing to properly segment
large packets. There are a couple of problems:
1. the inner protocol is not set so the gso segment functions for inner
protocol layers are not getting run, and
2 MPLS labels for packets that use the "native" (non-OVS) MPLS code
are not properly accounted for in mpls_gso_segment.
The MPLS GSO code was added for OVS. It is re-using skb_mac_gso_segment
to call the gso segment functions for the higher layer protocols. That
means skb_mac_gso_segment is called twice -- once with the network
protocol set to MPLS and again with the network protocol set to the
inner protocol.
This patch sets the inner skb protocol addressing item 1 above and sets
the network_header and inner_network_header to mark where the MPLS labels
start and end. The MPLS code in OVS is also updated to set the two
network markers.
From there the MPLS GSO code uses the difference between the network
header and the inner network header to know the size of the MPLS header
that was pushed. It then pulls the MPLS header, resets the mac_len and
protocol for the inner protocol and then calls skb_mac_gso_segment
to segment the skb.
Afterward the inner protocol segmentation is done the skb protocol
is set to mpls for each segment and the network and mac headers
restored.
Reported-by: Lennert Buytenhek <redacted>
Signed-off-by: David Ahern <redacted>
---
net/mpls/mpls_gso.c | 38 +++++++++++++++++++++++++++-----------
net/mpls/mpls_iptunnel.c | 4 ++++
net/openvswitch/actions.c | 6 ++++++
3 files changed, 37 insertions(+), 11 deletions(-)
@@ -23,32 +23,48 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,netdev_features_tfeatures){structsk_buff*segs=ERR_PTR(-EINVAL);+u16mac_offset=skb->mac_header;netdev_features_tmpls_features;+u16mac_len=skb->mac_len;__be16mpls_protocol;+intmpls_hlen;++skb_reset_network_header(skb);+mpls_hlen=skb_inner_network_header(skb)-skb_network_header(skb);+if(unlikely(!pskb_may_pull(skb,mpls_hlen)))+gotoout;/* Setup inner SKB. */mpls_protocol=skb->protocol;skb->protocol=skb->inner_protocol;-/* Push back the mac header that skb_mac_gso_segment() has pulled.-*Itwillbere-pulledbythecalltoskb_mac_gso_segment()below-*/-__skb_push(skb,skb->mac_len);+__skb_pull(skb,mpls_hlen);++skb->mac_len=0;+skb_reset_mac_header(skb);+skb_set_network_header(skb,skb_inner_network_offset(skb));/* Segment inner packet. */mpls_features=skb->dev->mpls_features&features;segs=skb_mac_gso_segment(skb,mpls_features);+if(IS_ERR_OR_NULL(segs)){+skb_gso_error_unwind(skb,mpls_protocol,mpls_hlen,mac_offset,+mac_len);+gotoout;+}+skb=segs;+do{+skb->mac_len=mac_len;+skb->protocol=mpls_protocol;-/* Restore outer protocol. */-skb->protocol=mpls_protocol;+__skb_push(skb,mpls_hlen+mac_len);-/* Re-pull the mac header that the call to skb_mac_gso_segment()-*abovepulled.Itwillbere-pushedafterreturning-*skb_mac_gso_segment(),anindirectcallerofthisfunction.-*/-__skb_pull(skb,skb->data-skb_mac_header(skb));+skb_reset_mac_header(skb);+skb_set_network_header(skb,mac_len);+}while((skb=skb->next));+out:returnsegs;}
@@ -167,6 +167,12 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,skb->mac_len);skb_reset_mac_header(skb);+/* for GSO: set MPLS as network header and encapsulated protocol+*headerasinnernetworkheader+*/+skb_set_network_header(skb,skb->mac_len);+skb_set_inner_network_header(skb,skb->mac_len+MPLS_HLEN);+new_mpls_lse=(__be32*)skb_mpls_header(skb);*new_mpls_lse=mpls->mpls_lse;
From: Alexander Duyck <hidden> Date: 2016-08-19 20:17:22
On Fri, Aug 19, 2016 at 10:09 AM, David Ahern [off-list ref] wrote:
quoted hunk
As reported by Lennert the MPLS GSO code is failing to properly segment
large packets. There are a couple of problems:
1. the inner protocol is not set so the gso segment functions for inner
protocol layers are not getting run, and
2 MPLS labels for packets that use the "native" (non-OVS) MPLS code
are not properly accounted for in mpls_gso_segment.
The MPLS GSO code was added for OVS. It is re-using skb_mac_gso_segment
to call the gso segment functions for the higher layer protocols. That
means skb_mac_gso_segment is called twice -- once with the network
protocol set to MPLS and again with the network protocol set to the
inner protocol.
This patch sets the inner skb protocol addressing item 1 above and sets
the network_header and inner_network_header to mark where the MPLS labels
start and end. The MPLS code in OVS is also updated to set the two
network markers.
From there the MPLS GSO code uses the difference between the network
header and the inner network header to know the size of the MPLS header
that was pushed. It then pulls the MPLS header, resets the mac_len and
protocol for the inner protocol and then calls skb_mac_gso_segment
to segment the skb.
Afterward the inner protocol segmentation is done the skb protocol
is set to mpls for each segment and the network and mac headers
restored.
Reported-by: Lennert Buytenhek <redacted>
Signed-off-by: David Ahern <redacted>
---
net/mpls/mpls_gso.c | 38 +++++++++++++++++++++++++++-----------
net/mpls/mpls_iptunnel.c | 4 ++++
net/openvswitch/actions.c | 6 ++++++
3 files changed, 37 insertions(+), 11 deletions(-)
@@ -23,32 +23,48 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,netdev_features_tfeatures){structsk_buff*segs=ERR_PTR(-EINVAL);+u16mac_offset=skb->mac_header;netdev_features_tmpls_features;+u16mac_len=skb->mac_len;__be16mpls_protocol;+intmpls_hlen;++skb_reset_network_header(skb);+mpls_hlen=skb_inner_network_header(skb)-skb_network_header(skb);+if(unlikely(!pskb_may_pull(skb,mpls_hlen)))+gotoout;/* Setup inner SKB. */mpls_protocol=skb->protocol;skb->protocol=skb->inner_protocol;-/* Push back the mac header that skb_mac_gso_segment() has pulled.-*Itwillbere-pulledbythecalltoskb_mac_gso_segment()below-*/-__skb_push(skb,skb->mac_len);+__skb_pull(skb,mpls_hlen);++skb->mac_len=0;+skb_reset_mac_header(skb);+skb_set_network_header(skb,skb_inner_network_offset(skb));
No need to set the network header. Both IPv4 and IPv6 GSO paths will
reset the network header just like you did at the start.
You could probably pull your math for mpls_hlen + mac_len out of the
loop below and just take care of adding mac_len to mpls_hlen up here
and store it of in mpls_hlen since it isn't used anywhere else.
+ do {
+ skb->mac_len = mac_len;
+ skb->protocol = mpls_protocol;
- /* Restore outer protocol. */
- skb->protocol = mpls_protocol;
+ __skb_push(skb, mpls_hlen + mac_len);
- /* Re-pull the mac header that the call to skb_mac_gso_segment()
- * above pulled. It will be re-pushed after returning
- * skb_mac_gso_segment(), an indirect caller of this function.
- */
- __skb_pull(skb, skb->data - skb_mac_header(skb));
You need to store off the inner network header before you overwrite it
in the lines below. Either skb_reset_inner_network_header before the
push, or skb_reset_inner_headers before you call the two lines below.
@@ -167,6 +167,12 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,skb->mac_len);skb_reset_mac_header(skb);+/* for GSO: set MPLS as network header and encapsulated protocol+*headerasinnernetworkheader+*/+skb_set_network_header(skb,skb->mac_len);+skb_set_inner_network_header(skb,skb->mac_len+MPLS_HLEN);+new_mpls_lse=(__be32*)skb_mpls_header(skb);*new_mpls_lse=mpls->mpls_lse;--
From: Simon Horman <hidden> Date: 2016-08-22 12:21:27
On Fri, Aug 19, 2016 at 10:09:01AM -0700, David Ahern wrote:
quoted hunk
As reported by Lennert the MPLS GSO code is failing to properly segment
large packets. There are a couple of problems:
1. the inner protocol is not set so the gso segment functions for inner
protocol layers are not getting run, and
2 MPLS labels for packets that use the "native" (non-OVS) MPLS code
are not properly accounted for in mpls_gso_segment.
The MPLS GSO code was added for OVS. It is re-using skb_mac_gso_segment
to call the gso segment functions for the higher layer protocols. That
means skb_mac_gso_segment is called twice -- once with the network
protocol set to MPLS and again with the network protocol set to the
inner protocol.
This patch sets the inner skb protocol addressing item 1 above and sets
the network_header and inner_network_header to mark where the MPLS labels
start and end. The MPLS code in OVS is also updated to set the two
network markers.
From there the MPLS GSO code uses the difference between the network
header and the inner network header to know the size of the MPLS header
that was pushed. It then pulls the MPLS header, resets the mac_len and
protocol for the inner protocol and then calls skb_mac_gso_segment
to segment the skb.
Afterward the inner protocol segmentation is done the skb protocol
is set to mpls for each segment and the network and mac headers
restored.
Reported-by: Lennert Buytenhek <redacted>
Signed-off-by: David Ahern <redacted>
---
net/mpls/mpls_gso.c | 38 +++++++++++++++++++++++++++-----------
net/mpls/mpls_iptunnel.c | 4 ++++
net/openvswitch/actions.c | 6 ++++++
3 files changed, 37 insertions(+), 11 deletions(-)
@@ -167,6 +167,12 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,skb->mac_len);skb_reset_mac_header(skb);+/* for GSO: set MPLS as network header and encapsulated protocol+*headerasinnernetworkheader+*/+skb_set_network_header(skb,skb->mac_len);+skb_set_inner_network_header(skb,skb->mac_len+MPLS_HLEN);+new_mpls_lse=(__be32*)skb_mpls_header(skb);*new_mpls_lse=mpls->mpls_lse;
Is the above calculation correct if push_mpls() is called multiple times?
@@ -167,6 +167,12 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,skb->mac_len);skb_reset_mac_header(skb);+/* for GSO: set MPLS as network header and encapsulated protocol+*headerasinnernetworkheader+*/+skb_set_network_header(skb,skb->mac_len);+skb_set_inner_network_header(skb,skb->mac_len+MPLS_HLEN);+new_mpls_lse=(__be32*)skb_mpls_header(skb);*new_mpls_lse=mpls->mpls_lse;
Is the above calculation correct if push_mpls() is called multiple times?
No. Does OVS support more than 1? I really need someone who is familiar with the OVS code to make sure it works for all use cases. e.g., set skb_set_inner_network_header() before pushing a series of MPLS labels.
@@ -167,6 +167,12 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,skb->mac_len);skb_reset_mac_header(skb);+/* for GSO: set MPLS as network header and encapsulated protocol+*headerasinnernetworkheader+*/+skb_set_network_header(skb,skb->mac_len);+skb_set_inner_network_header(skb,skb->mac_len+MPLS_HLEN);+new_mpls_lse=(__be32*)skb_mpls_header(skb);*new_mpls_lse=mpls->mpls_lse;
Is the above calculation correct if push_mpls() is called multiple times?
No. Does OVS support more than 1? I really need someone who is familiar with the OVS code to make sure it works for all use cases. e.g., set skb_set_inner_network_header() before pushing a series of MPLS labels.
Yes that is supported.
The scheme that OvS uses so far is that mac_len denotes the number of bytes
from the start of the MAC header until its end. In the absence of MPLS that
will be the beginning of the network header. And in the presence of MPLS it
will be the beginning of the MPLS label stack. The network header is... the
network header. This allows the MAC header, MPLS label stack and network
header to be tracked.
Pravin (CCed) may have different ideas but I wonder if the above scheme can
be preserved while also meeting the needs of your new MPLS GSO scheme if
you set skb_set_network_header() and skb_set_inner_network_header() in
net/openvswitch/actions.c:do_output().
It may also be possible to teach OvS to use skb_set_network_header to
denote the beginning of the MPLS LSE and skb_set_inner_network_header to
denote the network header in the presence of MPLS. Which is my current
understanding of what you are trying to achieve. But I think its likely
that I misunderstand things as it seems strange to me to pretend that an
MPLS LSE is a network header and the outer most network header is an inner
network header
From: David Ahern <hidden> Date: 2016-08-23 19:32:55
On 8/22/16 8:51 AM, Simon Horman wrote:
The scheme that OvS uses so far is that mac_len denotes the number of bytes
from the start of the MAC header until its end. In the absence of MPLS that
will be the beginning of the network header. And in the presence of MPLS it
will be the beginning of the MPLS label stack. The network header is... the
network header. This allows the MAC header, MPLS label stack and network
header to be tracked.
The neigh output functions do '__skb_pull(skb, skb_network_offset(skb))' so if mpls_xmit does not reset the network header the labels get dropped. To me this says MPLS labels can not be lumped with the mac header which leaves the only option as the outer network header.
Pravin (CCed) may have different ideas but I wonder if the above scheme can
be preserved while also meeting the needs of your new MPLS GSO scheme if
you set skb_set_network_header() and skb_set_inner_network_header() in
net/openvswitch/actions.c:do_output().
It may also be possible to teach OvS to use skb_set_network_header to
denote the beginning of the MPLS LSE and skb_set_inner_network_header to
denote the network header in the presence of MPLS. Which is my current
understanding of what you are trying to achieve. But I think its likely
that I misunderstand things as it seems strange to me to pretend that an
MPLS LSE is a network header and the outer most network header is an inner
network header
This is the only option I can see working, but open to patches showing an alternative.
I would like to get it resolved this week so I can move on to gso in the mpls forward case.
From: Simon Horman <hidden> Date: 2016-08-24 07:20:15
Hi David,
On Tue, Aug 23, 2016 at 01:24:51PM -0600, David Ahern wrote:
On 8/22/16 8:51 AM, Simon Horman wrote:
quoted
The scheme that OvS uses so far is that mac_len denotes the number of bytes
from the start of the MAC header until its end. In the absence of MPLS that
will be the beginning of the network header. And in the presence of MPLS it
will be the beginning of the MPLS label stack. The network header is... the
network header. This allows the MAC header, MPLS label stack and network
header to be tracked.
The neigh output functions do '__skb_pull(skb, skb_network_offset(skb))' so if mpls_xmit does not reset the network header the labels get dropped. To me this says MPLS labels can not be lumped with the mac header which leaves the only option as the outer network header.
quoted
Pravin (CCed) may have different ideas but I wonder if the above scheme can
be preserved while also meeting the needs of your new MPLS GSO scheme if
you set skb_set_network_header() and skb_set_inner_network_header() in
net/openvswitch/actions.c:do_output().
It may also be possible to teach OvS to use skb_set_network_header to
denote the beginning of the MPLS LSE and skb_set_inner_network_header to
denote the network header in the presence of MPLS. Which is my current
understanding of what you are trying to achieve. But I think its likely
that I misunderstand things as it seems strange to me to pretend that an
MPLS LSE is a network header and the outer most network header is an inner
network header
This is the only option I can see working, but open to patches showing an
alternative.
On reflection I came to a similar conclusion.
I would like to get it resolved this week so I can move on to gso in the
mpls forward case.
How do you feel about implementing the do_output() idea I suggested above?
I'm happy to provide testing and review.
On Wed, Aug 24, 2016 at 12:20 AM, Simon Horman
[off-list ref] wrote:
Hi David,
On Tue, Aug 23, 2016 at 01:24:51PM -0600, David Ahern wrote:
quoted
On 8/22/16 8:51 AM, Simon Horman wrote:
quoted
The scheme that OvS uses so far is that mac_len denotes the number of bytes
from the start of the MAC header until its end. In the absence of MPLS that
will be the beginning of the network header. And in the presence of MPLS it
will be the beginning of the MPLS label stack. The network header is... the
network header. This allows the MAC header, MPLS label stack and network
header to be tracked.
The neigh output functions do '__skb_pull(skb, skb_network_offset(skb))' so if mpls_xmit does not reset the network header the labels get dropped. To me this says MPLS labels can not be lumped with the mac header which leaves the only option as the outer network header.
quoted
Pravin (CCed) may have different ideas but I wonder if the above scheme can
be preserved while also meeting the needs of your new MPLS GSO scheme if
you set skb_set_network_header() and skb_set_inner_network_header() in
net/openvswitch/actions.c:do_output().
It may also be possible to teach OvS to use skb_set_network_header to
denote the beginning of the MPLS LSE and skb_set_inner_network_header to
denote the network header in the presence of MPLS. Which is my current
understanding of what you are trying to achieve. But I think its likely
that I misunderstand things as it seems strange to me to pretend that an
MPLS LSE is a network header and the outer most network header is an inner
network header
This is the only option I can see working, but open to patches showing an
alternative.
On reflection I came to a similar conclusion.
quoted
I would like to get it resolved this week so I can move on to gso in the
mpls forward case.
How do you feel about implementing the do_output() idea I suggested above?
I'm happy to provide testing and review.
I am not sure about changing do_output(). why not just use same scheme
to track mpls header in OVS datapath as done in mpls device?
From: David Ahern <hidden> Date: 2016-08-24 16:46:09
On 8/24/16 10:28 AM, pravin shelar wrote:
quoted
How do you feel about implementing the do_output() idea I suggested above?
I'm happy to provide testing and review.
I am not sure about changing do_output(). why not just use same scheme
to track mpls header in OVS datapath as done in mpls device?
was just replying with the same.
Something like this should be able to handle multiple labels. The inner network header is set once and the outer one pointing to MPLS is adjusted each time a label is pushed:
On Wed, Aug 24, 2016 at 9:37 AM, David Ahern [off-list ref] wrote:
quoted hunk
On 8/24/16 10:28 AM, pravin shelar wrote:
quoted
quoted
How do you feel about implementing the do_output() idea I suggested above?
I'm happy to provide testing and review.
I am not sure about changing do_output(). why not just use same scheme
to track mpls header in OVS datapath as done in mpls device?
was just replying with the same.
Something like this should be able to handle multiple labels. The inner network header is set once and the outer one pointing to MPLS is adjusted each time a label is pushed:
If it does, what else needs to be changed in OVS to handle the network layer now pointing to the MPLS labels?
You also need to change pop_mpls().
Anyways I was thinking about the neigh output functions skb pull
issue, where it is using network-header offset. Can we use mac_len?
this way we would not use any inner offsets for MPLS skb and current
scheme used by OVS datapath works.
From: David Ahern <hidden> Date: 2016-08-24 19:00:42
On 8/24/16 11:41 AM, pravin shelar wrote:
You also need to change pop_mpls().
What change is needed in pop_mpls? It already resets the mac_header and if MPLS labels are removed there is no need to set network_header. I take it you mean if the protocol is still MPLS and there are still labels then the network header needs to be set and that means finding the bottom label. Does OVS set the bottom of stack bit? From what I can tell OVS is not parsing the MPLS label so no requirement that BOS is set. Without that there is no way to tell when the labels are done short of guessing.
Anyways I was thinking about the neigh output functions skb pull
issue, where it is using network-header offset. Can we use mac_len?
this way we would not use any inner offsets for MPLS skb and current
scheme used by OVS datapath works.
neigh_resolve_output and neigh_connected_output both do an __skb_pull to the network offset. When these functions are called there may or may not be a mac header set in the skb making the mac_header unreliable for how you want to use it. e.g. I tried this:
On Wed, Aug 24, 2016 at 11:53 AM, David Ahern [off-list ref] wrote:
On 8/24/16 11:41 AM, pravin shelar wrote:
quoted
You also need to change pop_mpls().
What change is needed in pop_mpls? It already resets the mac_header and if MPLS labels are removed there is no need to set network_header. I take it you mean if the protocol is still MPLS and there are still labels then the network header needs to be set and that means finding the bottom label. Does OVS set the bottom of stack bit? From what I can tell OVS is not parsing the MPLS label so no requirement that BOS is set. Without that there is no way to tell when the labels are done short of guessing.
OVS mpls push and pop action works on outer most mpls label. So
according to new mpls offsets tracking scheme on mpls_pop action you
need to adjust skb network offset.
From: David Ahern <hidden> Date: 2016-08-25 04:53:38
On 8/24/16 12:53 PM, David Ahern wrote:
What change is needed in pop_mpls? It already resets the mac_header and if MPLS labels are removed there is no need to set network_header. I take it you mean if the protocol is still MPLS and there are still labels then the network header needs to be set and that means finding the bottom label. Does OVS set the bottom of stack bit? From what I can tell OVS is not parsing the MPLS label so no requirement that BOS is set. Without that there is no way to tell when the labels are done short of guessing.
I was confusing the inner network layer with the mpls network header. Just sent a v4. can you verify it works for single and multiple labels with OVS?
On Wed, 24 Aug 2016 10:37:51 -0600, David Ahern wrote:
quoted hunk
Something like this should be able to handle multiple labels. The
inner network header is set once and the outer one pointing to MPLS
is adjusted each time a label is pushed:
Sorry for chiming in after a month. The code above got in
(48d2ab609b6bb), I'm currently looking at this and it looks very
suspicious to me.
After push_mpls, network_header points to the start of MPLS headers.
Which I understand was the point of this patch. However, push_mpls also
calls invalidate_flow_key. Meaning that, depending on actions, we may
end up calling key_extract soon after. And key_extract sets the network
header *after* the MPLS headers.
That means that on output, for otherwise identical packet,
network_header can point before or after MPLS headers based on what
actions happened to be executed (recirculation, mainly).
If I'm not misreading the code or missing something, this can't be
right.
mpls_gso_segment does not care, it resets the network_header anyway.
What about drivers? What is the correct behavior?
Jiri
On Mon, 26 Sep 2016 17:56:22 +0200, Jiri Benc wrote:
After push_mpls, network_header points to the start of MPLS headers.
Which I understand was the point of this patch. However, push_mpls also
calls invalidate_flow_key. Meaning that, depending on actions, we may
end up calling key_extract soon after. And key_extract sets the network
header *after* the MPLS headers.
That means that on output, for otherwise identical packet,
network_header can point before or after MPLS headers based on what
actions happened to be executed (recirculation, mainly).
If I'm not misreading the code or missing something, this can't be
right.
mpls_gso_segment does not care, it resets the network_header anyway.
What about drivers? What is the correct behavior?
Answering to myself: it breaks skb_mac_gso_segment. Seems we need to
fix key_extract to set network_header to the beginning of MPLS headers.
I'll prepare a patch.
Jiri
From: David Ahern <hidden> Date: 2016-09-27 02:04:09
On 9/26/16 11:02 AM, Jiri Benc wrote:
On Mon, 26 Sep 2016 17:56:22 +0200, Jiri Benc wrote:
quoted
After push_mpls, network_header points to the start of MPLS headers.
Which I understand was the point of this patch. However, push_mpls also
calls invalidate_flow_key. Meaning that, depending on actions, we may
end up calling key_extract soon after. And key_extract sets the network
header *after* the MPLS headers.
you know this code better than me, but key_extract pulls the eth header and then sets network header. If MPLS labels are present then it is the labels that the network_header now points to. How did come to the conclusion it is after the labels?
quoted
That means that on output, for otherwise identical packet,
network_header can point before or after MPLS headers based on what
actions happened to be executed (recirculation, mainly).
If I'm not misreading the code or missing something, this can't be
right.
mpls_gso_segment does not care, it resets the network_header anyway.
What about drivers? What is the correct behavior?
Answering to myself: it breaks skb_mac_gso_segment. Seems we need to
fix key_extract to set network_header to the beginning of MPLS headers.
I'll prepare a patch.
Jiri
On Mon, 26 Sep 2016 20:04:06 -0600, David Ahern wrote:
you know this code better than me, but key_extract pulls the eth
header and then sets network header. If MPLS labels are present then
it is the labels that the network_header now points to. How did come
to the conclusion it is after the labels?
Look ~100 lines below that, to "if (eth_p_mpls(key->eth.type))".
There's a while loop advancing network header.
Jiri
From: David Ahern <hidden> Date: 2016-09-27 16:38:45
On 9/27/16 1:45 AM, Jiri Benc wrote:
On Mon, 26 Sep 2016 20:04:06 -0600, David Ahern wrote:
quoted
you know this code better than me, but key_extract pulls the eth
header and then sets network header. If MPLS labels are present then
it is the labels that the network_header now points to. How did come
to the conclusion it is after the labels?
Look ~100 lines below that, to "if (eth_p_mpls(key->eth.type))".
There's a while loop advancing network header.
got it, thanks. so that block can drop the while loop and just set mpls.top_lse
On Tue, 27 Sep 2016 10:38:41 -0600, David Ahern wrote:
On 9/27/16 1:45 AM, Jiri Benc wrote:
quoted
On Mon, 26 Sep 2016 20:04:06 -0600, David Ahern wrote:
quoted
you know this code better than me, but key_extract pulls the eth
header and then sets network header. If MPLS labels are present then
it is the labels that the network_header now points to. How did come
to the conclusion it is after the labels?
Look ~100 lines below that, to "if (eth_p_mpls(key->eth.type))".
There's a while loop advancing network header.
got it, thanks. so that block can drop the while loop and just set mpls.top_lse
I think we still need to traverse the loop to set inner_network_header.
Jiri