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 (err) { 31 error_cnt++; 32 return; 33 } 34 35 map_in_fd = bpf_find_map(__func__, obj, "map_in"); 36 if (map_in_fd < 0) 37 goto out; 38 39 map_out_fd = bpf_find_map(__func__, obj, "map_out"); 40 if (map_out_fd < 0) 41 goto out; 42 43 /* Push 32 elements to the input map */ 44 for (i = 0; i < MAP_SIZE; i++) { 45 err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0); 46 if (err) { 47 error_cnt++; 48 goto out; 49 } 50 } 51 52 /* The eBPF program pushes iph.saddr in the output map, 53 * pops the input map and saves this value in iph.daddr 54 */ 55 for (i = 0; i < MAP_SIZE; i++) { 56 if (type == QUEUE) { 57 val = vals[i]; 58 pkt_v4.iph.saddr = vals[i] * 5; 59 } else if (type == STACK) { 60 val = vals[MAP_SIZE - 1 - i]; 61 pkt_v4.iph.saddr = vals[MAP_SIZE - 1 - i] * 5; 62 } 63 64 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 65 buf, &size, &retval, &duration); 66 if (err || retval || size != sizeof(pkt_v4) || 67 iph->daddr != val) 68 break; 69 } 70 71 CHECK(err || retval || size != sizeof(pkt_v4) || iph->daddr != val, 72 "bpf_map_pop_elem", 73 "err %d errno %d retval %d size %d iph->daddr %u\n", 74 err, errno, retval, size, iph->daddr); 75 76 /* Queue is empty, program should return TC_ACT_SHOT */ 77 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 78 buf, &size, &retval, &duration); 79 CHECK(err || retval != 2 /* TC_ACT_SHOT */|| size != sizeof(pkt_v4), 80 "check-queue-stack-map-empty", 81 "err %d errno %d retval %d size %d\n", 82 err, errno, retval, size); 83 84 /* Check that the program pushed elements correctly */ 85 for (i = 0; i < MAP_SIZE; i++) { 86 err = bpf_map_lookup_and_delete_elem(map_out_fd, NULL, &val); 87 if (err || val != vals[i] * 5) 88 break; 89 } 90 91 CHECK(i != MAP_SIZE && (err || val != vals[i] * 5), 92 "bpf_map_push_elem", "err %d value %u\n", err, val); 93 94 out: 95 pkt_v4.iph.saddr = 0; 96 bpf_object__close(obj); 97 } 98 99 void test_queue_stack_map(void) 100 { 101 test_queue_stack_map_by_type(QUEUE); 102 test_queue_stack_map_by_type(STACK); 103 } 104