diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 1ba2cfe3f8e8..5367bfba0947 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2289,8 +2289,8 @@ EXPORT_SYMBOL(skb_checksum_help); | |||
2289 | 2289 | ||
2290 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2290 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
2291 | { | 2291 | { |
2292 | unsigned int vlan_depth = skb->mac_len; | ||
2292 | __be16 type = skb->protocol; | 2293 | __be16 type = skb->protocol; |
2293 | int vlan_depth = skb->mac_len; | ||
2294 | 2294 | ||
2295 | /* Tunnel gso handlers can set protocol to ethernet. */ | 2295 | /* Tunnel gso handlers can set protocol to ethernet. */ |
2296 | if (type == htons(ETH_P_TEB)) { | 2296 | if (type == htons(ETH_P_TEB)) { |
@@ -2303,15 +2303,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | |||
2303 | type = eth->h_proto; | 2303 | type = eth->h_proto; |
2304 | } | 2304 | } |
2305 | 2305 | ||
2306 | while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { | 2306 | /* if skb->protocol is 802.1Q/AD then the header should already be |
2307 | struct vlan_hdr *vh; | 2307 | * present at mac_len - VLAN_HLEN (if mac_len > 0), or at |
2308 | 2308 | * ETH_HLEN otherwise | |
2309 | if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) | 2309 | */ |
2310 | return 0; | 2310 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { |
2311 | 2311 | if (vlan_depth) { | |
2312 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | 2312 | if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN))) |
2313 | type = vh->h_vlan_encapsulated_proto; | 2313 | return 0; |
2314 | vlan_depth += VLAN_HLEN; | 2314 | vlan_depth -= VLAN_HLEN; |
2315 | } else { | ||
2316 | vlan_depth = ETH_HLEN; | ||
2317 | } | ||
2318 | do { | ||
2319 | struct vlan_hdr *vh; | ||
2320 | |||
2321 | if (unlikely(!pskb_may_pull(skb, | ||
2322 | vlan_depth + VLAN_HLEN))) | ||
2323 | return 0; | ||
2324 | |||
2325 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | ||
2326 | type = vh->h_vlan_encapsulated_proto; | ||
2327 | vlan_depth += VLAN_HLEN; | ||
2328 | } while (type == htons(ETH_P_8021Q) || | ||
2329 | type == htons(ETH_P_8021AD)); | ||
2315 | } | 2330 | } |
2316 | 2331 | ||
2317 | *depth = vlan_depth; | 2332 | *depth = vlan_depth; |