summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/filter.c
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2013-05-10 16:51:33 -0700
committerBen Hutchings <bhutchings@solarflare.com>2013-06-24 19:58:30 +0100
commit3ea84c5492e19daa478fad42f97b7dda9289e71c (patch)
tree0c689258b20bfba7f93a180a101e752501f8ff51 /drivers/net/ethernet/sfc/filter.c
parent62ebac926b7a5cd7cb6dc02a8d6fa925fa206a23 (diff)
downloadlinux-3ea84c5492e19daa478fad42f97b7dda9289e71c.tar.bz2
sfc: Enable accelerated RFS on vlans
As far as I know, the hardware doesn't support matching on both IP fields and vlan tag, but it can at least match on the IP fields. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/filter.c')
-rw-r--r--drivers/net/ethernet/sfc/filter.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 2397f0e8d3eb..b74a60ab9ac7 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -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));