Re: [PATCH net 9/9] virtio-net: XDP support for small buffers

2017-01-03 Thread Jason Wang



On 2017年01月04日 00:40, John Fastabend wrote:

On 17-01-02 10:16 PM, Jason Wang wrote:


On 2017年01月03日 06:43, John Fastabend wrote:

On 16-12-23 06:37 AM, Jason Wang wrote:

Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
small receive buffer untouched. This will confuse the user who want to
set XDP but use small buffers. Other than forbid XDP in small buffer
mode, let's make it work. XDP then can only work at skb->data since
virtio-net create skbs during refill, this is sub optimal which could
be optimized in the future.

Cc: John Fastabend 
Signed-off-by: Jason Wang 
---
   drivers/net/virtio_net.c | 112 
---
   1 file changed, 87 insertions(+), 25 deletions(-)


Hi Jason,

I was doing some more testing on this what do you think about doing this
so that free_unused_bufs() handles the buffer free with dev_kfree_skb()
instead of put_page in small receive mode. Seems more correct to me.


diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 783e842..27ff76c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1898,6 +1898,10 @@ static void free_receive_page_frags(struct virtnet_info
*vi)

   static bool is_xdp_queue(struct virtnet_info *vi, int q)
   {
+   /* For small receive mode always use kfree_skb variants */
+   if (!vi->mergeable_rx_bufs)
+   return false;
+
  if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
  return false;
  else if (q < vi->curr_queue_pairs)


patch is untested just spotted doing code review.

Thanks,
John

We probably need a better name for this function.

Acked-by: Jason Wang 


How about is_xdp_raw_buffer_queue()?

I'll submit a proper patch today.


Sounds good, thanks.



Re: [PATCH net 9/9] virtio-net: XDP support for small buffers

2017-01-03 Thread John Fastabend
On 17-01-02 10:16 PM, Jason Wang wrote:
> 
> 
> On 2017年01月03日 06:43, John Fastabend wrote:
>> On 16-12-23 06:37 AM, Jason Wang wrote:
>>> Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
>>> small receive buffer untouched. This will confuse the user who want to
>>> set XDP but use small buffers. Other than forbid XDP in small buffer
>>> mode, let's make it work. XDP then can only work at skb->data since
>>> virtio-net create skbs during refill, this is sub optimal which could
>>> be optimized in the future.
>>>
>>> Cc: John Fastabend 
>>> Signed-off-by: Jason Wang 
>>> ---
>>>   drivers/net/virtio_net.c | 112 
>>> ---
>>>   1 file changed, 87 insertions(+), 25 deletions(-)
>>>
>> Hi Jason,
>>
>> I was doing some more testing on this what do you think about doing this
>> so that free_unused_bufs() handles the buffer free with dev_kfree_skb()
>> instead of put_page in small receive mode. Seems more correct to me.
>>
>>
>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>> index 783e842..27ff76c 100644
>> --- a/drivers/net/virtio_net.c
>> +++ b/drivers/net/virtio_net.c
>> @@ -1898,6 +1898,10 @@ static void free_receive_page_frags(struct 
>> virtnet_info
>> *vi)
>>
>>   static bool is_xdp_queue(struct virtnet_info *vi, int q)
>>   {
>> +   /* For small receive mode always use kfree_skb variants */
>> +   if (!vi->mergeable_rx_bufs)
>> +   return false;
>> +
>>  if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
>>  return false;
>>  else if (q < vi->curr_queue_pairs)
>>
>>
>> patch is untested just spotted doing code review.
>>
>> Thanks,
>> John
> 
> We probably need a better name for this function.
> 
> Acked-by: Jason Wang 
> 

How about is_xdp_raw_buffer_queue()?

I'll submit a proper patch today.


Re: [PATCH net 9/9] virtio-net: XDP support for small buffers

2017-01-02 Thread Jason Wang



On 2017年01月03日 06:43, John Fastabend wrote:

On 16-12-23 06:37 AM, Jason Wang wrote:

Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
small receive buffer untouched. This will confuse the user who want to
set XDP but use small buffers. Other than forbid XDP in small buffer
mode, let's make it work. XDP then can only work at skb->data since
virtio-net create skbs during refill, this is sub optimal which could
be optimized in the future.

Cc: John Fastabend 
Signed-off-by: Jason Wang 
---
  drivers/net/virtio_net.c | 112 ---
  1 file changed, 87 insertions(+), 25 deletions(-)


Hi Jason,

I was doing some more testing on this what do you think about doing this
so that free_unused_bufs() handles the buffer free with dev_kfree_skb()
instead of put_page in small receive mode. Seems more correct to me.


diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 783e842..27ff76c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1898,6 +1898,10 @@ static void free_receive_page_frags(struct virtnet_info 
*vi)

  static bool is_xdp_queue(struct virtnet_info *vi, int q)
  {
+   /* For small receive mode always use kfree_skb variants */
+   if (!vi->mergeable_rx_bufs)
+   return false;
+
 if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
 return false;
 else if (q < vi->curr_queue_pairs)


patch is untested just spotted doing code review.

Thanks,
John


We probably need a better name for this function.

Acked-by: Jason Wang 



Re: [PATCH net 9/9] virtio-net: XDP support for small buffers

2017-01-02 Thread John Fastabend
On 16-12-23 06:37 AM, Jason Wang wrote:
> Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
> small receive buffer untouched. This will confuse the user who want to
> set XDP but use small buffers. Other than forbid XDP in small buffer
> mode, let's make it work. XDP then can only work at skb->data since
> virtio-net create skbs during refill, this is sub optimal which could
> be optimized in the future.
> 
> Cc: John Fastabend 
> Signed-off-by: Jason Wang 
> ---
>  drivers/net/virtio_net.c | 112 
> ---
>  1 file changed, 87 insertions(+), 25 deletions(-)
> 

Hi Jason,

I was doing some more testing on this what do you think about doing this
so that free_unused_bufs() handles the buffer free with dev_kfree_skb()
instead of put_page in small receive mode. Seems more correct to me.


diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 783e842..27ff76c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1898,6 +1898,10 @@ static void free_receive_page_frags(struct virtnet_info 
*vi)

 static bool is_xdp_queue(struct virtnet_info *vi, int q)
 {
+   /* For small receive mode always use kfree_skb variants */
+   if (!vi->mergeable_rx_bufs)
+   return false;
+
if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
return false;
else if (q < vi->curr_queue_pairs)


patch is untested just spotted doing code review.

Thanks,
John


Re: [PATCH net 9/9] virtio-net: XDP support for small buffers

2016-12-23 Thread John Fastabend
On 16-12-23 06:37 AM, Jason Wang wrote:
> Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
> small receive buffer untouched. This will confuse the user who want to
> set XDP but use small buffers. Other than forbid XDP in small buffer
> mode, let's make it work. XDP then can only work at skb->data since
> virtio-net create skbs during refill, this is sub optimal which could
> be optimized in the future.
> 
> Cc: John Fastabend 
> Signed-off-by: Jason Wang 
> ---


Looks good to me thanks!

Acked-by: John Fastabend 



[PATCH net 9/9] virtio-net: XDP support for small buffers

2016-12-23 Thread Jason Wang
Commit f600b6905015 ("virtio_net: Add XDP support") leaves the case of
small receive buffer untouched. This will confuse the user who want to
set XDP but use small buffers. Other than forbid XDP in small buffer
mode, let's make it work. XDP then can only work at skb->data since
virtio-net create skbs during refill, this is sub optimal which could
be optimized in the future.

Cc: John Fastabend 
Signed-off-by: Jason Wang 
---
 drivers/net/virtio_net.c | 112 ---
 1 file changed, 87 insertions(+), 25 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e53365a8..5deeda6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -333,9 +333,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
 static void virtnet_xdp_xmit(struct virtnet_info *vi,
 struct receive_queue *rq,
 struct send_queue *sq,
-struct xdp_buff *xdp)
+struct xdp_buff *xdp,
+void *data)
 {
-   struct page *page = virt_to_head_page(xdp->data);
struct virtio_net_hdr_mrg_rxbuf *hdr;
unsigned int num_sg, len;
void *xdp_sent;
@@ -343,20 +343,45 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi,
 
/* Free up any pending old buffers before queueing new ones. */
while ((xdp_sent = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-   struct page *sent_page = virt_to_head_page(xdp_sent);
-   put_page(sent_page);
+   if (vi->mergeable_rx_bufs) {
+   struct page *sent_page = virt_to_head_page(xdp_sent);
+
+   put_page(sent_page);
+   } else { /* small buffer */
+   struct sk_buff *skb = xdp_sent;
+
+   kfree_skb(skb);
+   }
}
 
-   /* Zero header and leave csum up to XDP layers */
-   hdr = xdp->data;
-   memset(hdr, 0, vi->hdr_len);
+   if (vi->mergeable_rx_bufs) {
+   /* Zero header and leave csum up to XDP layers */
+   hdr = xdp->data;
+   memset(hdr, 0, vi->hdr_len);
+
+   num_sg = 1;
+   sg_init_one(sq->sg, xdp->data, xdp->data_end - xdp->data);
+   } else { /* small buffer */
+   struct sk_buff *skb = data;
 
-   num_sg = 1;
-   sg_init_one(sq->sg, xdp->data, xdp->data_end - xdp->data);
+   /* Zero header and leave csum up to XDP layers */
+   hdr = skb_vnet_hdr(skb);
+   memset(hdr, 0, vi->hdr_len);
+
+   num_sg = 2;
+   sg_init_table(sq->sg, 2);
+   sg_set_buf(sq->sg, hdr, vi->hdr_len);
+   skb_to_sgvec(skb, sq->sg + 1, 0, skb->len);
+   }
err = virtqueue_add_outbuf(sq->vq, sq->sg, num_sg,
-  xdp->data, GFP_ATOMIC);
+  data, GFP_ATOMIC);
if (unlikely(err)) {
-   put_page(page);
+   if (vi->mergeable_rx_bufs) {
+   struct page *page = virt_to_head_page(xdp->data);
+
+   put_page(page);
+   } else /* small buffer */
+   kfree_skb(data);
return; // On error abort to avoid unnecessary kick
}
 
@@ -366,23 +391,26 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi,
 static u32 do_xdp_prog(struct virtnet_info *vi,
   struct receive_queue *rq,
   struct bpf_prog *xdp_prog,
-  struct page *page, int offset, int len)
+  void *data, int len)
 {
int hdr_padded_len;
struct xdp_buff xdp;
+   void *buf;
unsigned int qp;
u32 act;
-   u8 *buf;
-
-   buf = page_address(page) + offset;
 
-   if (vi->mergeable_rx_bufs)
+   if (vi->mergeable_rx_bufs) {
hdr_padded_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
-   else
-   hdr_padded_len = sizeof(struct padded_vnet_hdr);
+   xdp.data = data + hdr_padded_len;
+   xdp.data_end = xdp.data + (len - vi->hdr_len);
+   buf = data;
+   } else { /* small buffers */
+   struct sk_buff *skb = data;
 
-   xdp.data = buf + hdr_padded_len;
-   xdp.data_end = xdp.data + (len - vi->hdr_len);
+   xdp.data = skb->data;
+   xdp.data_end = xdp.data + len;
+   buf = skb->data;
+   }
 
act = bpf_prog_run_xdp(xdp_prog, &xdp);
switch (act) {
@@ -392,8 +420,8 @@ static u32 do_xdp_prog(struct virtnet_info *vi,
qp = vi->curr_queue_pairs -
vi->xdp_queue_pairs +
smp_processor_id();
-   xdp.data = buf + (vi->mergeable_rx_bufs ? 0 : 4);
-   virtnet_xdp_xmit(vi, rq, &vi->sq[qp