diff options
author | Simon Horman <horms@verge.net.au> | 2014-06-03 19:53:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-05 18:05:09 -0400 |
commit | 3b392ddba25a95dcf5fb30b33358961c49dd5cfc (patch) | |
tree | 22e328d33b1602dd704a6db95953725f9ed6c104 | |
parent | d68de60f73391ce6d19589d94a63bb5ce9070777 (diff) |
MPLS: Use mpls_features to activate software MPLS GSO segmentation
If an MPLS packet requires segmentation then use mpls_features
to determine if the software implementation should be used.
As no driver advertises MPLS GSO segmentation this will always be
the case.
I had not noticed that this was necessary before as software MPLS GSO
segmentation was already being used in my test environment. I believe that
the reason for that is the skbs in question always had fragments and the
driver I used does not advertise NETIF_F_FRAGLIST (which seems to be the
case for most drivers). Thus software segmentation was activated by
skb_gso_ok().
This introduces the overhead of an extra call to skb_network_protocol()
in the case where where CONFIG_NET_MPLS_GSO is set and
skb->ip_summed == CHECKSUM_NONE.
Thanks to Jesse Gross for prompting me to investigate this.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/dev.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index a9a08e4a4857..ed8fe62d41af 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2513,13 +2513,39 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) | |||
2513 | return 0; | 2513 | return 0; |
2514 | } | 2514 | } |
2515 | 2515 | ||
2516 | /* If MPLS offload request, verify we are testing hardware MPLS features | ||
2517 | * instead of standard features for the netdev. | ||
2518 | */ | ||
2519 | #ifdef CONFIG_NET_MPLS_GSO | ||
2520 | static netdev_features_t net_mpls_features(struct sk_buff *skb, | ||
2521 | netdev_features_t features, | ||
2522 | __be16 type) | ||
2523 | { | ||
2524 | if (type == htons(ETH_P_MPLS_UC) || type == htons(ETH_P_MPLS_MC)) | ||
2525 | features &= skb->dev->mpls_features; | ||
2526 | |||
2527 | return features; | ||
2528 | } | ||
2529 | #else | ||
2530 | static netdev_features_t net_mpls_features(struct sk_buff *skb, | ||
2531 | netdev_features_t features, | ||
2532 | __be16 type) | ||
2533 | { | ||
2534 | return features; | ||
2535 | } | ||
2536 | #endif | ||
2537 | |||
2516 | static netdev_features_t harmonize_features(struct sk_buff *skb, | 2538 | static netdev_features_t harmonize_features(struct sk_buff *skb, |
2517 | netdev_features_t features) | 2539 | netdev_features_t features) |
2518 | { | 2540 | { |
2519 | int tmp; | 2541 | int tmp; |
2542 | __be16 type; | ||
2543 | |||
2544 | type = skb_network_protocol(skb, &tmp); | ||
2545 | features = net_mpls_features(skb, features, type); | ||
2520 | 2546 | ||
2521 | if (skb->ip_summed != CHECKSUM_NONE && | 2547 | if (skb->ip_summed != CHECKSUM_NONE && |
2522 | !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) { | 2548 | !can_checksum_protocol(features, type)) { |
2523 | features &= ~NETIF_F_ALL_CSUM; | 2549 | features &= ~NETIF_F_ALL_CSUM; |
2524 | } else if (illegal_highdma(skb->dev, skb)) { | 2550 | } else if (illegal_highdma(skb->dev, skb)) { |
2525 | features &= ~NETIF_F_SG; | 2551 | features &= ~NETIF_F_SG; |