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 = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.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;
for(i=0;i<ln;i++){
printf("cpu %d: %d\n", i, arr[i]);
(*s)+=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
https://github.com/torvalds/linux/blob/master/kernel/bpf/arraymap.c#L81

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.


Thanks
forrest chen

Join iovisor-dev@lists.iovisor.org to automatically receive all group messages.