diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 0094562b732a..683d493aa1bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2563,7 +2563,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
2563 | 2563 | ||
2564 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2564 | netdev_features_t netif_skb_features(struct sk_buff *skb) |
2565 | { | 2565 | { |
2566 | const struct net_device *dev = skb->dev; | 2566 | struct net_device *dev = skb->dev; |
2567 | netdev_features_t features = dev->features; | 2567 | netdev_features_t features = dev->features; |
2568 | u16 gso_segs = skb_shinfo(skb)->gso_segs; | 2568 | u16 gso_segs = skb_shinfo(skb)->gso_segs; |
2569 | __be16 protocol = skb->protocol; | 2569 | __be16 protocol = skb->protocol; |
@@ -2571,13 +2571,20 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2571 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) | 2571 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) |
2572 | features &= ~NETIF_F_GSO_MASK; | 2572 | features &= ~NETIF_F_GSO_MASK; |
2573 | 2573 | ||
2574 | /* If encapsulation offload request, verify we are testing | ||
2575 | * hardware encapsulation features instead of standard | ||
2576 | * features for the netdev | ||
2577 | */ | ||
2578 | if (skb->encapsulation) | ||
2579 | features &= dev->hw_enc_features; | ||
2580 | |||
2574 | if (!vlan_tx_tag_present(skb)) { | 2581 | if (!vlan_tx_tag_present(skb)) { |
2575 | if (unlikely(protocol == htons(ETH_P_8021Q) || | 2582 | if (unlikely(protocol == htons(ETH_P_8021Q) || |
2576 | protocol == htons(ETH_P_8021AD))) { | 2583 | protocol == htons(ETH_P_8021AD))) { |
2577 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2584 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; |
2578 | protocol = veh->h_vlan_encapsulated_proto; | 2585 | protocol = veh->h_vlan_encapsulated_proto; |
2579 | } else { | 2586 | } else { |
2580 | return harmonize_features(skb, features); | 2587 | goto finalize; |
2581 | } | 2588 | } |
2582 | } | 2589 | } |
2583 | 2590 | ||
@@ -2595,6 +2602,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2595 | NETIF_F_HW_VLAN_CTAG_TX | | 2602 | NETIF_F_HW_VLAN_CTAG_TX | |
2596 | NETIF_F_HW_VLAN_STAG_TX); | 2603 | NETIF_F_HW_VLAN_STAG_TX); |
2597 | 2604 | ||
2605 | finalize: | ||
2606 | if (dev->netdev_ops->ndo_features_check) | ||
2607 | features &= dev->netdev_ops->ndo_features_check(skb, dev, | ||
2608 | features); | ||
2609 | |||
2598 | return harmonize_features(skb, features); | 2610 | return harmonize_features(skb, features); |
2599 | } | 2611 | } |
2600 | EXPORT_SYMBOL(netif_skb_features); | 2612 | EXPORT_SYMBOL(netif_skb_features); |
@@ -2665,13 +2677,6 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device | |||
2665 | if (unlikely(!skb)) | 2677 | if (unlikely(!skb)) |
2666 | goto out_null; | 2678 | goto out_null; |
2667 | 2679 | ||
2668 | /* If encapsulation offload request, verify we are testing | ||
2669 | * hardware encapsulation features instead of standard | ||
2670 | * features for the netdev | ||
2671 | */ | ||
2672 | if (skb->encapsulation) | ||
2673 | features &= dev->hw_enc_features; | ||
2674 | |||
2675 | if (netif_needs_gso(dev, skb, features)) { | 2680 | if (netif_needs_gso(dev, skb, features)) { |
2676 | struct sk_buff *segs; | 2681 | struct sk_buff *segs; |
2677 | 2682 | ||