BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/4] expose number of map entries to userspace
@ 2025-01-06 14:53 Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 1/4] bpf: Add map_num_entries map op Charalampos Stylianopoulos
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-06 14:53 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Nick Zavaritsky,
	Charalampos Stylianopoulos

This patch series provides an easy way for userspace applications to
query the number of entries currently present in a map.

Currently, the number of entries in a map is accessible only from kernel space
and eBPF programs. A userspace program that wants to track map utilization has to
create and attach an eBPF program solely for that purpose.

This series makes the number of entries in a map easily accessible, by extending the
main bpf syscall with a new command. The command supports only maps that already
track utilization, namely hash maps, LPM maps and queue/stack maps.

Charalampos Stylianopoulos (4):
  bpf: Add map_num_entries map op
  bpf: Add bpf command to get number of map entries
  libbpf: Add support for MAP_GET_NUM_ENTRIES command
  selftests/bpf: Add tests for bpf_map_get_num_entries

 include/linux/bpf.h                           |  3 ++
 include/linux/bpf_local_storage.h             |  1 +
 include/uapi/linux/bpf.h                      | 17 +++++++++
 kernel/bpf/devmap.c                           | 14 ++++++++
 kernel/bpf/hashtab.c                          | 10 ++++++
 kernel/bpf/lpm_trie.c                         |  8 +++++
 kernel/bpf/queue_stack_maps.c                 | 11 +++++-
 kernel/bpf/syscall.c                          | 32 +++++++++++++++++
 tools/include/uapi/linux/bpf.h                | 17 +++++++++
 tools/lib/bpf/bpf.c                           | 16 +++++++++
 tools/lib/bpf/bpf.h                           |  2 ++
 tools/lib/bpf/libbpf.map                      |  1 +
 .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
 tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
 14 files changed, 171 insertions(+), 1 deletion(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next 1/4] bpf: Add map_num_entries map op
  2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
@ 2025-01-06 14:53 ` Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries Charalampos Stylianopoulos
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-06 14:53 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Nick Zavaritsky,
	Charalampos Stylianopoulos

This patch extends map operations with map_num_entries that returns the number of
entries currently present in the map. Provides implementation of the ops
for maps that track the number of elements added in them.

Co-developed-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Charalampos Stylianopoulos <charalampos.stylianopoulos@gmail.com>
---
 include/linux/bpf.h               |  3 +++
 include/linux/bpf_local_storage.h |  1 +
 kernel/bpf/devmap.c               | 14 ++++++++++++++
 kernel/bpf/hashtab.c              | 10 ++++++++++
 kernel/bpf/lpm_trie.c             |  8 ++++++++
 kernel/bpf/queue_stack_maps.c     | 11 ++++++++++-
 6 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index feda0ce90f5a..217260a8f5f4 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -175,6 +175,7 @@ struct bpf_map_ops {
 				     void *callback_ctx, u64 flags);
 
 	u64 (*map_mem_usage)(const struct bpf_map *map);
+	s64 (*map_num_entries)(const struct bpf_map *map);
 
 	/* BTF id of struct allocated by map_alloc */
 	int *map_btf_id;
@@ -2402,6 +2403,8 @@ static inline void bpf_map_dec_elem_count(struct bpf_map *map)
 	this_cpu_dec(*map->elem_count);
 }
 
+s64 bpf_map_sum_elem_count(const struct bpf_map *map);
+
 extern int sysctl_unprivileged_bpf_disabled;
 
 bool bpf_token_capable(const struct bpf_token *token, int cap);
diff --git a/include/linux/bpf_local_storage.h b/include/linux/bpf_local_storage.h
index ab7244d8108f..3a9e69e44c1d 100644
--- a/include/linux/bpf_local_storage.h
+++ b/include/linux/bpf_local_storage.h
@@ -204,5 +204,6 @@ bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap,
 			 void *value, u64 map_flags, bool swap_uptrs, gfp_t gfp_flags);
 
 u64 bpf_local_storage_map_mem_usage(const struct bpf_map *map);
+s64 bpf_local_storage_map_num_entries(const struct bpf_map *map);
 
 #endif /* _BPF_LOCAL_STORAGE_H */
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index 3aa002a47a96..f43a58389f8f 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -1041,6 +1041,18 @@ static u64 dev_map_mem_usage(const struct bpf_map *map)
 	return usage;
 }
 
+static s64 dev_map_num_entries(const struct bpf_map *map)
+{
+	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
+	s64 entries = 0;
+
+	if (map->map_type == BPF_MAP_TYPE_DEVMAP_HASH)
+		entries = atomic_read((atomic_t *)&dtab->items);
+	else
+		entries = -EOPNOTSUPP;
+	return entries;
+}
+
 BTF_ID_LIST_SINGLE(dev_map_btf_ids, struct, bpf_dtab)
 const struct bpf_map_ops dev_map_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -1053,6 +1065,7 @@ const struct bpf_map_ops dev_map_ops = {
 	.map_delete_elem = dev_map_delete_elem,
 	.map_check_btf = map_check_no_btf,
 	.map_mem_usage = dev_map_mem_usage,
+	.map_num_entries = dev_map_num_entries,
 	.map_btf_id = &dev_map_btf_ids[0],
 	.map_redirect = dev_map_redirect,
 };
@@ -1068,6 +1081,7 @@ const struct bpf_map_ops dev_map_hash_ops = {
 	.map_delete_elem = dev_map_hash_delete_elem,
 	.map_check_btf = map_check_no_btf,
 	.map_mem_usage = dev_map_mem_usage,
+	.map_num_entries = dev_map_num_entries,
 	.map_btf_id = &dev_map_btf_ids[0],
 	.map_redirect = dev_hash_map_redirect,
 };
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 3ec941a0ea41..769a4c33c81f 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -2287,6 +2287,11 @@ static u64 htab_map_mem_usage(const struct bpf_map *map)
 	return usage;
 }
 
+static s64 htab_map_num_entries(const struct bpf_map *map)
+{
+	return bpf_map_sum_elem_count(map);
+}
+
 BTF_ID_LIST_SINGLE(htab_map_btf_ids, struct, bpf_htab)
 const struct bpf_map_ops htab_map_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -2304,6 +2309,7 @@ const struct bpf_map_ops htab_map_ops = {
 	.map_set_for_each_callback_args = map_set_for_each_callback_args,
 	.map_for_each_callback = bpf_for_each_hash_elem,
 	.map_mem_usage = htab_map_mem_usage,
+	.map_num_entries = htab_map_num_entries,
 	BATCH_OPS(htab),
 	.map_btf_id = &htab_map_btf_ids[0],
 	.iter_seq_info = &iter_seq_info,
@@ -2326,6 +2332,7 @@ const struct bpf_map_ops htab_lru_map_ops = {
 	.map_set_for_each_callback_args = map_set_for_each_callback_args,
 	.map_for_each_callback = bpf_for_each_hash_elem,
 	.map_mem_usage = htab_map_mem_usage,
+	.map_num_entries = htab_map_num_entries,
 	BATCH_OPS(htab_lru),
 	.map_btf_id = &htab_map_btf_ids[0],
 	.iter_seq_info = &iter_seq_info,
@@ -2499,6 +2506,7 @@ const struct bpf_map_ops htab_percpu_map_ops = {
 	.map_set_for_each_callback_args = map_set_for_each_callback_args,
 	.map_for_each_callback = bpf_for_each_hash_elem,
 	.map_mem_usage = htab_map_mem_usage,
+	.map_num_entries = htab_map_num_entries,
 	BATCH_OPS(htab_percpu),
 	.map_btf_id = &htab_map_btf_ids[0],
 	.iter_seq_info = &iter_seq_info,
@@ -2519,6 +2527,7 @@ const struct bpf_map_ops htab_lru_percpu_map_ops = {
 	.map_set_for_each_callback_args = map_set_for_each_callback_args,
 	.map_for_each_callback = bpf_for_each_hash_elem,
 	.map_mem_usage = htab_map_mem_usage,
+	.map_num_entries = htab_map_num_entries,
 	BATCH_OPS(htab_lru_percpu),
 	.map_btf_id = &htab_map_btf_ids[0],
 	.iter_seq_info = &iter_seq_info,
@@ -2663,6 +2672,7 @@ const struct bpf_map_ops htab_of_maps_map_ops = {
 	.map_gen_lookup = htab_of_map_gen_lookup,
 	.map_check_btf = map_check_no_btf,
 	.map_mem_usage = htab_map_mem_usage,
+	.map_num_entries = htab_map_num_entries,
 	BATCH_OPS(htab),
 	.map_btf_id = &htab_map_btf_ids[0],
 };
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index f8bc1e096182..5297eb2e8e97 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -780,6 +780,13 @@ static u64 trie_mem_usage(const struct bpf_map *map)
 	return elem_size * READ_ONCE(trie->n_entries);
 }
 
+static s64 trie_num_entries(const struct bpf_map *map)
+{
+	struct lpm_trie *trie = container_of(map, struct lpm_trie, map);
+
+	return READ_ONCE(trie->n_entries);
+}
+
 BTF_ID_LIST_SINGLE(trie_map_btf_ids, struct, lpm_trie)
 const struct bpf_map_ops trie_map_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -794,5 +801,6 @@ const struct bpf_map_ops trie_map_ops = {
 	.map_delete_batch = generic_map_delete_batch,
 	.map_check_btf = trie_check_btf,
 	.map_mem_usage = trie_mem_usage,
+	.map_num_entries = trie_num_entries,
 	.map_btf_id = &trie_map_btf_ids[0],
 };
diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
index d869f51ea93a..f66aa31248e7 100644
--- a/kernel/bpf/queue_stack_maps.c
+++ b/kernel/bpf/queue_stack_maps.c
@@ -22,7 +22,7 @@ struct bpf_queue_stack {
 	char elements[] __aligned(8);
 };
 
-static struct bpf_queue_stack *bpf_queue_stack(struct bpf_map *map)
+static struct bpf_queue_stack *bpf_queue_stack(const struct bpf_map *map)
 {
 	return container_of(map, struct bpf_queue_stack, map);
 }
@@ -265,6 +265,13 @@ static u64 queue_stack_map_mem_usage(const struct bpf_map *map)
 	return usage;
 }
 
+static s64 queue_stack_map_num_entries(const struct bpf_map *map)
+{
+	struct bpf_queue_stack *qs = bpf_queue_stack(map);
+	s64 entries = qs->head - qs->tail;
+	return entries;
+}
+
 BTF_ID_LIST_SINGLE(queue_map_btf_ids, struct, bpf_queue_stack)
 const struct bpf_map_ops queue_map_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -279,6 +286,7 @@ const struct bpf_map_ops queue_map_ops = {
 	.map_peek_elem = queue_map_peek_elem,
 	.map_get_next_key = queue_stack_map_get_next_key,
 	.map_mem_usage = queue_stack_map_mem_usage,
+	.map_num_entries = queue_stack_map_num_entries,
 	.map_btf_id = &queue_map_btf_ids[0],
 };
 
@@ -295,5 +303,6 @@ const struct bpf_map_ops stack_map_ops = {
 	.map_peek_elem = stack_map_peek_elem,
 	.map_get_next_key = queue_stack_map_get_next_key,
 	.map_mem_usage = queue_stack_map_mem_usage,
+	.map_num_entries = queue_stack_map_num_entries,
 	.map_btf_id = &queue_map_btf_ids[0],
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries
  2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 1/4] bpf: Add map_num_entries map op Charalampos Stylianopoulos
@ 2025-01-06 14:53 ` Charalampos Stylianopoulos
  2025-01-07 17:52   ` kernel test robot
  2025-01-06 14:53 ` [PATCH bpf-next 3/4] libbpf: Add support for MAP_GET_NUM_ENTRIES command Charalampos Stylianopoulos
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-06 14:53 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Nick Zavaritsky,
	Charalampos Stylianopoulos

Introduces a new command to the main bpf syscall to return the number
of entries in a map. Returns EOPNOTSUPP if the relevant map operation
is not implemented.

Co-developed-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Charalampos Stylianopoulos <charalampos.stylianopoulos@gmail.com>
---
 include/uapi/linux/bpf.h | 17 +++++++++++++++++
 kernel/bpf/syscall.c     | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 2acf9b336371..f5c7adea1387 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -903,6 +903,17 @@ union bpf_iter_link_info {
  *		A new file descriptor (a nonnegative integer), or -1 if an
  *		error occurred (in which case, *errno* is set appropriately).
  *
+ * BPF_MAP_GET_NUM_ENTRIES
+ *	Description
+ *		Get the number of entries currently present in the map.
+ *
+ *		This operation is supported only for a subset of maps. If the
+ *		map is not supported, the operation returns **EOPNOTSUPP**.
+ *
+ *	Return
+ *		Returns zero on success. On error, -1 is returned and *errno*
+ *		is set appropriately.
+ *
  * NOTES
  *	eBPF objects (maps and programs) can be shared between processes.
  *
@@ -958,6 +969,7 @@ enum bpf_cmd {
 	BPF_LINK_DETACH,
 	BPF_PROG_BIND_MAP,
 	BPF_TOKEN_CREATE,
+	BPF_MAP_GET_NUM_ENTRIES,
 	__MAX_BPF_CMD,
 };
 
@@ -1837,6 +1849,11 @@ union bpf_attr {
 		__u32		bpffs_fd;
 	} token_create;
 
+	struct { /* struct used by BPF_MAP_GET_NUM_ENTRIES command*/
+		__u32 map_fd;
+		__u32 num_entries;
+	} map_get_num_entries;
+
 } __attribute__((aligned(8)));
 
 /* The description below is an attempt at providing documentation to eBPF
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 4e88797fdbeb..a31a63a4aa5d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5748,6 +5748,35 @@ static int token_create(union bpf_attr *attr)
 	return bpf_token_create(attr);
 }
 
+#define BPF_MAP_GET_NUM_ENTRIES_LAST_FIELD map_get_num_entries.num_entries
+
+static int bpf_get_num_entries(union bpf_attr *attr, union bpf_attr __user *uattr)
+{
+	__u32 num_entries = 0;
+	struct bpf_map *map;
+
+	if (CHECK_ATTR(BPF_MAP_GET_NUM_ENTRIES))
+		return -EINVAL;
+
+
+	CLASS(fd, f)(attr->map_fd);
+	map = __bpf_map_get(f);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	if (!map->ops->map_num_entries)
+		return -EOPNOTSUPP;
+
+	num_entries = map->ops->map_num_entries(map);
+	if (num_entries < 0)
+		return num_entries;
+
+	if (put_user(num_entries, &uattr->map_get_num_entries.num_entries))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
 {
 	union bpf_attr attr;
@@ -5884,6 +5913,9 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
 	case BPF_TOKEN_CREATE:
 		err = token_create(&attr);
 		break;
+	case BPF_MAP_GET_NUM_ENTRIES:
+		err = bpf_get_num_entries(&attr, uattr.user);
+		break;
 	default:
 		err = -EINVAL;
 		break;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH bpf-next 3/4] libbpf: Add support for MAP_GET_NUM_ENTRIES command
  2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 1/4] bpf: Add map_num_entries map op Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries Charalampos Stylianopoulos
@ 2025-01-06 14:53 ` Charalampos Stylianopoulos
  2025-01-06 14:53 ` [PATCH bpf-next 4/4] selftests/bpf: Add tests for bpf_map_get_num_entries Charalampos Stylianopoulos
  2025-01-06 16:19 ` [PATCH bpf-next 0/4] expose number of map entries to userspace Daniel Borkmann
  4 siblings, 0 replies; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-06 14:53 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Nick Zavaritsky,
	Charalampos Stylianopoulos

Extend the libbpf API to provide support for getting the number of
entries in a map.

Co-developed-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Charalampos Stylianopoulos <charalampos.stylianopoulos@gmail.com>
---
 tools/include/uapi/linux/bpf.h | 17 +++++++++++++++++
 tools/lib/bpf/bpf.c            | 16 ++++++++++++++++
 tools/lib/bpf/bpf.h            |  2 ++
 tools/lib/bpf/libbpf.map       |  1 +
 4 files changed, 36 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 2acf9b336371..f5c7adea1387 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -903,6 +903,17 @@ union bpf_iter_link_info {
  *		A new file descriptor (a nonnegative integer), or -1 if an
  *		error occurred (in which case, *errno* is set appropriately).
  *
+ * BPF_MAP_GET_NUM_ENTRIES
+ *	Description
+ *		Get the number of entries currently present in the map.
+ *
+ *		This operation is supported only for a subset of maps. If the
+ *		map is not supported, the operation returns **EOPNOTSUPP**.
+ *
+ *	Return
+ *		Returns zero on success. On error, -1 is returned and *errno*
+ *		is set appropriately.
+ *
  * NOTES
  *	eBPF objects (maps and programs) can be shared between processes.
  *
@@ -958,6 +969,7 @@ enum bpf_cmd {
 	BPF_LINK_DETACH,
 	BPF_PROG_BIND_MAP,
 	BPF_TOKEN_CREATE,
+	BPF_MAP_GET_NUM_ENTRIES,
 	__MAX_BPF_CMD,
 };
 
@@ -1837,6 +1849,11 @@ union bpf_attr {
 		__u32		bpffs_fd;
 	} token_create;
 
+	struct { /* struct used by BPF_MAP_GET_NUM_ENTRIES command*/
+		__u32 map_fd;
+		__u32 num_entries;
+	} map_get_num_entries;
+
 } __attribute__((aligned(8)));
 
 /* The description below is an attempt at providing documentation to eBPF
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 359f73ead613..c91f43690624 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -1330,3 +1330,19 @@ int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts)
 	fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz);
 	return libbpf_err_errno(fd);
 }
+
+int bpf_map_get_num_entries(int fd, unsigned int *num_entries)
+{
+	const size_t attr_sz = offsetofend(union bpf_attr, map_get_num_entries);
+	union bpf_attr attr;
+	int ret;
+
+	memset(&attr, 0, attr_sz);
+	attr.map_get_num_entries.map_fd = fd;
+
+	ret = sys_bpf(BPF_MAP_GET_NUM_ENTRIES, &attr, attr_sz);
+	if (!ret)
+		*num_entries = attr.map_get_num_entries.num_entries;
+
+	return libbpf_err_errno(ret);
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 435da95d2058..efa5a092acc9 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -653,6 +653,8 @@ struct bpf_prog_bind_opts {
 LIBBPF_API int bpf_prog_bind_map(int prog_fd, int map_fd,
 				 const struct bpf_prog_bind_opts *opts);
 
+LIBBPF_API int bpf_map_get_num_entries(int fd, unsigned int *num_entries);
+
 struct bpf_test_run_opts {
 	size_t sz; /* size of this struct for forward/backward compatibility */
 	const void *data_in; /* optional */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index a8b2936a1646..63dbad55cc2d 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -436,4 +436,5 @@ LIBBPF_1.6.0 {
 		bpf_linker__add_buf;
 		bpf_linker__add_fd;
 		bpf_linker__new_fd;
+		bpf_map_get_num_entries;
 } LIBBPF_1.5.0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH bpf-next 4/4] selftests/bpf: Add tests for bpf_map_get_num_entries
  2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
                   ` (2 preceding siblings ...)
  2025-01-06 14:53 ` [PATCH bpf-next 3/4] libbpf: Add support for MAP_GET_NUM_ENTRIES command Charalampos Stylianopoulos
@ 2025-01-06 14:53 ` Charalampos Stylianopoulos
  2025-01-06 16:19 ` [PATCH bpf-next 0/4] expose number of map entries to userspace Daniel Borkmann
  4 siblings, 0 replies; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-06 14:53 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Nick Zavaritsky,
	Charalampos Stylianopoulos

Extend the existing selftests for maps with checks that the number of
map entries returned by bpf_map_get_num_entries is as expected.

Co-developed-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Nick Zavaritsky <mejedi@gmail.com>
Signed-off-by: Charalampos Stylianopoulos <charalampos.stylianopoulos@gmail.com>
---
 .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
 tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c
index d32e4edac930..40265b497791 100644
--- a/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c
+++ b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c
@@ -434,6 +434,11 @@ static void test_lpm_ipaddr(void)
 	inet_pton(AF_INET6, "2a00:ffff::", key_ipv6->data);
 	assert(bpf_map_lookup_elem(map_fd_ipv6, key_ipv6, &value) == -ENOENT);
 
+	unsigned int entries;
+	/* Check that the reported number of entries in the map is as expected. */
+	assert(bpf_map_get_num_entries(map_fd_ipv4, &entries) == 0 && entries == 5);
+	assert(bpf_map_get_num_entries(map_fd_ipv6, &entries) == 0 && entries == 1);
+
 	close(map_fd_ipv4);
 	close(map_fd_ipv6);
 }
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 8b40e9496af1..c61cf740a6b6 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -109,6 +109,10 @@ static void test_hashmap(unsigned int task, void *data)
 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 &&
 	       errno == ENOENT);
 
+	unsigned int entries;
+	/* Check that the number of entries in the map is 2. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 2);
+
 	/* Delete both elements. */
 	key = 1;
 	assert(bpf_map_delete_elem(fd, &key) == 0);
@@ -122,6 +126,7 @@ static void test_hashmap(unsigned int task, void *data)
 	       errno == ENOENT);
 	assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 &&
 	       errno == ENOENT);
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
 
 	close(fd);
 }
@@ -243,6 +248,11 @@ static void test_hashmap_percpu(unsigned int task, void *data)
 	key = 1;
 	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
 
+
+	unsigned int entries;
+	/* Check that the number of entries in the map is 2. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 2);
+
 	/* Delete both elements. */
 	key = 1;
 	assert(bpf_map_delete_elem(fd, &key) == 0);
@@ -256,6 +266,7 @@ static void test_hashmap_percpu(unsigned int task, void *data)
 	       errno == ENOENT);
 	assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 &&
 	       errno == ENOENT);
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
 
 	close(fd);
 }
@@ -529,6 +540,10 @@ static void test_devmap_hash(unsigned int task, void *data)
 		exit(1);
 	}
 
+	unsigned int entries;
+	/* Check that the number of entries in the map is 0. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
+
 	close(fd);
 }
 
@@ -557,10 +572,17 @@ static void test_queuemap(unsigned int task, void *data)
 		exit(1);
 	}
 
+	unsigned int entries;
+	/* Check that the number of entries in the map is 0. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
+
 	/* Push MAP_SIZE elements */
 	for (i = 0; i < MAP_SIZE; i++)
 		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
 
+	/* Check that the number of entries in the map is MAP_SIZE. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == MAP_SIZE);
+
 	/* Check that element cannot be pushed due to max_entries limit */
 	assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 &&
 	       errno == E2BIG);
@@ -581,6 +603,9 @@ static void test_queuemap(unsigned int task, void *data)
 	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 &&
 	       errno == ENOENT);
 
+	/* Check that the number of entries in the map is 0. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
+
 	/* Check that non supported functions set errno to EINVAL */
 	assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL);
 	assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL);
@@ -613,10 +638,17 @@ static void test_stackmap(unsigned int task, void *data)
 		exit(1);
 	}
 
+	unsigned int entries;
+	/* Check that the number of entries in the map is 0. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
+
 	/* Push MAP_SIZE elements */
 	for (i = 0; i < MAP_SIZE; i++)
 		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
 
+	/* Check that the number of entries in the map is MAP_SIZE. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == MAP_SIZE);
+
 	/* Check that element cannot be pushed due to max_entries limit */
 	assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 &&
 	       errno == E2BIG);
@@ -637,6 +669,9 @@ static void test_stackmap(unsigned int task, void *data)
 	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 &&
 	       errno == ENOENT);
 
+	/* Check that the number of entries in the map is 0. */
+	assert(bpf_map_get_num_entries(fd, &entries) == 0 && entries == 0);
+
 	/* Check that non supported functions set errno to EINVAL */
 	assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL);
 	assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
                   ` (3 preceding siblings ...)
  2025-01-06 14:53 ` [PATCH bpf-next 4/4] selftests/bpf: Add tests for bpf_map_get_num_entries Charalampos Stylianopoulos
@ 2025-01-06 16:19 ` Daniel Borkmann
  2025-01-07  7:43   ` Anton Protopopov
  2025-01-07  7:48   ` Anton Protopopov
  4 siblings, 2 replies; 15+ messages in thread
From: Daniel Borkmann @ 2025-01-06 16:19 UTC (permalink / raw)
  To: Charalampos Stylianopoulos, bpf
  Cc: Alexei Starovoitov, Nick Zavaritsky, aspsk2

On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> This patch series provides an easy way for userspace applications to
> query the number of entries currently present in a map.
> 
> Currently, the number of entries in a map is accessible only from kernel space
> and eBPF programs. A userspace program that wants to track map utilization has to
> create and attach an eBPF program solely for that purpose.
> 
> This series makes the number of entries in a map easily accessible, by extending the
> main bpf syscall with a new command. The command supports only maps that already
> track utilization, namely hash maps, LPM maps and queue/stack maps.

An earlier attempt to directly expose it to user space can be found here [0], which
eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
extending UAPI.

Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
bpf_map__max_entries) which does all the work to extract that info via [1] underneath?

Thanks,
Daniel

   [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
   [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
       https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/

> Charalampos Stylianopoulos (4):
>    bpf: Add map_num_entries map op
>    bpf: Add bpf command to get number of map entries
>    libbpf: Add support for MAP_GET_NUM_ENTRIES command
>    selftests/bpf: Add tests for bpf_map_get_num_entries
> 
>   include/linux/bpf.h                           |  3 ++
>   include/linux/bpf_local_storage.h             |  1 +
>   include/uapi/linux/bpf.h                      | 17 +++++++++
>   kernel/bpf/devmap.c                           | 14 ++++++++
>   kernel/bpf/hashtab.c                          | 10 ++++++
>   kernel/bpf/lpm_trie.c                         |  8 +++++
>   kernel/bpf/queue_stack_maps.c                 | 11 +++++-
>   kernel/bpf/syscall.c                          | 32 +++++++++++++++++
>   tools/include/uapi/linux/bpf.h                | 17 +++++++++
>   tools/lib/bpf/bpf.c                           | 16 +++++++++
>   tools/lib/bpf/bpf.h                           |  2 ++
>   tools/lib/bpf/libbpf.map                      |  1 +
>   .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
>   tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
>   14 files changed, 171 insertions(+), 1 deletion(-)
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-06 16:19 ` [PATCH bpf-next 0/4] expose number of map entries to userspace Daniel Borkmann
@ 2025-01-07  7:43   ` Anton Protopopov
  2025-01-07  7:48   ` Anton Protopopov
  1 sibling, 0 replies; 15+ messages in thread
From: Anton Protopopov @ 2025-01-07  7:43 UTC (permalink / raw)
  To: Charalampos Stylianopoulos
  Cc: Charalampos Stylianopoulos, bpf, Alexei Starovoitov,
	Nick Zavaritsky, aspsk2

On 25/01/06 05:19PM, Daniel Borkmann wrote:
> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> > This patch series provides an easy way for userspace applications to
> > query the number of entries currently present in a map.
> > 
> > Currently, the number of entries in a map is accessible only from kernel space
> > and eBPF programs. A userspace program that wants to track map utilization has to
> > create and attach an eBPF program solely for that purpose.
> > 
> > This series makes the number of entries in a map easily accessible, by extending the
> > main bpf syscall with a new command. The command supports only maps that already
> > track utilization, namely hash maps, LPM maps and queue/stack maps.
> 
> An earlier attempt to directly expose it to user space can be found here [0], which
> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
> extending UAPI.

Yes, see the bpf_map_sum_elem_count() kfunc in the
kernel/bpf/map_iter.c file, and the links posted by Daniel.

> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
>
> Thanks,
> Daniel
> 
>   [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
>   [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
>       https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
> 
> > Charalampos Stylianopoulos (4):
> >    bpf: Add map_num_entries map op
> >    bpf: Add bpf command to get number of map entries
> >    libbpf: Add support for MAP_GET_NUM_ENTRIES command
> >    selftests/bpf: Add tests for bpf_map_get_num_entries
> > 
> >   include/linux/bpf.h                           |  3 ++
> >   include/linux/bpf_local_storage.h             |  1 +
> >   include/uapi/linux/bpf.h                      | 17 +++++++++
> >   kernel/bpf/devmap.c                           | 14 ++++++++
> >   kernel/bpf/hashtab.c                          | 10 ++++++
> >   kernel/bpf/lpm_trie.c                         |  8 +++++
> >   kernel/bpf/queue_stack_maps.c                 | 11 +++++-
> >   kernel/bpf/syscall.c                          | 32 +++++++++++++++++
> >   tools/include/uapi/linux/bpf.h                | 17 +++++++++
> >   tools/lib/bpf/bpf.c                           | 16 +++++++++
> >   tools/lib/bpf/bpf.h                           |  2 ++
> >   tools/lib/bpf/libbpf.map                      |  1 +
> >   .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
> >   tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
> >   14 files changed, 171 insertions(+), 1 deletion(-)
> > 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-06 16:19 ` [PATCH bpf-next 0/4] expose number of map entries to userspace Daniel Borkmann
  2025-01-07  7:43   ` Anton Protopopov
@ 2025-01-07  7:48   ` Anton Protopopov
       [not found]     ` <CAAvdH+yNG=GefEd5CcP_52gPzzZexWMMxFAxnM3isX04iErMfQ@mail.gmail.com>
  1 sibling, 1 reply; 15+ messages in thread
From: Anton Protopopov @ 2025-01-07  7:48 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Charalampos Stylianopoulos, bpf, Alexei Starovoitov,
	Nick Zavaritsky, aspsk2

On 25/01/06 05:19PM, Daniel Borkmann wrote:
> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> > This patch series provides an easy way for userspace applications to
> > query the number of entries currently present in a map.
> > 
> > Currently, the number of entries in a map is accessible only from kernel space
> > and eBPF programs. A userspace program that wants to track map utilization has to
> > create and attach an eBPF program solely for that purpose.
> > 
> > This series makes the number of entries in a map easily accessible, by extending the
> > main bpf syscall with a new command. The command supports only maps that already
> > track utilization, namely hash maps, LPM maps and queue/stack maps.
> 
> An earlier attempt to directly expose it to user space can be found here [0], which
> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
> extending UAPI.
> 
> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?

One small thingy here is that bpf_map_sum_elem_count() is only
available from the map iterator. Which means that to get the
bpf_map_sum_elem_count() for one map only, one have to iterate
through the whole set of maps (and filter out all but one).

I wanted to follow up my series by either adding the result of
calling bpf_map_sum_elem_count() to map_info as u32 or to add
possibility to provide a map_fd/map_id when creating an iterator
(so that it is only called for one map). But so far I haven't
a real use case for getting the number of elements for one map only.

> Thanks,
> Daniel
> 
>   [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
>   [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
>       https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
> 
> > Charalampos Stylianopoulos (4):
> >    bpf: Add map_num_entries map op
> >    bpf: Add bpf command to get number of map entries
> >    libbpf: Add support for MAP_GET_NUM_ENTRIES command
> >    selftests/bpf: Add tests for bpf_map_get_num_entries
> > 
> >   include/linux/bpf.h                           |  3 ++
> >   include/linux/bpf_local_storage.h             |  1 +
> >   include/uapi/linux/bpf.h                      | 17 +++++++++
> >   kernel/bpf/devmap.c                           | 14 ++++++++
> >   kernel/bpf/hashtab.c                          | 10 ++++++
> >   kernel/bpf/lpm_trie.c                         |  8 +++++
> >   kernel/bpf/queue_stack_maps.c                 | 11 +++++-
> >   kernel/bpf/syscall.c                          | 32 +++++++++++++++++
> >   tools/include/uapi/linux/bpf.h                | 17 +++++++++
> >   tools/lib/bpf/bpf.c                           | 16 +++++++++
> >   tools/lib/bpf/bpf.h                           |  2 ++
> >   tools/lib/bpf/libbpf.map                      |  1 +
> >   .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
> >   tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
> >   14 files changed, 171 insertions(+), 1 deletion(-)
> > 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
       [not found]     ` <CAAvdH+yNG=GefEd5CcP_52gPzzZexWMMxFAxnM3isX04iErMfQ@mail.gmail.com>
@ 2025-01-07 11:10       ` Charalampos Stylianopoulos
  2025-01-09 17:37         ` Anton Protopopov
  0 siblings, 1 reply; 15+ messages in thread
From: Charalampos Stylianopoulos @ 2025-01-07 11:10 UTC (permalink / raw)
  To: Anton Protopopov
  Cc: Daniel Borkmann, bpf, Alexei Starovoitov, Nick Zavaritsky, aspsk2

(sorry for double posting, this time in plain text)
Thanks a lot for the feedback!

So, to double check, the suggestion is to only extend the libbpf API
with a new helper that does pretty much what get_cur_elements() does
in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?

> On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
>>
>> On 25/01/06 05:19PM, Daniel Borkmann wrote:
>> > On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
>> > > This patch series provides an easy way for userspace applications to
>> > > query the number of entries currently present in a map.
>> > >
>> > > Currently, the number of entries in a map is accessible only from kernel space
>> > > and eBPF programs. A userspace program that wants to track map utilization has to
>> > > create and attach an eBPF program solely for that purpose.
>> > >
>> > > This series makes the number of entries in a map easily accessible, by extending the
>> > > main bpf syscall with a new command. The command supports only maps that already
>> > > track utilization, namely hash maps, LPM maps and queue/stack maps.
>> >
>> > An earlier attempt to directly expose it to user space can be found here [0], which
>> > eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
>> > extending UAPI.
>> >
>> > Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
>> > bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
>>
>> One small thingy here is that bpf_map_sum_elem_count() is only
>> available from the map iterator. Which means that to get the
>> bpf_map_sum_elem_count() for one map only, one have to iterate
>> through the whole set of maps (and filter out all but one).
>>
>> I wanted to follow up my series by either adding the result of
>> calling bpf_map_sum_elem_count() to map_info as u32 or to add
>> possibility to provide a map_fd/map_id when creating an iterator
>> (so that it is only called for one map). But so far I haven't
>> a real use case for getting the number of elements for one map only.
>>
>> > Thanks,
>> > Daniel
>> >
>> >   [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
>> >   [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
>> >       https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
>> >
>> > > Charalampos Stylianopoulos (4):
>> > >    bpf: Add map_num_entries map op
>> > >    bpf: Add bpf command to get number of map entries
>> > >    libbpf: Add support for MAP_GET_NUM_ENTRIES command
>> > >    selftests/bpf: Add tests for bpf_map_get_num_entries
>> > >
>> > >   include/linux/bpf.h                           |  3 ++
>> > >   include/linux/bpf_local_storage.h             |  1 +
>> > >   include/uapi/linux/bpf.h                      | 17 +++++++++
>> > >   kernel/bpf/devmap.c                           | 14 ++++++++
>> > >   kernel/bpf/hashtab.c                          | 10 ++++++
>> > >   kernel/bpf/lpm_trie.c                         |  8 +++++
>> > >   kernel/bpf/queue_stack_maps.c                 | 11 +++++-
>> > >   kernel/bpf/syscall.c                          | 32 +++++++++++++++++
>> > >   tools/include/uapi/linux/bpf.h                | 17 +++++++++
>> > >   tools/lib/bpf/bpf.c                           | 16 +++++++++
>> > >   tools/lib/bpf/bpf.h                           |  2 ++
>> > >   tools/lib/bpf/libbpf.map                      |  1 +
>> > >   .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
>> > >   tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
>> > >   14 files changed, 171 insertions(+), 1 deletion(-)
>> > >
>> >

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries
  2025-01-06 14:53 ` [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries Charalampos Stylianopoulos
@ 2025-01-07 17:52   ` kernel test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2025-01-07 17:52 UTC (permalink / raw)
  To: Charalampos Stylianopoulos, bpf
  Cc: oe-kbuild-all, Alexei Starovoitov, Daniel Borkmann,
	Nick Zavaritsky, Charalampos Stylianopoulos

Hi Charalampos,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Charalampos-Stylianopoulos/bpf-Add-map_num_entries-map-op/20250106-225520
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20250106145328.399610-3-charalampos.stylianopoulos%40gmail.com
patch subject: [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries
config: nios2-randconfig-r072-20250107 (https://download.01.org/0day-ci/archive/20250108/202501080123.MlvmZO4I-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 14.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501080123.MlvmZO4I-lkp@intel.com/

New smatch warnings:
kernel/bpf/syscall.c:5771 bpf_get_num_entries() warn: unsigned 'num_entries' is never less than zero.

Old smatch warnings:
arch/nios2/include/asm/thread_info.h:62 current_thread_info() error: uninitialized symbol 'sp'.

vim +/num_entries +5771 kernel/bpf/syscall.c

  5752	
  5753	static int bpf_get_num_entries(union bpf_attr *attr, union bpf_attr __user *uattr)
  5754	{
  5755		__u32 num_entries = 0;
  5756		struct bpf_map *map;
  5757	
  5758		if (CHECK_ATTR(BPF_MAP_GET_NUM_ENTRIES))
  5759			return -EINVAL;
  5760	
  5761	
  5762		CLASS(fd, f)(attr->map_fd);
  5763		map = __bpf_map_get(f);
  5764		if (IS_ERR(map))
  5765			return PTR_ERR(map);
  5766	
  5767		if (!map->ops->map_num_entries)
  5768			return -EOPNOTSUPP;
  5769	
  5770		num_entries = map->ops->map_num_entries(map);
> 5771		if (num_entries < 0)
  5772			return num_entries;
  5773	
  5774		if (put_user(num_entries, &uattr->map_get_num_entries.num_entries))
  5775			return -EFAULT;
  5776	
  5777		return 0;
  5778	}
  5779	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-07 11:10       ` Charalampos Stylianopoulos
@ 2025-01-09 17:37         ` Anton Protopopov
  2025-01-14 11:38           ` Nick Zavaritsky
  0 siblings, 1 reply; 15+ messages in thread
From: Anton Protopopov @ 2025-01-09 17:37 UTC (permalink / raw)
  To: Charalampos Stylianopoulos
  Cc: Daniel Borkmann, bpf, Alexei Starovoitov, Nick Zavaritsky, aspsk2

On 25/01/07 12:10PM, Charalampos Stylianopoulos wrote:
> (sorry for double posting, this time in plain text)
> Thanks a lot for the feedback!
> 
> So, to double check, the suggestion is to only extend the libbpf API
> with a new helper that does pretty much what get_cur_elements() does
> in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?

What is your use case for getting the number of elements in a
particular map? Will it work for you to just use a variant of
get_cur_elements() from selftests vs. adding new API to libbpf?

[Also, please try not to top-post, see https://www.idallen.com/topposting.html]

> > On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
> >>
> >> On 25/01/06 05:19PM, Daniel Borkmann wrote:
> >> > On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> >> > > This patch series provides an easy way for userspace applications to
> >> > > query the number of entries currently present in a map.
> >> > >
> >> > > Currently, the number of entries in a map is accessible only from kernel space
> >> > > and eBPF programs. A userspace program that wants to track map utilization has to
> >> > > create and attach an eBPF program solely for that purpose.
> >> > >
> >> > > This series makes the number of entries in a map easily accessible, by extending the
> >> > > main bpf syscall with a new command. The command supports only maps that already
> >> > > track utilization, namely hash maps, LPM maps and queue/stack maps.
> >> >
> >> > An earlier attempt to directly expose it to user space can be found here [0], which
> >> > eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
> >> > extending UAPI.
> >> >
> >> > Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
> >> > bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
> >>
> >> One small thingy here is that bpf_map_sum_elem_count() is only
> >> available from the map iterator. Which means that to get the
> >> bpf_map_sum_elem_count() for one map only, one have to iterate
> >> through the whole set of maps (and filter out all but one).
> >>
> >> I wanted to follow up my series by either adding the result of
> >> calling bpf_map_sum_elem_count() to map_info as u32 or to add
> >> possibility to provide a map_fd/map_id when creating an iterator
> >> (so that it is only called for one map). But so far I haven't
> >> a real use case for getting the number of elements for one map only.
> >>
> >> > Thanks,
> >> > Daniel
> >> >
> >> >   [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
> >> >   [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
> >> >       https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
> >> >
> >> > > Charalampos Stylianopoulos (4):
> >> > >    bpf: Add map_num_entries map op
> >> > >    bpf: Add bpf command to get number of map entries
> >> > >    libbpf: Add support for MAP_GET_NUM_ENTRIES command
> >> > >    selftests/bpf: Add tests for bpf_map_get_num_entries
> >> > >
> >> > >   include/linux/bpf.h                           |  3 ++
> >> > >   include/linux/bpf_local_storage.h             |  1 +
> >> > >   include/uapi/linux/bpf.h                      | 17 +++++++++
> >> > >   kernel/bpf/devmap.c                           | 14 ++++++++
> >> > >   kernel/bpf/hashtab.c                          | 10 ++++++
> >> > >   kernel/bpf/lpm_trie.c                         |  8 +++++
> >> > >   kernel/bpf/queue_stack_maps.c                 | 11 +++++-
> >> > >   kernel/bpf/syscall.c                          | 32 +++++++++++++++++
> >> > >   tools/include/uapi/linux/bpf.h                | 17 +++++++++
> >> > >   tools/lib/bpf/bpf.c                           | 16 +++++++++
> >> > >   tools/lib/bpf/bpf.h                           |  2 ++
> >> > >   tools/lib/bpf/libbpf.map                      |  1 +
> >> > >   .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
> >> > >   tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
> >> > >   14 files changed, 171 insertions(+), 1 deletion(-)
> >> > >
> >> >

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-09 17:37         ` Anton Protopopov
@ 2025-01-14 11:38           ` Nick Zavaritsky
  2025-01-16 14:59             ` Anton Protopopov
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Zavaritsky @ 2025-01-14 11:38 UTC (permalink / raw)
  To: Anton Protopopov
  Cc: Charalampos Stylianopoulos, Daniel Borkmann, bpf,
	Alexei Starovoitov, aspsk2


> On 9. Jan 2025, at 18:37, Anton Protopopov <aspsk@isovalent.com> wrote:
> 
> On 25/01/07 12:10PM, Charalampos Stylianopoulos wrote:
>> (sorry for double posting, this time in plain text)
>> Thanks a lot for the feedback!
>> 
>> So, to double check, the suggestion is to only extend the libbpf API
>> with a new helper that does pretty much what get_cur_elements() does
>> in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?
> 
> What is your use case for getting the number of elements in a
> particular map? Will it work for you to just use a variant of
> get_cur_elements() from selftests vs. adding new API to libbpf?

(On behalf of Charalampos Stylianopoulos) we would like to get the
number of elements in some maps for monitoring purposes. The end goal is
to get someone paged when a fixed-capacity map is about to start
rejecting inserts.

We aim to operate a large number of apps in containers (custom packet
processing services, telekom). We find it most convenient for an app
itself to expose metrics concerning the maps it has created.

We currently use a map iterator and a bunch of bpf_probe_read_kernel. We
foresee the number of maps in our systems getting significantly higher
in the near future. Therefore enumerating every map in the system to get
a number of elements in a particular map doesn't look sustainable.

How do you feel about introducing bpf_map_sum_elem_count_by_fd kfunc,
available in syscall programs?


> 
> [Also, please try not to top-post, see https://www.idallen.com/topposting.html]
> 
>>> On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
>>>> 
>>>> On 25/01/06 05:19PM, Daniel Borkmann wrote:
>>>>> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
>>>>>> This patch series provides an easy way for userspace applications to
>>>>>> query the number of entries currently present in a map.
>>>>>> 
>>>>>> Currently, the number of entries in a map is accessible only from kernel space
>>>>>> and eBPF programs. A userspace program that wants to track map utilization has to
>>>>>> create and attach an eBPF program solely for that purpose.
>>>>>> 
>>>>>> This series makes the number of entries in a map easily accessible, by extending the
>>>>>> main bpf syscall with a new command. The command supports only maps that already
>>>>>> track utilization, namely hash maps, LPM maps and queue/stack maps.
>>>>> 
>>>>> An earlier attempt to directly expose it to user space can be found here [0], which
>>>>> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
>>>>> extending UAPI.
>>>>> 
>>>>> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
>>>>> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
>>>> 
>>>> One small thingy here is that bpf_map_sum_elem_count() is only
>>>> available from the map iterator. Which means that to get the
>>>> bpf_map_sum_elem_count() for one map only, one have to iterate
>>>> through the whole set of maps (and filter out all but one).
>>>> 
>>>> I wanted to follow up my series by either adding the result of
>>>> calling bpf_map_sum_elem_count() to map_info as u32 or to add
>>>> possibility to provide a map_fd/map_id when creating an iterator
>>>> (so that it is only called for one map). But so far I haven't
>>>> a real use case for getting the number of elements for one map only.
>>>> 
>>>>> Thanks,
>>>>> Daniel
>>>>> 
>>>>>  [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
>>>>>  [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
>>>>>      https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
>>>>> 
>>>>>> Charalampos Stylianopoulos (4):
>>>>>>   bpf: Add map_num_entries map op
>>>>>>   bpf: Add bpf command to get number of map entries
>>>>>>   libbpf: Add support for MAP_GET_NUM_ENTRIES command
>>>>>>   selftests/bpf: Add tests for bpf_map_get_num_entries
>>>>>> 
>>>>>>  include/linux/bpf.h                           |  3 ++
>>>>>>  include/linux/bpf_local_storage.h             |  1 +
>>>>>>  include/uapi/linux/bpf.h                      | 17 +++++++++
>>>>>>  kernel/bpf/devmap.c                           | 14 ++++++++
>>>>>>  kernel/bpf/hashtab.c                          | 10 ++++++
>>>>>>  kernel/bpf/lpm_trie.c                         |  8 +++++
>>>>>>  kernel/bpf/queue_stack_maps.c                 | 11 +++++-
>>>>>>  kernel/bpf/syscall.c                          | 32 +++++++++++++++++
>>>>>>  tools/include/uapi/linux/bpf.h                | 17 +++++++++
>>>>>>  tools/lib/bpf/bpf.c                           | 16 +++++++++
>>>>>>  tools/lib/bpf/bpf.h                           |  2 ++
>>>>>>  tools/lib/bpf/libbpf.map                      |  1 +
>>>>>>  .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
>>>>>>  tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
>>>>>>  14 files changed, 171 insertions(+), 1 deletion(-)
>>>>>> 
>>>>> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-14 11:38           ` Nick Zavaritsky
@ 2025-01-16 14:59             ` Anton Protopopov
  2025-01-16 17:52               ` Nick Zavaritsky
  0 siblings, 1 reply; 15+ messages in thread
From: Anton Protopopov @ 2025-01-16 14:59 UTC (permalink / raw)
  To: Nick Zavaritsky
  Cc: Charalampos Stylianopoulos, Daniel Borkmann, bpf,
	Alexei Starovoitov, aspsk2

On 25/01/14 12:38PM, Nick Zavaritsky wrote:
> 
> > On 9. Jan 2025, at 18:37, Anton Protopopov <aspsk@isovalent.com> wrote:
> > 
> > On 25/01/07 12:10PM, Charalampos Stylianopoulos wrote:
> >> (sorry for double posting, this time in plain text)
> >> Thanks a lot for the feedback!
> >> 
> >> So, to double check, the suggestion is to only extend the libbpf API
> >> with a new helper that does pretty much what get_cur_elements() does
> >> in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?
> > 
> > What is your use case for getting the number of elements in a
> > particular map? Will it work for you to just use a variant of
> > get_cur_elements() from selftests vs. adding new API to libbpf?
> 
> (On behalf of Charalampos Stylianopoulos) we would like to get the
> number of elements in some maps for monitoring purposes. The end goal is
> to get someone paged when a fixed-capacity map is about to start
> rejecting inserts.
> 
> We aim to operate a large number of apps in containers (custom packet
> processing services, telekom). We find it most convenient for an app
> itself to expose metrics concerning the maps it has created.
> 
> We currently use a map iterator and a bunch of bpf_probe_read_kernel. We
> foresee the number of maps in our systems getting significantly higher
> in the near future. Therefore enumerating every map in the system to get
> a number of elements in a particular map doesn't look sustainable.
> 
> How do you feel about introducing bpf_map_sum_elem_count_by_fd kfunc,
> available in syscall programs?

This should work already, something like

    __s64 bpf_map_sum_elem_count(const struct bpf_map *map) __ksym;
    __s64 ret_user;

    struct {
            __uint(type, BPF_MAP_TYPE_HASH);
            __type(key, int);
            __type(value, int);
            __uint(max_entries, 4);
    } your_map SEC(".maps");

    SEC("syscall")
    int sum(void *ctx)
    {
            struct bpf_map *map = (struct bpf_map *)&your_map;

            ret_user = bpf_map_sum_elem_count(map);

            return 0;
    }

    char _license[] SEC("license") = "GPL";

Is this sufficient for your use case?

> > 
> > [Also, please try not to top-post, see https://www.idallen.com/topposting.html]
> > 
> >>> On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
> >>>> 
> >>>> On 25/01/06 05:19PM, Daniel Borkmann wrote:
> >>>>> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> >>>>>> This patch series provides an easy way for userspace applications to
> >>>>>> query the number of entries currently present in a map.
> >>>>>> 
> >>>>>> Currently, the number of entries in a map is accessible only from kernel space
> >>>>>> and eBPF programs. A userspace program that wants to track map utilization has to
> >>>>>> create and attach an eBPF program solely for that purpose.
> >>>>>> 
> >>>>>> This series makes the number of entries in a map easily accessible, by extending the
> >>>>>> main bpf syscall with a new command. The command supports only maps that already
> >>>>>> track utilization, namely hash maps, LPM maps and queue/stack maps.
> >>>>> 
> >>>>> An earlier attempt to directly expose it to user space can be found here [0], which
> >>>>> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
> >>>>> extending UAPI.
> >>>>> 
> >>>>> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
> >>>>> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
> >>>> 
> >>>> One small thingy here is that bpf_map_sum_elem_count() is only
> >>>> available from the map iterator. Which means that to get the
> >>>> bpf_map_sum_elem_count() for one map only, one have to iterate
> >>>> through the whole set of maps (and filter out all but one).
> >>>> 
> >>>> I wanted to follow up my series by either adding the result of
> >>>> calling bpf_map_sum_elem_count() to map_info as u32 or to add
> >>>> possibility to provide a map_fd/map_id when creating an iterator
> >>>> (so that it is only called for one map). But so far I haven't
> >>>> a real use case for getting the number of elements for one map only.
> >>>> 
> >>>>> Thanks,
> >>>>> Daniel
> >>>>> 
> >>>>>  [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
> >>>>>  [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
> >>>>>      https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
> >>>>> 
> >>>>>> Charalampos Stylianopoulos (4):
> >>>>>>   bpf: Add map_num_entries map op
> >>>>>>   bpf: Add bpf command to get number of map entries
> >>>>>>   libbpf: Add support for MAP_GET_NUM_ENTRIES command
> >>>>>>   selftests/bpf: Add tests for bpf_map_get_num_entries
> >>>>>> 
> >>>>>>  include/linux/bpf.h                           |  3 ++
> >>>>>>  include/linux/bpf_local_storage.h             |  1 +
> >>>>>>  include/uapi/linux/bpf.h                      | 17 +++++++++
> >>>>>>  kernel/bpf/devmap.c                           | 14 ++++++++
> >>>>>>  kernel/bpf/hashtab.c                          | 10 ++++++
> >>>>>>  kernel/bpf/lpm_trie.c                         |  8 +++++
> >>>>>>  kernel/bpf/queue_stack_maps.c                 | 11 +++++-
> >>>>>>  kernel/bpf/syscall.c                          | 32 +++++++++++++++++
> >>>>>>  tools/include/uapi/linux/bpf.h                | 17 +++++++++
> >>>>>>  tools/lib/bpf/bpf.c                           | 16 +++++++++
> >>>>>>  tools/lib/bpf/bpf.h                           |  2 ++
> >>>>>>  tools/lib/bpf/libbpf.map                      |  1 +
> >>>>>>  .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
> >>>>>>  tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
> >>>>>>  14 files changed, 171 insertions(+), 1 deletion(-)
> >>>>>> 
> >>>>> 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-16 14:59             ` Anton Protopopov
@ 2025-01-16 17:52               ` Nick Zavaritsky
  2025-01-17 10:35                 ` Anton Protopopov
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Zavaritsky @ 2025-01-16 17:52 UTC (permalink / raw)
  To: Anton Protopopov
  Cc: Charalampos Stylianopoulos, Daniel Borkmann, bpf,
	Alexei Starovoitov, aspsk2


> On 16. Jan 2025, at 15:59, Anton Protopopov <aspsk@isovalent.com> wrote:
> 
> On 25/01/14 12:38PM, Nick Zavaritsky wrote:
>> 
>>> On 9. Jan 2025, at 18:37, Anton Protopopov <aspsk@isovalent.com> wrote:
>>> 
>>> On 25/01/07 12:10PM, Charalampos Stylianopoulos wrote:
>>>> (sorry for double posting, this time in plain text)
>>>> Thanks a lot for the feedback!
>>>> 
>>>> So, to double check, the suggestion is to only extend the libbpf API
>>>> with a new helper that does pretty much what get_cur_elements() does
>>>> in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?
>>> 
>>> What is your use case for getting the number of elements in a
>>> particular map? Will it work for you to just use a variant of
>>> get_cur_elements() from selftests vs. adding new API to libbpf?
>> 
>> (On behalf of Charalampos Stylianopoulos) we would like to get the
>> number of elements in some maps for monitoring purposes. The end goal is
>> to get someone paged when a fixed-capacity map is about to start
>> rejecting inserts.
>> 
>> We aim to operate a large number of apps in containers (custom packet
>> processing services, telekom). We find it most convenient for an app
>> itself to expose metrics concerning the maps it has created.
>> 
>> We currently use a map iterator and a bunch of bpf_probe_read_kernel. We
>> foresee the number of maps in our systems getting significantly higher
>> in the near future. Therefore enumerating every map in the system to get
>> a number of elements in a particular map doesn't look sustainable.
>> 
>> How do you feel about introducing bpf_map_sum_elem_count_by_fd kfunc,
>> available in syscall programs?
> 
> This should work already, something like
> 
>    __s64 bpf_map_sum_elem_count(const struct bpf_map *map) __ksym;
>    __s64 ret_user;
> 
>    struct {
>            __uint(type, BPF_MAP_TYPE_HASH);
>            __type(key, int);
>            __type(value, int);
>            __uint(max_entries, 4);
>    } your_map SEC(".maps");
> 
>    SEC("syscall")
>    int sum(void *ctx)
>    {
>            struct bpf_map *map = (struct bpf_map *)&your_map;
> 
>            ret_user = bpf_map_sum_elem_count(map);
> 
>            return 0;
>    }
> 
>    char _license[] SEC("license") = "GPL";
> 
> Is this sufficient for your use case?

Technically it works. One can add a program similar to the snippet below
to their bpf code to expose the number of elements in every map of
interest.

struct stats { __s64 a, b, c, d; };
SEC(“.maps”) struct { ... } a, b, c, d;

SEC(“syscall”)
int sum_element_count_bulk(void *ctx)
{
    struct stats *stats = ctx;
    stats->a = bpf_map_sum_element_count((void *)a);
    stats->b = bpf_map_sum_element_count((void *)b);
    ...
    return 0;
}

The downside is that it is boilerplate code that has to be written every
single time. With the proposed bpf_map_sum_element_count_by_fd, one can
have a library in user space that offers convenient
sum_element_count(int fd).

It could leverage the following bpf program behind the scenes:

SEC(“syscall”)
int sum_element_count(void *ctx)
{
    *(__s64 *)ctx = bpf_map_sum_element_count_by_fd(*(int *)ctx);
    return 0;
}

> 
>>> 
>>> [Also, please try not to top-post, see https://www.idallen.com/topposting.html]
>>> 
>>>>> On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
>>>>>> 
>>>>>> On 25/01/06 05:19PM, Daniel Borkmann wrote:
>>>>>>> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
>>>>>>>> This patch series provides an easy way for userspace applications to
>>>>>>>> query the number of entries currently present in a map.
>>>>>>>> 
>>>>>>>> Currently, the number of entries in a map is accessible only from kernel space
>>>>>>>> and eBPF programs. A userspace program that wants to track map utilization has to
>>>>>>>> create and attach an eBPF program solely for that purpose.
>>>>>>>> 
>>>>>>>> This series makes the number of entries in a map easily accessible, by extending the
>>>>>>>> main bpf syscall with a new command. The command supports only maps that already
>>>>>>>> track utilization, namely hash maps, LPM maps and queue/stack maps.
>>>>>>> 
>>>>>>> An earlier attempt to directly expose it to user space can be found here [0], which
>>>>>>> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
>>>>>>> extending UAPI.
>>>>>>> 
>>>>>>> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
>>>>>>> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
>>>>>> 
>>>>>> One small thingy here is that bpf_map_sum_elem_count() is only
>>>>>> available from the map iterator. Which means that to get the
>>>>>> bpf_map_sum_elem_count() for one map only, one have to iterate
>>>>>> through the whole set of maps (and filter out all but one).
>>>>>> 
>>>>>> I wanted to follow up my series by either adding the result of
>>>>>> calling bpf_map_sum_elem_count() to map_info as u32 or to add
>>>>>> possibility to provide a map_fd/map_id when creating an iterator
>>>>>> (so that it is only called for one map). But so far I haven't
>>>>>> a real use case for getting the number of elements for one map only.
>>>>>> 
>>>>>>> Thanks,
>>>>>>> Daniel
>>>>>>> 
>>>>>>> [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
>>>>>>> [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
>>>>>>>     https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
>>>>>>> 
>>>>>>>> Charalampos Stylianopoulos (4):
>>>>>>>>  bpf: Add map_num_entries map op
>>>>>>>>  bpf: Add bpf command to get number of map entries
>>>>>>>>  libbpf: Add support for MAP_GET_NUM_ENTRIES command
>>>>>>>>  selftests/bpf: Add tests for bpf_map_get_num_entries
>>>>>>>> 
>>>>>>>> include/linux/bpf.h                           |  3 ++
>>>>>>>> include/linux/bpf_local_storage.h             |  1 +
>>>>>>>> include/uapi/linux/bpf.h                      | 17 +++++++++
>>>>>>>> kernel/bpf/devmap.c                           | 14 ++++++++
>>>>>>>> kernel/bpf/hashtab.c                          | 10 ++++++
>>>>>>>> kernel/bpf/lpm_trie.c                         |  8 +++++
>>>>>>>> kernel/bpf/queue_stack_maps.c                 | 11 +++++-
>>>>>>>> kernel/bpf/syscall.c                          | 32 +++++++++++++++++
>>>>>>>> tools/include/uapi/linux/bpf.h                | 17 +++++++++
>>>>>>>> tools/lib/bpf/bpf.c                           | 16 +++++++++
>>>>>>>> tools/lib/bpf/bpf.h                           |  2 ++
>>>>>>>> tools/lib/bpf/libbpf.map                      |  1 +
>>>>>>>> .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
>>>>>>>> tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
>>>>>>>> 14 files changed, 171 insertions(+), 1 deletion(-)



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next 0/4] expose number of map entries to userspace
  2025-01-16 17:52               ` Nick Zavaritsky
@ 2025-01-17 10:35                 ` Anton Protopopov
  0 siblings, 0 replies; 15+ messages in thread
From: Anton Protopopov @ 2025-01-17 10:35 UTC (permalink / raw)
  To: Nick Zavaritsky
  Cc: Charalampos Stylianopoulos, Daniel Borkmann, bpf,
	Alexei Starovoitov, aspsk2

On 25/01/16 06:52PM, Nick Zavaritsky wrote:
> 
> > On 16. Jan 2025, at 15:59, Anton Protopopov <aspsk@isovalent.com> wrote:
> > 
> > On 25/01/14 12:38PM, Nick Zavaritsky wrote:
> >> 
> >>> On 9. Jan 2025, at 18:37, Anton Protopopov <aspsk@isovalent.com> wrote:
> >>> 
> >>> On 25/01/07 12:10PM, Charalampos Stylianopoulos wrote:
> >>>> (sorry for double posting, this time in plain text)
> >>>> Thanks a lot for the feedback!
> >>>> 
> >>>> So, to double check, the suggestion is to only extend the libbpf API
> >>>> with a new helper that does pretty much what get_cur_elements() does
> >>>> in tools/testing/selftests/bpf/map_tests/map_percpu_stats.c ?
> >>> 
> >>> What is your use case for getting the number of elements in a
> >>> particular map? Will it work for you to just use a variant of
> >>> get_cur_elements() from selftests vs. adding new API to libbpf?
> >> 
> >> (On behalf of Charalampos Stylianopoulos) we would like to get the
> >> number of elements in some maps for monitoring purposes. The end goal is
> >> to get someone paged when a fixed-capacity map is about to start
> >> rejecting inserts.
> >> 
> >> We aim to operate a large number of apps in containers (custom packet
> >> processing services, telekom). We find it most convenient for an app
> >> itself to expose metrics concerning the maps it has created.
> >> 
> >> We currently use a map iterator and a bunch of bpf_probe_read_kernel. We
> >> foresee the number of maps in our systems getting significantly higher
> >> in the near future. Therefore enumerating every map in the system to get
> >> a number of elements in a particular map doesn't look sustainable.
> >> 
> >> How do you feel about introducing bpf_map_sum_elem_count_by_fd kfunc,
> >> available in syscall programs?
> > 
> > This should work already, something like
> > 
> >    __s64 bpf_map_sum_elem_count(const struct bpf_map *map) __ksym;
> >    __s64 ret_user;
> > 
> >    struct {
> >            __uint(type, BPF_MAP_TYPE_HASH);
> >            __type(key, int);
> >            __type(value, int);
> >            __uint(max_entries, 4);
> >    } your_map SEC(".maps");
> > 
> >    SEC("syscall")
> >    int sum(void *ctx)
> >    {
> >            struct bpf_map *map = (struct bpf_map *)&your_map;
> > 
> >            ret_user = bpf_map_sum_elem_count(map);
> > 
> >            return 0;
> >    }
> > 
> >    char _license[] SEC("license") = "GPL";
> > 
> > Is this sufficient for your use case?
> 
> Technically it works. One can add a program similar to the snippet below
> to their bpf code to expose the number of elements in every map of
> interest.
> 
> struct stats { __s64 a, b, c, d; };
> SEC(“.maps”) struct { ... } a, b, c, d;
> 
> SEC(“syscall”)
> int sum_element_count_bulk(void *ctx)
> {
>     struct stats *stats = ctx;
>     stats->a = bpf_map_sum_element_count((void *)a);
>     stats->b = bpf_map_sum_element_count((void *)b);
>     ...
>     return 0;
> }
> 
> The downside is that it is boilerplate code that has to be written every
> single time. With the proposed bpf_map_sum_element_count_by_fd, one can
> have a library in user space that offers convenient
> sum_element_count(int fd).
> 
> It could leverage the following bpf program behind the scenes:
> 
> SEC(“syscall”)
> int sum_element_count(void *ctx)
> {
>     *(__s64 *)ctx = bpf_map_sum_element_count_by_fd(*(int *)ctx);
>     return 0;
> }

Makes sense. And this can also be used for multiple maps in one call.

I've quickly tested that the following implementation works, please
send a patch + selftests. Note that unlike the bpf_map_sum_elem_count
function, the bpf_map_sum_elem_count_by_fd should be only allowed for
SYSCALL programs.

__bpf_kfunc s64 bpf_map_sum_elem_count_by_fd(int fd)
{
        struct bpf_map *map;
        s64 ret;

        map = bpf_map_get(fd);
        if (IS_ERR(map))
                return 0;

        ret = bpf_map_sum_elem_count(map);
        bpf_map_put(map);
        return ret;
}

> > 
> >>> 
> >>> [Also, please try not to top-post, see https://www.idallen.com/topposting.html]
> >>> 
> >>>>> On Tue, 7 Jan 2025 at 08:44, Anton Protopopov <aspsk@isovalent.com> wrote:
> >>>>>> 
> >>>>>> On 25/01/06 05:19PM, Daniel Borkmann wrote:
> >>>>>>> On 1/6/25 3:53 PM, Charalampos Stylianopoulos wrote:
> >>>>>>>> This patch series provides an easy way for userspace applications to
> >>>>>>>> query the number of entries currently present in a map.
> >>>>>>>> 
> >>>>>>>> Currently, the number of entries in a map is accessible only from kernel space
> >>>>>>>> and eBPF programs. A userspace program that wants to track map utilization has to
> >>>>>>>> create and attach an eBPF program solely for that purpose.
> >>>>>>>> 
> >>>>>>>> This series makes the number of entries in a map easily accessible, by extending the
> >>>>>>>> main bpf syscall with a new command. The command supports only maps that already
> >>>>>>>> track utilization, namely hash maps, LPM maps and queue/stack maps.
> >>>>>>> 
> >>>>>>> An earlier attempt to directly expose it to user space can be found here [0], which
> >>>>>>> eventually led to [1] to only expose it via kfunc for BPF programs in order to avoid
> >>>>>>> extending UAPI.
> >>>>>>> 
> >>>>>>> Perhaps instead add a small libbpf helper (e.g. bpf_map__current_entries to complement
> >>>>>>> bpf_map__max_entries) which does all the work to extract that info via [1] underneath?
> >>>>>> 
> >>>>>> One small thingy here is that bpf_map_sum_elem_count() is only
> >>>>>> available from the map iterator. Which means that to get the
> >>>>>> bpf_map_sum_elem_count() for one map only, one have to iterate
> >>>>>> through the whole set of maps (and filter out all but one).
> >>>>>> 
> >>>>>> I wanted to follow up my series by either adding the result of
> >>>>>> calling bpf_map_sum_elem_count() to map_info as u32 or to add
> >>>>>> possibility to provide a map_fd/map_id when creating an iterator
> >>>>>> (so that it is only called for one map). But so far I haven't
> >>>>>> a real use case for getting the number of elements for one map only.
> >>>>>> 
> >>>>>>> Thanks,
> >>>>>>> Daniel
> >>>>>>> 
> >>>>>>> [0] https://lore.kernel.org/bpf/20230531110511.64612-1-aspsk@isovalent.com/
> >>>>>>> [1] https://lore.kernel.org/bpf/20230705160139.19967-1-aspsk@isovalent.com/
> >>>>>>>     https://lore.kernel.org/bpf/20230719092952.41202-1-aspsk@isovalent.com/
> >>>>>>> 
> >>>>>>>> Charalampos Stylianopoulos (4):
> >>>>>>>>  bpf: Add map_num_entries map op
> >>>>>>>>  bpf: Add bpf command to get number of map entries
> >>>>>>>>  libbpf: Add support for MAP_GET_NUM_ENTRIES command
> >>>>>>>>  selftests/bpf: Add tests for bpf_map_get_num_entries
> >>>>>>>> 
> >>>>>>>> include/linux/bpf.h                           |  3 ++
> >>>>>>>> include/linux/bpf_local_storage.h             |  1 +
> >>>>>>>> include/uapi/linux/bpf.h                      | 17 +++++++++
> >>>>>>>> kernel/bpf/devmap.c                           | 14 ++++++++
> >>>>>>>> kernel/bpf/hashtab.c                          | 10 ++++++
> >>>>>>>> kernel/bpf/lpm_trie.c                         |  8 +++++
> >>>>>>>> kernel/bpf/queue_stack_maps.c                 | 11 +++++-
> >>>>>>>> kernel/bpf/syscall.c                          | 32 +++++++++++++++++
> >>>>>>>> tools/include/uapi/linux/bpf.h                | 17 +++++++++
> >>>>>>>> tools/lib/bpf/bpf.c                           | 16 +++++++++
> >>>>>>>> tools/lib/bpf/bpf.h                           |  2 ++
> >>>>>>>> tools/lib/bpf/libbpf.map                      |  1 +
> >>>>>>>> .../bpf/map_tests/lpm_trie_map_basic_ops.c    |  5 +++
> >>>>>>>> tools/testing/selftests/bpf/test_maps.c       | 35 +++++++++++++++++++
> >>>>>>>> 14 files changed, 171 insertions(+), 1 deletion(-)
> 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-01-17 10:31 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-06 14:53 [PATCH bpf-next 0/4] expose number of map entries to userspace Charalampos Stylianopoulos
2025-01-06 14:53 ` [PATCH bpf-next 1/4] bpf: Add map_num_entries map op Charalampos Stylianopoulos
2025-01-06 14:53 ` [PATCH bpf-next 2/4] bpf: Add bpf command to get number of map entries Charalampos Stylianopoulos
2025-01-07 17:52   ` kernel test robot
2025-01-06 14:53 ` [PATCH bpf-next 3/4] libbpf: Add support for MAP_GET_NUM_ENTRIES command Charalampos Stylianopoulos
2025-01-06 14:53 ` [PATCH bpf-next 4/4] selftests/bpf: Add tests for bpf_map_get_num_entries Charalampos Stylianopoulos
2025-01-06 16:19 ` [PATCH bpf-next 0/4] expose number of map entries to userspace Daniel Borkmann
2025-01-07  7:43   ` Anton Protopopov
2025-01-07  7:48   ` Anton Protopopov
     [not found]     ` <CAAvdH+yNG=GefEd5CcP_52gPzzZexWMMxFAxnM3isX04iErMfQ@mail.gmail.com>
2025-01-07 11:10       ` Charalampos Stylianopoulos
2025-01-09 17:37         ` Anton Protopopov
2025-01-14 11:38           ` Nick Zavaritsky
2025-01-16 14:59             ` Anton Protopopov
2025-01-16 17:52               ` Nick Zavaritsky
2025-01-17 10:35                 ` Anton Protopopov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox