Jiayuan Chen says: ==================== Optimize bpf selftest to increase CI success rate 1. Optimized some static bound port selftests to avoid port occupation when running test_progs -j. 2. Optimized the retry logic for test_maps. Some Failed CI: https://github.com/kernel-patches/bpf/actions/runs/13275542359/job/37064974076 https://github.com/kernel-patches/bpf/actions/runs/13549227497/job/37868926343 https://github.com/kernel-patches/bpf/actions/runs/13548089029/job/37865812030 https://github.com/kernel-patches/bpf/actions/runs/13553536268/job/37883329296 (Perhaps it's due to the large number of pull requests requiring CI runs?) ====================
Unified · Split
| @@ -72,11 +72,14 @@ static void test_bpf_nf_ct(int mode) · 71 unmodified lines | |||
| 72 | if (!ASSERT_OK(system(cmd), cmd)) | 72 | if (!ASSERT_OK(system(cmd), cmd)) |
| 73 | goto end; | 73 | goto end; |
| 74 | 74 | ||
| 75 | srv_port = (mode == TEST_XDP) ? 5005 : 5006; | 75 | srv_fd = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", 0, TIMEOUT_MS); |
| 76 | srv_fd = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", srv_port, TIMEOUT_MS); | ||
| 77 | if (!ASSERT_GE(srv_fd, 0, "start_server")) | 76 | if (!ASSERT_GE(srv_fd, 0, "start_server")) |
| 78 | goto end; | 77 | goto end; |
| 79 | 78 | ||
| 79 | srv_port = get_socket_local_port(srv_fd); | ||
| 80 | if (!ASSERT_GE(srv_port, 0, "get_sock_local_port")) | ||
| 81 | goto end; | ||
| 82 | |||
| 80 | client_fd = connect_to_server(srv_fd); | 83 | client_fd = connect_to_server(srv_fd); |
| 81 | if (!ASSERT_GE(client_fd, 0, "connect_to_server")) | 84 | if (!ASSERT_GE(client_fd, 0, "connect_to_server")) |
| 82 | goto end; | 85 | goto end; |
| @@ -91,7 +94,7 @@ static void test_bpf_nf_ct(int mode) · 8 unmodified lines | |||
| 91 | skel->bss->saddr = peer_addr.sin_addr.s_addr; | 94 | skel->bss->saddr = peer_addr.sin_addr.s_addr; |
| 92 | skel->bss->sport = peer_addr.sin_port; | 95 | skel->bss->sport = peer_addr.sin_port; |
| 93 | skel->bss->daddr = peer_addr.sin_addr.s_addr; | 96 | skel->bss->daddr = peer_addr.sin_addr.s_addr; |
| 94 | skel->bss->dport = htons(srv_port); | 97 | skel->bss->dport = srv_port; |
| 95 | 98 | ||
| 96 | if (mode == TEST_XDP) | 99 | if (mode == TEST_XDP) |
| 97 | prog_fd = bpf_program__fd(skel->progs.nf_xdp_ct_test); | 100 | prog_fd = bpf_program__fd(skel->progs.nf_xdp_ct_test); |
| @@ -10,12 +10,18 @@ · 9 unmodified lines | |||
| 10 | static int run_test(int cgroup_fd, int server_fd, bool classid) | 10 | static int run_test(int cgroup_fd, int server_fd, bool classid) |
| 11 | { | 11 | { |
| 12 | struct connect4_dropper *skel; | 12 | struct connect4_dropper *skel; |
| 13 | int fd, err = 0; | 13 | int fd, err = 0, port; |
| 14 | 14 | ||
| 15 | skel = connect4_dropper__open_and_load(); | 15 | skel = connect4_dropper__open_and_load(); |
| 16 | if (!ASSERT_OK_PTR(skel, "skel_open")) | 16 | if (!ASSERT_OK_PTR(skel, "skel_open")) |
| 17 | return -1; | 17 | return -1; |
| 18 | 18 | ||
| 19 | port = get_socket_local_port(server_fd); | ||
| 20 | if (!ASSERT_GE(port, 0, "get_socket_local_port")) | ||
| 21 | return -1; | ||
| 22 | |||
| 23 | skel->bss->port = ntohs(port); | ||
| 24 | |||
| 19 | skel->links.connect_v4_dropper = | 25 | skel->links.connect_v4_dropper = |
| 20 | bpf_program__attach_cgroup(skel->progs.connect_v4_dropper, | 26 | bpf_program__attach_cgroup(skel->progs.connect_v4_dropper, |
| 21 | cgroup_fd); | 27 | cgroup_fd); |
| @@ -48,10 +54,9 @@ void test_cgroup_v1v2(void) · 26 unmodified lines | |||
| 48 | { | 54 | { |
| 49 | struct network_helper_opts opts = {}; | 55 | struct network_helper_opts opts = {}; |
| 50 | int server_fd, client_fd, cgroup_fd; | 56 | int server_fd, client_fd, cgroup_fd; |
| 51 | static const int port = 60120; | ||
| 52 | 57 | ||
| 53 | /* Step 1: Check base connectivity works without any BPF. */ | 58 | /* Step 1: Check base connectivity works without any BPF. */ |
| 54 | server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0); | 59 | server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0); |
| 55 | if (!ASSERT_GE(server_fd, 0, "server_fd")) | 60 | if (!ASSERT_GE(server_fd, 0, "server_fd")) |
| 56 | return; | 61 | return; |
| 57 | client_fd = connect_to_fd_opts(server_fd, &opts); | 62 | client_fd = connect_to_fd_opts(server_fd, &opts); |
| @@ -66,7 +71,7 @@ void test_cgroup_v1v2(void) · 8 unmodified lines | |||
| 66 | cgroup_fd = test__join_cgroup("/connect_dropper"); | 71 | cgroup_fd = test__join_cgroup("/connect_dropper"); |
| 67 | if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd")) | 72 | if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd")) |
| 68 | return; | 73 | return; |
| 69 | server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0); | 74 | server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0); |
| 70 | if (!ASSERT_GE(server_fd, 0, "server_fd")) { | 75 | if (!ASSERT_GE(server_fd, 0, "server_fd")) { |
| 71 | close(cgroup_fd); | 76 | close(cgroup_fd); |
| 72 | return; | 77 | return; |
| @@ -13,12 +13,14 @@ · 12 unmodified lines | |||
| 13 | #define VERDICT_REJECT 0 | 13 | #define VERDICT_REJECT 0 |
| 14 | #define VERDICT_PROCEED 1 | 14 | #define VERDICT_PROCEED 1 |
| 15 | 15 | ||
| 16 | int port; | ||
| 17 | |||
| 16 | SEC("cgroup/connect4") | 18 | SEC("cgroup/connect4") |
| 17 | int connect_v4_dropper(struct bpf_sock_addr *ctx) | 19 | int connect_v4_dropper(struct bpf_sock_addr *ctx) |
| 18 | { | 20 | { |
| 19 | if (ctx->type != SOCK_STREAM) | 21 | if (ctx->type != SOCK_STREAM) |
| 20 | return VERDICT_PROCEED; | 22 | return VERDICT_PROCEED; |
| 21 | if (ctx->user_port == bpf_htons(60120)) | 23 | if (ctx->user_port == bpf_htons(port)) |
| 22 | return VERDICT_REJECT; | 24 | return VERDICT_REJECT; |
| 23 | return VERDICT_PROCEED; | 25 | return VERDICT_PROCEED; |
| 24 | } | 26 | } |
| @@ -1396,9 +1396,10 @@ static void test_map_stress(void) · 1395 unmodified lines | |||
| 1396 | #define MAX_DELAY_US 50000 | 1396 | #define MAX_DELAY_US 50000 |
| 1397 | #define MIN_DELAY_RANGE_US 5000 | 1397 | #define MIN_DELAY_RANGE_US 5000 |
| 1398 | 1398 | ||
| 1399 | static bool retry_for_again_or_busy(int err) | 1399 | static bool can_retry(int err) |
| 1400 | { | 1400 | { |
| 1401 | return (err == EAGAIN || err == EBUSY); | 1401 | return (err == EAGAIN || err == EBUSY || |
| 1402 | (err == ENOMEM && map_opts.map_flags == BPF_F_NO_PREALLOC)); | ||
| 1402 | } | 1403 | } |
| 1403 | 1404 | ||
| 1404 | int map_update_retriable(int map_fd, const void *key, const void *value, int flags, int attempts, | 1405 | int map_update_retriable(int map_fd, const void *key, const void *value, int flags, int attempts, |
| @@ -1451,12 +1452,12 @@ static void test_update_delete(unsigned int fn, void *data) · 46 unmodified lines | |||
| 1451 | 1452 | ||
| 1452 | if (do_update) { | 1453 | if (do_update) { |
| 1453 | err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES, | 1454 | err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES, |
| 1454 | retry_for_again_or_busy); | 1455 | can_retry); |
| 1455 | if (err) | 1456 | if (err) |
| 1456 | printf("error %d %d\n", err, errno); | 1457 | printf("error %d %d\n", err, errno); |
| 1457 | assert(err == 0); | 1458 | assert(err == 0); |
| 1458 | err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES, | 1459 | err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES, |
| 1459 | retry_for_again_or_busy); | 1460 | can_retry); |
| 1460 | if (err) | 1461 | if (err) |
| 1461 | printf("error %d %d\n", err, errno); | 1462 | printf("error %d %d\n", err, errno); |
| 1462 | assert(err == 0); | 1463 | assert(err == 0); |