18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Refer to samples/bpf/tcp_bpf.readme for the instructions on
38c2ecf20Sopenharmony_ci * how to run this sample program.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#include <linux/bpf.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h>
88c2ecf20Sopenharmony_ci#include <bpf/bpf_endian.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define INTERVAL			1000000000ULL
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciint _version SEC("version") = 1;
138c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL";
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistruct {
168c2ecf20Sopenharmony_ci	__u32 type;
178c2ecf20Sopenharmony_ci	__u32 map_flags;
188c2ecf20Sopenharmony_ci	int *key;
198c2ecf20Sopenharmony_ci	__u64 *value;
208c2ecf20Sopenharmony_ci} bpf_next_dump SEC(".maps") = {
218c2ecf20Sopenharmony_ci	.type = BPF_MAP_TYPE_SK_STORAGE,
228c2ecf20Sopenharmony_ci	.map_flags = BPF_F_NO_PREALLOC,
238c2ecf20Sopenharmony_ci};
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciSEC("sockops")
268c2ecf20Sopenharmony_ciint _sockops(struct bpf_sock_ops *ctx)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct bpf_tcp_sock *tcp_sk;
298c2ecf20Sopenharmony_ci	struct bpf_sock *sk;
308c2ecf20Sopenharmony_ci	__u64 *next_dump;
318c2ecf20Sopenharmony_ci	__u64 now;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	switch (ctx->op) {
348c2ecf20Sopenharmony_ci	case BPF_SOCK_OPS_TCP_CONNECT_CB:
358c2ecf20Sopenharmony_ci		bpf_sock_ops_cb_flags_set(ctx, BPF_SOCK_OPS_RTT_CB_FLAG);
368c2ecf20Sopenharmony_ci		return 1;
378c2ecf20Sopenharmony_ci	case BPF_SOCK_OPS_RTT_CB:
388c2ecf20Sopenharmony_ci		break;
398c2ecf20Sopenharmony_ci	default:
408c2ecf20Sopenharmony_ci		return 1;
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	sk = ctx->sk;
448c2ecf20Sopenharmony_ci	if (!sk)
458c2ecf20Sopenharmony_ci		return 1;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	next_dump = bpf_sk_storage_get(&bpf_next_dump, sk, 0,
488c2ecf20Sopenharmony_ci				       BPF_SK_STORAGE_GET_F_CREATE);
498c2ecf20Sopenharmony_ci	if (!next_dump)
508c2ecf20Sopenharmony_ci		return 1;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	now = bpf_ktime_get_ns();
538c2ecf20Sopenharmony_ci	if (now < *next_dump)
548c2ecf20Sopenharmony_ci		return 1;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	tcp_sk = bpf_tcp_sock(sk);
578c2ecf20Sopenharmony_ci	if (!tcp_sk)
588c2ecf20Sopenharmony_ci		return 1;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	*next_dump = now + INTERVAL;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	bpf_printk("dsack_dups=%u delivered=%u\n",
638c2ecf20Sopenharmony_ci		   tcp_sk->dsack_dups, tcp_sk->delivered);
648c2ecf20Sopenharmony_ci	bpf_printk("delivered_ce=%u icsk_retransmits=%u\n",
658c2ecf20Sopenharmony_ci		   tcp_sk->delivered_ce, tcp_sk->icsk_retransmits);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	return 1;
688c2ecf20Sopenharmony_ci}
69