Skip to content

Commit 79c29b9

Browse files
AsphalttKernel Patches Daemon
authored andcommitted
libbpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu maps
Add libbpf support for the BPF_F_CPU flag for percpu 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() And the flag can be BPF_F_ALL_CPUS, but cannot be 'BPF_F_CPU | BPF_F_ALL_CPUS'. Behavior: * If the flag is BPF_F_ALL_CPUS, the update is applied across all CPUs. * If the flag is BPF_F_CPU, it updates value only to the specified CPU. * If the flag is BPF_F_CPU, lookup value only from the specified CPU. * lookup does not support BPF_F_ALL_CPUS. Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Leon Hwang <[email protected]>
1 parent 9c252ef commit 79c29b9

File tree

3 files changed

+36
-19
lines changed

3 files changed

+36
-19
lines changed

tools/lib/bpf/bpf.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,14 @@ LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
289289
* Update spin_lock-ed map elements. This must be
290290
* specified if the map value contains a spinlock.
291291
*
292+
* **BPF_F_CPU**
293+
* As for percpu maps, update value on the specified CPU. And the cpu
294+
* info is embedded into the high 32 bits of **opts->elem_flags**.
295+
*
296+
* **BPF_F_ALL_CPUS**
297+
* As for percpu maps, update value across all CPUs. This flag cannot
298+
* be used with BPF_F_CPU at the same time.
299+
*
292300
* @param fd BPF map file descriptor
293301
* @param keys pointer to an array of *count* keys
294302
* @param values pointer to an array of *count* values

tools/lib/bpf/libbpf.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10913,7 +10913,7 @@ bpf_object__find_map_fd_by_name(const struct bpf_object *obj, const char *name)
1091310913
}
1091410914

1091510915
static int validate_map_op(const struct bpf_map *map, size_t key_sz,
10916-
size_t value_sz, bool check_value_sz)
10916+
size_t value_sz, bool check_value_sz, __u64 flags)
1091710917
{
1091810918
if (!map_is_created(map)) /* map is not yet created */
1091910919
return -ENOENT;
@@ -10940,6 +10940,20 @@ static int validate_map_op(const struct bpf_map *map, size_t key_sz,
1094010940
int num_cpu = libbpf_num_possible_cpus();
1094110941
size_t elem_sz = roundup(map->def.value_size, 8);
1094210942

10943+
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS)) {
10944+
if ((flags & BPF_F_CPU) && (flags & BPF_F_ALL_CPUS)) {
10945+
pr_warn("map '%s': BPF_F_CPU and BPF_F_ALL_CPUS are mutually exclusive\n",
10946+
map->name);
10947+
return -EINVAL;
10948+
}
10949+
if (map->def.value_size != value_sz) {
10950+
pr_warn("map '%s': unexpected value size %zu provided for either BPF_F_CPU or BPF_F_ALL_CPUS, expected %u\n",
10951+
map->name, value_sz, map->def.value_size);
10952+
return -EINVAL;
10953+
}
10954+
break;
10955+
}
10956+
1094310957
if (value_sz != num_cpu * elem_sz) {
1094410958
pr_warn("map '%s': unexpected value size %zu provided for per-CPU map, expected %d * %zu = %zd\n",
1094510959
map->name, value_sz, num_cpu, elem_sz, num_cpu * elem_sz);
@@ -10964,7 +10978,7 @@ int bpf_map__lookup_elem(const struct bpf_map *map,
1096410978
{
1096510979
int err;
1096610980

10967-
err = validate_map_op(map, key_sz, value_sz, true);
10981+
err = validate_map_op(map, key_sz, value_sz, true, flags);
1096810982
if (err)
1096910983
return libbpf_err(err);
1097010984

@@ -10977,7 +10991,7 @@ int bpf_map__update_elem(const struct bpf_map *map,
1097710991
{
1097810992
int err;
1097910993

10980-
err = validate_map_op(map, key_sz, value_sz, true);
10994+
err = validate_map_op(map, key_sz, value_sz, true, flags);
1098110995
if (err)
1098210996
return libbpf_err(err);
1098310997

@@ -10989,7 +11003,7 @@ int bpf_map__delete_elem(const struct bpf_map *map,
1098911003
{
1099011004
int err;
1099111005

10992-
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */);
11006+
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */, flags);
1099311007
if (err)
1099411008
return libbpf_err(err);
1099511009

@@ -11002,7 +11016,7 @@ int bpf_map__lookup_and_delete_elem(const struct bpf_map *map,
1100211016
{
1100311017
int err;
1100411018

11005-
err = validate_map_op(map, key_sz, value_sz, true);
11019+
err = validate_map_op(map, key_sz, value_sz, true, flags);
1100611020
if (err)
1100711021
return libbpf_err(err);
1100811022

@@ -11014,7 +11028,7 @@ int bpf_map__get_next_key(const struct bpf_map *map,
1101411028
{
1101511029
int err;
1101611030

11017-
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */);
11031+
err = validate_map_op(map, key_sz, 0, false /* check_value_sz */, 0);
1101811032
if (err)
1101911033
return libbpf_err(err);
1102011034

tools/lib/bpf/libbpf.h

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,12 +1196,13 @@ LIBBPF_API struct bpf_map *bpf_map__inner_map(struct bpf_map *map);
11961196
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
11971197
* @param value pointer to memory in which looked up value will be stored
11981198
* @param value_sz size in byte of value data memory; it has to match BPF map
1199-
* definition's **value_size**. For per-CPU BPF maps value size has to be
1200-
* a product of BPF map value size and number of possible CPUs in the system
1201-
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
1202-
* per-CPU values value size has to be aligned up to closest 8 bytes for
1203-
* alignment reasons, so expected size is: `round_up(value_size, 8)
1204-
* * libbpf_num_possible_cpus()`.
1199+
* definition's **value_size**. For per-CPU BPF maps, value size can be
1200+
* `value_size` if either **BPF_F_CPU** or **BPF_F_ALL_CPUS** is specified
1201+
* in **flags**, otherwise a product of BPF map value size and number of
1202+
* possible CPUs in the system (could be fetched with
1203+
* **libbpf_num_possible_cpus()**). Note also that for per-CPU values value
1204+
* size has to be aligned up to closest 8 bytes, so expected size is:
1205+
* `round_up(value_size, 8) * libbpf_num_possible_cpus()`.
12051206
* @flags extra flags passed to kernel for this operation
12061207
* @return 0, on success; negative error, otherwise
12071208
*
@@ -1219,13 +1220,7 @@ LIBBPF_API int bpf_map__lookup_elem(const struct bpf_map *map,
12191220
* @param key pointer to memory containing bytes of the key
12201221
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
12211222
* @param value pointer to memory containing bytes of the value
1222-
* @param value_sz size in byte of value data memory; it has to match BPF map
1223-
* definition's **value_size**. For per-CPU BPF maps value size has to be
1224-
* a product of BPF map value size and number of possible CPUs in the system
1225-
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
1226-
* per-CPU values value size has to be aligned up to closest 8 bytes for
1227-
* alignment reasons, so expected size is: `round_up(value_size, 8)
1228-
* * libbpf_num_possible_cpus()`.
1223+
* @param value_sz refer to **bpf_map__lookup_elem**'s description.'
12291224
* @flags extra flags passed to kernel for this operation
12301225
* @return 0, on success; negative error, otherwise
12311226
*

0 commit comments

Comments
 (0)