xen-netfront: use __pskb_pull_tail to ensure linear area is big enough on RX
I'm slightly concerned by the "only in exceptional circumstances" comment on __pskb_pull_tail but the structure of an skb just created by netfront shouldn't hit any of the especially slow cases. This approach still does slightly more work than the old way, since if we pull up the entire first frag we now have to shuffle everything down where before we just received into the right place in the first place. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Cc: Mel Gorman <mgorman@suse.de> Cc: xen-devel@lists.xensource.com Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
072a9c4860
commit
3683243b2c
1 changed files with 10 additions and 29 deletions
|
@ -57,8 +57,7 @@
|
||||||
static const struct ethtool_ops xennet_ethtool_ops;
|
static const struct ethtool_ops xennet_ethtool_ops;
|
||||||
|
|
||||||
struct netfront_cb {
|
struct netfront_cb {
|
||||||
struct page *page;
|
int pull_to;
|
||||||
unsigned offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
|
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
|
||||||
|
@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev,
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
while ((skb = __skb_dequeue(rxq)) != NULL) {
|
while ((skb = __skb_dequeue(rxq)) != NULL) {
|
||||||
struct page *page = NETFRONT_SKB_CB(skb)->page;
|
int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
|
||||||
void *vaddr = page_address(page);
|
|
||||||
unsigned offset = NETFRONT_SKB_CB(skb)->offset;
|
|
||||||
|
|
||||||
memcpy(skb->data, vaddr + offset,
|
__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
|
||||||
skb_headlen(skb));
|
|
||||||
|
|
||||||
if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
|
|
||||||
__free_page(page);
|
|
||||||
|
|
||||||
/* Ethernet work: Delayed to here as it peeks the header. */
|
/* Ethernet work: Delayed to here as it peeks the header. */
|
||||||
skb->protocol = eth_type_trans(skb, dev);
|
skb->protocol = eth_type_trans(skb, dev);
|
||||||
|
@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
|
||||||
struct sk_buff_head errq;
|
struct sk_buff_head errq;
|
||||||
struct sk_buff_head tmpq;
|
struct sk_buff_head tmpq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int len;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock(&np->rx_lock);
|
spin_lock(&np->rx_lock);
|
||||||
|
@ -955,24 +947,13 @@ static int xennet_poll(struct napi_struct *napi, int budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NETFRONT_SKB_CB(skb)->page =
|
NETFRONT_SKB_CB(skb)->pull_to = rx->status;
|
||||||
skb_frag_page(&skb_shinfo(skb)->frags[0]);
|
if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
|
||||||
NETFRONT_SKB_CB(skb)->offset = rx->offset;
|
NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
|
||||||
|
|
||||||
len = rx->status;
|
skb_shinfo(skb)->frags[0].page_offset = rx->offset;
|
||||||
if (len > RX_COPY_THRESHOLD)
|
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
|
||||||
len = RX_COPY_THRESHOLD;
|
skb->data_len = rx->status;
|
||||||
skb_put(skb, len);
|
|
||||||
|
|
||||||
if (rx->status > len) {
|
|
||||||
skb_shinfo(skb)->frags[0].page_offset =
|
|
||||||
rx->offset + len;
|
|
||||||
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
|
|
||||||
skb->data_len = rx->status - len;
|
|
||||||
} else {
|
|
||||||
__skb_fill_page_desc(skb, 0, NULL, 0, 0);
|
|
||||||
skb_shinfo(skb)->nr_frags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = xennet_fill_frags(np, skb, &tmpq);
|
i = xennet_fill_frags(np, skb, &tmpq);
|
||||||
|
|
||||||
|
@ -999,7 +980,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
|
||||||
* receive throughout using the standard receive
|
* receive throughout using the standard receive
|
||||||
* buffer size was cut by 25%(!!!).
|
* buffer size was cut by 25%(!!!).
|
||||||
*/
|
*/
|
||||||
skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
|
skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
|
||||||
skb->len += skb->data_len;
|
skb->len += skb->data_len;
|
||||||
|
|
||||||
if (rx->flags & XEN_NETRXF_csum_blank)
|
if (rx->flags & XEN_NETRXF_csum_blank)
|
||||||
|
|
Loading…
Reference in a new issue