// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2021 Facebook */ #include "bpf_iter.h" #include "bpf_tracing_net.h" #include <bpf/bpf_helpers.h> #include <bpf/bpf_endian.h> #define bpf_tcp_sk(skc) ({ \ struct sock_common *_skc = skc; \ sk = NULL; \ tp = NULL; \ if (_skc) { \ tp = bpf_skc_to_tcp_sock(_skc); \ sk = (struct sock *)tp; \ } \ tp; \ }) unsigned short reuse_listen_hport = 0; unsigned short listen_hport = 0; char cubic_cc[TCP_CA_NAME_MAX] = "bpf_cubic"; char dctcp_cc[TCP_CA_NAME_MAX] = "bpf_dctcp"; bool random_retry = false; static bool tcp_cc_eq(const char *a, const char *b) { int i; for (i = 0; i < TCP_CA_NAME_MAX; i++) { if (a[i] != b[i]) return false; if (!a[i]) break; } return true; } SEC("iter/tcp") int change_tcp_cc(struct bpf_iter__tcp *ctx) { char cur_cc[TCP_CA_NAME_MAX]; struct tcp_sock *tp; struct sock *sk; if (!bpf_tcp_sk(ctx->sk_common)) return 0; if (sk->sk_family != AF_INET6 || (sk->sk_state != TCP_LISTEN && sk->sk_state != TCP_ESTABLISHED) || (sk->sk_num != reuse_listen_hport && sk->sk_num != listen_hport && bpf_ntohs(sk->sk_dport) != listen_hport)) return 0; if (bpf_getsockopt(tp, SOL_TCP, TCP_CONGESTION, cur_cc, sizeof(cur_cc))) return 0; if (!tcp_cc_eq(cur_cc, cubic_cc)) return 0; if (random_retry && bpf_get_prandom_u32() % 4 == 1) return 1; bpf_setsockopt(tp, SOL_TCP, TCP_CONGESTION, dctcp_cc, sizeof(dctcp_cc)); return 0; } char _license[] SEC("license") = "GPL";