1cd13c91dSDaniel Borkmann // SPDX-License-Identifier: GPL-2.0 2cd13c91dSDaniel Borkmann /* Copyright (c) 2023 Isovalent */ 3cd13c91dSDaniel Borkmann #include <uapi/linux/if_link.h> 4cd13c91dSDaniel Borkmann #include <net/if.h> 5cd13c91dSDaniel Borkmann #include <test_progs.h> 6cd13c91dSDaniel Borkmann 7cd13c91dSDaniel Borkmann #define loopback 1 8cd13c91dSDaniel Borkmann #define ping_cmd "ping -q -c1 -w1 127.0.0.1 > /dev/null" 9cd13c91dSDaniel Borkmann 10cd13c91dSDaniel Borkmann #include "test_tc_link.skel.h" 11cd13c91dSDaniel Borkmann #include "tc_helpers.h" 12cd13c91dSDaniel Borkmann 13cd13c91dSDaniel Borkmann void serial_test_tc_opts_basic(void) 14cd13c91dSDaniel Borkmann { 15cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 16cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 17cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 18cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2; 19cd13c91dSDaniel Borkmann struct test_tc_link *skel; 20cd13c91dSDaniel Borkmann __u32 prog_ids[2]; 21cd13c91dSDaniel Borkmann int err; 22cd13c91dSDaniel Borkmann 23cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 24cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 25cd13c91dSDaniel Borkmann goto cleanup; 26cd13c91dSDaniel Borkmann 27cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 28cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 29cd13c91dSDaniel Borkmann 30cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 31cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 32cd13c91dSDaniel Borkmann 33cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 34cd13c91dSDaniel Borkmann 35cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 0); 36cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0); 37cd13c91dSDaniel Borkmann 38cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1"); 39cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); 40cd13c91dSDaniel Borkmann 41cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, BPF_TCX_INGRESS, &opta); 42cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 43cd13c91dSDaniel Borkmann goto cleanup; 44cd13c91dSDaniel Borkmann 45cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1); 46cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0); 47cd13c91dSDaniel Borkmann 48cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 49cd13c91dSDaniel Borkmann 50cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 51cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 52cd13c91dSDaniel Borkmann 53cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, BPF_TCX_INGRESS, &optq); 54cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 55cd13c91dSDaniel Borkmann goto cleanup_in; 56cd13c91dSDaniel Borkmann 57cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count"); 58cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 2, "revision"); 59cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 60cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); 61cd13c91dSDaniel Borkmann 62cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 63cd13c91dSDaniel Borkmann 64cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 65cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); 66cd13c91dSDaniel Borkmann 67cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, BPF_TCX_EGRESS, &opta); 68cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 69cd13c91dSDaniel Borkmann goto cleanup_in; 70cd13c91dSDaniel Borkmann 71cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1); 72cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 1); 73cd13c91dSDaniel Borkmann 74cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 75cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 76cd13c91dSDaniel Borkmann 77cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, BPF_TCX_EGRESS, &optq); 78cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 79cd13c91dSDaniel Borkmann goto cleanup_eg; 80cd13c91dSDaniel Borkmann 81cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count"); 82cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 2, "revision"); 83cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 84cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); 85cd13c91dSDaniel Borkmann 86cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 87cd13c91dSDaniel Borkmann 88cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 89cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 90cd13c91dSDaniel Borkmann 91cd13c91dSDaniel Borkmann cleanup_eg: 92cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, BPF_TCX_EGRESS, &optd); 93cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach_eg"); 94cd13c91dSDaniel Borkmann 95cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1); 96cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0); 97cd13c91dSDaniel Borkmann 98cd13c91dSDaniel Borkmann cleanup_in: 99cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, BPF_TCX_INGRESS, &optd); 100cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach_in"); 101cd13c91dSDaniel Borkmann 102cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 0); 103cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0); 104cd13c91dSDaniel Borkmann 105cd13c91dSDaniel Borkmann cleanup: 106cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 107cd13c91dSDaniel Borkmann } 108cd13c91dSDaniel Borkmann 109cd13c91dSDaniel Borkmann static void test_tc_opts_before_target(int target) 110cd13c91dSDaniel Borkmann { 111cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 112cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 113cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 114cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 115cd13c91dSDaniel Borkmann struct test_tc_link *skel; 116cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 117cd13c91dSDaniel Borkmann int err; 118cd13c91dSDaniel Borkmann 119cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 120cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 121cd13c91dSDaniel Borkmann goto cleanup; 122cd13c91dSDaniel Borkmann 123cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 124cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 125cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 126cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 127cd13c91dSDaniel Borkmann 128cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 129cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 130cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 131cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 132cd13c91dSDaniel Borkmann 133cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 134cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 135cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 136cd13c91dSDaniel Borkmann 137cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 138cd13c91dSDaniel Borkmann 139cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 140cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 141cd13c91dSDaniel Borkmann goto cleanup; 142cd13c91dSDaniel Borkmann 143cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 144cd13c91dSDaniel Borkmann 145cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 146cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 147cd13c91dSDaniel Borkmann goto cleanup_target; 148cd13c91dSDaniel Borkmann 149cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 150cd13c91dSDaniel Borkmann 151cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 152cd13c91dSDaniel Borkmann 153cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 154cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 155cd13c91dSDaniel Borkmann 156cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 157cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 158cd13c91dSDaniel Borkmann goto cleanup_target2; 159cd13c91dSDaniel Borkmann 160cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 161cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 162cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 163cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 164cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 165cd13c91dSDaniel Borkmann 166cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 167cd13c91dSDaniel Borkmann 168cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 169cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 170cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 171cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); 172cd13c91dSDaniel Borkmann 173cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 174cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 175cd13c91dSDaniel Borkmann .relative_fd = fd2, 176cd13c91dSDaniel Borkmann ); 177cd13c91dSDaniel Borkmann 178cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 179cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 180cd13c91dSDaniel Borkmann goto cleanup_target2; 181cd13c91dSDaniel Borkmann 182cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 183cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 184cd13c91dSDaniel Borkmann 185cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 186cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 187cd13c91dSDaniel Borkmann goto cleanup_target3; 188cd13c91dSDaniel Borkmann 189cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 190cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision"); 191cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 192cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 193cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]"); 194cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 195cd13c91dSDaniel Borkmann 196cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 197cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 198cd13c91dSDaniel Borkmann .relative_id = id1, 199cd13c91dSDaniel Borkmann ); 200cd13c91dSDaniel Borkmann 201cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 202cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 203cd13c91dSDaniel Borkmann goto cleanup_target3; 204cd13c91dSDaniel Borkmann 205cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 206cd13c91dSDaniel Borkmann 207cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 208cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 209cd13c91dSDaniel Borkmann 210cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 211cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 212cd13c91dSDaniel Borkmann goto cleanup_target4; 213cd13c91dSDaniel Borkmann 214cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 215cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 216cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]"); 217cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); 218cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); 219cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id2, "prog_ids[3]"); 220cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 221cd13c91dSDaniel Borkmann 222cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 223cd13c91dSDaniel Borkmann 224cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 225cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 226cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); 227cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); 228cd13c91dSDaniel Borkmann 229cd13c91dSDaniel Borkmann cleanup_target4: 230cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 231cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 232cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 233cd13c91dSDaniel Borkmann 234cd13c91dSDaniel Borkmann cleanup_target3: 235cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 236cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 237cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 238cd13c91dSDaniel Borkmann 239cd13c91dSDaniel Borkmann cleanup_target2: 240cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 241cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 242cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 243cd13c91dSDaniel Borkmann 244cd13c91dSDaniel Borkmann cleanup_target: 245cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 246cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 247cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 248cd13c91dSDaniel Borkmann 249cd13c91dSDaniel Borkmann cleanup: 250cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 251cd13c91dSDaniel Borkmann } 252cd13c91dSDaniel Borkmann 253cd13c91dSDaniel Borkmann void serial_test_tc_opts_before(void) 254cd13c91dSDaniel Borkmann { 255cd13c91dSDaniel Borkmann test_tc_opts_before_target(BPF_TCX_INGRESS); 256cd13c91dSDaniel Borkmann test_tc_opts_before_target(BPF_TCX_EGRESS); 257cd13c91dSDaniel Borkmann } 258cd13c91dSDaniel Borkmann 259cd13c91dSDaniel Borkmann static void test_tc_opts_after_target(int target) 260cd13c91dSDaniel Borkmann { 261cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 262cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 263cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 264cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 265cd13c91dSDaniel Borkmann struct test_tc_link *skel; 266cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 267cd13c91dSDaniel Borkmann int err; 268cd13c91dSDaniel Borkmann 269cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 270cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 271cd13c91dSDaniel Borkmann goto cleanup; 272cd13c91dSDaniel Borkmann 273cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 274cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 275cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 276cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 277cd13c91dSDaniel Borkmann 278cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 279cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 280cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 281cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 282cd13c91dSDaniel Borkmann 283cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 284cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 285cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 286cd13c91dSDaniel Borkmann 287cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 288cd13c91dSDaniel Borkmann 289cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 290cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 291cd13c91dSDaniel Borkmann goto cleanup; 292cd13c91dSDaniel Borkmann 293cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 294cd13c91dSDaniel Borkmann 295cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 296cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 297cd13c91dSDaniel Borkmann goto cleanup_target; 298cd13c91dSDaniel Borkmann 299cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 300cd13c91dSDaniel Borkmann 301cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 302cd13c91dSDaniel Borkmann 303cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 304cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 305cd13c91dSDaniel Borkmann 306cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 307cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 308cd13c91dSDaniel Borkmann goto cleanup_target2; 309cd13c91dSDaniel Borkmann 310cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 311cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 312cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 313cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 314cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 315cd13c91dSDaniel Borkmann 316cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 317cd13c91dSDaniel Borkmann 318cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 319cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 320cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 321cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); 322cd13c91dSDaniel Borkmann 323cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 324cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 325cd13c91dSDaniel Borkmann .relative_fd = fd1, 326cd13c91dSDaniel Borkmann ); 327cd13c91dSDaniel Borkmann 328cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 329cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 330cd13c91dSDaniel Borkmann goto cleanup_target2; 331cd13c91dSDaniel Borkmann 332cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 333cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 334cd13c91dSDaniel Borkmann 335cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 336cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 337cd13c91dSDaniel Borkmann goto cleanup_target3; 338cd13c91dSDaniel Borkmann 339cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 340cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision"); 341cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 342cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 343cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]"); 344cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 345cd13c91dSDaniel Borkmann 346cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 347cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 348cd13c91dSDaniel Borkmann .relative_id = id2, 349cd13c91dSDaniel Borkmann ); 350cd13c91dSDaniel Borkmann 351cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 352cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 353cd13c91dSDaniel Borkmann goto cleanup_target3; 354cd13c91dSDaniel Borkmann 355cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 356cd13c91dSDaniel Borkmann 357cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 358cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 359cd13c91dSDaniel Borkmann 360cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 361cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 362cd13c91dSDaniel Borkmann goto cleanup_target4; 363cd13c91dSDaniel Borkmann 364cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 365cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 366cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 367cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 368cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]"); 369cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); 370cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 371cd13c91dSDaniel Borkmann 372cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 373cd13c91dSDaniel Borkmann 374cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 375cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 376cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); 377cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); 378cd13c91dSDaniel Borkmann 379cd13c91dSDaniel Borkmann cleanup_target4: 380cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 381cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 382cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 383cd13c91dSDaniel Borkmann 384cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 385cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 386cd13c91dSDaniel Borkmann 387cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 388cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 389cd13c91dSDaniel Borkmann goto cleanup_target3; 390cd13c91dSDaniel Borkmann 391cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 392cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision"); 393cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 394cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 395cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]"); 396cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 397cd13c91dSDaniel Borkmann 398cd13c91dSDaniel Borkmann cleanup_target3: 399cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 400cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 401cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 402cd13c91dSDaniel Borkmann 403cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 404cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 405cd13c91dSDaniel Borkmann 406cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 407cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 408cd13c91dSDaniel Borkmann goto cleanup_target2; 409cd13c91dSDaniel Borkmann 410cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 411cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision"); 412cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 413cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 414cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 415cd13c91dSDaniel Borkmann 416cd13c91dSDaniel Borkmann cleanup_target2: 417cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 418cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 419cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 420cd13c91dSDaniel Borkmann 421cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 422cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 423cd13c91dSDaniel Borkmann 424cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 425cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 426cd13c91dSDaniel Borkmann goto cleanup_target; 427cd13c91dSDaniel Borkmann 428cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count"); 429cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision"); 430cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 431cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); 432cd13c91dSDaniel Borkmann 433cd13c91dSDaniel Borkmann cleanup_target: 434cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 435cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 436cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 437cd13c91dSDaniel Borkmann 438cd13c91dSDaniel Borkmann cleanup: 439cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 440cd13c91dSDaniel Borkmann } 441cd13c91dSDaniel Borkmann 442cd13c91dSDaniel Borkmann void serial_test_tc_opts_after(void) 443cd13c91dSDaniel Borkmann { 444cd13c91dSDaniel Borkmann test_tc_opts_after_target(BPF_TCX_INGRESS); 445cd13c91dSDaniel Borkmann test_tc_opts_after_target(BPF_TCX_EGRESS); 446cd13c91dSDaniel Borkmann } 447cd13c91dSDaniel Borkmann 448cd13c91dSDaniel Borkmann static void test_tc_opts_revision_target(int target) 449cd13c91dSDaniel Borkmann { 450cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 451cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 452cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 453cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2; 454cd13c91dSDaniel Borkmann struct test_tc_link *skel; 455cd13c91dSDaniel Borkmann __u32 prog_ids[3]; 456cd13c91dSDaniel Borkmann int err; 457cd13c91dSDaniel Borkmann 458cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 459cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 460cd13c91dSDaniel Borkmann goto cleanup; 461cd13c91dSDaniel Borkmann 462cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 463cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 464cd13c91dSDaniel Borkmann 465cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 466cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 467cd13c91dSDaniel Borkmann 468cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 469cd13c91dSDaniel Borkmann 470cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 471cd13c91dSDaniel Borkmann 472cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 473cd13c91dSDaniel Borkmann .expected_revision = 1, 474cd13c91dSDaniel Borkmann ); 475cd13c91dSDaniel Borkmann 476cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 477cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 478cd13c91dSDaniel Borkmann goto cleanup; 479cd13c91dSDaniel Borkmann 480cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 481cd13c91dSDaniel Borkmann 482cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 483cd13c91dSDaniel Borkmann .expected_revision = 1, 484cd13c91dSDaniel Borkmann ); 485cd13c91dSDaniel Borkmann 486cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 487cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, -ESTALE, "prog_attach")) 488cd13c91dSDaniel Borkmann goto cleanup_target; 489cd13c91dSDaniel Borkmann 490cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 491cd13c91dSDaniel Borkmann 492cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 493cd13c91dSDaniel Borkmann .expected_revision = 2, 494cd13c91dSDaniel Borkmann ); 495cd13c91dSDaniel Borkmann 496cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 497cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 498cd13c91dSDaniel Borkmann goto cleanup_target; 499cd13c91dSDaniel Borkmann 500cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 501cd13c91dSDaniel Borkmann 502cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 503cd13c91dSDaniel Borkmann 504cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 505cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 506cd13c91dSDaniel Borkmann 507cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 508cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 509cd13c91dSDaniel Borkmann goto cleanup_target2; 510cd13c91dSDaniel Borkmann 511cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 512cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 513cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 514cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 515cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 516cd13c91dSDaniel Borkmann 517cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 518cd13c91dSDaniel Borkmann 519cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 520cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 521cd13c91dSDaniel Borkmann 522cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 523cd13c91dSDaniel Borkmann .expected_revision = 2, 524cd13c91dSDaniel Borkmann ); 525cd13c91dSDaniel Borkmann 526cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 527cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ESTALE, "prog_detach"); 528cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 529cd13c91dSDaniel Borkmann 530cd13c91dSDaniel Borkmann cleanup_target2: 531cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 532cd13c91dSDaniel Borkmann .expected_revision = 3, 533cd13c91dSDaniel Borkmann ); 534cd13c91dSDaniel Borkmann 535cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 536cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 537cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 538cd13c91dSDaniel Borkmann 539cd13c91dSDaniel Borkmann cleanup_target: 540cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd); 541cd13c91dSDaniel Borkmann 542cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 543cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 544cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 545cd13c91dSDaniel Borkmann 546cd13c91dSDaniel Borkmann cleanup: 547cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 548cd13c91dSDaniel Borkmann } 549cd13c91dSDaniel Borkmann 550cd13c91dSDaniel Borkmann void serial_test_tc_opts_revision(void) 551cd13c91dSDaniel Borkmann { 552cd13c91dSDaniel Borkmann test_tc_opts_revision_target(BPF_TCX_INGRESS); 553cd13c91dSDaniel Borkmann test_tc_opts_revision_target(BPF_TCX_EGRESS); 554cd13c91dSDaniel Borkmann } 555cd13c91dSDaniel Borkmann 556cd13c91dSDaniel Borkmann static void test_tc_chain_classic(int target, bool chain_tc_old) 557cd13c91dSDaniel Borkmann { 558cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1); 559cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tc_hook, tc_hook, .ifindex = loopback); 560cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 561cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 562cd13c91dSDaniel Borkmann bool hook_created = false, tc_attached = false; 563cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, id1, id2, id3; 564cd13c91dSDaniel Borkmann struct test_tc_link *skel; 565cd13c91dSDaniel Borkmann int err; 566cd13c91dSDaniel Borkmann 567cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 568cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 569cd13c91dSDaniel Borkmann goto cleanup; 570cd13c91dSDaniel Borkmann 571cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 572cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 573cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 574cd13c91dSDaniel Borkmann 575cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 576cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 577cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 578cd13c91dSDaniel Borkmann 579cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 580cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 581cd13c91dSDaniel Borkmann 582cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 583cd13c91dSDaniel Borkmann 584cd13c91dSDaniel Borkmann if (chain_tc_old) { 585cd13c91dSDaniel Borkmann tc_hook.attach_point = target == BPF_TCX_INGRESS ? 586cd13c91dSDaniel Borkmann BPF_TC_INGRESS : BPF_TC_EGRESS; 587cd13c91dSDaniel Borkmann err = bpf_tc_hook_create(&tc_hook); 588cd13c91dSDaniel Borkmann if (err == 0) 589cd13c91dSDaniel Borkmann hook_created = true; 590cd13c91dSDaniel Borkmann err = err == -EEXIST ? 0 : err; 591cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_hook_create")) 592cd13c91dSDaniel Borkmann goto cleanup; 593cd13c91dSDaniel Borkmann 594cd13c91dSDaniel Borkmann tc_opts.prog_fd = fd3; 595cd13c91dSDaniel Borkmann err = bpf_tc_attach(&tc_hook, &tc_opts); 596cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_attach")) 597cd13c91dSDaniel Borkmann goto cleanup; 598cd13c91dSDaniel Borkmann tc_attached = true; 599cd13c91dSDaniel Borkmann } 600cd13c91dSDaniel Borkmann 601cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 602cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 603cd13c91dSDaniel Borkmann goto cleanup; 604cd13c91dSDaniel Borkmann 605cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 606cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 607cd13c91dSDaniel Borkmann goto cleanup_detach; 608cd13c91dSDaniel Borkmann 609cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 610cd13c91dSDaniel Borkmann 611cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 612cd13c91dSDaniel Borkmann 613cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 614cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 615cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); 616cd13c91dSDaniel Borkmann 617cd13c91dSDaniel Borkmann skel->bss->seen_tc1 = false; 618cd13c91dSDaniel Borkmann skel->bss->seen_tc2 = false; 619cd13c91dSDaniel Borkmann skel->bss->seen_tc3 = false; 620cd13c91dSDaniel Borkmann 621cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 622cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_detach")) 623cd13c91dSDaniel Borkmann goto cleanup_detach; 624cd13c91dSDaniel Borkmann 625cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 626cd13c91dSDaniel Borkmann 627cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 628cd13c91dSDaniel Borkmann 629cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 630cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); 631cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); 632cd13c91dSDaniel Borkmann 633cd13c91dSDaniel Borkmann cleanup_detach: 634cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 635cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_detach")) 636cd13c91dSDaniel Borkmann goto cleanup; 637cd13c91dSDaniel Borkmann 638cd13c91dSDaniel Borkmann __assert_mprog_count(target, 0, chain_tc_old, loopback); 639cd13c91dSDaniel Borkmann cleanup: 640cd13c91dSDaniel Borkmann if (tc_attached) { 641cd13c91dSDaniel Borkmann tc_opts.flags = tc_opts.prog_fd = tc_opts.prog_id = 0; 642cd13c91dSDaniel Borkmann err = bpf_tc_detach(&tc_hook, &tc_opts); 643cd13c91dSDaniel Borkmann ASSERT_OK(err, "bpf_tc_detach"); 644cd13c91dSDaniel Borkmann } 645cd13c91dSDaniel Borkmann if (hook_created) { 646cd13c91dSDaniel Borkmann tc_hook.attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS; 647cd13c91dSDaniel Borkmann bpf_tc_hook_destroy(&tc_hook); 648cd13c91dSDaniel Borkmann } 649cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 650cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 651cd13c91dSDaniel Borkmann } 652cd13c91dSDaniel Borkmann 653cd13c91dSDaniel Borkmann void serial_test_tc_opts_chain_classic(void) 654cd13c91dSDaniel Borkmann { 655cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_INGRESS, false); 656cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_EGRESS, false); 657cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_INGRESS, true); 658cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_EGRESS, true); 659cd13c91dSDaniel Borkmann } 660cd13c91dSDaniel Borkmann 661cd13c91dSDaniel Borkmann static void test_tc_opts_replace_target(int target) 662cd13c91dSDaniel Borkmann { 663cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 664cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 665cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 666cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, id1, id2, id3, detach_fd; 667cd13c91dSDaniel Borkmann __u32 prog_ids[4], prog_flags[4]; 668cd13c91dSDaniel Borkmann struct test_tc_link *skel; 669cd13c91dSDaniel Borkmann int err; 670cd13c91dSDaniel Borkmann 671cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 672cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 673cd13c91dSDaniel Borkmann goto cleanup; 674cd13c91dSDaniel Borkmann 675cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 676cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 677cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 678cd13c91dSDaniel Borkmann 679cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 680cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 681cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 682cd13c91dSDaniel Borkmann 683cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 684cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 685cd13c91dSDaniel Borkmann 686cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 687cd13c91dSDaniel Borkmann 688cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 689cd13c91dSDaniel Borkmann .expected_revision = 1, 690cd13c91dSDaniel Borkmann ); 691cd13c91dSDaniel Borkmann 692cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 693cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 694cd13c91dSDaniel Borkmann goto cleanup; 695cd13c91dSDaniel Borkmann 696cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 697cd13c91dSDaniel Borkmann 698cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 699cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 700cd13c91dSDaniel Borkmann .relative_id = id1, 701cd13c91dSDaniel Borkmann .expected_revision = 2, 702cd13c91dSDaniel Borkmann ); 703cd13c91dSDaniel Borkmann 704cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 705cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 706cd13c91dSDaniel Borkmann goto cleanup_target; 707cd13c91dSDaniel Borkmann 708cd13c91dSDaniel Borkmann detach_fd = fd2; 709cd13c91dSDaniel Borkmann 710cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 711cd13c91dSDaniel Borkmann 712cd13c91dSDaniel Borkmann optq.prog_attach_flags = prog_flags; 713cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 714cd13c91dSDaniel Borkmann 715cd13c91dSDaniel Borkmann memset(prog_flags, 0, sizeof(prog_flags)); 716cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 717cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 718cd13c91dSDaniel Borkmann 719cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 720cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 721cd13c91dSDaniel Borkmann goto cleanup_target2; 722cd13c91dSDaniel Borkmann 723cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 724cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 725cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 726cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); 727cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 728cd13c91dSDaniel Borkmann 729cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[0], 0, "prog_flags[0]"); 730cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]"); 731cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]"); 732cd13c91dSDaniel Borkmann 733cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 734cd13c91dSDaniel Borkmann 735cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 736cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 737cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 738cd13c91dSDaniel Borkmann 739cd13c91dSDaniel Borkmann skel->bss->seen_tc1 = false; 740cd13c91dSDaniel Borkmann skel->bss->seen_tc2 = false; 741cd13c91dSDaniel Borkmann skel->bss->seen_tc3 = false; 742cd13c91dSDaniel Borkmann 743cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 744cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 745cd13c91dSDaniel Borkmann .replace_prog_fd = fd2, 746cd13c91dSDaniel Borkmann .expected_revision = 3, 747cd13c91dSDaniel Borkmann ); 748cd13c91dSDaniel Borkmann 749cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 750cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 751cd13c91dSDaniel Borkmann goto cleanup_target2; 752cd13c91dSDaniel Borkmann 753cd13c91dSDaniel Borkmann detach_fd = fd3; 754cd13c91dSDaniel Borkmann 755cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 756cd13c91dSDaniel Borkmann 757cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 758cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 759cd13c91dSDaniel Borkmann 760cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 761cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 762cd13c91dSDaniel Borkmann goto cleanup_target2; 763cd13c91dSDaniel Borkmann 764cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 765cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision"); 766cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id3, "prog_ids[0]"); 767cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); 768cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 769cd13c91dSDaniel Borkmann 770cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 771cd13c91dSDaniel Borkmann 772cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 773cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); 774cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); 775cd13c91dSDaniel Borkmann 776cd13c91dSDaniel Borkmann skel->bss->seen_tc1 = false; 777cd13c91dSDaniel Borkmann skel->bss->seen_tc2 = false; 778cd13c91dSDaniel Borkmann skel->bss->seen_tc3 = false; 779cd13c91dSDaniel Borkmann 780cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 781cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE | BPF_F_BEFORE, 782cd13c91dSDaniel Borkmann .replace_prog_fd = fd3, 783cd13c91dSDaniel Borkmann .relative_fd = fd1, 784cd13c91dSDaniel Borkmann .expected_revision = 4, 785cd13c91dSDaniel Borkmann ); 786cd13c91dSDaniel Borkmann 787cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 788cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 789cd13c91dSDaniel Borkmann goto cleanup_target2; 790cd13c91dSDaniel Borkmann 791cd13c91dSDaniel Borkmann detach_fd = fd2; 792cd13c91dSDaniel Borkmann 793cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 794cd13c91dSDaniel Borkmann 795cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 796cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 797cd13c91dSDaniel Borkmann 798cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 799cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 800cd13c91dSDaniel Borkmann goto cleanup_target2; 801cd13c91dSDaniel Borkmann 802cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 803cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 804cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 805cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); 806cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 807cd13c91dSDaniel Borkmann 808cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 809cd13c91dSDaniel Borkmann 810cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 811cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 812cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 813cd13c91dSDaniel Borkmann 814cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 815cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 816cd13c91dSDaniel Borkmann .replace_prog_fd = fd2, 817cd13c91dSDaniel Borkmann ); 818cd13c91dSDaniel Borkmann 819cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 820cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 821cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 822cd13c91dSDaniel Borkmann 823cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 824cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE | BPF_F_AFTER, 825cd13c91dSDaniel Borkmann .replace_prog_fd = fd2, 826cd13c91dSDaniel Borkmann .relative_fd = fd1, 827cd13c91dSDaniel Borkmann .expected_revision = 5, 828cd13c91dSDaniel Borkmann ); 829cd13c91dSDaniel Borkmann 830cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 831cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach"); 832cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 833cd13c91dSDaniel Borkmann 834cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 835cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER | BPF_F_REPLACE, 836cd13c91dSDaniel Borkmann .replace_prog_fd = fd2, 837cd13c91dSDaniel Borkmann .relative_fd = fd1, 838cd13c91dSDaniel Borkmann .expected_revision = 5, 839cd13c91dSDaniel Borkmann ); 840cd13c91dSDaniel Borkmann 841cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 842cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach"); 843cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 844cd13c91dSDaniel Borkmann 845cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 846cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 847cd13c91dSDaniel Borkmann .relative_id = id1, 848cd13c91dSDaniel Borkmann .expected_revision = 5, 849cd13c91dSDaniel Borkmann ); 850cd13c91dSDaniel Borkmann 851cd13c91dSDaniel Borkmann cleanup_target2: 852cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd); 853cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 854cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 855cd13c91dSDaniel Borkmann 856cd13c91dSDaniel Borkmann cleanup_target: 857cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd); 858cd13c91dSDaniel Borkmann 859cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 860cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 861cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 862cd13c91dSDaniel Borkmann 863cd13c91dSDaniel Borkmann cleanup: 864cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 865cd13c91dSDaniel Borkmann } 866cd13c91dSDaniel Borkmann 867cd13c91dSDaniel Borkmann void serial_test_tc_opts_replace(void) 868cd13c91dSDaniel Borkmann { 869cd13c91dSDaniel Borkmann test_tc_opts_replace_target(BPF_TCX_INGRESS); 870cd13c91dSDaniel Borkmann test_tc_opts_replace_target(BPF_TCX_EGRESS); 871cd13c91dSDaniel Borkmann } 872cd13c91dSDaniel Borkmann 873cd13c91dSDaniel Borkmann static void test_tc_opts_invalid_target(int target) 874cd13c91dSDaniel Borkmann { 875cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 876cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 877cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2; 878cd13c91dSDaniel Borkmann struct test_tc_link *skel; 879cd13c91dSDaniel Borkmann int err; 880cd13c91dSDaniel Borkmann 881cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 882cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 883cd13c91dSDaniel Borkmann goto cleanup; 884cd13c91dSDaniel Borkmann 885cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 886cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 887cd13c91dSDaniel Borkmann 888cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 889cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 890cd13c91dSDaniel Borkmann 891cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 892cd13c91dSDaniel Borkmann 893cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 894cd13c91dSDaniel Borkmann 895cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 896cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER, 897cd13c91dSDaniel Borkmann ); 898cd13c91dSDaniel Borkmann 899cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 900cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach"); 901cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 902cd13c91dSDaniel Borkmann 903cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 904cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_ID, 905cd13c91dSDaniel Borkmann ); 906cd13c91dSDaniel Borkmann 907cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 908cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach"); 909cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 910cd13c91dSDaniel Borkmann 911cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 912cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER | BPF_F_ID, 913cd13c91dSDaniel Borkmann ); 914cd13c91dSDaniel Borkmann 915cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 916cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach"); 917cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 918cd13c91dSDaniel Borkmann 919cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 920cd13c91dSDaniel Borkmann .relative_fd = fd2, 921cd13c91dSDaniel Borkmann ); 922cd13c91dSDaniel Borkmann 923cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 924cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach"); 925cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 926cd13c91dSDaniel Borkmann 927cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 928cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER, 929cd13c91dSDaniel Borkmann .relative_fd = fd2, 930cd13c91dSDaniel Borkmann ); 931cd13c91dSDaniel Borkmann 932cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 933cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach"); 934cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 935cd13c91dSDaniel Borkmann 936cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 937cd13c91dSDaniel Borkmann .flags = BPF_F_ID, 938cd13c91dSDaniel Borkmann .relative_id = id2, 939cd13c91dSDaniel Borkmann ); 940cd13c91dSDaniel Borkmann 941cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 942cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach"); 943cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 944cd13c91dSDaniel Borkmann 945cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 946cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 947cd13c91dSDaniel Borkmann .relative_fd = fd1, 948cd13c91dSDaniel Borkmann ); 949cd13c91dSDaniel Borkmann 950cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 951cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach"); 952cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 953cd13c91dSDaniel Borkmann 954cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 955cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 956cd13c91dSDaniel Borkmann .relative_fd = fd1, 957cd13c91dSDaniel Borkmann ); 958cd13c91dSDaniel Borkmann 959cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 960cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach"); 961cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 962cd13c91dSDaniel Borkmann 963cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta); 964cd13c91dSDaniel Borkmann 965cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 966cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 967cd13c91dSDaniel Borkmann goto cleanup; 968cd13c91dSDaniel Borkmann 969cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 970cd13c91dSDaniel Borkmann 971cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta); 972cd13c91dSDaniel Borkmann 973cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 974cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 975cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 976cd13c91dSDaniel Borkmann 977cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 978cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 979cd13c91dSDaniel Borkmann .relative_fd = fd1, 980cd13c91dSDaniel Borkmann ); 981cd13c91dSDaniel Borkmann 982cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 983cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 984cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 985cd13c91dSDaniel Borkmann 986cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 987cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 988cd13c91dSDaniel Borkmann .relative_fd = fd1, 989cd13c91dSDaniel Borkmann ); 990cd13c91dSDaniel Borkmann 991cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 992cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 993cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 994cd13c91dSDaniel Borkmann 995cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 996cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 997cd13c91dSDaniel Borkmann .relative_fd = fd1, 998cd13c91dSDaniel Borkmann ); 999cd13c91dSDaniel Borkmann 1000cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1001cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach_x1"); 1002cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1003cd13c91dSDaniel Borkmann 1004cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1005cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1006cd13c91dSDaniel Borkmann .replace_prog_fd = fd1, 1007cd13c91dSDaniel Borkmann ); 1008cd13c91dSDaniel Borkmann 1009cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1010cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 1011cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1012cd13c91dSDaniel Borkmann 1013cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1014cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1015cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1016cd13c91dSDaniel Borkmann cleanup: 1017cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1018cd13c91dSDaniel Borkmann } 1019cd13c91dSDaniel Borkmann 1020cd13c91dSDaniel Borkmann void serial_test_tc_opts_invalid(void) 1021cd13c91dSDaniel Borkmann { 1022cd13c91dSDaniel Borkmann test_tc_opts_invalid_target(BPF_TCX_INGRESS); 1023cd13c91dSDaniel Borkmann test_tc_opts_invalid_target(BPF_TCX_EGRESS); 1024cd13c91dSDaniel Borkmann } 1025cd13c91dSDaniel Borkmann 1026cd13c91dSDaniel Borkmann static void test_tc_opts_prepend_target(int target) 1027cd13c91dSDaniel Borkmann { 1028cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1029cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1030cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1031cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 1032cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1033cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 1034cd13c91dSDaniel Borkmann int err; 1035cd13c91dSDaniel Borkmann 1036cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 1037cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 1038cd13c91dSDaniel Borkmann goto cleanup; 1039cd13c91dSDaniel Borkmann 1040cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 1041cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 1042cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 1043cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 1044cd13c91dSDaniel Borkmann 1045cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 1046cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 1047cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 1048cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 1049cd13c91dSDaniel Borkmann 1050cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 1051cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 1052cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 1053cd13c91dSDaniel Borkmann 1054cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1055cd13c91dSDaniel Borkmann 1056cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1057cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1058cd13c91dSDaniel Borkmann goto cleanup; 1059cd13c91dSDaniel Borkmann 1060cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1061cd13c91dSDaniel Borkmann 1062cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1063cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1064cd13c91dSDaniel Borkmann ); 1065cd13c91dSDaniel Borkmann 1066cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 1067cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1068cd13c91dSDaniel Borkmann goto cleanup_target; 1069cd13c91dSDaniel Borkmann 1070cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1071cd13c91dSDaniel Borkmann 1072cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 1073cd13c91dSDaniel Borkmann 1074cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1075cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1076cd13c91dSDaniel Borkmann 1077cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1078cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1079cd13c91dSDaniel Borkmann goto cleanup_target2; 1080cd13c91dSDaniel Borkmann 1081cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 1082cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 1083cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 1084cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); 1085cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 1086cd13c91dSDaniel Borkmann 1087cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 1088cd13c91dSDaniel Borkmann 1089cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 1090cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 1091cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 1092cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); 1093cd13c91dSDaniel Borkmann 1094cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1095cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1096cd13c91dSDaniel Borkmann ); 1097cd13c91dSDaniel Borkmann 1098cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 1099cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1100cd13c91dSDaniel Borkmann goto cleanup_target2; 1101cd13c91dSDaniel Borkmann 1102cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1103cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1104cd13c91dSDaniel Borkmann ); 1105cd13c91dSDaniel Borkmann 1106cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 1107cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1108cd13c91dSDaniel Borkmann goto cleanup_target3; 1109cd13c91dSDaniel Borkmann 1110cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 1111cd13c91dSDaniel Borkmann 1112cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1113cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1114cd13c91dSDaniel Borkmann 1115cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1116cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1117cd13c91dSDaniel Borkmann goto cleanup_target4; 1118cd13c91dSDaniel Borkmann 1119cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 1120cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 1121cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]"); 1122cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 1123cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]"); 1124cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id1, "prog_ids[3]"); 1125cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 1126cd13c91dSDaniel Borkmann 1127cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 1128cd13c91dSDaniel Borkmann 1129cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 1130cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 1131cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); 1132cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); 1133cd13c91dSDaniel Borkmann 1134cd13c91dSDaniel Borkmann cleanup_target4: 1135cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 1136cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1137cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1138cd13c91dSDaniel Borkmann 1139cd13c91dSDaniel Borkmann cleanup_target3: 1140cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1141cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1142cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1143cd13c91dSDaniel Borkmann 1144cd13c91dSDaniel Borkmann cleanup_target2: 1145cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1146cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1147cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1148cd13c91dSDaniel Borkmann 1149cd13c91dSDaniel Borkmann cleanup_target: 1150cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1151cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1152cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1153cd13c91dSDaniel Borkmann 1154cd13c91dSDaniel Borkmann cleanup: 1155cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1156cd13c91dSDaniel Borkmann } 1157cd13c91dSDaniel Borkmann 1158cd13c91dSDaniel Borkmann void serial_test_tc_opts_prepend(void) 1159cd13c91dSDaniel Borkmann { 1160cd13c91dSDaniel Borkmann test_tc_opts_prepend_target(BPF_TCX_INGRESS); 1161cd13c91dSDaniel Borkmann test_tc_opts_prepend_target(BPF_TCX_EGRESS); 1162cd13c91dSDaniel Borkmann } 1163cd13c91dSDaniel Borkmann 1164cd13c91dSDaniel Borkmann static void test_tc_opts_append_target(int target) 1165cd13c91dSDaniel Borkmann { 1166cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1167cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1168cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1169cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 1170cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1171cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 1172cd13c91dSDaniel Borkmann int err; 1173cd13c91dSDaniel Borkmann 1174cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 1175cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 1176cd13c91dSDaniel Borkmann goto cleanup; 1177cd13c91dSDaniel Borkmann 1178cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 1179cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 1180cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 1181cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 1182cd13c91dSDaniel Borkmann 1183cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 1184cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 1185cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 1186cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 1187cd13c91dSDaniel Borkmann 1188cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 1189cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 1190cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 1191cd13c91dSDaniel Borkmann 1192cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1193cd13c91dSDaniel Borkmann 1194cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1195cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1196cd13c91dSDaniel Borkmann goto cleanup; 1197cd13c91dSDaniel Borkmann 1198cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1199cd13c91dSDaniel Borkmann 1200cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1201cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1202cd13c91dSDaniel Borkmann ); 1203cd13c91dSDaniel Borkmann 1204cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 1205cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1206cd13c91dSDaniel Borkmann goto cleanup_target; 1207cd13c91dSDaniel Borkmann 1208cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1209cd13c91dSDaniel Borkmann 1210cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 1211cd13c91dSDaniel Borkmann 1212cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1213cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1214cd13c91dSDaniel Borkmann 1215cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1216cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1217cd13c91dSDaniel Borkmann goto cleanup_target2; 1218cd13c91dSDaniel Borkmann 1219cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 1220cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision"); 1221cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 1222cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 1223cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 1224cd13c91dSDaniel Borkmann 1225cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 1226cd13c91dSDaniel Borkmann 1227cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 1228cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 1229cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); 1230cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); 1231cd13c91dSDaniel Borkmann 1232cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1233cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1234cd13c91dSDaniel Borkmann ); 1235cd13c91dSDaniel Borkmann 1236cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 1237cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1238cd13c91dSDaniel Borkmann goto cleanup_target2; 1239cd13c91dSDaniel Borkmann 1240cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1241cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1242cd13c91dSDaniel Borkmann ); 1243cd13c91dSDaniel Borkmann 1244cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 1245cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1246cd13c91dSDaniel Borkmann goto cleanup_target3; 1247cd13c91dSDaniel Borkmann 1248cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 1249cd13c91dSDaniel Borkmann 1250cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1251cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1252cd13c91dSDaniel Borkmann 1253cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1254cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1255cd13c91dSDaniel Borkmann goto cleanup_target4; 1256cd13c91dSDaniel Borkmann 1257cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 1258cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 1259cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 1260cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 1261cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); 1262cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); 1263cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 1264cd13c91dSDaniel Borkmann 1265cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 1266cd13c91dSDaniel Borkmann 1267cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 1268cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); 1269cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); 1270cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); 1271cd13c91dSDaniel Borkmann 1272cd13c91dSDaniel Borkmann cleanup_target4: 1273cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 1274cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1275cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1276cd13c91dSDaniel Borkmann 1277cd13c91dSDaniel Borkmann cleanup_target3: 1278cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1279cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1280cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1281cd13c91dSDaniel Borkmann 1282cd13c91dSDaniel Borkmann cleanup_target2: 1283cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1284cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1285cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1286cd13c91dSDaniel Borkmann 1287cd13c91dSDaniel Borkmann cleanup_target: 1288cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1289cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1290cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1291cd13c91dSDaniel Borkmann 1292cd13c91dSDaniel Borkmann cleanup: 1293cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1294cd13c91dSDaniel Borkmann } 1295cd13c91dSDaniel Borkmann 1296cd13c91dSDaniel Borkmann void serial_test_tc_opts_append(void) 1297cd13c91dSDaniel Borkmann { 1298cd13c91dSDaniel Borkmann test_tc_opts_append_target(BPF_TCX_INGRESS); 1299cd13c91dSDaniel Borkmann test_tc_opts_append_target(BPF_TCX_EGRESS); 1300cd13c91dSDaniel Borkmann } 1301cd13c91dSDaniel Borkmann 1302cd13c91dSDaniel Borkmann static void test_tc_opts_dev_cleanup_target(int target) 1303cd13c91dSDaniel Borkmann { 1304cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1305cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1306cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1307cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 1308cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1309cd13c91dSDaniel Borkmann int err, ifindex; 1310cd13c91dSDaniel Borkmann 1311cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth"); 1312cd13c91dSDaniel Borkmann ifindex = if_nametoindex("tcx_opts1"); 1313cd13c91dSDaniel Borkmann ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); 1314cd13c91dSDaniel Borkmann 1315cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 1316cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 1317cd13c91dSDaniel Borkmann goto cleanup; 1318cd13c91dSDaniel Borkmann 1319cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 1320cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 1321cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 1322cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 1323cd13c91dSDaniel Borkmann 1324cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 1325cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 1326cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 1327cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 1328cd13c91dSDaniel Borkmann 1329cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 1330cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 1331cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 1332cd13c91dSDaniel Borkmann 1333cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 0); 1334cd13c91dSDaniel Borkmann 1335cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, ifindex, target, &opta); 1336cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1337cd13c91dSDaniel Borkmann goto cleanup; 1338cd13c91dSDaniel Borkmann 1339cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 1); 1340cd13c91dSDaniel Borkmann 1341cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, ifindex, target, &opta); 1342cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1343cd13c91dSDaniel Borkmann goto cleanup1; 1344cd13c91dSDaniel Borkmann 1345cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 2); 1346cd13c91dSDaniel Borkmann 1347cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, ifindex, target, &opta); 1348cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1349cd13c91dSDaniel Borkmann goto cleanup2; 1350cd13c91dSDaniel Borkmann 1351cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 3); 1352cd13c91dSDaniel Borkmann 1353cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, ifindex, target, &opta); 1354cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1355cd13c91dSDaniel Borkmann goto cleanup3; 1356cd13c91dSDaniel Borkmann 1357cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 4); 1358cd13c91dSDaniel Borkmann 1359cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); 1360cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); 1361cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); 1362cd13c91dSDaniel Borkmann return; 1363cd13c91dSDaniel Borkmann cleanup3: 1364cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1365cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1366cd13c91dSDaniel Borkmann 1367cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 2); 1368cd13c91dSDaniel Borkmann cleanup2: 1369cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1370cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1371cd13c91dSDaniel Borkmann 1372cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 1); 1373cd13c91dSDaniel Borkmann cleanup1: 1374cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1375cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1376cd13c91dSDaniel Borkmann 1377cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 0); 1378cd13c91dSDaniel Borkmann cleanup: 1379cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1380cd13c91dSDaniel Borkmann 1381cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); 1382cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); 1383cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); 1384cd13c91dSDaniel Borkmann } 1385cd13c91dSDaniel Borkmann 1386cd13c91dSDaniel Borkmann void serial_test_tc_opts_dev_cleanup(void) 1387cd13c91dSDaniel Borkmann { 1388cd13c91dSDaniel Borkmann test_tc_opts_dev_cleanup_target(BPF_TCX_INGRESS); 1389cd13c91dSDaniel Borkmann test_tc_opts_dev_cleanup_target(BPF_TCX_EGRESS); 1390cd13c91dSDaniel Borkmann } 1391cd13c91dSDaniel Borkmann 1392cd13c91dSDaniel Borkmann static void test_tc_opts_mixed_target(int target) 1393cd13c91dSDaniel Borkmann { 1394cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1395cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1396cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1397cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tcx_opts, optl); 1398cd13c91dSDaniel Borkmann __u32 pid1, pid2, pid3, pid4, lid2, lid4; 1399cd13c91dSDaniel Borkmann __u32 prog_flags[4], link_flags[4]; 1400cd13c91dSDaniel Borkmann __u32 prog_ids[4], link_ids[4]; 1401cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1402cd13c91dSDaniel Borkmann struct bpf_link *link; 1403cd13c91dSDaniel Borkmann int err, detach_fd; 1404cd13c91dSDaniel Borkmann 1405cd13c91dSDaniel Borkmann skel = test_tc_link__open(); 1406cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_open")) 1407cd13c91dSDaniel Borkmann goto cleanup; 1408cd13c91dSDaniel Borkmann 1409cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1, target), 1410cd13c91dSDaniel Borkmann 0, "tc1_attach_type"); 1411cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2, target), 1412cd13c91dSDaniel Borkmann 0, "tc2_attach_type"); 1413cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc3, target), 1414cd13c91dSDaniel Borkmann 0, "tc3_attach_type"); 1415cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc4, target), 1416cd13c91dSDaniel Borkmann 0, "tc4_attach_type"); 1417cd13c91dSDaniel Borkmann 1418cd13c91dSDaniel Borkmann err = test_tc_link__load(skel); 1419cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "skel_load")) 1420cd13c91dSDaniel Borkmann goto cleanup; 1421cd13c91dSDaniel Borkmann 1422cd13c91dSDaniel Borkmann pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1)); 1423cd13c91dSDaniel Borkmann pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2)); 1424cd13c91dSDaniel Borkmann pid3 = id_from_prog_fd(bpf_program__fd(skel->progs.tc3)); 1425cd13c91dSDaniel Borkmann pid4 = id_from_prog_fd(bpf_program__fd(skel->progs.tc4)); 1426cd13c91dSDaniel Borkmann 1427cd13c91dSDaniel Borkmann ASSERT_NEQ(pid1, pid2, "prog_ids_1_2"); 1428cd13c91dSDaniel Borkmann ASSERT_NEQ(pid3, pid4, "prog_ids_3_4"); 1429cd13c91dSDaniel Borkmann ASSERT_NEQ(pid2, pid3, "prog_ids_2_3"); 1430cd13c91dSDaniel Borkmann 1431cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1432cd13c91dSDaniel Borkmann 1433cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1), 1434cd13c91dSDaniel Borkmann loopback, target, &opta); 1435cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1436cd13c91dSDaniel Borkmann goto cleanup; 1437cd13c91dSDaniel Borkmann 1438cd13c91dSDaniel Borkmann detach_fd = bpf_program__fd(skel->progs.tc1); 1439cd13c91dSDaniel Borkmann 1440cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1441cd13c91dSDaniel Borkmann 1442cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc2, loopback, &optl); 1443cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach")) 1444cd13c91dSDaniel Borkmann goto cleanup1; 1445cd13c91dSDaniel Borkmann skel->links.tc2 = link; 1446cd13c91dSDaniel Borkmann 1447cd13c91dSDaniel Borkmann lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2)); 1448cd13c91dSDaniel Borkmann 1449cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1450cd13c91dSDaniel Borkmann 1451cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1452cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1453cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc1), 1454cd13c91dSDaniel Borkmann ); 1455cd13c91dSDaniel Borkmann 1456cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc2), 1457cd13c91dSDaniel Borkmann loopback, target, &opta); 1458cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 1459cd13c91dSDaniel Borkmann 1460cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1461cd13c91dSDaniel Borkmann 1462cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1463cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1464cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc2), 1465cd13c91dSDaniel Borkmann ); 1466cd13c91dSDaniel Borkmann 1467cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1), 1468cd13c91dSDaniel Borkmann loopback, target, &opta); 1469cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 1470cd13c91dSDaniel Borkmann 1471cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1472cd13c91dSDaniel Borkmann 1473cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1474cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1475cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc2), 1476cd13c91dSDaniel Borkmann ); 1477cd13c91dSDaniel Borkmann 1478cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc3), 1479cd13c91dSDaniel Borkmann loopback, target, &opta); 1480cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EBUSY, "prog_attach"); 1481cd13c91dSDaniel Borkmann 1482cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1483cd13c91dSDaniel Borkmann 1484cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1485cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1486cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc1), 1487cd13c91dSDaniel Borkmann ); 1488cd13c91dSDaniel Borkmann 1489cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc3), 1490cd13c91dSDaniel Borkmann loopback, target, &opta); 1491cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1492cd13c91dSDaniel Borkmann goto cleanup1; 1493cd13c91dSDaniel Borkmann 1494cd13c91dSDaniel Borkmann detach_fd = bpf_program__fd(skel->progs.tc3); 1495cd13c91dSDaniel Borkmann 1496cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1497cd13c91dSDaniel Borkmann 1498cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc4, loopback, &optl); 1499cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach")) 1500cd13c91dSDaniel Borkmann goto cleanup1; 1501cd13c91dSDaniel Borkmann skel->links.tc4 = link; 1502cd13c91dSDaniel Borkmann 1503cd13c91dSDaniel Borkmann lid4 = id_from_link_fd(bpf_link__fd(skel->links.tc4)); 1504cd13c91dSDaniel Borkmann 1505cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1506cd13c91dSDaniel Borkmann 1507cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta, 1508cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE, 1509cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc4), 1510cd13c91dSDaniel Borkmann ); 1511cd13c91dSDaniel Borkmann 1512cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc2), 1513cd13c91dSDaniel Borkmann loopback, target, &opta); 1514cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach"); 1515cd13c91dSDaniel Borkmann 1516cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 1517cd13c91dSDaniel Borkmann optq.prog_attach_flags = prog_flags; 1518cd13c91dSDaniel Borkmann optq.link_ids = link_ids; 1519cd13c91dSDaniel Borkmann optq.link_attach_flags = link_flags; 1520cd13c91dSDaniel Borkmann 1521cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1522cd13c91dSDaniel Borkmann memset(prog_flags, 0, sizeof(prog_flags)); 1523cd13c91dSDaniel Borkmann memset(link_ids, 0, sizeof(link_ids)); 1524cd13c91dSDaniel Borkmann memset(link_flags, 0, sizeof(link_flags)); 1525cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1526cd13c91dSDaniel Borkmann 1527cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1528cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1529cd13c91dSDaniel Borkmann goto cleanup1; 1530cd13c91dSDaniel Borkmann 1531cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 1532cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 1533cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], pid3, "prog_ids[0]"); 1534cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[0], 0, "prog_flags[0]"); 1535cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[0], 0, "link_ids[0]"); 1536cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[0], 0, "link_flags[0]"); 1537cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], pid2, "prog_ids[1]"); 1538cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]"); 1539cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[1], lid2, "link_ids[1]"); 1540cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[1], 0, "link_flags[1]"); 1541cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], pid4, "prog_ids[2]"); 1542cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]"); 1543cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[2], lid4, "link_ids[2]"); 1544cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[2], 0, "link_flags[2]"); 1545cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 1546cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[3], 0, "prog_flags[3]"); 1547cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[3], 0, "link_ids[3]"); 1548cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[3], 0, "link_flags[3]"); 1549cd13c91dSDaniel Borkmann 1550cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd); 1551cd13c91dSDaniel Borkmann 1552cd13c91dSDaniel Borkmann cleanup1: 1553cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd); 1554cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1555cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1556cd13c91dSDaniel Borkmann 1557cd13c91dSDaniel Borkmann cleanup: 1558cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1559cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1560cd13c91dSDaniel Borkmann } 1561cd13c91dSDaniel Borkmann 1562cd13c91dSDaniel Borkmann void serial_test_tc_opts_mixed(void) 1563cd13c91dSDaniel Borkmann { 1564cd13c91dSDaniel Borkmann test_tc_opts_mixed_target(BPF_TCX_INGRESS); 1565cd13c91dSDaniel Borkmann test_tc_opts_mixed_target(BPF_TCX_EGRESS); 1566cd13c91dSDaniel Borkmann } 1567cd13c91dSDaniel Borkmann 1568cd13c91dSDaniel Borkmann static void test_tc_opts_demixed_target(int target) 1569cd13c91dSDaniel Borkmann { 1570cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1571cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1572cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tcx_opts, optl); 1573cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1574cd13c91dSDaniel Borkmann struct bpf_link *link; 1575cd13c91dSDaniel Borkmann __u32 pid1, pid2; 1576cd13c91dSDaniel Borkmann int err; 1577cd13c91dSDaniel Borkmann 1578cd13c91dSDaniel Borkmann skel = test_tc_link__open(); 1579cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_open")) 1580cd13c91dSDaniel Borkmann goto cleanup; 1581cd13c91dSDaniel Borkmann 1582cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1, target), 1583cd13c91dSDaniel Borkmann 0, "tc1_attach_type"); 1584cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2, target), 1585cd13c91dSDaniel Borkmann 0, "tc2_attach_type"); 1586cd13c91dSDaniel Borkmann 1587cd13c91dSDaniel Borkmann err = test_tc_link__load(skel); 1588cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "skel_load")) 1589cd13c91dSDaniel Borkmann goto cleanup; 1590cd13c91dSDaniel Borkmann 1591cd13c91dSDaniel Borkmann pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1)); 1592cd13c91dSDaniel Borkmann pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2)); 1593cd13c91dSDaniel Borkmann ASSERT_NEQ(pid1, pid2, "prog_ids_1_2"); 1594cd13c91dSDaniel Borkmann 1595cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1596cd13c91dSDaniel Borkmann 1597cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1), 1598cd13c91dSDaniel Borkmann loopback, target, &opta); 1599cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1600cd13c91dSDaniel Borkmann goto cleanup; 1601cd13c91dSDaniel Borkmann 1602cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1603cd13c91dSDaniel Borkmann 1604cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc2, loopback, &optl); 1605cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach")) 1606cd13c91dSDaniel Borkmann goto cleanup1; 1607cd13c91dSDaniel Borkmann skel->links.tc2 = link; 1608cd13c91dSDaniel Borkmann 1609cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1610cd13c91dSDaniel Borkmann 1611cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1612cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1613cd13c91dSDaniel Borkmann ); 1614cd13c91dSDaniel Borkmann 1615cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1616cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EBUSY, "prog_detach"); 1617cd13c91dSDaniel Borkmann 1618cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1619cd13c91dSDaniel Borkmann 1620cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1621cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1622cd13c91dSDaniel Borkmann ); 1623cd13c91dSDaniel Borkmann 1624cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1625cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1626cd13c91dSDaniel Borkmann 1627cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1628cd13c91dSDaniel Borkmann goto cleanup; 1629cd13c91dSDaniel Borkmann 1630cd13c91dSDaniel Borkmann cleanup1: 1631cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(bpf_program__fd(skel->progs.tc1), 1632cd13c91dSDaniel Borkmann loopback, target, &optd); 1633cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1634cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1635cd13c91dSDaniel Borkmann 1636cd13c91dSDaniel Borkmann cleanup: 1637cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1638cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1639cd13c91dSDaniel Borkmann } 1640cd13c91dSDaniel Borkmann 1641cd13c91dSDaniel Borkmann void serial_test_tc_opts_demixed(void) 1642cd13c91dSDaniel Borkmann { 1643cd13c91dSDaniel Borkmann test_tc_opts_demixed_target(BPF_TCX_INGRESS); 1644cd13c91dSDaniel Borkmann test_tc_opts_demixed_target(BPF_TCX_EGRESS); 1645cd13c91dSDaniel Borkmann } 1646cd13c91dSDaniel Borkmann 1647cd13c91dSDaniel Borkmann static void test_tc_opts_detach_target(int target) 1648cd13c91dSDaniel Borkmann { 1649cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1650cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1651cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1652cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 1653cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1654cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 1655cd13c91dSDaniel Borkmann int err; 1656cd13c91dSDaniel Borkmann 1657cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 1658cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 1659cd13c91dSDaniel Borkmann goto cleanup; 1660cd13c91dSDaniel Borkmann 1661cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 1662cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 1663cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 1664cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 1665cd13c91dSDaniel Borkmann 1666cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 1667cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 1668cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 1669cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 1670cd13c91dSDaniel Borkmann 1671cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 1672cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 1673cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 1674cd13c91dSDaniel Borkmann 1675cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1676cd13c91dSDaniel Borkmann 1677cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1678cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1679cd13c91dSDaniel Borkmann goto cleanup; 1680cd13c91dSDaniel Borkmann 1681cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1682cd13c91dSDaniel Borkmann 1683cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 1684cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1685cd13c91dSDaniel Borkmann goto cleanup1; 1686cd13c91dSDaniel Borkmann 1687cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1688cd13c91dSDaniel Borkmann 1689cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 1690cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1691cd13c91dSDaniel Borkmann goto cleanup2; 1692cd13c91dSDaniel Borkmann 1693cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1694cd13c91dSDaniel Borkmann 1695cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 1696cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1697cd13c91dSDaniel Borkmann goto cleanup3; 1698cd13c91dSDaniel Borkmann 1699cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 1700cd13c91dSDaniel Borkmann 1701cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 1702cd13c91dSDaniel Borkmann 1703cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1704cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1705cd13c91dSDaniel Borkmann 1706cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1707cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1708cd13c91dSDaniel Borkmann goto cleanup4; 1709cd13c91dSDaniel Borkmann 1710cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 1711cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 1712cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 1713cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 1714cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); 1715cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); 1716cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 1717cd13c91dSDaniel Borkmann 1718cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1719cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1720cd13c91dSDaniel Borkmann ); 1721cd13c91dSDaniel Borkmann 1722cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1723cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1724cd13c91dSDaniel Borkmann 1725cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1726cd13c91dSDaniel Borkmann 1727cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1728cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1729cd13c91dSDaniel Borkmann 1730cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1731cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1732cd13c91dSDaniel Borkmann goto cleanup4; 1733cd13c91dSDaniel Borkmann 1734cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 1735cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision"); 1736cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 1737cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 1738cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]"); 1739cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 1740cd13c91dSDaniel Borkmann 1741cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1742cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1743cd13c91dSDaniel Borkmann ); 1744cd13c91dSDaniel Borkmann 1745cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1746cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1747cd13c91dSDaniel Borkmann 1748cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1749cd13c91dSDaniel Borkmann 1750cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1751cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1752cd13c91dSDaniel Borkmann 1753cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1754cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1755cd13c91dSDaniel Borkmann goto cleanup4; 1756cd13c91dSDaniel Borkmann 1757cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 1758cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision"); 1759cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 1760cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 1761cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 1762cd13c91dSDaniel Borkmann 1763cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd); 1764cd13c91dSDaniel Borkmann 1765cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1766cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1767cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1768cd13c91dSDaniel Borkmann 1769cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1770cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1771cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1772cd13c91dSDaniel Borkmann 1773cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1774cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1775cd13c91dSDaniel Borkmann ); 1776cd13c91dSDaniel Borkmann 1777cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1778cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 1779cd13c91dSDaniel Borkmann 1780cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1781cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 1782cd13c91dSDaniel Borkmann ); 1783cd13c91dSDaniel Borkmann 1784cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1785cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 1786cd13c91dSDaniel Borkmann goto cleanup; 1787cd13c91dSDaniel Borkmann 1788cd13c91dSDaniel Borkmann cleanup4: 1789cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 1790cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1791cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1792cd13c91dSDaniel Borkmann 1793cd13c91dSDaniel Borkmann cleanup3: 1794cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 1795cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1796cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1797cd13c91dSDaniel Borkmann 1798cd13c91dSDaniel Borkmann cleanup2: 1799cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1800cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1801cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1802cd13c91dSDaniel Borkmann 1803cd13c91dSDaniel Borkmann cleanup1: 1804cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1805cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1806cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1807cd13c91dSDaniel Borkmann 1808cd13c91dSDaniel Borkmann cleanup: 1809cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 1810cd13c91dSDaniel Borkmann } 1811cd13c91dSDaniel Borkmann 1812cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach(void) 1813cd13c91dSDaniel Borkmann { 1814cd13c91dSDaniel Borkmann test_tc_opts_detach_target(BPF_TCX_INGRESS); 1815cd13c91dSDaniel Borkmann test_tc_opts_detach_target(BPF_TCX_EGRESS); 1816cd13c91dSDaniel Borkmann } 1817cd13c91dSDaniel Borkmann 1818cd13c91dSDaniel Borkmann static void test_tc_opts_detach_before_target(int target) 1819cd13c91dSDaniel Borkmann { 1820cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 1821cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 1822cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 1823cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 1824cd13c91dSDaniel Borkmann struct test_tc_link *skel; 1825cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 1826cd13c91dSDaniel Borkmann int err; 1827cd13c91dSDaniel Borkmann 1828cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 1829cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 1830cd13c91dSDaniel Borkmann goto cleanup; 1831cd13c91dSDaniel Borkmann 1832cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 1833cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 1834cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 1835cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 1836cd13c91dSDaniel Borkmann 1837cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 1838cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 1839cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 1840cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 1841cd13c91dSDaniel Borkmann 1842cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 1843cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 1844cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 1845cd13c91dSDaniel Borkmann 1846cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1847cd13c91dSDaniel Borkmann 1848cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 1849cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1850cd13c91dSDaniel Borkmann goto cleanup; 1851cd13c91dSDaniel Borkmann 1852cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1853cd13c91dSDaniel Borkmann 1854cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 1855cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1856cd13c91dSDaniel Borkmann goto cleanup1; 1857cd13c91dSDaniel Borkmann 1858cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1859cd13c91dSDaniel Borkmann 1860cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 1861cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1862cd13c91dSDaniel Borkmann goto cleanup2; 1863cd13c91dSDaniel Borkmann 1864cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1865cd13c91dSDaniel Borkmann 1866cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 1867cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 1868cd13c91dSDaniel Borkmann goto cleanup3; 1869cd13c91dSDaniel Borkmann 1870cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 1871cd13c91dSDaniel Borkmann 1872cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 1873cd13c91dSDaniel Borkmann 1874cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1875cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1876cd13c91dSDaniel Borkmann 1877cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1878cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1879cd13c91dSDaniel Borkmann goto cleanup4; 1880cd13c91dSDaniel Borkmann 1881cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 1882cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 1883cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 1884cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 1885cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); 1886cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); 1887cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 1888cd13c91dSDaniel Borkmann 1889cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1890cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1891cd13c91dSDaniel Borkmann .relative_fd = fd2, 1892cd13c91dSDaniel Borkmann ); 1893cd13c91dSDaniel Borkmann 1894cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1895cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1896cd13c91dSDaniel Borkmann 1897cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1898cd13c91dSDaniel Borkmann 1899cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1900cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1901cd13c91dSDaniel Borkmann 1902cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1903cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1904cd13c91dSDaniel Borkmann goto cleanup4; 1905cd13c91dSDaniel Borkmann 1906cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 1907cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision"); 1908cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); 1909cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 1910cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]"); 1911cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 1912cd13c91dSDaniel Borkmann 1913cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1914cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1915cd13c91dSDaniel Borkmann .relative_fd = fd2, 1916cd13c91dSDaniel Borkmann ); 1917cd13c91dSDaniel Borkmann 1918cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 1919cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 1920cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1921cd13c91dSDaniel Borkmann 1922cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1923cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1924cd13c91dSDaniel Borkmann .relative_fd = fd4, 1925cd13c91dSDaniel Borkmann ); 1926cd13c91dSDaniel Borkmann 1927cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1928cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach"); 1929cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1930cd13c91dSDaniel Borkmann 1931cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1932cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1933cd13c91dSDaniel Borkmann .relative_fd = fd1, 1934cd13c91dSDaniel Borkmann ); 1935cd13c91dSDaniel Borkmann 1936cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1937cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 1938cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1939cd13c91dSDaniel Borkmann 1940cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1941cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1942cd13c91dSDaniel Borkmann .relative_fd = fd3, 1943cd13c91dSDaniel Borkmann ); 1944cd13c91dSDaniel Borkmann 1945cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 1946cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1947cd13c91dSDaniel Borkmann 1948cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 1949cd13c91dSDaniel Borkmann 1950cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1951cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1952cd13c91dSDaniel Borkmann 1953cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1954cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1955cd13c91dSDaniel Borkmann goto cleanup4; 1956cd13c91dSDaniel Borkmann 1957cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 1958cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision"); 1959cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id3, "prog_ids[0]"); 1960cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id4, "prog_ids[1]"); 1961cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 1962cd13c91dSDaniel Borkmann 1963cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1964cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1965cd13c91dSDaniel Borkmann .relative_fd = fd4, 1966cd13c91dSDaniel Borkmann ); 1967cd13c91dSDaniel Borkmann 1968cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1969cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1970cd13c91dSDaniel Borkmann 1971cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 1972cd13c91dSDaniel Borkmann 1973cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 1974cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 1975cd13c91dSDaniel Borkmann 1976cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 1977cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 1978cd13c91dSDaniel Borkmann goto cleanup4; 1979cd13c91dSDaniel Borkmann 1980cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count"); 1981cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision"); 1982cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]"); 1983cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); 1984cd13c91dSDaniel Borkmann 1985cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 1986cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE, 1987cd13c91dSDaniel Borkmann ); 1988cd13c91dSDaniel Borkmann 1989cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 1990cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1991cd13c91dSDaniel Borkmann 1992cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 1993cd13c91dSDaniel Borkmann goto cleanup; 1994cd13c91dSDaniel Borkmann 1995cd13c91dSDaniel Borkmann cleanup4: 1996cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 1997cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 1998cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 1999cd13c91dSDaniel Borkmann 2000cd13c91dSDaniel Borkmann cleanup3: 2001cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 2002cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2003cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 2004cd13c91dSDaniel Borkmann 2005cd13c91dSDaniel Borkmann cleanup2: 2006cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 2007cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2008cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 2009cd13c91dSDaniel Borkmann 2010cd13c91dSDaniel Borkmann cleanup1: 2011cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 2012cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2013cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 2014cd13c91dSDaniel Borkmann 2015cd13c91dSDaniel Borkmann cleanup: 2016cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 2017cd13c91dSDaniel Borkmann } 2018cd13c91dSDaniel Borkmann 2019cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach_before(void) 2020cd13c91dSDaniel Borkmann { 2021cd13c91dSDaniel Borkmann test_tc_opts_detach_before_target(BPF_TCX_INGRESS); 2022cd13c91dSDaniel Borkmann test_tc_opts_detach_before_target(BPF_TCX_EGRESS); 2023cd13c91dSDaniel Borkmann } 2024cd13c91dSDaniel Borkmann 2025cd13c91dSDaniel Borkmann static void test_tc_opts_detach_after_target(int target) 2026cd13c91dSDaniel Borkmann { 2027cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta); 2028cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 2029cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq); 2030cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; 2031cd13c91dSDaniel Borkmann struct test_tc_link *skel; 2032cd13c91dSDaniel Borkmann __u32 prog_ids[5]; 2033cd13c91dSDaniel Borkmann int err; 2034cd13c91dSDaniel Borkmann 2035cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load(); 2036cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load")) 2037cd13c91dSDaniel Borkmann goto cleanup; 2038cd13c91dSDaniel Borkmann 2039cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1); 2040cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2); 2041cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3); 2042cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4); 2043cd13c91dSDaniel Borkmann 2044cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1); 2045cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2); 2046cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3); 2047cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4); 2048cd13c91dSDaniel Borkmann 2049cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2"); 2050cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4"); 2051cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3"); 2052cd13c91dSDaniel Borkmann 2053cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 2054cd13c91dSDaniel Borkmann 2055cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta); 2056cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 2057cd13c91dSDaniel Borkmann goto cleanup; 2058cd13c91dSDaniel Borkmann 2059cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 2060cd13c91dSDaniel Borkmann 2061cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta); 2062cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 2063cd13c91dSDaniel Borkmann goto cleanup1; 2064cd13c91dSDaniel Borkmann 2065cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 2066cd13c91dSDaniel Borkmann 2067cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta); 2068cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 2069cd13c91dSDaniel Borkmann goto cleanup2; 2070cd13c91dSDaniel Borkmann 2071cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2072cd13c91dSDaniel Borkmann 2073cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta); 2074cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach")) 2075cd13c91dSDaniel Borkmann goto cleanup3; 2076cd13c91dSDaniel Borkmann 2077cd13c91dSDaniel Borkmann assert_mprog_count(target, 4); 2078cd13c91dSDaniel Borkmann 2079cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids; 2080cd13c91dSDaniel Borkmann 2081cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 2082cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 2083cd13c91dSDaniel Borkmann 2084cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 2085cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 2086cd13c91dSDaniel Borkmann goto cleanup4; 2087cd13c91dSDaniel Borkmann 2088cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count"); 2089cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision"); 2090cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 2091cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); 2092cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); 2093cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); 2094cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); 2095cd13c91dSDaniel Borkmann 2096cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2097cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2098cd13c91dSDaniel Borkmann .relative_fd = fd1, 2099cd13c91dSDaniel Borkmann ); 2100cd13c91dSDaniel Borkmann 2101cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 2102cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2103cd13c91dSDaniel Borkmann 2104cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2105cd13c91dSDaniel Borkmann 2106cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 2107cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 2108cd13c91dSDaniel Borkmann 2109cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 2110cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 2111cd13c91dSDaniel Borkmann goto cleanup4; 2112cd13c91dSDaniel Borkmann 2113cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count"); 2114cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision"); 2115cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 2116cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]"); 2117cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]"); 2118cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]"); 2119cd13c91dSDaniel Borkmann 2120cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2121cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2122cd13c91dSDaniel Borkmann .relative_fd = fd1, 2123cd13c91dSDaniel Borkmann ); 2124cd13c91dSDaniel Borkmann 2125cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 2126cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 2127cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2128cd13c91dSDaniel Borkmann 2129cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2130cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2131cd13c91dSDaniel Borkmann .relative_fd = fd4, 2132cd13c91dSDaniel Borkmann ); 2133cd13c91dSDaniel Borkmann 2134cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 2135cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach"); 2136cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2137cd13c91dSDaniel Borkmann 2138cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2139cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2140cd13c91dSDaniel Borkmann .relative_fd = fd3, 2141cd13c91dSDaniel Borkmann ); 2142cd13c91dSDaniel Borkmann 2143cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 2144cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach"); 2145cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2146cd13c91dSDaniel Borkmann 2147cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2148cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2149cd13c91dSDaniel Borkmann .relative_fd = fd1, 2150cd13c91dSDaniel Borkmann ); 2151cd13c91dSDaniel Borkmann 2152cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 2153cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach"); 2154cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2155cd13c91dSDaniel Borkmann 2156cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2157cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2158cd13c91dSDaniel Borkmann .relative_fd = fd1, 2159cd13c91dSDaniel Borkmann ); 2160cd13c91dSDaniel Borkmann 2161cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 2162cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2163cd13c91dSDaniel Borkmann 2164cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 2165cd13c91dSDaniel Borkmann 2166cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 2167cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 2168cd13c91dSDaniel Borkmann 2169cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 2170cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 2171cd13c91dSDaniel Borkmann goto cleanup4; 2172cd13c91dSDaniel Borkmann 2173cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count"); 2174cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision"); 2175cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 2176cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id4, "prog_ids[1]"); 2177cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); 2178cd13c91dSDaniel Borkmann 2179cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2180cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2181cd13c91dSDaniel Borkmann .relative_fd = fd1, 2182cd13c91dSDaniel Borkmann ); 2183cd13c91dSDaniel Borkmann 2184cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 2185cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2186cd13c91dSDaniel Borkmann 2187cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 2188cd13c91dSDaniel Borkmann 2189cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids)); 2190cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids); 2191cd13c91dSDaniel Borkmann 2192cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq); 2193cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query")) 2194cd13c91dSDaniel Borkmann goto cleanup4; 2195cd13c91dSDaniel Borkmann 2196cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count"); 2197cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision"); 2198cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); 2199cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); 2200cd13c91dSDaniel Borkmann 2201cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd, 2202cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER, 2203cd13c91dSDaniel Borkmann ); 2204cd13c91dSDaniel Borkmann 2205cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 2206cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2207cd13c91dSDaniel Borkmann 2208cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 2209cd13c91dSDaniel Borkmann goto cleanup; 2210cd13c91dSDaniel Borkmann 2211cd13c91dSDaniel Borkmann cleanup4: 2212cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd); 2213cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2214cd13c91dSDaniel Borkmann assert_mprog_count(target, 3); 2215cd13c91dSDaniel Borkmann 2216cd13c91dSDaniel Borkmann cleanup3: 2217cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd); 2218cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2219cd13c91dSDaniel Borkmann assert_mprog_count(target, 2); 2220cd13c91dSDaniel Borkmann 2221cd13c91dSDaniel Borkmann cleanup2: 2222cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd); 2223cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2224cd13c91dSDaniel Borkmann assert_mprog_count(target, 1); 2225cd13c91dSDaniel Borkmann 2226cd13c91dSDaniel Borkmann cleanup1: 2227cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd); 2228cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach"); 2229cd13c91dSDaniel Borkmann assert_mprog_count(target, 0); 2230cd13c91dSDaniel Borkmann 2231cd13c91dSDaniel Borkmann cleanup: 2232cd13c91dSDaniel Borkmann test_tc_link__destroy(skel); 2233cd13c91dSDaniel Borkmann } 2234cd13c91dSDaniel Borkmann 2235cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach_after(void) 2236cd13c91dSDaniel Borkmann { 2237cd13c91dSDaniel Borkmann test_tc_opts_detach_after_target(BPF_TCX_INGRESS); 2238cd13c91dSDaniel Borkmann test_tc_opts_detach_after_target(BPF_TCX_EGRESS); 2239cd13c91dSDaniel Borkmann } 2240*21ce6abeSDaniel Borkmann 2241*21ce6abeSDaniel Borkmann static void test_tc_opts_delete_empty(int target, bool chain_tc_old) 2242*21ce6abeSDaniel Borkmann { 2243*21ce6abeSDaniel Borkmann LIBBPF_OPTS(bpf_tc_hook, tc_hook, .ifindex = loopback); 2244*21ce6abeSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd); 2245*21ce6abeSDaniel Borkmann int err; 2246*21ce6abeSDaniel Borkmann 2247*21ce6abeSDaniel Borkmann assert_mprog_count(target, 0); 2248*21ce6abeSDaniel Borkmann if (chain_tc_old) { 2249*21ce6abeSDaniel Borkmann tc_hook.attach_point = target == BPF_TCX_INGRESS ? 2250*21ce6abeSDaniel Borkmann BPF_TC_INGRESS : BPF_TC_EGRESS; 2251*21ce6abeSDaniel Borkmann err = bpf_tc_hook_create(&tc_hook); 2252*21ce6abeSDaniel Borkmann ASSERT_OK(err, "bpf_tc_hook_create"); 2253*21ce6abeSDaniel Borkmann __assert_mprog_count(target, 0, true, loopback); 2254*21ce6abeSDaniel Borkmann } 2255*21ce6abeSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd); 2256*21ce6abeSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach"); 2257*21ce6abeSDaniel Borkmann if (chain_tc_old) { 2258*21ce6abeSDaniel Borkmann tc_hook.attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS; 2259*21ce6abeSDaniel Borkmann bpf_tc_hook_destroy(&tc_hook); 2260*21ce6abeSDaniel Borkmann } 2261*21ce6abeSDaniel Borkmann assert_mprog_count(target, 0); 2262*21ce6abeSDaniel Borkmann } 2263*21ce6abeSDaniel Borkmann 2264*21ce6abeSDaniel Borkmann void serial_test_tc_opts_delete_empty(void) 2265*21ce6abeSDaniel Borkmann { 2266*21ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_INGRESS, false); 2267*21ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_EGRESS, false); 2268*21ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_INGRESS, true); 2269*21ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_EGRESS, true); 2270*21ce6abeSDaniel Borkmann } 2271