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; 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_test_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 break; 65 memcpy(&iph, buf + sizeof(struct ethhdr), sizeof(iph)); 66 if (iph.daddr != val) 67 break; 68 } 69 70 CHECK(err || retval || size != sizeof(pkt_v4) || iph.daddr != val, 71 "bpf_map_pop_elem", 72 "err %d errno %d retval %d size %d iph->daddr %u\n", 73 err, errno, retval, size, iph.daddr); 74 75 /* Queue is empty, program should return TC_ACT_SHOT */ 76 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 77 buf, &size, &retval, &duration); 78 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4), 79 "check-queue-stack-map-empty", 80 "err %d errno %d retval %d size %d\n", 81 err, errno, retval, size); 82 83 /* Check that the program pushed elements correctly */ 84 for (i = 0; i < MAP_SIZE; i++) { 85 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val); 86 if (err || val != vals[i] * 5) 87 break; 88 } 89 90 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5), 91 "bpf_map_push_elem", "err %d value %u\n", err, val); 92 93 out: 94 pkt_v4.iph.saddr = 0; 95 bpf_object__close(obj); 96 } 97 98 void test_queue_stack_map(void) 99 { 100 test_queue_stack_map_by_type(QUEUE); 101 test_queue_stack_map_by_type(STACK); 102 } 103