From: Shirley Ma <mashirle@us.ibm.com>
To: Rusty Russell <rusty@rustcorp.com.au>
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
Avi Kivity <avi@redhat.com>,
netdev@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org,
Anthony Liguori <anthony@codemonkey.ws>
Subject: [PATCH v2 2/4] Defer skb allocation -- new skb_set calls & chain pages in virtio_net
Date: Fri, 11 Dec 2009 04:43:02 -0800 [thread overview]
Message-ID: <1260535382.30371.20.camel@localhost.localdomain> (raw)
In-Reply-To: <1260534506.30371.6.camel@localhost.localdomain>
Signed-off-by: Shirley Ma <xma@us.ibm.com>
--------------
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index bb5eb7b..100b4b9 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -80,29 +80,25 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
return (struct skb_vnet_hdr *)skb->cb;
}
-static void give_a_page(struct virtnet_info *vi, struct page *page)
+static void give_pages(struct virtnet_info *vi, struct page *page)
{
- page->private = (unsigned long)vi->pages;
- vi->pages = page;
-}
+ struct page *end;
-static void trim_pages(struct virtnet_info *vi, struct sk_buff *skb)
-{
- unsigned int i;
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
- give_a_page(vi, skb_shinfo(skb)->frags[i].page);
- skb_shinfo(skb)->nr_frags = 0;
- skb->data_len = 0;
+ /* Find end of list, sew whole thing into vi->pages. */
+ for (end = page; end->private; end = (struct page *)end->private);
+ end->private = (unsigned long)vi->pages;
+ vi->pages = page;
}
static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
{
struct page *p = vi->pages;
- if (p)
+ if (p) {
vi->pages = (struct page *)p->private;
- else
+ /* use private to chain pages for big packets */
+ p->private = 0;
+ } else
p = alloc_page(gfp_mask);
return p;
}
@@ -128,6 +124,85 @@ static void skb_xmit_done(struct virtqueue *svq)
netif_wake_queue(vi->dev);
}
+static int skb_set_frag(struct sk_buff *skb, struct page *page,
+ int offset, int len)
+{
+ int i = skb_shinfo(skb)->nr_frags;
+ skb_frag_t *f;
+
+ i = skb_shinfo(skb)->nr_frags;
+ f = &skb_shinfo(skb)->frags[i];
+ f->page = page;
+ f->page_offset = offset;
+
+ if (len > PAGE_SIZE - f->page_offset)
+ f->size = PAGE_SIZE - f->page_offset;
+ else
+ f->size = len;
+
+ skb_shinfo(skb)->nr_frags++;
+ skb->data_len += f->size;
+ skb->len += f->size;
+
+ len -= f->size;
+ return len;
+}
+
+static struct sk_buff *skb_goodcopy(struct virtnet_info *vi, struct page **page,
+ unsigned int *len)
+{
+ struct sk_buff *skb;
+ struct skb_vnet_hdr *hdr;
+ int copy, hdr_len, offset;
+ char *p;
+
+ p = page_address(*page);
+
+ skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ hdr = skb_vnet_hdr(skb);
+
+ if (vi->mergeable_rx_bufs) {
+ hdr_len = sizeof(hdr->mhdr);
+ offset = hdr_len;
+ } else {
+ /* share one page between virtio_net header and data */
+ struct padded_vnet_hdr {
+ struct virtio_net_hdr hdr;
+ /* This padding makes our data 16 byte aligned */
+ char padding[6];
+ };
+ hdr_len = sizeof(hdr->hdr);
+ offset = sizeof(struct padded_vnet_hdr);
+ }
+
+ memcpy(hdr, p, hdr_len);
+
+ *len -= hdr_len;
+ p += offset;
+
+ copy = *len;
+ if (copy > skb_tailroom(skb))
+ copy = skb_tailroom(skb);
+ memcpy(skb_put(skb, copy), p, copy);
+
+ *len -= copy;
+ offset += copy;
+
+ if (*len) {
+ *len = skb_set_frag(skb, *page, offset, *len);
+ *page = (struct page *)(*page)->private;
+ } else {
+ give_pages(vi, *page);
+ *page = NULL;
+ }
+
+ return skb;
+}
+
static void receive_skb(struct net_device *dev, struct sk_buff *skb,
unsigned len)
{
@@ -162,7 +237,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
len -= copy;
if (!len) {
- give_a_page(vi, skb_shinfo(skb)->frags[0].page);
+ give_pages(vi, skb_shinfo(skb)->frags[0].page);
skb_shinfo(skb)->nr_frags--;
} else {
skb_shinfo(skb)->frags[0].page_offset +=
next prev parent reply other threads:[~2009-12-11 12:43 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-20 6:09 [PATCH 0/1] Defer skb allocation for both mergeable buffers and big packets in virtio_net Shirley Ma
2009-11-23 0:53 ` Rusty Russell
2009-11-23 8:51 ` Mark McLoughlin
2009-12-08 12:21 ` Michael S. Tsirkin
2009-12-11 12:28 ` [PATCH v2 0/4] " Shirley Ma
2009-12-11 12:33 ` [PATCH v2 1/4] Defer skb allocation -- add destroy buffers function for virtio Shirley Ma
2009-12-13 10:26 ` Michael S. Tsirkin
2009-12-14 20:08 ` Shirley Ma
2009-12-14 20:22 ` Michael S. Tsirkin
2009-12-14 23:22 ` Shirley Ma
2009-12-15 10:57 ` Michael S. Tsirkin
2009-12-15 22:36 ` Rusty Russell
2009-12-15 22:40 ` Michael S. Tsirkin
2009-12-16 5:04 ` Rusty Russell
2009-12-14 3:25 ` Rusty Russell
2009-12-14 22:09 ` Shirley Ma
2009-12-11 12:43 ` Shirley Ma [this message]
2009-12-13 11:24 ` [PATCH v2 2/4] Defer skb allocation -- new skb_set calls & chain pages in virtio_net Michael S. Tsirkin
2009-12-14 21:23 ` Shirley Ma
2009-12-15 11:21 ` Michael S. Tsirkin
2009-12-14 6:54 ` Rusty Russell
2009-12-14 22:10 ` Shirley Ma
2009-12-11 12:46 ` PATCH v2 3/4] Defer skb allocation -- new recvbuf alloc & receive calls Shirley Ma
2009-12-13 11:43 ` Michael S. Tsirkin
2009-12-14 22:08 ` Shirley Ma
2009-12-15 0:37 ` Shirley Ma
2009-12-15 11:33 ` Michael S. Tsirkin
2009-12-15 16:25 ` Shirley Ma
2009-12-15 16:39 ` Michael S. Tsirkin
2009-12-15 18:42 ` [RFC PATCH] Subject: virtio: Add unused buffers detach from vring Shirley Ma
2009-12-15 18:47 ` Michael S. Tsirkin
2009-12-15 19:08 ` Shirley Ma
2009-12-15 19:14 ` Shirley Ma
2009-12-15 21:14 ` Michael S. Tsirkin
2009-12-11 12:49 ` [PATCH v2 4/4] Defer skb allocation -- change allocation & receiving in recv path Shirley Ma
2009-12-13 11:08 ` Michael S. Tsirkin
2009-12-15 8:43 ` Shirley Ma
2009-12-13 10:19 ` [PATCH v2 0/4] Defer skb allocation for both mergeable buffers and big packets in virtio_net Michael S. Tsirkin
2009-12-14 19:59 ` Shirley Ma
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=1260535382.30371.20.camel@localhost.localdomain \
--to=mashirle@us.ibm.com \
--cc=anthony@codemonkey.ws \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=rusty@rustcorp.com.au \
/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.