selftests/bpf: extend the storage test to test per-cpu cgroup storage
This test extends the cgroup storage test to use per-cpu flavor of the cgroup storage as well. The test initializes a per-cpu cgroup storage to some non-zero initial value (1000), and then simple bumps a per-cpu counter each time the shared counter is atomically incremented. Then it reads all per-cpu areas from the userspace side, and checks that the sum of values adds to the expected sum. Expected output: $ ./test_cgroup_storage test_cgroup_storage:PASS Signed-off-by: Roman Gushchin <guro@fb.com> Acked-by: Song Liu <songliubraving@fb.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
		
							parent
							
								
									a3c6054f81
								
							
						
					
					
						commit
						919646d2a3
					
				| @ -4,6 +4,7 @@ | |||||||
| #include <linux/filter.h> | #include <linux/filter.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  | #include <sys/sysinfo.h> | ||||||
| 
 | 
 | ||||||
| #include "bpf_rlimit.h" | #include "bpf_rlimit.h" | ||||||
| #include "cgroup_helpers.h" | #include "cgroup_helpers.h" | ||||||
| @ -15,6 +16,14 @@ char bpf_log_buf[BPF_LOG_BUF_SIZE]; | |||||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||||
| { | { | ||||||
| 	struct bpf_insn prog[] = { | 	struct bpf_insn prog[] = { | ||||||
|  | 		BPF_LD_MAP_FD(BPF_REG_1, 0), /* percpu map fd */ | ||||||
|  | 		BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */ | ||||||
|  | 		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||||||
|  | 			     BPF_FUNC_get_local_storage), | ||||||
|  | 		BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), | ||||||
|  | 		BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1), | ||||||
|  | 		BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0), | ||||||
|  | 
 | ||||||
| 		BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */ | 		BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */ | ||||||
| 		BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */ | 		BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */ | ||||||
| 		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | 		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||||||
| @ -28,9 +37,18 @@ int main(int argc, char **argv) | |||||||
| 	}; | 	}; | ||||||
| 	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); | 	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); | ||||||
| 	int error = EXIT_FAILURE; | 	int error = EXIT_FAILURE; | ||||||
| 	int map_fd, prog_fd, cgroup_fd; | 	int map_fd, percpu_map_fd, prog_fd, cgroup_fd; | ||||||
| 	struct bpf_cgroup_storage_key key; | 	struct bpf_cgroup_storage_key key; | ||||||
| 	unsigned long long value; | 	unsigned long long value; | ||||||
|  | 	unsigned long long *percpu_value; | ||||||
|  | 	int cpu, nproc; | ||||||
|  | 
 | ||||||
|  | 	nproc = get_nprocs_conf(); | ||||||
|  | 	percpu_value = malloc(sizeof(*percpu_value) * nproc); | ||||||
|  | 	if (!percpu_value) { | ||||||
|  | 		printf("Not enough memory for per-cpu area (%d cpus)\n", nproc); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	map_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, sizeof(key), | 	map_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, sizeof(key), | ||||||
| 				sizeof(value), 0, 0); | 				sizeof(value), 0, 0); | ||||||
| @ -39,7 +57,15 @@ int main(int argc, char **argv) | |||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	prog[0].imm = map_fd; | 	percpu_map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, | ||||||
|  | 				       sizeof(key), sizeof(value), 0, 0); | ||||||
|  | 	if (percpu_map_fd < 0) { | ||||||
|  | 		printf("Failed to create map: %s\n", strerror(errno)); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prog[0].imm = percpu_map_fd; | ||||||
|  | 	prog[7].imm = map_fd; | ||||||
| 	prog_fd = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, | 	prog_fd = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, | ||||||
| 				   prog, insns_cnt, "GPL", 0, | 				   prog, insns_cnt, "GPL", 0, | ||||||
| 				   bpf_log_buf, BPF_LOG_BUF_SIZE); | 				   bpf_log_buf, BPF_LOG_BUF_SIZE); | ||||||
| @ -77,7 +103,15 @@ int main(int argc, char **argv) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (bpf_map_lookup_elem(map_fd, &key, &value)) { | 	if (bpf_map_lookup_elem(map_fd, &key, &value)) { | ||||||
| 		printf("Failed to lookup cgroup storage\n"); | 		printf("Failed to lookup cgroup storage 0\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (cpu = 0; cpu < nproc; cpu++) | ||||||
|  | 		percpu_value[cpu] = 1000; | ||||||
|  | 
 | ||||||
|  | 	if (bpf_map_update_elem(percpu_map_fd, &key, percpu_value, 0)) { | ||||||
|  | 		printf("Failed to update the data in the cgroup storage\n"); | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -120,11 +154,31 @@ int main(int argc, char **argv) | |||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* Check the final value of the counter in the percpu local storage */ | ||||||
|  | 
 | ||||||
|  | 	for (cpu = 0; cpu < nproc; cpu++) | ||||||
|  | 		percpu_value[cpu] = 0; | ||||||
|  | 
 | ||||||
|  | 	if (bpf_map_lookup_elem(percpu_map_fd, &key, percpu_value)) { | ||||||
|  | 		printf("Failed to lookup the per-cpu cgroup storage\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value = 0; | ||||||
|  | 	for (cpu = 0; cpu < nproc; cpu++) | ||||||
|  | 		value += percpu_value[cpu]; | ||||||
|  | 
 | ||||||
|  | 	if (value != nproc * 1000 + 6) { | ||||||
|  | 		printf("Unexpected data in the per-cpu cgroup storage\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	error = 0; | 	error = 0; | ||||||
| 	printf("test_cgroup_storage:PASS\n"); | 	printf("test_cgroup_storage:PASS\n"); | ||||||
| 
 | 
 | ||||||
| err: | err: | ||||||
| 	cleanup_cgroup_environment(); | 	cleanup_cgroup_environment(); | ||||||
|  | 	free(percpu_value); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	return error; | 	return error; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user