This patch adds a helper to handle jiffies. Some of the tcp_sock's timing is stored in jiffies. Although things could be deduced by CONFIG_HZ, having an easy way to get jiffies will make the later bpf-tcp-cc implementation easier. While at it, instead of reading jiffies alone, it also takes a "flags" argument to help converting between ns and jiffies. This helper is available to CAP_SYS_ADMIN. Signed-off-by: Martin KaFai Lau <kafai@xxxxxx> --- include/linux/bpf.h | 1 + include/uapi/linux/bpf.h | 16 +++++++++++++++- kernel/bpf/core.c | 1 + kernel/bpf/helpers.c | 25 +++++++++++++++++++++++++ net/core/filter.c | 2 ++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 349cedd7b97b..00491961421e 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1371,6 +1371,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto; extern const struct bpf_func_proto bpf_strtol_proto; extern const struct bpf_func_proto bpf_strtoul_proto; extern const struct bpf_func_proto bpf_tcp_sock_proto; +extern const struct bpf_func_proto bpf_jiffies_proto; /* Shared helpers among cBPF and eBPF. */ void bpf_user_rnd_init_once(void); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 602449a56dde..cf864a5f7d61 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2835,6 +2835,16 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. * + * u64 bpf_jiffies(u64 in, u64 flags) + * Description + * jiffies helper. + * Return + * *flags*: 0, return the current jiffies. + * BPF_F_NS_TO_JIFFIES, convert *in* from ns to jiffies. + * BPF_F_JIFFIES_TO_NS, convert *in* from jiffies to + * ns. If *in* is zero, it returns the current + * jiffies as ns. + * */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2953,7 +2963,8 @@ union bpf_attr { FN(probe_read_kernel), \ FN(probe_read_user_str), \ FN(probe_read_kernel_str), \ - FN(tcp_send_ack), + FN(tcp_send_ack), \ + FN(jiffies), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@ -3032,6 +3043,9 @@ enum bpf_func_id { /* BPF_FUNC_sk_storage_get flags */ #define BPF_SK_STORAGE_GET_F_CREATE (1ULL << 0) +#define BPF_F_NS_TO_JIFFIES (1ULL << 0) +#define BPF_F_JIFFIES_TO_NS (1ULL << 1) + /* Mode for BPF_FUNC_skb_adjust_room helper. */ enum bpf_adj_room_mode { BPF_ADJ_ROOM_NET, diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 2ff01a716128..0ffbda9a13e9 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2134,6 +2134,7 @@ const struct bpf_func_proto bpf_map_pop_elem_proto __weak; const struct bpf_func_proto bpf_map_peek_elem_proto __weak; const struct bpf_func_proto bpf_spin_lock_proto __weak; const struct bpf_func_proto bpf_spin_unlock_proto __weak; +const struct bpf_func_proto bpf_jiffies_proto __weak; const struct bpf_func_proto bpf_get_prandom_u32_proto __weak; const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak; diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index cada974c9f4e..e87c332d1b61 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -11,6 +11,7 @@ #include <linux/uidgid.h> #include <linux/filter.h> #include <linux/ctype.h> +#include <linux/jiffies.h> #include "../../lib/kstrtox.h" @@ -486,4 +487,28 @@ const struct bpf_func_proto bpf_strtoul_proto = { .arg3_type = ARG_ANYTHING, .arg4_type = ARG_PTR_TO_LONG, }; + +BPF_CALL_2(bpf_jiffies, u64, in, u64, flags) +{ + if (!flags) + return get_jiffies_64(); + + if (flags & BPF_F_NS_TO_JIFFIES) { + return nsecs_to_jiffies(in); + } else if (flags & BPF_F_JIFFIES_TO_NS) { + if (!in) + in = get_jiffies_64(); + return jiffies_to_nsecs(in); + } + + return 0; +} + +const struct bpf_func_proto bpf_jiffies_proto = { + .func = bpf_jiffies, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_ANYTHING, + .arg2_type = ARG_ANYTHING, +}; #endif diff --git a/net/core/filter.c b/net/core/filter.c index fbb3698026bd..355746715901 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -6015,6 +6015,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_spin_unlock_proto; case BPF_FUNC_trace_printk: return bpf_get_trace_printk_proto(); + case BPF_FUNC_jiffies: + return &bpf_jiffies_proto; default: return NULL; } -- 2.17.1