Skip to content

Commit a7e54f8

Browse files
Asphaltttheihor
authored andcommitted
libbpf: Support BPF_F_CPU for percpu_array maps
Add libbpf support for the BPF_F_CPU flag for percpu_array maps by embedding the cpu info into the high 32 bits of: 1. **flags**: bpf_map_lookup_elem_flags(), bpf_map__lookup_elem(), bpf_map_update_elem() and bpf_map__update_elem() 2. **opts->elem_flags**: bpf_map_lookup_batch() and bpf_map_update_batch() Behavior: * If cpu is (u32)~0, the update is applied across all CPUs. * Otherwise, it updates value only to the specified CPU. * If cpu is (u32)~0, lookup values across all CPUs. * Otherwise, it lookups value only from the specified CPU. Signed-off-by: Leon Hwang <[email protected]>
1 parent 9d2416b commit a7e54f8

File tree

3 files changed

+33
-17
lines changed

3 files changed

+33
-17
lines changed

tools/lib/bpf/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
286286
* Update spin_lock-ed map elements. This must be
287287
* specified if the map value contains a spinlock.
288288
*
289+
* **BPF_F_CPU**
290+
* As for percpu map, the cpu info is embedded into the high 32 bits of
291+
* **opts->elem_flags**. Update value across all CPUs if cpu is (__u32)~0,
292+
* or on specified CPU otherwise.
293+
*
289294
* @param fd BPF map file descriptor
290295
* @param keys pointer to an array of *count* keys
291296
* @param values pointer to an array of *count* values

tools/lib/bpf/libbpf.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10593,8 +10593,10 @@ bpf_object__find_map_fd_by_name(const struct bpf_object *obj, const char *name)
1059310593
}
1059410594

1059510595
static int validate_map_op(const struct bpf_map *map, size_t key_sz,
10596-
size_t value_sz, bool check_value_sz)
10596+
size_t value_sz, bool check_value_sz, __u64 flags)
1059710597
{
10598+
__u32 cpu;
10599+
1059810600
if (!map_is_created(map)) /* map is not yet created */
1059910601
return -ENOENT;
1060010602

@@ -10612,6 +10614,20 @@ static int validate_map_op(const struct bpf_map *map, size_t key_sz,
1061210614
if (!check_value_sz)
1061310615
return 0;
1061410616

10617+
if (flags & BPF_F_CPU) {
10618+
if (map->def.type != BPF_MAP_TYPE_PERCPU_ARRAY)
10619+
return -EINVAL;
10620+
cpu = flags >> 32;
10621+
if (cpu != BPF_ALL_CPUS && cpu >= libbpf_num_possible_cpus())
10622+
return -ERANGE;
10623+
if (map->def.value_size != value_sz) {
10624+
pr_warn("map '%s': unexpected value size %zu provided, expected %u\n",
10625+
map->name, value_sz, map->def.value_size);
10626+
return -EINVAL;
10627+
}
10628+
return 0;
10629+
}
10630+
1061510631
switch (map->def.type) {
1061610632
case BPF_MAP_TYPE_PERCPU_ARRAY:
1061710633
case BPF_MAP_TYPE_PERCPU_HASH:
@@ -10644,7 +10660,7 @@ int bpf_map__lookup_elem(const struct bpf_map *map,
1064410660
{
1064510661
int err;
1064610662

10647-
err = validate_map_op(map, key_sz, value_sz, true);
10663+
err = validate_map_op(map, key_sz, value_sz, true, flags);
1064810664
if (err)
1064910665
return libbpf_err(err);
1065010666

@@ -10657,7 +10673,7 @@ int bpf_map__update_elem(const struct bpf_map *map,
1065710673
{
1065810674
int err;
1065910675

10660-
err = validate_map_op(map, key_sz, value_sz, true);
10676+
err = validate_map_op(map, key_sz, value_sz, true, flags);
1066110677
if (err)
1066210678
return libbpf_err(err);
1066310679

@@ -10669,7 +10685,7 @@ int bpf_map__delete_elem(const struct bpf_map *map,
1066910685
{
1067010686
int err;
1067110687

10672-
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */);
10688+
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */, 0);
1067310689
if (err)
1067410690
return libbpf_err(err);
1067510691

@@ -10682,7 +10698,7 @@ int bpf_map__lookup_and_delete_elem(const struct bpf_map *map,
1068210698
{
1068310699
int err;
1068410700

10685-
err = validate_map_op(map, key_sz, value_sz, true);
10701+
err = validate_map_op(map, key_sz, value_sz, true, 0);
1068610702
if (err)
1068710703
return libbpf_err(err);
1068810704

@@ -10694,7 +10710,7 @@ int bpf_map__get_next_key(const struct bpf_map *map,
1069410710
{
1069510711
int err;
1069610712

10697-
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */);
10713+
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */, 0);
1069810714
if (err)
1069910715
return libbpf_err(err);
1070010716

tools/lib/bpf/libbpf.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,10 +1169,11 @@ LIBBPF_API struct bpf_map *bpf_map__inner_map(struct bpf_map *map);
11691169
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
11701170
* @param value pointer to memory in which looked up value will be stored
11711171
* @param value_sz size in byte of value data memory; it has to match BPF map
1172-
* definition's **value_size**. For per-CPU BPF maps value size has to be
1173-
* a product of BPF map value size and number of possible CPUs in the system
1174-
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
1175-
* per-CPU values value size has to be aligned up to closest 8 bytes for
1172+
* definition's **value_size**. For per-CPU BPF maps, value size can be
1173+
* definition's **value_size** if **BPF_F_CPU** is specified in **flags**,
1174+
* otherwise a product of BPF map value size and number of possible CPUs in the
1175+
* system (could be fetched with **libbpf_num_possible_cpus()**). Note else that
1176+
* for per-CPU values value size has to be aligned up to closest 8 bytes for
11761177
* alignment reasons, so expected size is: `round_up(value_size, 8)
11771178
* * libbpf_num_possible_cpus()`.
11781179
* @flags extra flags passed to kernel for this operation
@@ -1192,13 +1193,7 @@ LIBBPF_API int bpf_map__lookup_elem(const struct bpf_map *map,
11921193
* @param key pointer to memory containing bytes of the key
11931194
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
11941195
* @param value pointer to memory containing bytes of the value
1195-
* @param value_sz size in byte of value data memory; it has to match BPF map
1196-
* definition's **value_size**. For per-CPU BPF maps value size has to be
1197-
* a product of BPF map value size and number of possible CPUs in the system
1198-
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
1199-
* per-CPU values value size has to be aligned up to closest 8 bytes for
1200-
* alignment reasons, so expected size is: `round_up(value_size, 8)
1201-
* * libbpf_num_possible_cpus()`.
1196+
* @param value_sz refer to **bpf_map__lookup_elem**'s description.'
12021197
* @flags extra flags passed to kernel for this operation
12031198
* @return 0, on success; negative error, otherwise
12041199
*

0 commit comments

Comments
 (0)