BPF helper improvements and cleanups
Subsystems (5)
Daniel Borkmann
maintainercover BPF helper improvements and cleanups
This set adds various improvements to BPF helpers, a cleanup to use skb_pkt_type_ok() helper, addition of bpf_skb_change_tail(), a follow up for event output helper and removing ifdefs around the cgroupv2 helper bits. For details please see individual patches.
The set is based against net-next tree, but requires a merge of net into net-next first.
Thanks a lot!
Daniel Borkmann (4):
bpf: use skb_pkt_type_ok helper in bpf_skb_change_type
bpf: add bpf_skb_change_tail helper
bpf: enable event output helper also for xdp types
bpf: get rid of cgroup helper related ifdefs
include/linux/skbuff.h | 43 +++++++++++++- include/net/sock.h | 10 ++++ include/uapi/linux/bpf.h | 11 ++++ net/core/filter.c | 152 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 204 insertions(+), 12 deletions(-)
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 1/4 bpf: use skb_pkt_type_ok helper in bpf_skb_change_type
Since we have a skb_pkt_type_ok() helper for checking the type before mangling, make use of it instead of open coding. Follow-up to commit 8b10cab64c13 ("net: simplify and make pkt_type_ok() available for other users") that came in after d2485c4242a8 ("bpf: add bpf_skb_change_type helper").
--- net/core/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/filter.c +2 -2
@@ -1976,8 +1976,8 @@ static u64 bpf_skb_change_type(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)u32 pkt_type = r2;/* We only allow a restricted subset to be changed for now. */ -if (unlikely (skb->pkt_type >PACKET_OTHERHOST || - pkt_type >PACKET_OTHERHOST )) +if (unlikely (!skb_pkt_type_ok (skb->pkt_type) || + !skb_pkt_type_ok (pkt_type)))return -EINVAL ; skb->pkt_type = pkt_type;
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 2/4 bpf: add bpf_skb_change_tail helper
In reply to Daniel BorkmannThis work adds a bpf_skb_change_tail() helper for tc BPF programs. The basic idea is to expand or shrink the skb in a controlled manner. The eBPF program can then rewrite the rest via helpers like bpf_skb_store_bytes(), bpf_lX_csum_replace() and others rather than passing a raw buffer for writing here.
bpf_skb_change_tail() is really a slow path helper and intended for replies with f.e. ICMP control messages. Concept is similar to other helpers like bpf_skb_change_proto() helper to keep the helper without protocol specifics and let the BPF program mangle the remaining parts. A flags field has been added and is reserved for now should we extend the helper in future.
--- include/linux/skbuff.h | 43 +++++++++++++++++++- include/uapi/linux/bpf.h | 11 ++++++ net/core/filter.c | 100 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 150 insertions(+), 4 deletions(-)
include/linux/skbuff.h +42 -1
@@ -2295,7 +2295,7 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)int ___pskb_trim (struct sk_buff *skb,unsigned int len); -static inline void __skb_trim (struct sk_buff *skb,unsigned int len) +static inline void __skb_set_length (struct sk_buff *skb,unsigned int len) {if (unlikely (skb_is_nonlinear (skb))) {WARN_ON (1 );
@@ -2305,6 +2305,11 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)skb_set_tail_pointer (skb, len); } +static inline void __skb_trim (struct sk_buff *skb,unsigned int len) +{ +__skb_set_length (skb, len); +} +void skb_trim (struct sk_buff *skb,unsigned int len);static inline int __pskb_trim (struct sk_buff *skb,unsigned int len)
@@ -2335,6 +2340,20 @@ static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)BUG_ON (err); } +static inline int __skb_grow (struct sk_buff *skb,unsigned int len) +{ +unsigned int diff = len - skb->len; + +if (skb_tailroom (skb) < diff) { +int ret =pskb_expand_head (skb,0 , diff -skb_tailroom (skb), +GFP_ATOMIC ); +if (ret) +return ret; + } +__skb_set_length (skb, len); +return 0 ; +} +/** * skb_orphan - orphan a buffer * @skb: buffer to orphan
@@ -2938,6 +2957,21 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)return __pskb_trim (skb, len); } +static inline int __skb_trim_rcsum (struct sk_buff *skb,unsigned int len) +{ +if (skb->ip_summed ==CHECKSUM_COMPLETE ) + skb->ip_summed =CHECKSUM_NONE ; +__skb_trim (skb, len); +return 0 ; +} + +static inline int __skb_grow_rcsum (struct sk_buff *skb,unsigned int len) +{ +if (skb->ip_summed ==CHECKSUM_COMPLETE ) + skb->ip_summed =CHECKSUM_NONE ; +return __skb_grow (skb, len); +} +#define skb_queue_walk (queue, skb) \ for (skb = (queue)->next; \ skb != (struct sk_buff *)(queue); \
@@ -3726,6 +3760,13 @@ static inline bool skb_is_gso_v6(const struct sk_buff *skb)return skb_shinfo (skb)->gso_type &SKB_GSO_TCPV6 ; } +static inline void skb_gso_reset (struct sk_buff *skb) +{ +skb_shinfo (skb)->gso_size =0 ; +skb_shinfo (skb)->gso_segs =0 ; +skb_shinfo (skb)->gso_type =0 ; +} +void __skb_warn_lro_forwarding (const struct sk_buff *skb);static inline bool skb_warn_if_lro (const struct sk_buff *skb)
include/uapi/linux/bpf.h +11 -0
@@ -386,6 +386,17 @@ enum bpf_func_id {*/ BPF_FUNC_current_task_under_cgroup, +/** +* bpf_skb_change_tail(skb, len, flags) +* The helper will resize the skb to the given new size, +* to be used f.e. with control messages. +* @skb: pointer to skb +* @len: new skb length +* @flags: reserved +* Return: 0 on success or negative error +*/ + BPF_FUNC_skb_change_tail, + __BPF_FUNC_MAX_ID, };
net/core/filter.c +97 -3
129 lines not on this page · raw message
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 3/4 bpf: enable event output helper also for xdp types
In reply to Daniel BorkmannFollow-up to 555c8a8623a3 ("bpf: avoid stack copy and use skb ctx for event output") for also adding the event output helper for XDP typed programs. The event output helper has been very useful in particular for debugging or event notification purposes, since it's much faster and flexible than regular trace printk due to programmatically being able to attach meta data. Same flags structure applies as with tc BPF programs.
--- net/core/filter.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
net/core/filter.c +41 -1
@@ -2408,6 +2408,41 @@ static const struct bpf_func_proto bpf_skb_under_cgroup_proto = { };#endif +static unsigned long bpf_xdp_copy (void *dst_buff,const void *src_buff, +unsigned long off,unsigned long len) +{ +memcpy (dst_buff, src_buff + off, len); +return 0 ; +} + +static u64 bpf_xdp_event_output (u64 r1,u64 r2,u64 flags,u64 r4, +u64 meta_size) +{ +struct xdp_buff *xdp = (struct xdp_buff *)(long ) r1; +struct bpf_map *map = (struct bpf_map *)(long ) r2; +u64 xdp_size = (flags &BPF_F_CTXLEN_MASK ) >>32 ; +void *meta = (void *)(long ) r4; + +if (unlikely (flags & ~(BPF_F_CTXLEN_MASK |BPF_F_INDEX_MASK ))) +return -EINVAL ; +if (unlikely (xdp_size > (unsigned long )(xdp->data_end - xdp->data))) +return -EFAULT ; + +return bpf_event_output (map, flags, meta, meta_size, xdp, xdp_size, + bpf_xdp_copy); +} + +static const struct bpf_func_proto bpf_xdp_event_output_proto = { + .func = bpf_xdp_event_output, + .gpl_only = true, + .ret_type =RET_INTEGER , + .arg1_type =ARG_PTR_TO_CTX , + .arg2_type =ARG_CONST_MAP_PTR , + .arg3_type =ARG_ANYTHING , + .arg4_type =ARG_PTR_TO_STACK , + .arg5_type =ARG_CONST_STACK_SIZE , +}; +static const struct bpf_func_proto *sk_filter_func_proto (enum bpf_func_id func_id) {
@@ -2492,7 +2527,12 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)static const struct bpf_func_proto *xdp_func_proto (enum bpf_func_id func_id) { -return sk_filter_func_proto (func_id); +switch (func_id) { +case BPF_FUNC_perf_event_output: +return &bpf_xdp_event_output_proto; +default : +return sk_filter_func_proto (func_id); + } }static bool __is_valid_access (int off,int size,enum bpf_access_type type)
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 4/4 bpf: get rid of cgroup helper related ifdefs
In reply to Daniel BorkmannAs recently discussed during the task_under_cgroup_hierarchy() addition, we should get rid of the ifdefs surrounding the bpf_skb_under_cgroup() helper. If related functionality is not built-in, the helper cannot be used anyway, which is also in line with what we do for all other helpers.
--- include/net/sock.h | 10 ++++++++++ net/core/filter.c | 6 +----- 2 files changed, 11 insertions(+), 5 deletions(-)
include/net/sock.h +10 -0
@@ -1114,6 +1114,16 @@ static inline bool sk_stream_is_writeable(const struct sock *sk)sk_stream_memory_free (sk); } +static inline int sk_under_cgroup_hierarchy (struct sock *sk, +struct cgroup *ancestor) +{ +#ifdef CONFIG_SOCK_CGROUP_DATA +return cgroup_is_descendant (sock_cgroup_ptr (&sk->sk_cgrp_data), + ancestor); +#else +return -ENOTSUPP ; +#endif +}static inline bool sk_has_memory_pressure (const struct sock *sk) {
net/core/filter.c +1 -5
@@ -2374,7 +2374,6 @@ bpf_get_skb_set_tunnel_proto(enum bpf_func_id which) } } -#ifdef CONFIG_SOCK_CGROUP_DATA static u64 bpf_skb_under_cgroup (u64 r1,u64 r2,u64 r3,u64 r4,u64 r5) {struct sk_buff *skb = (struct sk_buff *)(long )r1;
@@ -2395,7 +2394,7 @@ static u64 bpf_skb_under_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)if (unlikely (!cgrp))return -EAGAIN ; -return cgroup_is_descendant (sock_cgroup_ptr (&sk->sk_cgrp_data), cgrp); +return sk_under_cgroup_hierarchy (sk, cgrp); }static const struct bpf_func_proto bpf_skb_under_cgroup_proto = {
@@ -2406,7 +2405,6 @@ static const struct bpf_func_proto bpf_skb_under_cgroup_proto = { .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, }; -#endif static unsigned long bpf_xdp_copy (void *dst_buff,const void *src_buff,unsigned long off,unsigned long len)
@@ -2515,10 +2513,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)return &bpf_skb_event_output_proto;case BPF_FUNC_get_smp_processor_id:return &bpf_get_smp_processor_id_proto; -#ifdef CONFIG_SOCK_CGROUP_DATA case BPF_FUNC_skb_under_cgroup:return &bpf_skb_under_cgroup_proto; -#endif default :return sk_filter_func_proto (func_id); }
Signature · 1 line
1.9.3
David Miller
maintainerFrom: Daniel Borkmann <[email protected]>
Date: Thu, 18 Aug 2016 01:00:37 +0200
Quoted 7 lines
This set adds various improvements to BPF helpers, a cleanup to use
skb_pkt_type_ok()helper, addition ofbpf_skb_change_tail(), a follow up for event output helper and removing ifdefs around the cgroupv2 helper bits. For details please see individual patches.The set is based against net-next tree, but requires a merge of net into net-next first.
I'm pretty sure I did the correct merge, so applied, thanks!