8
8
#include "bpf_dctcp.skel.h"
9
9
#include "bpf_cubic.skel.h"
10
10
#include "bpf_tcp_nogpl.skel.h"
11
+ #include "tcp_ca_update.skel.h"
11
12
#include "bpf_dctcp_release.skel.h"
12
13
#include "tcp_ca_write_sk_pacing.skel.h"
13
14
#include "tcp_ca_incompl_cong_ops.skel.h"
@@ -381,6 +382,155 @@ static void test_unsupp_cong_op(void)
381
382
libbpf_set_print (old_print_fn );
382
383
}
383
384
385
+ static void test_update_ca (void )
386
+ {
387
+ struct tcp_ca_update * skel ;
388
+ struct bpf_link * link ;
389
+ int saved_ca1_cnt ;
390
+ int err ;
391
+
392
+ skel = tcp_ca_update__open_and_load ();
393
+ if (!ASSERT_OK_PTR (skel , "open" ))
394
+ return ;
395
+
396
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
397
+ ASSERT_OK_PTR (link , "attach_struct_ops" );
398
+
399
+ do_test ("tcp_ca_update" , NULL );
400
+ saved_ca1_cnt = skel -> bss -> ca1_cnt ;
401
+ ASSERT_GT (saved_ca1_cnt , 0 , "ca1_ca1_cnt" );
402
+
403
+ err = bpf_link__update_map (link , skel -> maps .ca_update_2 );
404
+ ASSERT_OK (err , "update_map" );
405
+
406
+ do_test ("tcp_ca_update" , NULL );
407
+ ASSERT_EQ (skel -> bss -> ca1_cnt , saved_ca1_cnt , "ca2_ca1_cnt" );
408
+ ASSERT_GT (skel -> bss -> ca2_cnt , 0 , "ca2_ca2_cnt" );
409
+
410
+ bpf_link__destroy (link );
411
+ tcp_ca_update__destroy (skel );
412
+ }
413
+
414
+ static void test_update_wrong (void )
415
+ {
416
+ struct tcp_ca_update * skel ;
417
+ struct bpf_link * link ;
418
+ int saved_ca1_cnt ;
419
+ int err ;
420
+
421
+ skel = tcp_ca_update__open_and_load ();
422
+ if (!ASSERT_OK_PTR (skel , "open" ))
423
+ return ;
424
+
425
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
426
+ ASSERT_OK_PTR (link , "attach_struct_ops" );
427
+
428
+ do_test ("tcp_ca_update" , NULL );
429
+ saved_ca1_cnt = skel -> bss -> ca1_cnt ;
430
+ ASSERT_GT (saved_ca1_cnt , 0 , "ca1_ca1_cnt" );
431
+
432
+ err = bpf_link__update_map (link , skel -> maps .ca_wrong );
433
+ ASSERT_ERR (err , "update_map" );
434
+
435
+ do_test ("tcp_ca_update" , NULL );
436
+ ASSERT_GT (skel -> bss -> ca1_cnt , saved_ca1_cnt , "ca2_ca1_cnt" );
437
+
438
+ bpf_link__destroy (link );
439
+ tcp_ca_update__destroy (skel );
440
+ }
441
+
442
+ static void test_mixed_links (void )
443
+ {
444
+ struct tcp_ca_update * skel ;
445
+ struct bpf_link * link , * link_nl ;
446
+ int err ;
447
+
448
+ skel = tcp_ca_update__open_and_load ();
449
+ if (!ASSERT_OK_PTR (skel , "open" ))
450
+ return ;
451
+
452
+ link_nl = bpf_map__attach_struct_ops (skel -> maps .ca_no_link );
453
+ ASSERT_OK_PTR (link_nl , "attach_struct_ops_nl" );
454
+
455
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
456
+ ASSERT_OK_PTR (link , "attach_struct_ops" );
457
+
458
+ do_test ("tcp_ca_update" , NULL );
459
+ ASSERT_GT (skel -> bss -> ca1_cnt , 0 , "ca1_ca1_cnt" );
460
+
461
+ err = bpf_link__update_map (link , skel -> maps .ca_no_link );
462
+ ASSERT_ERR (err , "update_map" );
463
+
464
+ bpf_link__destroy (link );
465
+ bpf_link__destroy (link_nl );
466
+ tcp_ca_update__destroy (skel );
467
+ }
468
+
469
+ static void test_multi_links (void )
470
+ {
471
+ struct tcp_ca_update * skel ;
472
+ struct bpf_link * link ;
473
+
474
+ skel = tcp_ca_update__open_and_load ();
475
+ if (!ASSERT_OK_PTR (skel , "open" ))
476
+ return ;
477
+
478
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
479
+ ASSERT_OK_PTR (link , "attach_struct_ops_1st" );
480
+ bpf_link__destroy (link );
481
+
482
+ /* A map should be able to be used to create links multiple
483
+ * times.
484
+ */
485
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
486
+ ASSERT_OK_PTR (link , "attach_struct_ops_2nd" );
487
+ bpf_link__destroy (link );
488
+
489
+ tcp_ca_update__destroy (skel );
490
+ }
491
+
492
+ static void test_link_replace (void )
493
+ {
494
+ DECLARE_LIBBPF_OPTS (bpf_link_update_opts , opts );
495
+ struct tcp_ca_update * skel ;
496
+ struct bpf_link * link ;
497
+ int err ;
498
+
499
+ skel = tcp_ca_update__open_and_load ();
500
+ if (!ASSERT_OK_PTR (skel , "open" ))
501
+ return ;
502
+
503
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_1 );
504
+ ASSERT_OK_PTR (link , "attach_struct_ops_1st" );
505
+ bpf_link__destroy (link );
506
+
507
+ link = bpf_map__attach_struct_ops (skel -> maps .ca_update_2 );
508
+ ASSERT_OK_PTR (link , "attach_struct_ops_2nd" );
509
+
510
+ /* BPF_F_REPLACE with a wrong old map Fd. It should fail!
511
+ *
512
+ * With BPF_F_REPLACE, the link should be updated only if the
513
+ * old map fd given here matches the map backing the link.
514
+ */
515
+ opts .old_map_fd = bpf_map__fd (skel -> maps .ca_update_1 );
516
+ opts .flags = BPF_F_REPLACE ;
517
+ err = bpf_link_update (bpf_link__fd (link ),
518
+ bpf_map__fd (skel -> maps .ca_update_1 ),
519
+ & opts );
520
+ ASSERT_ERR (err , "bpf_link_update_fail" );
521
+
522
+ /* BPF_F_REPLACE with a correct old map Fd. It should success! */
523
+ opts .old_map_fd = bpf_map__fd (skel -> maps .ca_update_2 );
524
+ err = bpf_link_update (bpf_link__fd (link ),
525
+ bpf_map__fd (skel -> maps .ca_update_1 ),
526
+ & opts );
527
+ ASSERT_OK (err , "bpf_link_update_success" );
528
+
529
+ bpf_link__destroy (link );
530
+
531
+ tcp_ca_update__destroy (skel );
532
+ }
533
+
384
534
void test_bpf_tcp_ca (void )
385
535
{
386
536
if (test__start_subtest ("dctcp" ))
@@ -399,4 +549,14 @@ void test_bpf_tcp_ca(void)
399
549
test_incompl_cong_ops ();
400
550
if (test__start_subtest ("unsupp_cong_op" ))
401
551
test_unsupp_cong_op ();
552
+ if (test__start_subtest ("update_ca" ))
553
+ test_update_ca ();
554
+ if (test__start_subtest ("update_wrong" ))
555
+ test_update_wrong ();
556
+ if (test__start_subtest ("mixed_links" ))
557
+ test_mixed_links ();
558
+ if (test__start_subtest ("multi_links" ))
559
+ test_multi_links ();
560
+ if (test__start_subtest ("link_replace" ))
561
+ test_link_replace ();
402
562
}
0 commit comments