|
@@ -1218,6 +1218,7 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
|
|
|
union {
|
|
|
void *ptr;
|
|
|
struct ethhdr *eth;
|
|
|
+ struct vlan_ethhdr *veth;
|
|
|
struct iphdr *ipv4;
|
|
|
struct ipv6hdr *ipv6;
|
|
|
struct tcphdr *tcp;
|
|
@@ -1228,16 +1229,24 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
|
|
|
if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen))
|
|
|
return 0;
|
|
|
|
|
|
+ if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
|
|
|
+ skb->protocol == cpu_to_be16(ETH_P_8021AD))
|
|
|
+ hlen = sizeof(struct vlan_ethhdr);
|
|
|
+ else
|
|
|
+ hlen = sizeof(struct ethhdr);
|
|
|
+
|
|
|
hdr.eth = eth_hdr(skb);
|
|
|
if (gdesc->rcd.v4) {
|
|
|
- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP));
|
|
|
- hdr.ptr += sizeof(struct ethhdr);
|
|
|
+ BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) &&
|
|
|
+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP));
|
|
|
+ hdr.ptr += hlen;
|
|
|
BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP);
|
|
|
hlen = hdr.ipv4->ihl << 2;
|
|
|
hdr.ptr += hdr.ipv4->ihl << 2;
|
|
|
} else if (gdesc->rcd.v6) {
|
|
|
- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6));
|
|
|
- hdr.ptr += sizeof(struct ethhdr);
|
|
|
+ BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) &&
|
|
|
+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6));
|
|
|
+ hdr.ptr += hlen;
|
|
|
/* Use an estimated value, since we also need to handle
|
|
|
* TSO case.
|
|
|
*/
|