Re: the size of BPF_MAP_TYPE_PERCPU_ARRAY doesn't match the number of CPU

Yonghong Song

On Thu, Aug 1, 2019 at 7:02 PM <forrest0579@...> wrote:

map defined:
struct bpf_map_def SEC("maps/protocount") proto_count = {
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = 1,

userspace code:
int32_t * allocArray(size_t ln) { return (int32_t*) malloc(ln * sizeof(int32_t)); }
void sum(int32_t* arr, size_t ln, void* sum) {
int32_t* s = (int32_t*)sum;
int i=0;
printf("cpu %d: %d\n", i, arr[i]);
sum = (void*)s;

Hi Yonghong Song,
The code is as above.
When I use 32bit key, the count result is in CPU 0 and 2, when I use 64bit key, the result is in CPU 0 and 1 as expect.
For array map, the key type must be 32bit int.
int array_map_alloc_check(union bpf_attr *attr)
bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY;
int numa_node = bpf_map_attr_numa_node(attr);

/* check sanity of attributes */
if (attr->max_entries == 0 || attr->key_size != 4 ||
attr->value_size == 0 ||
attr->map_flags & ~ARRAY_CREATE_FLAG_MASK ||
!bpf_map_flags_access_ok(attr->map_flags) ||
(percpu && numa_node != NUMA_NO_NODE))
return -EINVAL;

if (attr->value_size > KMALLOC_MAX_SIZE)
/* if value_size is bigger, the user space won't be able to
* access the elements.
return -E2BIG;

return 0;

I guess you mean value size. here.
When you got the values from kernel, the value size is rounded to 8. See

So if you use 64bit value size, you will get correct value.
If you use 32bit value size, you should iterate through with int64_t
size, but only read the first 4 bytes for each iteration.

forrest chen

Join to automatically receive all group messages.