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