Skip to content

Commit dea1526

Browse files
ameryhungMartin KaFai Lau
authored andcommitted
bpf: Allow bpf_xdp_shrink_data to shrink a frag from head and tail
Move skb_frag_t adjustment into bpf_xdp_shrink_data() and extend its functionality to be able to shrink an xdp fragment from both head and tail. In a later patch, bpf_xdp_pull_data() will reuse it to shrink an xdp fragment from head. Additionally, in bpf_xdp_frags_shrink_tail(), breaking the loop when bpf_xdp_shrink_data() returns false (i.e., not releasing the current fragment) is not necessary as the loop condition, offset > 0, has the same effect. Remove the else branch to simplify the code. Signed-off-by: Amery Hung <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Reviewed-by: Maciej Fijalkowski <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 8f12d11 commit dea1526

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

include/net/xdp_sock_drv.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,23 @@ static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
160160
return ret;
161161
}
162162

163-
static inline void xsk_buff_del_tail(struct xdp_buff *tail)
163+
static inline void xsk_buff_del_frag(struct xdp_buff *xdp)
164164
{
165-
struct xdp_buff_xsk *xskb = container_of(tail, struct xdp_buff_xsk, xdp);
165+
struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp);
166166

167167
list_del(&xskb->list_node);
168168
}
169169

170+
static inline struct xdp_buff *xsk_buff_get_head(struct xdp_buff *first)
171+
{
172+
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
173+
struct xdp_buff_xsk *frag;
174+
175+
frag = list_first_entry(&xskb->pool->xskb_list, struct xdp_buff_xsk,
176+
list_node);
177+
return &frag->xdp;
178+
}
179+
170180
static inline struct xdp_buff *xsk_buff_get_tail(struct xdp_buff *first)
171181
{
172182
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
@@ -389,8 +399,13 @@ static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
389399
return NULL;
390400
}
391401

392-
static inline void xsk_buff_del_tail(struct xdp_buff *tail)
402+
static inline void xsk_buff_del_frag(struct xdp_buff *xdp)
403+
{
404+
}
405+
406+
static inline struct xdp_buff *xsk_buff_get_head(struct xdp_buff *first)
393407
{
408+
return NULL;
394409
}
395410

396411
static inline struct xdp_buff *xsk_buff_get_tail(struct xdp_buff *first)

net/core/filter.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4153,34 +4153,45 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
41534153
return 0;
41544154
}
41554155

4156-
static void bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,
4157-
enum xdp_mem_type mem_type, bool release)
4156+
static struct xdp_buff *bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,
4157+
bool tail, bool release)
41584158
{
4159-
struct xdp_buff *zc_frag = xsk_buff_get_tail(xdp);
4159+
struct xdp_buff *zc_frag = tail ? xsk_buff_get_tail(xdp) :
4160+
xsk_buff_get_head(xdp);
41604161

41614162
if (release) {
4162-
xsk_buff_del_tail(zc_frag);
4163-
__xdp_return(0, mem_type, false, zc_frag);
4163+
xsk_buff_del_frag(zc_frag);
41644164
} else {
4165-
zc_frag->data_end -= shrink;
4165+
if (tail)
4166+
zc_frag->data_end -= shrink;
4167+
else
4168+
zc_frag->data += shrink;
41664169
}
4170+
4171+
return zc_frag;
41674172
}
41684173

41694174
static bool bpf_xdp_shrink_data(struct xdp_buff *xdp, skb_frag_t *frag,
4170-
int shrink)
4175+
int shrink, bool tail)
41714176
{
41724177
enum xdp_mem_type mem_type = xdp->rxq->mem.type;
41734178
bool release = skb_frag_size(frag) == shrink;
4179+
netmem_ref netmem = skb_frag_netmem(frag);
4180+
struct xdp_buff *zc_frag = NULL;
41744181

41754182
if (mem_type == MEM_TYPE_XSK_BUFF_POOL) {
4176-
bpf_xdp_shrink_data_zc(xdp, shrink, mem_type, release);
4177-
goto out;
4183+
netmem = 0;
4184+
zc_frag = bpf_xdp_shrink_data_zc(xdp, shrink, tail, release);
41784185
}
41794186

4180-
if (release)
4181-
__xdp_return(skb_frag_netmem(frag), mem_type, false, NULL);
4187+
if (release) {
4188+
__xdp_return(netmem, mem_type, false, zc_frag);
4189+
} else {
4190+
if (!tail)
4191+
skb_frag_off_add(frag, shrink);
4192+
skb_frag_size_sub(frag, shrink);
4193+
}
41824194

4183-
out:
41844195
return release;
41854196
}
41864197

@@ -4198,12 +4209,8 @@ static int bpf_xdp_frags_shrink_tail(struct xdp_buff *xdp, int offset)
41984209

41994210
len_free += shrink;
42004211
offset -= shrink;
4201-
if (bpf_xdp_shrink_data(xdp, frag, shrink)) {
4212+
if (bpf_xdp_shrink_data(xdp, frag, shrink, true))
42024213
n_frags_free++;
4203-
} else {
4204-
skb_frag_size_sub(frag, shrink);
4205-
break;
4206-
}
42074214
}
42084215
sinfo->nr_frags -= n_frags_free;
42094216
sinfo->xdp_frags_size -= len_free;

0 commit comments

Comments
 (0)