18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/bpf.h>
38c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL";
68c2ecf20Sopenharmony_ci__u32 _version SEC("version") = 1;
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistruct tcp_rtt_storage {
98c2ecf20Sopenharmony_ci	__u32 invoked;
108c2ecf20Sopenharmony_ci	__u32 dsack_dups;
118c2ecf20Sopenharmony_ci	__u32 delivered;
128c2ecf20Sopenharmony_ci	__u32 delivered_ce;
138c2ecf20Sopenharmony_ci	__u32 icsk_retransmits;
148c2ecf20Sopenharmony_ci};
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct {
178c2ecf20Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
188c2ecf20Sopenharmony_ci	__uint(map_flags, BPF_F_NO_PREALLOC);
198c2ecf20Sopenharmony_ci	__type(key, int);
208c2ecf20Sopenharmony_ci	__type(value, struct tcp_rtt_storage);
218c2ecf20Sopenharmony_ci} socket_storage_map SEC(".maps");
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciSEC("sockops")
248c2ecf20Sopenharmony_ciint _sockops(struct bpf_sock_ops *ctx)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct tcp_rtt_storage *storage;
278c2ecf20Sopenharmony_ci	struct bpf_tcp_sock *tcp_sk;
288c2ecf20Sopenharmony_ci	int op = (int) ctx->op;
298c2ecf20Sopenharmony_ci	struct bpf_sock *sk;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	sk = ctx->sk;
328c2ecf20Sopenharmony_ci	if (!sk)
338c2ecf20Sopenharmony_ci		return 1;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	storage = bpf_sk_storage_get(&socket_storage_map, sk, 0,
368c2ecf20Sopenharmony_ci				     BPF_SK_STORAGE_GET_F_CREATE);
378c2ecf20Sopenharmony_ci	if (!storage)
388c2ecf20Sopenharmony_ci		return 1;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (op == BPF_SOCK_OPS_TCP_CONNECT_CB) {
418c2ecf20Sopenharmony_ci		bpf_sock_ops_cb_flags_set(ctx, BPF_SOCK_OPS_RTT_CB_FLAG);
428c2ecf20Sopenharmony_ci		return 1;
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (op != BPF_SOCK_OPS_RTT_CB)
468c2ecf20Sopenharmony_ci		return 1;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	tcp_sk = bpf_tcp_sock(sk);
498c2ecf20Sopenharmony_ci	if (!tcp_sk)
508c2ecf20Sopenharmony_ci		return 1;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	storage->invoked++;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	storage->dsack_dups = tcp_sk->dsack_dups;
558c2ecf20Sopenharmony_ci	storage->delivered = tcp_sk->delivered;
568c2ecf20Sopenharmony_ci	storage->delivered_ce = tcp_sk->delivered_ce;
578c2ecf20Sopenharmony_ci	storage->icsk_retransmits = tcp_sk->icsk_retransmits;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return 1;
608c2ecf20Sopenharmony_ci}
61