Skip to content

Commit 3804fea

Browse files
ameryhungKernel Patches Daemon
authored andcommitted
bpf: Support pulling non-linear xdp data
Add kfunc, bpf_xdp_pull_data(), to support pulling data from xdp fragments. Similar to bpf_skb_pull_data(), bpf_xdp_pull_data() makes the first len bytes of data directly readable and writable in bpf programs. If the "len" argument is larger than the linear data size, data in fragments will be copied to the linear region when there is enough room between xdp->data_end and xdp_data_hard_end(xdp), which is subject to driver implementation. A use case of the kfunc is to decapsulate headers residing in xdp fragments. It is possible for a NIC driver to place headers in xdp fragments. To keep using direct packet access for parsing and decapsulating headers, users can pull headers into the linear data area by calling bpf_xdp_pull_data() and then pop the header with bpf_xdp_adjust_head(). An unused argument, flags is reserved for future extension (e.g., tossing the data instead of copying it to the linear data area). Signed-off-by: Amery Hung <[email protected]>
1 parent 6bb1bc2 commit 3804fea

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

net/core/filter.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12212,6 +12212,81 @@ __bpf_kfunc int bpf_sock_ops_enable_tx_tstamp(struct bpf_sock_ops_kern *skops,
1221212212
return 0;
1221312213
}
1221412214

12215+
/**
12216+
* bpf_xdp_pull_data() - Pull in non-linear xdp data.
12217+
* @x: &xdp_md associated with the XDP buffer
12218+
* @len: length of data to be made directly accessible in the linear part
12219+
* @flags: future use, must be zero
12220+
*
12221+
* Pull in non-linear data in case the XDP buffer associated with @x is
12222+
* non-linear and not all @len are in the linear data area.
12223+
*
12224+
* Direct packet access allows reading and writing linear XDP data through
12225+
* packet pointers (i.e., &xdp_md->data + offsets). When an eBPF program wants
12226+
* to directly access data that may be in the non-linear area, call this kfunc
12227+
* to make sure the data is available in the linear area.
12228+
*
12229+
* This kfunc can also be used with bpf_xdp_adjust_head() to decapsulate
12230+
* headers in the non-linear data area.
12231+
*
12232+
* A call to this kfunc is susceptible to change the underlying packet buffer.
12233+
* Therefore, at load time, all checks on pointers previously done by the
12234+
* verifier are invalidated and must be performed again, if the kfunc is used
12235+
* in combination with direct packet access.
12236+
*
12237+
* Return:
12238+
* * %0 - success
12239+
* * %-EINVAL - invalid len or flags
12240+
*/
12241+
__bpf_kfunc int bpf_xdp_pull_data(struct xdp_md *x, u32 len, u64 flags)
12242+
{
12243+
struct xdp_buff *xdp = (struct xdp_buff *)x;
12244+
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
12245+
void *data_hard_end = xdp_data_hard_end(xdp);
12246+
void *data_end = xdp->data + len;
12247+
int i, delta, n_frags_free = 0, len_free = 0;
12248+
12249+
if (flags)
12250+
return -EINVAL;
12251+
12252+
if (unlikely(len > xdp_get_buff_len(xdp)))
12253+
return -EINVAL;
12254+
12255+
if (unlikely(data_end < xdp->data || data_end > data_hard_end))
12256+
return -EINVAL;
12257+
12258+
delta = data_end - xdp->data_end;
12259+
if (delta <= 0)
12260+
return 0;
12261+
12262+
for (i = 0; i < sinfo->nr_frags && delta; i++) {
12263+
skb_frag_t *frag = &sinfo->frags[i];
12264+
u32 shrink = min_t(u32, delta, skb_frag_size(frag));
12265+
12266+
memcpy(xdp->data_end + len_free, skb_frag_address(frag), shrink);
12267+
12268+
len_free += shrink;
12269+
delta -= shrink;
12270+
if (bpf_xdp_shrink_data(xdp, frag, shrink, false))
12271+
n_frags_free++;
12272+
}
12273+
12274+
if (unlikely(n_frags_free)) {
12275+
memmove(sinfo->frags, sinfo->frags + n_frags_free,
12276+
(sinfo->nr_frags - n_frags_free) * sizeof(skb_frag_t));
12277+
12278+
sinfo->nr_frags -= n_frags_free;
12279+
12280+
if (!sinfo->nr_frags)
12281+
xdp_buff_clear_frags_flag(xdp);
12282+
}
12283+
12284+
sinfo->xdp_frags_size -= len_free;
12285+
xdp->data_end = data_end;
12286+
12287+
return 0;
12288+
}
12289+
1221512290
__bpf_kfunc_end_defs();
1221612291

1221712292
int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
@@ -12239,6 +12314,7 @@ BTF_KFUNCS_END(bpf_kfunc_check_set_skb_meta)
1223912314

1224012315
BTF_KFUNCS_START(bpf_kfunc_check_set_xdp)
1224112316
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
12317+
BTF_ID_FLAGS(func, bpf_xdp_pull_data)
1224212318
BTF_KFUNCS_END(bpf_kfunc_check_set_xdp)
1224312319

1224412320
BTF_KFUNCS_START(bpf_kfunc_check_set_sock_addr)

0 commit comments

Comments
 (0)