diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 3a12ee132b59..fad4c385f7a1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2212,7 +2212,7 @@ __be16 skb_network_protocol(struct sk_buff *skb) | |||
2212 | __be16 type = skb->protocol; | 2212 | __be16 type = skb->protocol; |
2213 | int vlan_depth = ETH_HLEN; | 2213 | int vlan_depth = ETH_HLEN; |
2214 | 2214 | ||
2215 | while (type == htons(ETH_P_8021Q)) { | 2215 | while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { |
2216 | struct vlan_hdr *vh; | 2216 | struct vlan_hdr *vh; |
2217 | 2217 | ||
2218 | if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) | 2218 | if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) |
@@ -2428,20 +2428,22 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2428 | if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) | 2428 | if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) |
2429 | features &= ~NETIF_F_GSO_MASK; | 2429 | features &= ~NETIF_F_GSO_MASK; |
2430 | 2430 | ||
2431 | if (protocol == htons(ETH_P_8021Q)) { | 2431 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { |
2432 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2432 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; |
2433 | protocol = veh->h_vlan_encapsulated_proto; | 2433 | protocol = veh->h_vlan_encapsulated_proto; |
2434 | } else if (!vlan_tx_tag_present(skb)) { | 2434 | } else if (!vlan_tx_tag_present(skb)) { |
2435 | return harmonize_features(skb, protocol, features); | 2435 | return harmonize_features(skb, protocol, features); |
2436 | } | 2436 | } |
2437 | 2437 | ||
2438 | features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX); | 2438 | features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | |
2439 | NETIF_F_HW_VLAN_STAG_TX); | ||
2439 | 2440 | ||
2440 | if (protocol != htons(ETH_P_8021Q)) { | 2441 | if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD)) { |
2441 | return harmonize_features(skb, protocol, features); | 2442 | return harmonize_features(skb, protocol, features); |
2442 | } else { | 2443 | } else { |
2443 | features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | | 2444 | features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | |
2444 | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX; | 2445 | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | |
2446 | NETIF_F_HW_VLAN_STAG_TX; | ||
2445 | return harmonize_features(skb, protocol, features); | 2447 | return harmonize_features(skb, protocol, features); |
2446 | } | 2448 | } |
2447 | } | 2449 | } |
@@ -3360,6 +3362,7 @@ static bool skb_pfmemalloc_protocol(struct sk_buff *skb) | |||
3360 | case __constant_htons(ETH_P_IP): | 3362 | case __constant_htons(ETH_P_IP): |
3361 | case __constant_htons(ETH_P_IPV6): | 3363 | case __constant_htons(ETH_P_IPV6): |
3362 | case __constant_htons(ETH_P_8021Q): | 3364 | case __constant_htons(ETH_P_8021Q): |
3365 | case __constant_htons(ETH_P_8021AD): | ||
3363 | return true; | 3366 | return true; |
3364 | default: | 3367 | default: |
3365 | return false; | 3368 | return false; |
@@ -3400,7 +3403,8 @@ another_round: | |||
3400 | 3403 | ||
3401 | __this_cpu_inc(softnet_data.processed); | 3404 | __this_cpu_inc(softnet_data.processed); |
3402 | 3405 | ||
3403 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { | 3406 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || |
3407 | skb->protocol == cpu_to_be16(ETH_P_8021AD)) { | ||
3404 | skb = vlan_untag(skb); | 3408 | skb = vlan_untag(skb); |
3405 | if (unlikely(!skb)) | 3409 | if (unlikely(!skb)) |
3406 | goto unlock; | 3410 | goto unlock; |