Skip to content

Commit 05421ae

Browse files
joannekoongAlexei Starovoitov
authored andcommitted
bpf: Add xdp dynptrs
Add xdp dynptrs, which are dynptrs whose underlying pointer points to a xdp_buff. The dynptr acts on xdp data. xdp dynptrs have two main benefits. One is that they allow operations on sizes that are not statically known at compile-time (eg variable-sized accesses). Another is that parsing the packet data through dynptrs (instead of through direct access of xdp->data and xdp->data_end) can be more ergonomic and less brittle (eg does not need manual if checking for being within bounds of data_end). For reads and writes on the dynptr, this includes reading/writing from/to and across fragments. Data slices through the bpf_dynptr_data API are not supported; instead bpf_dynptr_slice() and bpf_dynptr_slice_rdwr() should be used. For examples of how xdp dynptrs can be used, please see the attached selftests. Signed-off-by: Joanne Koong <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent b5964b9 commit 05421ae

File tree

7 files changed

+76
-6
lines changed

7 files changed

+76
-6
lines changed

include/linux/bpf.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,11 +610,15 @@ enum bpf_type_flag {
610610
/* DYNPTR points to sk_buff */
611611
DYNPTR_TYPE_SKB = BIT(15 + BPF_BASE_TYPE_BITS),
612612

613+
/* DYNPTR points to xdp_buff */
614+
DYNPTR_TYPE_XDP = BIT(16 + BPF_BASE_TYPE_BITS),
615+
613616
__BPF_TYPE_FLAG_MAX,
614617
__BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1,
615618
};
616619

617-
#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF | DYNPTR_TYPE_SKB)
620+
#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF | DYNPTR_TYPE_SKB \
621+
| DYNPTR_TYPE_XDP)
618622

619623
/* Max number of base types. */
620624
#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS)
@@ -1151,6 +1155,8 @@ enum bpf_dynptr_type {
11511155
BPF_DYNPTR_TYPE_RINGBUF,
11521156
/* Underlying data is a sk_buff */
11531157
BPF_DYNPTR_TYPE_SKB,
1158+
/* Underlying data is a xdp_buff */
1159+
BPF_DYNPTR_TYPE_XDP,
11541160
};
11551161

11561162
int bpf_dynptr_check_size(u32 size);

include/linux/filter.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,8 @@ static __always_inline int __bpf_xdp_redirect_map(struct bpf_map *map, u64 index
15461546
int __bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len);
15471547
int __bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from,
15481548
u32 len, u64 flags);
1549+
int __bpf_xdp_load_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len);
1550+
int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len);
15491551
#else /* CONFIG_NET */
15501552
static inline int __bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset,
15511553
void *to, u32 len)
@@ -1558,6 +1560,18 @@ static inline int __bpf_skb_store_bytes(struct sk_buff *skb, u32 offset,
15581560
{
15591561
return -EOPNOTSUPP;
15601562
}
1563+
1564+
static inline int __bpf_xdp_load_bytes(struct xdp_buff *xdp, u32 offset,
1565+
void *buf, u32 len)
1566+
{
1567+
return -EOPNOTSUPP;
1568+
}
1569+
1570+
static inline int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset,
1571+
void *buf, u32 len)
1572+
{
1573+
return -EOPNOTSUPP;
1574+
}
15611575
#endif /* CONFIG_NET */
15621576

15631577
#endif /* __LINUX_FILTER_H__ */

include/uapi/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5344,7 +5344,7 @@ union bpf_attr {
53445344
* *len* must be a statically known value. The returned data slice
53455345
* is invalidated whenever the dynptr is invalidated.
53465346
*
5347-
* skb type dynptrs may not use bpf_dynptr_data. They should
5347+
* skb and xdp type dynptrs may not use bpf_dynptr_data. They should
53485348
* instead use bpf_dynptr_slice and bpf_dynptr_slice_rdwr.
53495349
* Return
53505350
* Pointer to the underlying dynptr data, NULL if the dynptr is

kernel/bpf/helpers.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,8 @@ BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, const struct bpf_dynptr_kern
15301530
return 0;
15311531
case BPF_DYNPTR_TYPE_SKB:
15321532
return __bpf_skb_load_bytes(src->data, src->offset + offset, dst, len);
1533+
case BPF_DYNPTR_TYPE_XDP:
1534+
return __bpf_xdp_load_bytes(src->data, src->offset + offset, dst, len);
15331535
default:
15341536
WARN_ONCE(true, "bpf_dynptr_read: unknown dynptr type %d\n", type);
15351537
return -EFAULT;
@@ -1576,6 +1578,10 @@ BPF_CALL_5(bpf_dynptr_write, const struct bpf_dynptr_kern *, dst, u32, offset, v
15761578
case BPF_DYNPTR_TYPE_SKB:
15771579
return __bpf_skb_store_bytes(dst->data, dst->offset + offset, src, len,
15781580
flags);
1581+
case BPF_DYNPTR_TYPE_XDP:
1582+
if (flags)
1583+
return -EINVAL;
1584+
return __bpf_xdp_store_bytes(dst->data, dst->offset + offset, src, len);
15791585
default:
15801586
WARN_ONCE(true, "bpf_dynptr_write: unknown dynptr type %d\n", type);
15811587
return -EFAULT;
@@ -1615,7 +1621,8 @@ BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u3
16151621
case BPF_DYNPTR_TYPE_RINGBUF:
16161622
return (unsigned long)(ptr->data + ptr->offset + offset);
16171623
case BPF_DYNPTR_TYPE_SKB:
1618-
/* skb dynptrs should use bpf_dynptr_slice / bpf_dynptr_slice_rdwr */
1624+
case BPF_DYNPTR_TYPE_XDP:
1625+
/* skb and xdp dynptrs should use bpf_dynptr_slice / bpf_dynptr_slice_rdwr */
16191626
return 0;
16201627
default:
16211628
WARN_ONCE(true, "bpf_dynptr_data: unknown dynptr type %d\n", type);

kernel/bpf/verifier.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ static enum bpf_dynptr_type arg_to_dynptr_type(enum bpf_arg_type arg_type)
752752
return BPF_DYNPTR_TYPE_RINGBUF;
753753
case DYNPTR_TYPE_SKB:
754754
return BPF_DYNPTR_TYPE_SKB;
755+
case DYNPTR_TYPE_XDP:
756+
return BPF_DYNPTR_TYPE_XDP;
755757
default:
756758
return BPF_DYNPTR_TYPE_INVALID;
757759
}
@@ -6300,6 +6302,9 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
63006302
case DYNPTR_TYPE_SKB:
63016303
err_extra = "skb ";
63026304
break;
6305+
case DYNPTR_TYPE_XDP:
6306+
err_extra = "xdp ";
6307+
break;
63036308
default:
63046309
err_extra = "<unknown>";
63056310
break;
@@ -8943,6 +8948,7 @@ enum special_kfunc_type {
89438948
KF_bpf_rbtree_add,
89448949
KF_bpf_rbtree_first,
89458950
KF_bpf_dynptr_from_skb,
8951+
KF_bpf_dynptr_from_xdp,
89468952
};
89478953

89488954
BTF_SET_START(special_kfunc_set)
@@ -8958,6 +8964,7 @@ BTF_ID(func, bpf_rbtree_remove)
89588964
BTF_ID(func, bpf_rbtree_add)
89598965
BTF_ID(func, bpf_rbtree_first)
89608966
BTF_ID(func, bpf_dynptr_from_skb)
8967+
BTF_ID(func, bpf_dynptr_from_xdp)
89618968
BTF_SET_END(special_kfunc_set)
89628969

89638970
BTF_ID_LIST(special_kfunc_list)
@@ -8975,6 +8982,7 @@ BTF_ID(func, bpf_rbtree_remove)
89758982
BTF_ID(func, bpf_rbtree_add)
89768983
BTF_ID(func, bpf_rbtree_first)
89778984
BTF_ID(func, bpf_dynptr_from_skb)
8985+
BTF_ID(func, bpf_dynptr_from_xdp)
89788986

89798987
static bool is_kfunc_bpf_rcu_read_lock(struct bpf_kfunc_call_arg_meta *meta)
89808988
{
@@ -9731,6 +9739,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
97319739

97329740
if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb])
97339741
dynptr_arg_type |= DYNPTR_TYPE_SKB;
9742+
else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp])
9743+
dynptr_arg_type |= DYNPTR_TYPE_XDP;
97349744

97359745
ret = process_dynptr_func(env, regno, insn_idx, dynptr_arg_type);
97369746
if (ret < 0)

net/core/filter.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,7 +3839,7 @@ static const struct bpf_func_proto sk_skb_change_head_proto = {
38393839
.arg3_type = ARG_ANYTHING,
38403840
};
38413841

3842-
BPF_CALL_1(bpf_xdp_get_buff_len, struct xdp_buff*, xdp)
3842+
BPF_CALL_1(bpf_xdp_get_buff_len, struct xdp_buff*, xdp)
38433843
{
38443844
return xdp_get_buff_len(xdp);
38453845
}
@@ -3999,6 +3999,11 @@ static const struct bpf_func_proto bpf_xdp_load_bytes_proto = {
39993999
.arg4_type = ARG_CONST_SIZE,
40004000
};
40014001

4002+
int __bpf_xdp_load_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len)
4003+
{
4004+
return ____bpf_xdp_load_bytes(xdp, offset, buf, len);
4005+
}
4006+
40024007
BPF_CALL_4(bpf_xdp_store_bytes, struct xdp_buff *, xdp, u32, offset,
40034008
void *, buf, u32, len)
40044009
{
@@ -4026,6 +4031,11 @@ static const struct bpf_func_proto bpf_xdp_store_bytes_proto = {
40264031
.arg4_type = ARG_CONST_SIZE,
40274032
};
40284033

4034+
int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len)
4035+
{
4036+
return ____bpf_xdp_store_bytes(xdp, offset, buf, len);
4037+
}
4038+
40294039
static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
40304040
{
40314041
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
@@ -11648,6 +11658,19 @@ __bpf_kfunc int bpf_dynptr_from_skb(struct sk_buff *skb, u64 flags,
1164811658

1164911659
return 0;
1165011660
}
11661+
11662+
__bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
11663+
struct bpf_dynptr_kern *ptr__uninit)
11664+
{
11665+
if (flags) {
11666+
bpf_dynptr_set_null(ptr__uninit);
11667+
return -EINVAL;
11668+
}
11669+
11670+
bpf_dynptr_init(ptr__uninit, xdp, BPF_DYNPTR_TYPE_XDP, 0, xdp_get_buff_len(xdp));
11671+
11672+
return 0;
11673+
}
1165111674
__diag_pop();
1165211675

1165311676
int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
@@ -11668,11 +11691,20 @@ BTF_SET8_START(bpf_kfunc_check_set_skb)
1166811691
BTF_ID_FLAGS(func, bpf_dynptr_from_skb)
1166911692
BTF_SET8_END(bpf_kfunc_check_set_skb)
1167011693

11694+
BTF_SET8_START(bpf_kfunc_check_set_xdp)
11695+
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
11696+
BTF_SET8_END(bpf_kfunc_check_set_xdp)
11697+
1167111698
static const struct btf_kfunc_id_set bpf_kfunc_set_skb = {
1167211699
.owner = THIS_MODULE,
1167311700
.set = &bpf_kfunc_check_set_skb,
1167411701
};
1167511702

11703+
static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {
11704+
.owner = THIS_MODULE,
11705+
.set = &bpf_kfunc_check_set_xdp,
11706+
};
11707+
1167611708
static int __init bpf_kfunc_init(void)
1167711709
{
1167811710
int ret;
@@ -11685,6 +11717,7 @@ static int __init bpf_kfunc_init(void)
1168511717
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_OUT, &bpf_kfunc_set_skb);
1168611718
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_IN, &bpf_kfunc_set_skb);
1168711719
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_XMIT, &bpf_kfunc_set_skb);
11688-
return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb);
11720+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb);
11721+
return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp);
1168911722
}
1169011723
late_initcall(bpf_kfunc_init);

tools/include/uapi/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5344,7 +5344,7 @@ union bpf_attr {
53445344
* *len* must be a statically known value. The returned data slice
53455345
* is invalidated whenever the dynptr is invalidated.
53465346
*
5347-
* skb type dynptrs may not use bpf_dynptr_data. They should
5347+
* skb and xdp type dynptrs may not use bpf_dynptr_data. They should
53485348
* instead use bpf_dynptr_slice and bpf_dynptr_slice_rdwr.
53495349
* Return
53505350
* Pointer to the underlying dynptr data, NULL if the dynptr is

0 commit comments

Comments
 (0)