Hi Daniel, 2018-05-28 02:43 UTC+0200 ~ Daniel Borkmann <dan...@iogearbox.net> > Add a new bpf_skb_cgroup_id() helper that allows to retrieve the > cgroup id from the skb's socket. This is useful in particular to > enable bpf_get_cgroup_classid()-like behavior for cgroup v1 in > cgroup v2 by allowing ID based matching on egress. This can in > particular be used in combination with applying policy e.g. from > map lookups, and also complements the older bpf_skb_under_cgroup() > interface. In user space the cgroup id for a given path can be > retrieved through the f_handle as demonstrated in [0] recently. > > [0] https://lkml.org/lkml/2018/5/22/1190 > > Signed-off-by: Daniel Borkmann <dan...@iogearbox.net> > Acked-by: Alexei Starovoitov <a...@kernel.org> > --- > include/uapi/linux/bpf.h | 17 ++++++++++++++++- > net/core/filter.c | 29 +++++++++++++++++++++++++++-- > 2 files changed, 43 insertions(+), 3 deletions(-) > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 9b8c6e3..e2853aa 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -2004,6 +2004,20 @@ union bpf_attr { > * direct packet access. > * Return > * 0 on success, or a negative error in case of failure. > + * > + * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) > + * Description > + * Return the cgroup v2 id of the socket associated with the *skb*. > + * This is roughly similar to the **bpf_get_cgroup_classid**\ () > + * helper for cgroup v1 by providing a tag resp. identifier that > + * can be matched on or used for map lookups e.g. to implement > + * policy. The cgroup v2 id of a given path in the hierarchy is > + * exposed in user space through the f_handle API in order to get > + * to the same 64-bit id. > + * > + * This helper can be used on TC egress path, but not on ingress.
Nitpick: Maybe mention that the kernel must be built with CONFIG_SOCK_CGROUP_DATA option for the helper to be available? Best, Quentin > + * Return > + * The id is returned or 0 in case the id could not be retrieved. > */ > #define __BPF_FUNC_MAPPER(FN) \ > FN(unspec), \ > @@ -2082,7 +2096,8 @@ union bpf_attr { > FN(lwt_push_encap), \ > FN(lwt_seg6_store_bytes), \ > FN(lwt_seg6_adjust_srh), \ > - FN(lwt_seg6_action), > + FN(lwt_seg6_action), \ > + FN(skb_cgroup_id), > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper > * function eBPF program intends to call > diff --git a/net/core/filter.c b/net/core/filter.c > index acf1f4f..717c740 100644 > --- a/net/core/filter.c > +++ b/net/core/filter.c > @@ -3661,6 +3661,27 @@ static const struct bpf_func_proto > bpf_skb_under_cgroup_proto = { > .arg3_type = ARG_ANYTHING, > }; > > +#ifdef CONFIG_SOCK_CGROUP_DATA > +BPF_CALL_1(bpf_skb_cgroup_id, const struct sk_buff *, skb) > +{ > + struct sock *sk = skb_to_full_sk(skb); > + struct cgroup *cgrp; > + > + if (!sk || !sk_fullsock(sk)) > + return 0; > + > + cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data); > + return cgrp->kn->id.id; > +} > + > +static const struct bpf_func_proto bpf_skb_cgroup_id_proto = { > + .func = bpf_skb_cgroup_id, > + .gpl_only = false, > + .ret_type = RET_INTEGER, > + .arg1_type = ARG_PTR_TO_CTX, > +}; > +#endif > + > static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff, > unsigned long off, unsigned long len) > { > @@ -4741,12 +4762,16 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const > struct bpf_prog *prog) > return &bpf_get_socket_cookie_proto; > case BPF_FUNC_get_socket_uid: > return &bpf_get_socket_uid_proto; > + case BPF_FUNC_fib_lookup: > + return &bpf_skb_fib_lookup_proto; > #ifdef CONFIG_XFRM > case BPF_FUNC_skb_get_xfrm_state: > return &bpf_skb_get_xfrm_state_proto; > #endif > - case BPF_FUNC_fib_lookup: > - return &bpf_skb_fib_lookup_proto; > +#ifdef CONFIG_SOCK_CGROUP_DATA > + case BPF_FUNC_skb_cgroup_id: > + return &bpf_skb_cgroup_id_proto; > +#endif > default: > return bpf_base_func_proto(func_id); > } >