@@ -2462,3 +2462,170 @@ void serial_test_tc_opts_max(void)
2462
2462
test_tc_opts_max_target (BPF_TCX_INGRESS , BPF_F_AFTER , true);
2463
2463
test_tc_opts_max_target (BPF_TCX_EGRESS , BPF_F_AFTER , false);
2464
2464
}
2465
+
2466
+ static void test_tc_opts_query_target (int target )
2467
+ {
2468
+ const size_t attr_size = offsetofend (union bpf_attr , query );
2469
+ LIBBPF_OPTS (bpf_prog_attach_opts , opta );
2470
+ LIBBPF_OPTS (bpf_prog_detach_opts , optd );
2471
+ LIBBPF_OPTS (bpf_prog_query_opts , optq );
2472
+ __u32 fd1 , fd2 , fd3 , fd4 , id1 , id2 , id3 , id4 ;
2473
+ struct test_tc_link * skel ;
2474
+ union bpf_attr attr ;
2475
+ __u32 prog_ids [5 ];
2476
+ int err ;
2477
+
2478
+ skel = test_tc_link__open_and_load ();
2479
+ if (!ASSERT_OK_PTR (skel , "skel_load" ))
2480
+ goto cleanup ;
2481
+
2482
+ fd1 = bpf_program__fd (skel -> progs .tc1 );
2483
+ fd2 = bpf_program__fd (skel -> progs .tc2 );
2484
+ fd3 = bpf_program__fd (skel -> progs .tc3 );
2485
+ fd4 = bpf_program__fd (skel -> progs .tc4 );
2486
+
2487
+ id1 = id_from_prog_fd (fd1 );
2488
+ id2 = id_from_prog_fd (fd2 );
2489
+ id3 = id_from_prog_fd (fd3 );
2490
+ id4 = id_from_prog_fd (fd4 );
2491
+
2492
+ assert_mprog_count (target , 0 );
2493
+
2494
+ LIBBPF_OPTS_RESET (opta ,
2495
+ .expected_revision = 1 ,
2496
+ );
2497
+
2498
+ err = bpf_prog_attach_opts (fd1 , loopback , target , & opta );
2499
+ if (!ASSERT_EQ (err , 0 , "prog_attach" ))
2500
+ goto cleanup ;
2501
+
2502
+ assert_mprog_count (target , 1 );
2503
+
2504
+ LIBBPF_OPTS_RESET (opta ,
2505
+ .expected_revision = 2 ,
2506
+ );
2507
+
2508
+ err = bpf_prog_attach_opts (fd2 , loopback , target , & opta );
2509
+ if (!ASSERT_EQ (err , 0 , "prog_attach" ))
2510
+ goto cleanup1 ;
2511
+
2512
+ assert_mprog_count (target , 2 );
2513
+
2514
+ LIBBPF_OPTS_RESET (opta ,
2515
+ .expected_revision = 3 ,
2516
+ );
2517
+
2518
+ err = bpf_prog_attach_opts (fd3 , loopback , target , & opta );
2519
+ if (!ASSERT_EQ (err , 0 , "prog_attach" ))
2520
+ goto cleanup2 ;
2521
+
2522
+ assert_mprog_count (target , 3 );
2523
+
2524
+ LIBBPF_OPTS_RESET (opta ,
2525
+ .expected_revision = 4 ,
2526
+ );
2527
+
2528
+ err = bpf_prog_attach_opts (fd4 , loopback , target , & opta );
2529
+ if (!ASSERT_EQ (err , 0 , "prog_attach" ))
2530
+ goto cleanup3 ;
2531
+
2532
+ assert_mprog_count (target , 4 );
2533
+
2534
+ /* Test 1: Double query via libbpf API */
2535
+ err = bpf_prog_query_opts (loopback , target , & optq );
2536
+ if (!ASSERT_OK (err , "prog_query" ))
2537
+ goto cleanup4 ;
2538
+
2539
+ ASSERT_EQ (optq .count , 4 , "count" );
2540
+ ASSERT_EQ (optq .revision , 5 , "revision" );
2541
+ ASSERT_EQ (optq .prog_ids , NULL , "prog_ids" );
2542
+ ASSERT_EQ (optq .link_ids , NULL , "link_ids" );
2543
+
2544
+ memset (prog_ids , 0 , sizeof (prog_ids ));
2545
+ optq .prog_ids = prog_ids ;
2546
+
2547
+ err = bpf_prog_query_opts (loopback , target , & optq );
2548
+ if (!ASSERT_OK (err , "prog_query" ))
2549
+ goto cleanup4 ;
2550
+
2551
+ ASSERT_EQ (optq .count , 4 , "count" );
2552
+ ASSERT_EQ (optq .revision , 5 , "revision" );
2553
+ ASSERT_EQ (optq .prog_ids [0 ], id1 , "prog_ids[0]" );
2554
+ ASSERT_EQ (optq .prog_ids [1 ], id2 , "prog_ids[1]" );
2555
+ ASSERT_EQ (optq .prog_ids [2 ], id3 , "prog_ids[2]" );
2556
+ ASSERT_EQ (optq .prog_ids [3 ], id4 , "prog_ids[3]" );
2557
+ ASSERT_EQ (optq .prog_ids [4 ], 0 , "prog_ids[4]" );
2558
+ ASSERT_EQ (optq .link_ids , NULL , "link_ids" );
2559
+
2560
+ /* Test 2: Double query via bpf_attr & bpf(2) directly */
2561
+ memset (& attr , 0 , attr_size );
2562
+ attr .query .target_ifindex = loopback ;
2563
+ attr .query .attach_type = target ;
2564
+
2565
+ err = syscall (__NR_bpf , BPF_PROG_QUERY , & attr , attr_size );
2566
+ if (!ASSERT_OK (err , "prog_query" ))
2567
+ goto cleanup4 ;
2568
+
2569
+ ASSERT_EQ (attr .query .count , 4 , "count" );
2570
+ ASSERT_EQ (attr .query .revision , 5 , "revision" );
2571
+ ASSERT_EQ (attr .query .query_flags , 0 , "query_flags" );
2572
+ ASSERT_EQ (attr .query .attach_flags , 0 , "attach_flags" );
2573
+ ASSERT_EQ (attr .query .target_ifindex , loopback , "target_ifindex" );
2574
+ ASSERT_EQ (attr .query .attach_type , target , "attach_type" );
2575
+ ASSERT_EQ (attr .query .prog_ids , 0 , "prog_ids" );
2576
+ ASSERT_EQ (attr .query .prog_attach_flags , 0 , "prog_attach_flags" );
2577
+ ASSERT_EQ (attr .query .link_ids , 0 , "link_ids" );
2578
+ ASSERT_EQ (attr .query .link_attach_flags , 0 , "link_attach_flags" );
2579
+
2580
+ memset (prog_ids , 0 , sizeof (prog_ids ));
2581
+ attr .query .prog_ids = ptr_to_u64 (prog_ids );
2582
+
2583
+ err = syscall (__NR_bpf , BPF_PROG_QUERY , & attr , attr_size );
2584
+ if (!ASSERT_OK (err , "prog_query" ))
2585
+ goto cleanup4 ;
2586
+
2587
+ ASSERT_EQ (attr .query .count , 4 , "count" );
2588
+ ASSERT_EQ (attr .query .revision , 5 , "revision" );
2589
+ ASSERT_EQ (attr .query .query_flags , 0 , "query_flags" );
2590
+ ASSERT_EQ (attr .query .attach_flags , 0 , "attach_flags" );
2591
+ ASSERT_EQ (attr .query .target_ifindex , loopback , "target_ifindex" );
2592
+ ASSERT_EQ (attr .query .attach_type , target , "attach_type" );
2593
+ ASSERT_EQ (attr .query .prog_ids , ptr_to_u64 (prog_ids ), "prog_ids" );
2594
+ ASSERT_EQ (prog_ids [0 ], id1 , "prog_ids[0]" );
2595
+ ASSERT_EQ (prog_ids [1 ], id2 , "prog_ids[1]" );
2596
+ ASSERT_EQ (prog_ids [2 ], id3 , "prog_ids[2]" );
2597
+ ASSERT_EQ (prog_ids [3 ], id4 , "prog_ids[3]" );
2598
+ ASSERT_EQ (prog_ids [4 ], 0 , "prog_ids[4]" );
2599
+ ASSERT_EQ (attr .query .prog_attach_flags , 0 , "prog_attach_flags" );
2600
+ ASSERT_EQ (attr .query .link_ids , 0 , "link_ids" );
2601
+ ASSERT_EQ (attr .query .link_attach_flags , 0 , "link_attach_flags" );
2602
+
2603
+ cleanup4 :
2604
+ err = bpf_prog_detach_opts (fd4 , loopback , target , & optd );
2605
+ ASSERT_OK (err , "prog_detach" );
2606
+ assert_mprog_count (target , 3 );
2607
+
2608
+ cleanup3 :
2609
+ err = bpf_prog_detach_opts (fd3 , loopback , target , & optd );
2610
+ ASSERT_OK (err , "prog_detach" );
2611
+ assert_mprog_count (target , 2 );
2612
+
2613
+ cleanup2 :
2614
+ err = bpf_prog_detach_opts (fd2 , loopback , target , & optd );
2615
+ ASSERT_OK (err , "prog_detach" );
2616
+ assert_mprog_count (target , 1 );
2617
+
2618
+ cleanup1 :
2619
+ err = bpf_prog_detach_opts (fd1 , loopback , target , & optd );
2620
+ ASSERT_OK (err , "prog_detach" );
2621
+ assert_mprog_count (target , 0 );
2622
+
2623
+ cleanup :
2624
+ test_tc_link__destroy (skel );
2625
+ }
2626
+
2627
+ void serial_test_tc_opts_query (void )
2628
+ {
2629
+ test_tc_opts_query_target (BPF_TCX_INGRESS );
2630
+ test_tc_opts_query_target (BPF_TCX_EGRESS );
2631
+ }
0 commit comments