Skip to content

Commit 0ebab78

Browse files
LorenzoBianconikuba-moo
authored andcommitted
net: veth: add page_pool for page recycling
Introduce page_pool support in veth driver in order to recycle pages in veth_convert_skb_to_xdp_buff routine and avoid reallocating the skb through the page allocator. The patch has been tested sending tcp traffic to a veth pair where the remote peer is running a simple xdp program just returning xdp_pass: veth upstream codebase: MTU 1500B: ~ 8Gbps MTU 8000B: ~ 13.9Gbps veth upstream codebase + pp support: MTU 1500B: ~ 9.2Gbps MTU 8000B: ~ 16.2Gbps Tested-by: Maryam Tahhan <mtahhan@redhat.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent ffcddca commit 0ebab78

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

drivers/net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ config TUN_VNET_CROSS_LE
402402

403403
config VETH
404404
tristate "Virtual ethernet pair device"
405+
select PAGE_POOL
405406
help
406407
This device is a local ethernet tunnel. Devices are created in pairs.
407408
When one end receives the packet it appears on its pair and vice

drivers/net/veth.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/ptr_ring.h>
2727
#include <linux/bpf_trace.h>
2828
#include <linux/net_tstamp.h>
29+
#include <net/page_pool.h>
2930

3031
#define DRV_NAME "veth"
3132
#define DRV_VERSION "1.0"
@@ -65,6 +66,7 @@ struct veth_rq {
6566
bool rx_notify_masked;
6667
struct ptr_ring xdp_ring;
6768
struct xdp_rxq_info xdp_rxq;
69+
struct page_pool *page_pool;
6870
};
6971

7072
struct veth_priv {
@@ -727,25 +729,27 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
727729
goto drop;
728730

729731
/* Allocate skb head */
730-
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
732+
page = page_pool_dev_alloc_pages(rq->page_pool);
731733
if (!page)
732734
goto drop;
733735

734736
nskb = build_skb(page_address(page), PAGE_SIZE);
735737
if (!nskb) {
736-
put_page(page);
738+
page_pool_put_full_page(rq->page_pool, page, true);
737739
goto drop;
738740
}
739741

740742
skb_reserve(nskb, VETH_XDP_HEADROOM);
743+
skb_copy_header(nskb, skb);
744+
skb_mark_for_recycle(nskb);
745+
741746
size = min_t(u32, skb->len, max_head_size);
742747
if (skb_copy_bits(skb, 0, nskb->data, size)) {
743748
consume_skb(nskb);
744749
goto drop;
745750
}
746751
skb_put(nskb, size);
747752

748-
skb_copy_header(nskb, skb);
749753
head_off = skb_headroom(nskb) - skb_headroom(skb);
750754
skb_headers_offset_update(nskb, head_off);
751755

@@ -754,7 +758,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
754758
len = skb->len - off;
755759

756760
for (i = 0; i < MAX_SKB_FRAGS && off < skb->len; i++) {
757-
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
761+
page = page_pool_dev_alloc_pages(rq->page_pool);
758762
if (!page) {
759763
consume_skb(nskb);
760764
goto drop;
@@ -1002,11 +1006,37 @@ static int veth_poll(struct napi_struct *napi, int budget)
10021006
return done;
10031007
}
10041008

1009+
static int veth_create_page_pool(struct veth_rq *rq)
1010+
{
1011+
struct page_pool_params pp_params = {
1012+
.order = 0,
1013+
.pool_size = VETH_RING_SIZE,
1014+
.nid = NUMA_NO_NODE,
1015+
.dev = &rq->dev->dev,
1016+
};
1017+
1018+
rq->page_pool = page_pool_create(&pp_params);
1019+
if (IS_ERR(rq->page_pool)) {
1020+
int err = PTR_ERR(rq->page_pool);
1021+
1022+
rq->page_pool = NULL;
1023+
return err;
1024+
}
1025+
1026+
return 0;
1027+
}
1028+
10051029
static int __veth_napi_enable_range(struct net_device *dev, int start, int end)
10061030
{
10071031
struct veth_priv *priv = netdev_priv(dev);
10081032
int err, i;
10091033

1034+
for (i = start; i < end; i++) {
1035+
err = veth_create_page_pool(&priv->rq[i]);
1036+
if (err)
1037+
goto err_page_pool;
1038+
}
1039+
10101040
for (i = start; i < end; i++) {
10111041
struct veth_rq *rq = &priv->rq[i];
10121042

@@ -1027,6 +1057,11 @@ static int __veth_napi_enable_range(struct net_device *dev, int start, int end)
10271057
err_xdp_ring:
10281058
for (i--; i >= start; i--)
10291059
ptr_ring_cleanup(&priv->rq[i].xdp_ring, veth_ptr_free);
1060+
err_page_pool:
1061+
for (i = start; i < end; i++) {
1062+
page_pool_destroy(priv->rq[i].page_pool);
1063+
priv->rq[i].page_pool = NULL;
1064+
}
10301065

10311066
return err;
10321067
}
@@ -1056,6 +1091,11 @@ static void veth_napi_del_range(struct net_device *dev, int start, int end)
10561091
rq->rx_notify_masked = false;
10571092
ptr_ring_cleanup(&rq->xdp_ring, veth_ptr_free);
10581093
}
1094+
1095+
for (i = start; i < end; i++) {
1096+
page_pool_destroy(priv->rq[i].page_pool);
1097+
priv->rq[i].page_pool = NULL;
1098+
}
10591099
}
10601100

10611101
static void veth_napi_del(struct net_device *dev)

0 commit comments

Comments
 (0)