1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 #include <network_helpers.h> 4 5 static void test_xdp_update_frags(void) 6 { 7 const char *file = "./test_xdp_update_frags.o"; 8 int err, prog_fd, max_skb_frags, buf_size, num; 9 struct bpf_program *prog; 10 struct bpf_object *obj; 11 __u32 *offset; 12 __u8 *buf; 13 FILE *f; 14 LIBBPF_OPTS(bpf_test_run_opts, topts); 15 16 obj = bpf_object__open(file); 17 if (libbpf_get_error(obj)) 18 return; 19 20 prog = bpf_object__next_program(obj, NULL); 21 if (bpf_object__load(obj)) 22 return; 23 24 prog_fd = bpf_program__fd(prog); 25 26 buf = malloc(128); 27 if (!ASSERT_OK_PTR(buf, "alloc buf 128b")) 28 goto out; 29 30 memset(buf, 0, 128); 31 offset = (__u32 *)buf; 32 *offset = 16; 33 buf[*offset] = 0xaa; /* marker at offset 16 (head) */ 34 buf[*offset + 15] = 0xaa; /* marker at offset 31 (head) */ 35 36 topts.data_in = buf; 37 topts.data_out = buf; 38 topts.data_size_in = 128; 39 topts.data_size_out = 128; 40 41 err = bpf_prog_test_run_opts(prog_fd, &topts); 42 43 /* test_xdp_update_frags: buf[16,31]: 0xaa -> 0xbb */ 44 ASSERT_OK(err, "xdp_update_frag"); 45 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval"); 46 ASSERT_EQ(buf[16], 0xbb, "xdp_update_frag buf[16]"); 47 ASSERT_EQ(buf[31], 0xbb, "xdp_update_frag buf[31]"); 48 49 free(buf); 50 51 buf = malloc(9000); 52 if (!ASSERT_OK_PTR(buf, "alloc buf 9Kb")) 53 goto out; 54 55 memset(buf, 0, 9000); 56 offset = (__u32 *)buf; 57 *offset = 5000; 58 buf[*offset] = 0xaa; /* marker at offset 5000 (frag0) */ 59 buf[*offset + 15] = 0xaa; /* marker at offset 5015 (frag0) */ 60 61 topts.data_in = buf; 62 topts.data_out = buf; 63 topts.data_size_in = 9000; 64 topts.data_size_out = 9000; 65 66 err = bpf_prog_test_run_opts(prog_fd, &topts); 67 68 /* test_xdp_update_frags: buf[5000,5015]: 0xaa -> 0xbb */ 69 ASSERT_OK(err, "xdp_update_frag"); 70 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval"); 71 ASSERT_EQ(buf[5000], 0xbb, "xdp_update_frag buf[5000]"); 72 ASSERT_EQ(buf[5015], 0xbb, "xdp_update_frag buf[5015]"); 73 74 memset(buf, 0, 9000); 75 offset = (__u32 *)buf; 76 *offset = 3510; 77 buf[*offset] = 0xaa; /* marker at offset 3510 (head) */ 78 buf[*offset + 15] = 0xaa; /* marker at offset 3525 (frag0) */ 79 80 err = bpf_prog_test_run_opts(prog_fd, &topts); 81 82 /* test_xdp_update_frags: buf[3510,3525]: 0xaa -> 0xbb */ 83 ASSERT_OK(err, "xdp_update_frag"); 84 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval"); 85 ASSERT_EQ(buf[3510], 0xbb, "xdp_update_frag buf[3510]"); 86 ASSERT_EQ(buf[3525], 0xbb, "xdp_update_frag buf[3525]"); 87 88 memset(buf, 0, 9000); 89 offset = (__u32 *)buf; 90 *offset = 7606; 91 buf[*offset] = 0xaa; /* marker at offset 7606 (frag0) */ 92 buf[*offset + 15] = 0xaa; /* marker at offset 7621 (frag1) */ 93 94 err = bpf_prog_test_run_opts(prog_fd, &topts); 95 96 /* test_xdp_update_frags: buf[7606,7621]: 0xaa -> 0xbb */ 97 ASSERT_OK(err, "xdp_update_frag"); 98 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval"); 99 ASSERT_EQ(buf[7606], 0xbb, "xdp_update_frag buf[7606]"); 100 ASSERT_EQ(buf[7621], 0xbb, "xdp_update_frag buf[7621]"); 101 102 free(buf); 103 104 /* test_xdp_update_frags: unsupported buffer size */ 105 f = fopen("/proc/sys/net/core/max_skb_frags", "r"); 106 if (!ASSERT_OK_PTR(f, "max_skb_frag file pointer")) 107 goto out; 108 109 num = fscanf(f, "%d", &max_skb_frags); 110 fclose(f); 111 112 if (!ASSERT_EQ(num, 1, "max_skb_frags read failed")) 113 goto out; 114 115 /* xdp_buff linear area size is always set to 4096 in the 116 * bpf_prog_test_run_xdp routine. 117 */ 118 buf_size = 4096 + (max_skb_frags + 1) * sysconf(_SC_PAGE_SIZE); 119 buf = malloc(buf_size); 120 if (!ASSERT_OK_PTR(buf, "alloc buf")) 121 goto out; 122 123 memset(buf, 0, buf_size); 124 offset = (__u32 *)buf; 125 *offset = 16; 126 buf[*offset] = 0xaa; 127 buf[*offset + 15] = 0xaa; 128 129 topts.data_in = buf; 130 topts.data_out = buf; 131 topts.data_size_in = buf_size; 132 topts.data_size_out = buf_size; 133 134 err = bpf_prog_test_run_opts(prog_fd, &topts); 135 ASSERT_EQ(err, -ENOMEM, 136 "unsupported buf size, possible non-default /proc/sys/net/core/max_skb_flags?"); 137 free(buf); 138 out: 139 bpf_object__close(obj); 140 } 141 142 void test_xdp_adjust_frags(void) 143 { 144 if (test__start_subtest("xdp_adjust_frags")) 145 test_xdp_update_frags(); 146 } 147