1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #include <vmlinux.h> 4 #include "bpf_tracing_net.h" 5 #include <bpf/bpf_helpers.h> 6 #include <bpf/bpf_endian.h> 7 8 #define bpf_tcp_sk(skc) ({ \ 9 struct sock_common *_skc = skc; \ 10 sk = NULL; \ 11 tp = NULL; \ 12 if (_skc) { \ 13 tp = bpf_skc_to_tcp_sock(_skc); \ 14 sk = (struct sock *)tp; \ 15 } \ 16 tp; \ 17 }) 18 19 unsigned short reuse_listen_hport = 0; 20 unsigned short listen_hport = 0; 21 char cubic_cc[TCP_CA_NAME_MAX] = "bpf_cubic"; 22 char dctcp_cc[TCP_CA_NAME_MAX] = "bpf_dctcp"; 23 bool random_retry = false; 24 25 static bool tcp_cc_eq(const char *a, const char *b) 26 { 27 int i; 28 29 for (i = 0; i < TCP_CA_NAME_MAX; i++) { 30 if (a[i] != b[i]) 31 return false; 32 if (!a[i]) 33 break; 34 } 35 36 return true; 37 } 38 39 SEC("iter/tcp") 40 int change_tcp_cc(struct bpf_iter__tcp *ctx) 41 { 42 char cur_cc[TCP_CA_NAME_MAX]; 43 struct tcp_sock *tp; 44 struct sock *sk; 45 46 if (!bpf_tcp_sk(ctx->sk_common)) 47 return 0; 48 49 if (sk->sk_family != AF_INET6 || 50 (sk->sk_state != TCP_LISTEN && 51 sk->sk_state != TCP_ESTABLISHED) || 52 (sk->sk_num != reuse_listen_hport && 53 sk->sk_num != listen_hport && 54 bpf_ntohs(sk->sk_dport) != listen_hport)) 55 return 0; 56 57 if (bpf_getsockopt(tp, SOL_TCP, TCP_CONGESTION, 58 cur_cc, sizeof(cur_cc))) 59 return 0; 60 61 if (!tcp_cc_eq(cur_cc, cubic_cc)) 62 return 0; 63 64 if (random_retry && bpf_get_prandom_u32() % 4 == 1) 65 return 1; 66 67 bpf_setsockopt(tp, SOL_TCP, TCP_CONGESTION, dctcp_cc, sizeof(dctcp_cc)); 68 return 0; 69 } 70 71 char _license[] SEC("license") = "GPL"; 72