Skip to content

Commit 5aaac1a

Browse files
alobakinanguy11
authored andcommitted
libeth: support different types of buffers for Rx
Unlike previous generations, idpf requires more buffer types for optimal performance. This includes: header buffers, short buffers, and no-overhead buffers (w/o headroom and tailroom, for TCP zerocopy when the header split is enabled). Introduce libeth Rx buffer type and calculate page_pool params accordingly. All the HW-related details like buffer alignment are still accounted. For the header buffers, pick 256 bytes as in most places in the kernel (have you ever seen frames with bigger headers?). Reviewed-by: Przemek Kitszel <[email protected]> Signed-off-by: Alexander Lobakin <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 4309363 commit 5aaac1a

File tree

2 files changed

+140
-11
lines changed
  • drivers/net/ethernet/intel/libeth
  • include/net/libeth

2 files changed

+140
-11
lines changed

drivers/net/ethernet/intel/libeth/rx.c

Lines changed: 121 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
/* Rx buffer management */
77

88
/**
9-
* libeth_rx_hw_len - get the actual buffer size to be passed to HW
9+
* libeth_rx_hw_len_mtu - get the actual buffer size to be passed to HW
1010
* @pp: &page_pool_params of the netdev to calculate the size for
1111
* @max_len: maximum buffer size for a single descriptor
1212
*
1313
* Return: HW-writeable length per one buffer to pass it to the HW accounting:
1414
* MTU the @dev has, HW required alignment, minimum and maximum allowed values,
1515
* and system's page size.
1616
*/
17-
static u32 libeth_rx_hw_len(const struct page_pool_params *pp, u32 max_len)
17+
static u32 libeth_rx_hw_len_mtu(const struct page_pool_params *pp, u32 max_len)
1818
{
1919
u32 len;
2020

@@ -26,6 +26,118 @@ static u32 libeth_rx_hw_len(const struct page_pool_params *pp, u32 max_len)
2626
return len;
2727
}
2828

29+
/**
30+
* libeth_rx_hw_len_truesize - get the short buffer size to be passed to HW
31+
* @pp: &page_pool_params of the netdev to calculate the size for
32+
* @max_len: maximum buffer size for a single descriptor
33+
* @truesize: desired truesize for the buffers
34+
*
35+
* Return: HW-writeable length per one buffer to pass it to the HW ignoring the
36+
* MTU and closest to the passed truesize. Can be used for "short" buffer
37+
* queues to fragment pages more efficiently.
38+
*/
39+
static u32 libeth_rx_hw_len_truesize(const struct page_pool_params *pp,
40+
u32 max_len, u32 truesize)
41+
{
42+
u32 min, len;
43+
44+
min = SKB_HEAD_ALIGN(pp->offset + LIBETH_RX_BUF_STRIDE);
45+
truesize = clamp(roundup_pow_of_two(truesize), roundup_pow_of_two(min),
46+
PAGE_SIZE << LIBETH_RX_PAGE_ORDER);
47+
48+
len = SKB_WITH_OVERHEAD(truesize - pp->offset);
49+
len = ALIGN_DOWN(len, LIBETH_RX_BUF_STRIDE) ? : LIBETH_RX_BUF_STRIDE;
50+
len = min3(len, ALIGN_DOWN(max_len ? : U32_MAX, LIBETH_RX_BUF_STRIDE),
51+
pp->max_len);
52+
53+
return len;
54+
}
55+
56+
/**
57+
* libeth_rx_page_pool_params - calculate params with the stack overhead
58+
* @fq: buffer queue to calculate the size for
59+
* @pp: &page_pool_params of the netdev
60+
*
61+
* Set the PP params to will all needed stack overhead (headroom, tailroom) and
62+
* both the HW buffer length and the truesize for all types of buffers. For
63+
* "short" buffers, truesize never exceeds the "wanted" one; for the rest,
64+
* it can be up to the page size.
65+
*
66+
* Return: true on success, false on invalid input params.
67+
*/
68+
static bool libeth_rx_page_pool_params(struct libeth_fq *fq,
69+
struct page_pool_params *pp)
70+
{
71+
pp->offset = LIBETH_SKB_HEADROOM;
72+
/* HW-writeable / syncable length per one page */
73+
pp->max_len = LIBETH_RX_PAGE_LEN(pp->offset);
74+
75+
/* HW-writeable length per buffer */
76+
switch (fq->type) {
77+
case LIBETH_FQE_MTU:
78+
fq->buf_len = libeth_rx_hw_len_mtu(pp, fq->buf_len);
79+
break;
80+
case LIBETH_FQE_SHORT:
81+
fq->buf_len = libeth_rx_hw_len_truesize(pp, fq->buf_len,
82+
fq->truesize);
83+
break;
84+
case LIBETH_FQE_HDR:
85+
fq->buf_len = ALIGN(LIBETH_MAX_HEAD, LIBETH_RX_BUF_STRIDE);
86+
break;
87+
default:
88+
return false;
89+
}
90+
91+
/* Buffer size to allocate */
92+
fq->truesize = roundup_pow_of_two(SKB_HEAD_ALIGN(pp->offset +
93+
fq->buf_len));
94+
95+
return true;
96+
}
97+
98+
/**
99+
* libeth_rx_page_pool_params_zc - calculate params without the stack overhead
100+
* @fq: buffer queue to calculate the size for
101+
* @pp: &page_pool_params of the netdev
102+
*
103+
* Set the PP params to exclude the stack overhead and both the buffer length
104+
* and the truesize, which are equal for the data buffers. Note that this
105+
* requires separate header buffers to be always active and account the
106+
* overhead.
107+
* With the MTU == ``PAGE_SIZE``, this allows the kernel to enable the zerocopy
108+
* mode.
109+
*
110+
* Return: true on success, false on invalid input params.
111+
*/
112+
static bool libeth_rx_page_pool_params_zc(struct libeth_fq *fq,
113+
struct page_pool_params *pp)
114+
{
115+
u32 mtu, max;
116+
117+
pp->offset = 0;
118+
pp->max_len = PAGE_SIZE << LIBETH_RX_PAGE_ORDER;
119+
120+
switch (fq->type) {
121+
case LIBETH_FQE_MTU:
122+
mtu = READ_ONCE(pp->netdev->mtu);
123+
break;
124+
case LIBETH_FQE_SHORT:
125+
mtu = fq->truesize;
126+
break;
127+
default:
128+
return false;
129+
}
130+
131+
mtu = roundup_pow_of_two(mtu);
132+
max = min(rounddown_pow_of_two(fq->buf_len ? : U32_MAX),
133+
pp->max_len);
134+
135+
fq->buf_len = clamp(mtu, LIBETH_RX_BUF_STRIDE, max);
136+
fq->truesize = fq->buf_len;
137+
138+
return true;
139+
}
140+
29141
/**
30142
* libeth_rx_fq_create - create a PP with the default libeth settings
31143
* @fq: buffer queue struct to fill
@@ -44,19 +156,17 @@ int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct *napi)
44156
.netdev = napi->dev,
45157
.napi = napi,
46158
.dma_dir = DMA_FROM_DEVICE,
47-
.offset = LIBETH_SKB_HEADROOM,
48159
};
49160
struct libeth_fqe *fqes;
50161
struct page_pool *pool;
162+
bool ret;
51163

52-
/* HW-writeable / syncable length per one page */
53-
pp.max_len = LIBETH_RX_PAGE_LEN(pp.offset);
54-
55-
/* HW-writeable length per buffer */
56-
fq->buf_len = libeth_rx_hw_len(&pp, fq->buf_len);
57-
/* Buffer size to allocate */
58-
fq->truesize = roundup_pow_of_two(SKB_HEAD_ALIGN(pp.offset +
59-
fq->buf_len));
164+
if (!fq->hsplit)
165+
ret = libeth_rx_page_pool_params(fq, &pp);
166+
else
167+
ret = libeth_rx_page_pool_params_zc(fq, &pp);
168+
if (!ret)
169+
return -EINVAL;
60170

61171
pool = page_pool_create(&pp);
62172
if (IS_ERR(pool))

include/net/libeth/rx.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define LIBETH_MAX_HEADROOM LIBETH_SKB_HEADROOM
1818
/* Link layer / L2 overhead: Ethernet, 2 VLAN tags (C + S), FCS */
1919
#define LIBETH_RX_LL_LEN (ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN)
20+
/* Maximum supported L2-L4 header length */
21+
#define LIBETH_MAX_HEAD roundup_pow_of_two(max(MAX_HEADER, 256))
2022

2123
/* Always use order-0 pages */
2224
#define LIBETH_RX_PAGE_ORDER 0
@@ -43,13 +45,27 @@ struct libeth_fqe {
4345
u32 truesize;
4446
} __aligned_largest;
4547

48+
/**
49+
* enum libeth_fqe_type - enum representing types of Rx buffers
50+
* @LIBETH_FQE_MTU: buffer size is determined by MTU
51+
* @LIBETH_FQE_SHORT: buffer size is smaller than MTU, for short frames
52+
* @LIBETH_FQE_HDR: buffer size is ```LIBETH_MAX_HEAD```-sized, for headers
53+
*/
54+
enum libeth_fqe_type {
55+
LIBETH_FQE_MTU = 0U,
56+
LIBETH_FQE_SHORT,
57+
LIBETH_FQE_HDR,
58+
};
59+
4660
/**
4761
* struct libeth_fq - structure representing a buffer (fill) queue
4862
* @fp: hotpath part of the structure
4963
* @pp: &page_pool for buffer management
5064
* @fqes: array of Rx buffers
5165
* @truesize: size to allocate per buffer, w/overhead
5266
* @count: number of descriptors/buffers the queue has
67+
* @type: type of the buffers this queue has
68+
* @hsplit: flag whether header split is enabled
5369
* @buf_len: HW-writeable length per each buffer
5470
* @nid: ID of the closest NUMA node with memory
5571
*/
@@ -63,6 +79,9 @@ struct libeth_fq {
6379
);
6480

6581
/* Cold fields */
82+
enum libeth_fqe_type type:2;
83+
bool hsplit:1;
84+
6685
u32 buf_len;
6786
int nid;
6887
};

0 commit comments

Comments
 (0)