|
@@ -1185,8 +1185,21 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
|
|
|
|
|
nhoff = skb_network_offset(skb);
|
|
|
|
|
|
- if (skb->protocol != htons(ETH_P_IP))
|
|
|
+ if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
|
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) <
|
|
|
+ nhoff + sizeof(struct vlan_hdr));
|
|
|
+ if (((const struct vlan_hdr *)skb->data + nhoff)->
|
|
|
+ h_vlan_encapsulated_proto != htons(ETH_P_IP))
|
|
|
+ return -EPROTONOSUPPORT;
|
|
|
+
|
|
|
+ /* This is IP over 802.1q VLAN. We can't filter on the
|
|
|
+ * IP 5-tuple and the vlan together, so just strip the
|
|
|
+ * vlan header and filter on the IP part.
|
|
|
+ */
|
|
|
+ nhoff += sizeof(struct vlan_hdr);
|
|
|
+ } else if (skb->protocol != htons(ETH_P_IP)) {
|
|
|
return -EPROTONOSUPPORT;
|
|
|
+ }
|
|
|
|
|
|
/* RFS must validate the IP header length before calling us */
|
|
|
EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
|