From: Edward Cree <ecree@solarflare.com>
To: <linux-net-drivers@solarflare.com>, <davem@davemloft.net>,
<netdev@vger.kernel.org>
Subject: [PATCH net 1/2] sfc: handle nonlinear SKBs in efx_filter_rfs()
Date: Thu, 26 May 2016 17:01:57 +0100 [thread overview]
Message-ID: <57471DF5.8010901@solarflare.com> (raw)
In-Reply-To: <57471D92.2000708@solarflare.com>
Previously efx_filter_rfs() assumed that the headers it needed (802.1Q, IP)
would be present in the linear data area of the SKB.
When running with debugging I found that this is not always the case and
that in fact the data may all be paged.
So now use skb_header_pointer() to extract the data.
Also replace EFX_BUG_ON_PARANOID checks for insufficient data with checks
that return -EINVAL, as this case is possible if the received packet was
too short.
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
drivers/net/ethernet/sfc/rx.c | 39 +++++++++++++++++++++++----------------
1 file changed, 23 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 8956995..52790f0 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -842,25 +842,32 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
struct efx_filter_spec spec;
+ /* 60 octets is the maximum length of an IPv4 header (all IPv6 headers
+ * are 40 octets), and we pull 4 more to get the port numbers
+ */
+ #define EFX_RFS_HEADER_LENGTH (sizeof(struct vlan_hdr) + 60 + 4)
+ unsigned char header[EFX_RFS_HEADER_LENGTH];
+ int headlen = min_t(int, EFX_RFS_HEADER_LENGTH, skb->len);
+ #undef EFX_RFS_HEADER_LENGTH
+ void *hptr;
const __be16 *ports;
__be16 ether_type;
int nhoff;
int rc;
- /* The core RPS/RFS code has already parsed and validated
- * VLAN, IP and transport headers. We assume they are in the
- * header area.
- */
+ hptr = skb_header_pointer(skb, 0, headlen, header);
+ if (!hptr)
+ return -EINVAL;
if (skb->protocol == htons(ETH_P_8021Q)) {
- const struct vlan_hdr *vh =
- (const struct vlan_hdr *)skb->data;
+ const struct vlan_hdr *vh = hptr;
/* 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.
*/
- EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh));
+ if (headlen < sizeof(*vh))
+ return -EINVAL;
ether_type = vh->h_vlan_encapsulated_proto;
nhoff = sizeof(struct vlan_hdr);
} else {
@@ -881,23 +888,23 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
spec.ether_type = ether_type;
if (ether_type == htons(ETH_P_IP)) {
- const struct iphdr *ip =
- (const struct iphdr *)(skb->data + nhoff);
+ const struct iphdr *ip = hptr + nhoff;
- EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
+ if (headlen < nhoff + sizeof(*ip))
+ return -EINVAL;
if (ip_is_fragment(ip))
return -EPROTONOSUPPORT;
spec.ip_proto = ip->protocol;
spec.rem_host[0] = ip->saddr;
spec.loc_host[0] = ip->daddr;
- EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
- ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+ if (headlen < nhoff + 4 * ip->ihl + 4)
+ return -EINVAL;
+ ports = (const __be16 *)(hptr + nhoff + 4 * ip->ihl);
} else {
- const struct ipv6hdr *ip6 =
- (const struct ipv6hdr *)(skb->data + nhoff);
+ const struct ipv6hdr *ip6 = (hptr + nhoff);
- EFX_BUG_ON_PARANOID(skb_headlen(skb) <
- nhoff + sizeof(*ip6) + 4);
+ if (headlen < nhoff + sizeof(*ip6) + 4)
+ return -EINVAL;
spec.ip_proto = ip6->nexthdr;
memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr));
memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr));
next prev parent reply other threads:[~2016-05-26 16:02 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-26 16:00 [PATCH net 0/2] sfc: aRFS fixes Edward Cree
2016-05-26 16:01 ` Edward Cree [this message]
2016-05-26 16:56 ` [PATCH net 1/2] sfc: handle nonlinear SKBs in efx_filter_rfs() Eric Dumazet
2016-05-26 17:11 ` Edward Cree
2016-05-26 19:47 ` David Miller
2016-05-26 20:46 ` [PATCH net] sfc: use flow dissector helpers for aRFS Edward Cree
2016-05-30 5:39 ` David Miller
2016-05-26 16:02 ` [PATCH net 2/2] sfc: Track RPS flow IDs per channel instead of per function Edward Cree
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=57471DF5.8010901@solarflare.com \
--to=ecree@solarflare.com \
--cc=davem@davemloft.net \
--cc=linux-net-drivers@solarflare.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.