1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 4 enum { 5 QUEUE, 6 STACK, 7 }; 8 9 static void test_queue_stack_map_by_type(int type) 10 { 11 const int MAP_SIZE = 32; 12 __u32 vals[MAP_SIZE], duration, retval, size, val; 13 int i, err, prog_fd, map_in_fd, map_out_fd; 14 char file[32], buf[128]; 15 struct bpf_object *obj; 16 struct iphdr *iph = (void *)buf + sizeof(struct ethhdr); 17 18 /* Fill test values to be used */ 19 for (i = 0; i < MAP_SIZE; i++) 20 vals[i] = rand(); 21 22 if (type == QUEUE) 23 strncpy(file, "./test_queue_map.o", sizeof(file)); 24 else if (type == STACK) 25 strncpy(file, "./test_stack_map.o", sizeof(file)); 26 else 27 return; 28 29 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 30 if (CHECK_FAIL(err)) 31 return; 32 33 map_in_fd = bpf_find_map(__func__, obj, "map_in"); 34 if (map_in_fd < 0) 35 goto out; 36 37 map_out_fd = bpf_find_map(__func__, obj, "map_out"); 38 if (map_out_fd < 0) 39 goto out; 40 41 /* Push 32 elements to the input map */ 42 for (i = 0; i < MAP_SIZE; i++) { 43 err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0); 44 if (CHECK_FAIL(err)) 45 goto out; 46 } 47 48 /* The eBPF program pushes iph.saddr in the output map, 49 * pops the input map and saves this value in iph.daddr 50 */ 51 for (i = 0; i < MAP_SIZE; i++) { 52 if (type == QUEUE) { 53 val = vals[i]; 54 pkt_v4.iph.saddr = vals[i] * 5; 55 } else if (type == STACK) { 56 val = vals[MAP_SIZE - 1 - i]; 57 pkt_v4.iph.saddr = vals[MAP_SIZE - 1 - i] * 5; 58 } 59 60 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 61 buf, &size, &retval, &duration); 62 if (err || retval || size != sizeof(pkt_v4) || 63 iph->daddr != val) 64 break; 65 } 66 67 CHECK(err || retval || size != sizeof(pkt_v4) || iph->daddr != val, 68 "bpf_map_pop_elem", 69 "err %d errno %d retval %d size %d iph->daddr %u\n", 70 err, errno, retval, size, iph->daddr); 71 72 /* Queue is empty, program should return TC_ACT_SHOT */ 73 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 74 buf, &size, &retval, &duration); 75 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4), 76 "check-queue-stack-map-empty", 77 "err %d errno %d retval %d size %d\n", 78 err, errno, retval, size); 79 80 /* Check that the program pushed elements correctly */ 81 for (i = 0; i < MAP_SIZE; i++) { 82 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val); 83 if (err || val != vals[i] * 5) 84 break; 85 } 86 87 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5), 88 "bpf_map_push_elem", "err %d value %u\n", err, val); 89 90 out: 91 pkt_v4.iph.saddr = 0; 92 bpf_object__close(obj); 93 } 94 95 void test_queue_stack_map(void) 96 { 97 test_queue_stack_map_by_type(QUEUE); 98 test_queue_stack_map_by_type(STACK); 99 } 100