Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF
On 02/06/2017 03:17 AM, Chenbo Feng wrote: From: Chenbo FengRetrieve the socket cookie generated by sock_gen_cookie() from a sk_buff with a known socket. Generates a new cookie if one was not yet set.If the socket pointer inside sk_buff is NULL, 0 is returned. The helper function coud be useful in monitoring per socket networking traffic statistics and provide a unique socket identifier per namespace. Signed-off-by: Chenbo Feng [...] diff --git a/net/core/filter.c b/net/core/filter.c index 0b753cb..632fb91 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2599,6 +2600,18 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = { .arg5_type = ARG_CONST_SIZE, }; +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) +{ + return skb->sk ? sock_gen_cookie(skb->sk) : 0; +} + +static const struct bpf_func_proto bpf_get_socket_cookie_proto = { + .func = bpf_get_socket_cookie, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + static const struct bpf_func_proto * bpf_base_func_proto(enum bpf_func_id func_id) { @@ -2622,6 +2635,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) case BPF_FUNC_trace_printk: if (capable(CAP_SYS_ADMIN)) return bpf_get_trace_printk_proto(); + case BPF_FUNC_get_socket_cookie: + return _get_socket_cookie_proto; default: return NULL; } This still has one issue that would need to be addressed, otherwise looks good and ready to me. Issue is that it cannot be added to bpf_base_func_proto(), because that is also used by cg_sock_ops, which has struct sock as input instead of struct sk_buff. I suggest, we initially add this to both, sk_filter_func_proto() and tc_cls_act_func_proto() and, if needed, we could follow-up with other prog types at some later point in time. Otherwise, looks fine. diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 6b10573..acd2a6c 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); static DEFINE_MUTEX(sock_diag_table_mutex); static struct workqueue_struct *broadcast_wq; -static u64 sock_gen_cookie(struct sock *sk) +u64 sock_gen_cookie(struct sock *sk) { while (1) { u64 res = atomic64_read(>sk_cookie);
Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF
On Mon, 2017-02-06 at 12:01 +0900, Lorenzo Colitti wrote: > On Mon, Feb 6, 2017 at 11:17 AM, Chenbo Feng >wrote: > > +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) > > +{ > > + return skb->sk ? sock_gen_cookie(skb->sk) : 0; > > +} > > + > > Does this code need to increment the socket refcount, or call > ACCESS_ONCE to get skb->sk? The socket filter codepath should be safe, > but if this function is called in xt_ebpf, could it race with > something that sets skb->sk to null? I do not see how this could possibly happen. READ_ONCE() would not prevent the 'old' sk from disappearing anyway.
Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF
On Mon, Feb 6, 2017 at 11:17 AM, Chenbo Fengwrote: > +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) > +{ > + return skb->sk ? sock_gen_cookie(skb->sk) : 0; > +} > + Does this code need to increment the socket refcount, or call ACCESS_ONCE to get skb->sk? The socket filter codepath should be safe, but if this function is called in xt_ebpf, could it race with something that sets skb->sk to null?
Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF
On Sun, 2017-02-05 at 18:17 -0800, Chenbo Feng wrote: > From: Chenbo Feng> > Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff > with a known socket. Generates a new cookie if one was not yet set.If > the socket pointer inside sk_buff is NULL, 0 is returned. The helper > function coud be useful in monitoring per socket networking traffic > statistics and provide a unique socket identifier per namespace. > > Signed-off-by: Chenbo Feng > --- Acked-by: Eric Dumazet
[PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF
From: Chenbo FengRetrieve the socket cookie generated by sock_gen_cookie() from a sk_buff with a known socket. Generates a new cookie if one was not yet set.If the socket pointer inside sk_buff is NULL, 0 is returned. The helper function coud be useful in monitoring per socket networking traffic statistics and provide a unique socket identifier per namespace. Signed-off-by: Chenbo Feng --- include/linux/sock_diag.h | 1 + include/uapi/linux/bpf.h | 9 - net/core/filter.c | 15 +++ net/core/sock_diag.c | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index a0596ca0..a2f8109 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -24,6 +24,7 @@ void sock_diag_unregister(const struct sock_diag_handler *h); void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); +u64 sock_gen_cookie(struct sock *sk); int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie); void sock_diag_save_cookie(struct sock *sk, __u32 *cookie); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index e07fd5a..6923d21 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -449,6 +449,12 @@ union bpf_attr { * Return: * > 0 length of the string including the trailing NUL on success * < 0 error + * + * u64 bpf_bpf_get_socket_cookie(skb) + * Get the cookie for the socket stored inside sk_buff. + * @skb: pointer to skb + * Return: 8 Bytes non-decreasing number on success or 0 if the socket + * field is missing inside sk_buff */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -496,7 +502,8 @@ union bpf_attr { FN(get_numa_node_id), \ FN(skb_change_head),\ FN(xdp_adjust_head),\ - FN(probe_read_str), + FN(probe_read_str), \ + FN(get_socket_cookie), /* 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 0b753cb..632fb91 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2599,6 +2600,18 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = { .arg5_type = ARG_CONST_SIZE, }; +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) +{ + return skb->sk ? sock_gen_cookie(skb->sk) : 0; +} + +static const struct bpf_func_proto bpf_get_socket_cookie_proto = { + .func = bpf_get_socket_cookie, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + static const struct bpf_func_proto * bpf_base_func_proto(enum bpf_func_id func_id) { @@ -2622,6 +2635,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) case BPF_FUNC_trace_printk: if (capable(CAP_SYS_ADMIN)) return bpf_get_trace_printk_proto(); + case BPF_FUNC_get_socket_cookie: + return _get_socket_cookie_proto; default: return NULL; } diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 6b10573..acd2a6c 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); static DEFINE_MUTEX(sock_diag_table_mutex); static struct workqueue_struct *broadcast_wq; -static u64 sock_gen_cookie(struct sock *sk) +u64 sock_gen_cookie(struct sock *sk) { while (1) { u64 res = atomic64_read(>sk_cookie); -- 2.7.4