16e945d57SJörn-Thorben Hinz // SPDX-License-Identifier: GPL-2.0
26e945d57SJörn-Thorben Hinz 
36e945d57SJörn-Thorben Hinz #include "vmlinux.h"
46e945d57SJörn-Thorben Hinz 
56e945d57SJörn-Thorben Hinz #include <bpf/bpf_helpers.h>
66e945d57SJörn-Thorben Hinz #include <bpf/bpf_tracing.h>
76e945d57SJörn-Thorben Hinz 
86e945d57SJörn-Thorben Hinz char _license[] SEC("license") = "GPL";
96e945d57SJörn-Thorben Hinz 
106e945d57SJörn-Thorben Hinz #define USEC_PER_SEC 1000000UL
116e945d57SJörn-Thorben Hinz 
126e945d57SJörn-Thorben Hinz #define min(a, b) ((a) < (b) ? (a) : (b))
136e945d57SJörn-Thorben Hinz 
tcp_sk(const struct sock * sk)146e945d57SJörn-Thorben Hinz static inline struct tcp_sock *tcp_sk(const struct sock *sk)
156e945d57SJörn-Thorben Hinz {
166e945d57SJörn-Thorben Hinz 	return (struct tcp_sock *)sk;
176e945d57SJörn-Thorben Hinz }
186e945d57SJörn-Thorben Hinz 
tcp_left_out(const struct tcp_sock * tp)19*4239561bSYixin Shen static inline unsigned int tcp_left_out(const struct tcp_sock *tp)
20*4239561bSYixin Shen {
21*4239561bSYixin Shen 	return tp->sacked_out + tp->lost_out;
22*4239561bSYixin Shen }
23*4239561bSYixin Shen 
tcp_packets_in_flight(const struct tcp_sock * tp)24*4239561bSYixin Shen static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
25*4239561bSYixin Shen {
26*4239561bSYixin Shen 	return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
27*4239561bSYixin Shen }
28*4239561bSYixin Shen 
296e945d57SJörn-Thorben Hinz SEC("struct_ops/write_sk_pacing_init")
BPF_PROG(write_sk_pacing_init,struct sock * sk)306e945d57SJörn-Thorben Hinz void BPF_PROG(write_sk_pacing_init, struct sock *sk)
316e945d57SJörn-Thorben Hinz {
326e945d57SJörn-Thorben Hinz #ifdef ENABLE_ATOMICS_TESTS
336e945d57SJörn-Thorben Hinz 	__sync_bool_compare_and_swap(&sk->sk_pacing_status, SK_PACING_NONE,
346e945d57SJörn-Thorben Hinz 				     SK_PACING_NEEDED);
356e945d57SJörn-Thorben Hinz #else
366e945d57SJörn-Thorben Hinz 	sk->sk_pacing_status = SK_PACING_NEEDED;
376e945d57SJörn-Thorben Hinz #endif
386e945d57SJörn-Thorben Hinz }
396e945d57SJörn-Thorben Hinz 
406e945d57SJörn-Thorben Hinz SEC("struct_ops/write_sk_pacing_cong_control")
BPF_PROG(write_sk_pacing_cong_control,struct sock * sk,const struct rate_sample * rs)416e945d57SJörn-Thorben Hinz void BPF_PROG(write_sk_pacing_cong_control, struct sock *sk,
426e945d57SJörn-Thorben Hinz 	      const struct rate_sample *rs)
436e945d57SJörn-Thorben Hinz {
44*4239561bSYixin Shen 	struct tcp_sock *tp = tcp_sk(sk);
456e945d57SJörn-Thorben Hinz 	unsigned long rate =
466e945d57SJörn-Thorben Hinz 		((tp->snd_cwnd * tp->mss_cache * USEC_PER_SEC) << 3) /
476e945d57SJörn-Thorben Hinz 		(tp->srtt_us ?: 1U << 3);
486e945d57SJörn-Thorben Hinz 	sk->sk_pacing_rate = min(rate, sk->sk_max_pacing_rate);
49*4239561bSYixin Shen 	tp->app_limited = (tp->delivered + tcp_packets_in_flight(tp)) ?: 1;
506e945d57SJörn-Thorben Hinz }
516e945d57SJörn-Thorben Hinz 
526e945d57SJörn-Thorben Hinz SEC("struct_ops/write_sk_pacing_ssthresh")
BPF_PROG(write_sk_pacing_ssthresh,struct sock * sk)536e945d57SJörn-Thorben Hinz __u32 BPF_PROG(write_sk_pacing_ssthresh, struct sock *sk)
546e945d57SJörn-Thorben Hinz {
556e945d57SJörn-Thorben Hinz 	return tcp_sk(sk)->snd_ssthresh;
566e945d57SJörn-Thorben Hinz }
576e945d57SJörn-Thorben Hinz 
586e945d57SJörn-Thorben Hinz SEC("struct_ops/write_sk_pacing_undo_cwnd")
BPF_PROG(write_sk_pacing_undo_cwnd,struct sock * sk)596e945d57SJörn-Thorben Hinz __u32 BPF_PROG(write_sk_pacing_undo_cwnd, struct sock *sk)
606e945d57SJörn-Thorben Hinz {
616e945d57SJörn-Thorben Hinz 	return tcp_sk(sk)->snd_cwnd;
626e945d57SJörn-Thorben Hinz }
636e945d57SJörn-Thorben Hinz 
646e945d57SJörn-Thorben Hinz SEC(".struct_ops")
656e945d57SJörn-Thorben Hinz struct tcp_congestion_ops write_sk_pacing = {
666e945d57SJörn-Thorben Hinz 	.init = (void *)write_sk_pacing_init,
676e945d57SJörn-Thorben Hinz 	.cong_control = (void *)write_sk_pacing_cong_control,
686e945d57SJörn-Thorben Hinz 	.ssthresh = (void *)write_sk_pacing_ssthresh,
696e945d57SJörn-Thorben Hinz 	.undo_cwnd = (void *)write_sk_pacing_undo_cwnd,
706e945d57SJörn-Thorben Hinz 	.name = "bpf_w_sk_pacing",
716e945d57SJörn-Thorben Hinz };
72