/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM tcp

#if !defined(_TRACE_TCP_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_TCP_H

#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <linux/tracepoint.h>
#include <net/ipv6.h>
#include <net/tcp.h>
#include <linux/sock_diag.h>
#include <net/rstreason.h>

TRACE_EVENT(tcp_retransmit_skb,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb, int err),

	TP_ARGS(sk, skb, err),

	TP_STRUCT__entry(
		__field(const void *, skbaddr)
		__field(const void *, skaddr)
		__field(int, state)
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__array(__u8, saddr, 4)
		__array(__u8, daddr, 4)
		__array(__u8, saddr_v6, 16)
		__array(__u8, daddr_v6, 16)
		__field(int, err)
	),

	TP_fast_assign(
		const struct inet_sock *inet = inet_sk(sk);
		__be32 *p32;

		__entry->skbaddr = skb;
		__entry->skaddr = sk;
		__entry->state = sk->sk_state;

		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		p32 = (__be32 *) __entry->saddr;
		*p32 = inet->inet_saddr;

		p32 = (__be32 *) __entry->daddr;
		*p32 =  inet->inet_daddr;

		TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
			      sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);

		__entry->err = err;
	),

	TP_printk("skbaddr=%p skaddr=%p family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c state=%s err=%d",
		  __entry->skbaddr, __entry->skaddr,
		  show_family_name(__entry->family),
		  __entry->sport, __entry->dport, __entry->saddr, __entry->daddr,
		  __entry->saddr_v6, __entry->daddr_v6,
		  show_tcp_state_name(__entry->state),
		  __entry->err)
);

#undef FN
#define FN(reason)	TRACE_DEFINE_ENUM(SK_RST_REASON_##reason);
DEFINE_RST_REASON(FN, FN)

#undef FN
#undef FNe
#define FN(reason)	{ SK_RST_REASON_##reason, #reason },
#define FNe(reason)	{ SK_RST_REASON_##reason, #reason }

/*
 * skb of trace_tcp_send_reset is the skb that caused RST. In case of
 * active reset, skb should be NULL
 */
TRACE_EVENT(tcp_send_reset,

	TP_PROTO(const struct sock *sk,
		 const struct sk_buff *skb__nullable,
		 const enum sk_rst_reason reason),

	TP_ARGS(sk, skb__nullable, reason),

	TP_STRUCT__entry(
		__field(const void *, skbaddr)
		__field(const void *, skaddr)
		__field(int, state)
		__field(enum sk_rst_reason, reason)
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))
	),

	TP_fast_assign(
		__entry->skbaddr = skb__nullable;
		__entry->skaddr = sk;
		/* Zero means unknown state. */
		__entry->state = sk ? sk->sk_state : 0;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));

		if (sk && sk_fullsock(sk)) {
			const struct inet_sock *inet = inet_sk(sk);

			TP_STORE_ADDR_PORTS(__entry, inet, sk);
		} else if (skb__nullable) {
			const struct tcphdr *th = (const struct tcphdr *)skb__nullable->data;
			/*
			 * We should reverse the 4-tuple of skb, so later
			 * it can print the right flow direction of rst.
			 */
			TP_STORE_ADDR_PORTS_SKB(skb__nullable, th, entry->daddr, entry->saddr);
		}
		__entry->reason = reason;
	),

	TP_printk("skbaddr=%p skaddr=%p src=%pISpc dest=%pISpc state=%s reason=%s",
		  __entry->skbaddr, __entry->skaddr,
		  __entry->saddr, __entry->daddr,
		  __entry->state ? show_tcp_state_name(__entry->state) : "UNKNOWN",
		  __print_symbolic(__entry->reason, DEFINE_RST_REASON(FN, FNe)))
);

#undef FN
#undef FNe

/*
 * tcp event with arguments sk
 *
 * Note: this class requires a valid sk pointer.
 */
DECLARE_EVENT_CLASS(tcp_event_sk,

	TP_PROTO(struct sock *sk),

	TP_ARGS(sk),

	TP_STRUCT__entry(
		__field(const void *, skaddr)
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__array(__u8, saddr, 4)
		__array(__u8, daddr, 4)
		__array(__u8, saddr_v6, 16)
		__array(__u8, daddr_v6, 16)
		__field(__u64, sock_cookie)
	),

	TP_fast_assign(
		struct inet_sock *inet = inet_sk(sk);
		__be32 *p32;

		__entry->skaddr = sk;

		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		p32 = (__be32 *) __entry->saddr;
		*p32 = inet->inet_saddr;

		p32 = (__be32 *) __entry->daddr;
		*p32 =  inet->inet_daddr;

		TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
			       sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);

		__entry->sock_cookie = sock_gen_cookie(sk);
	),

	TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c sock_cookie=%llx",
		  show_family_name(__entry->family),
		  __entry->sport, __entry->dport,
		  __entry->saddr, __entry->daddr,
		  __entry->saddr_v6, __entry->daddr_v6,
		  __entry->sock_cookie)
);

DEFINE_EVENT(tcp_event_sk, tcp_receive_reset,

	TP_PROTO(struct sock *sk),

	TP_ARGS(sk)
);

DEFINE_EVENT(tcp_event_sk, tcp_destroy_sock,

	TP_PROTO(struct sock *sk),

	TP_ARGS(sk)
);

DEFINE_EVENT(tcp_event_sk, tcp_rcv_space_adjust,

	TP_PROTO(struct sock *sk),

	TP_ARGS(sk)
);

TRACE_EVENT(tcp_rcvbuf_grow,

	TP_PROTO(struct sock *sk, int time),

	TP_ARGS(sk, time),

	TP_STRUCT__entry(
		__field(int, time)
		__field(__u32, rtt_us)
		__field(__u32, copied)
		__field(__u32, inq)
		__field(__u32, space)
		__field(__u32, ooo_space)
		__field(__u32, rcvbuf)
		__field(__u32, rcv_ssthresh)
		__field(__u32, window_clamp)
		__field(__u32, rcv_wnd)
		__field(__u8, scaling_ratio)
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__array(__u8, saddr, 4)
		__array(__u8, daddr, 4)
		__array(__u8, saddr_v6, 16)
		__array(__u8, daddr_v6, 16)
		__field(const void *, skaddr)
		__field(__u64, sock_cookie)
	),

	TP_fast_assign(
		struct inet_sock *inet = inet_sk(sk);
		struct tcp_sock *tp = tcp_sk(sk);
		__be32 *p32;

		__entry->time = time;
		__entry->rtt_us = tp->rcv_rtt_est.rtt_us >> 3;
		__entry->copied = tp->copied_seq - tp->rcvq_space.seq;
		__entry->inq = tp->rcv_nxt - tp->copied_seq;
		__entry->space = tp->rcvq_space.space;
		__entry->ooo_space = RB_EMPTY_ROOT(&tp->out_of_order_queue) ? 0 :
				     TCP_SKB_CB(tp->ooo_last_skb)->end_seq -
				     tp->rcv_nxt;

		__entry->rcvbuf = sk->sk_rcvbuf;
		__entry->rcv_ssthresh = tp->rcv_ssthresh;
		__entry->window_clamp = tp->window_clamp;
		__entry->rcv_wnd = tp->rcv_wnd;
		__entry->scaling_ratio = tp->scaling_ratio;
		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		p32 = (__be32 *) __entry->saddr;
		*p32 = inet->inet_saddr;

		p32 = (__be32 *) __entry->daddr;
		*p32 = inet->inet_daddr;

		TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
			       sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);

		__entry->skaddr = sk;
		__entry->sock_cookie = sock_gen_cookie(sk);
	),

	TP_printk("time=%u rtt_us=%u copied=%u inq=%u space=%u ooo=%u scaling_ratio=%u rcvbuf=%u "
		  "rcv_ssthresh=%u window_clamp=%u rcv_wnd=%u "
		  "family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 "
		  "saddrv6=%pI6c daddrv6=%pI6c skaddr=%p sock_cookie=%llx",
		  __entry->time, __entry->rtt_us, __entry->copied,
		  __entry->inq, __entry->space, __entry->ooo_space,
		  __entry->scaling_ratio, __entry->rcvbuf,
		  __entry->rcv_ssthresh, __entry->window_clamp,
		  __entry->rcv_wnd,
		  show_family_name(__entry->family),
		  __entry->sport, __entry->dport,
		  __entry->saddr, __entry->daddr,
		  __entry->saddr_v6, __entry->daddr_v6,
		  __entry->skaddr,
		  __entry->sock_cookie)
);

TRACE_EVENT(tcp_retransmit_synack,

	TP_PROTO(const struct sock *sk, const struct request_sock *req),

	TP_ARGS(sk, req),

	TP_STRUCT__entry(
		__field(const void *, skaddr)
		__field(const void *, req)
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__array(__u8, saddr, 4)
		__array(__u8, daddr, 4)
		__array(__u8, saddr_v6, 16)
		__array(__u8, daddr_v6, 16)
	),

	TP_fast_assign(
		struct inet_request_sock *ireq = inet_rsk(req);
		__be32 *p32;

		__entry->skaddr = sk;
		__entry->req = req;

		__entry->sport = ireq->ir_num;
		__entry->dport = ntohs(ireq->ir_rmt_port);
		__entry->family = sk->sk_family;

		p32 = (__be32 *) __entry->saddr;
		*p32 = ireq->ir_loc_addr;

		p32 = (__be32 *) __entry->daddr;
		*p32 = ireq->ir_rmt_addr;

		TP_STORE_ADDRS(__entry, ireq->ir_loc_addr, ireq->ir_rmt_addr,
			      ireq->ir_v6_loc_addr, ireq->ir_v6_rmt_addr);
	),

	TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c",
		  show_family_name(__entry->family),
		  __entry->sport, __entry->dport,
		  __entry->saddr, __entry->daddr,
		  __entry->saddr_v6, __entry->daddr_v6)
);

TRACE_EVENT(tcp_sendmsg_locked,
	TP_PROTO(const struct sock *sk, const struct msghdr *msg,
		 const struct sk_buff *skb, int size_goal),

	TP_ARGS(sk, msg, skb, size_goal),

	TP_STRUCT__entry(
		__field(const void *, skb_addr)
		__field(int, skb_len)
		__field(int, msg_left)
		__field(int, size_goal)
	),

	TP_fast_assign(
		__entry->skb_addr = skb;
		__entry->skb_len = skb ? skb->len : 0;
		__entry->msg_left = msg_data_left(msg);
		__entry->size_goal = size_goal;
	),

	TP_printk("skb_addr %p skb_len %d msg_left %d size_goal %d",
		  __entry->skb_addr, __entry->skb_len, __entry->msg_left,
		  __entry->size_goal));

DECLARE_TRACE(tcp_cwnd_reduction,
	TP_PROTO(const struct sock *sk, int newly_acked_sacked,
		 int newly_lost, int flag),
	TP_ARGS(sk, newly_acked_sacked, newly_lost, flag)
);

#include <trace/events/net_probe_common.h>

TRACE_EVENT(tcp_probe,

	TP_PROTO(struct sock *sk, const struct sk_buff *skb),

	TP_ARGS(sk, skb),

	TP_STRUCT__entry(
		/* sockaddr_in6 is always bigger than sockaddr_in */
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__field(__u32, mark)
		__field(__u16, data_len)
		__field(__u32, snd_nxt)
		__field(__u32, snd_una)
		__field(__u32, snd_cwnd)
		__field(__u32, ssthresh)
		__field(__u32, snd_wnd)
		__field(__u32, srtt)
		__field(__u32, rcv_wnd)
		__field(__u64, sock_cookie)
		__field(const void *, skbaddr)
		__field(const void *, skaddr)
	),

	TP_fast_assign(
		const struct tcphdr *th = (const struct tcphdr *)skb->data;
		const struct inet_sock *inet = inet_sk(sk);
		const struct tcp_sock *tp = tcp_sk(sk);

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));

		TP_STORE_ADDR_PORTS(__entry, inet, sk);

		/* For filtering use */
		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->mark = skb->mark;
		__entry->family = sk->sk_family;

		__entry->data_len = skb->len - __tcp_hdrlen(th);
		__entry->snd_nxt = tp->snd_nxt;
		__entry->snd_una = tp->snd_una;
		__entry->snd_cwnd = tcp_snd_cwnd(tp);
		__entry->snd_wnd = tp->snd_wnd;
		__entry->rcv_wnd = tp->rcv_wnd;
		__entry->ssthresh = tcp_current_ssthresh(sk);
		__entry->srtt = tp->srtt_us >> 3;
		__entry->sock_cookie = sock_gen_cookie(sk);

		__entry->skbaddr = skb;
		__entry->skaddr = sk;
	),

	TP_printk("family=%s src=%pISpc dest=%pISpc mark=%#x data_len=%d snd_nxt=%#x snd_una=%#x snd_cwnd=%u ssthresh=%u snd_wnd=%u srtt=%u rcv_wnd=%u sock_cookie=%llx skbaddr=%p skaddr=%p",
		  show_family_name(__entry->family),
		  __entry->saddr, __entry->daddr, __entry->mark,
		  __entry->data_len, __entry->snd_nxt, __entry->snd_una,
		  __entry->snd_cwnd, __entry->ssthresh, __entry->snd_wnd,
		  __entry->srtt, __entry->rcv_wnd, __entry->sock_cookie,
		  __entry->skbaddr, __entry->skaddr)
);

/*
 * tcp event with only skb
 */
DECLARE_EVENT_CLASS(tcp_event_skb,

	TP_PROTO(const struct sk_buff *skb),

	TP_ARGS(skb),

	TP_STRUCT__entry(
		__field(const void *, skbaddr)
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))
	),

	TP_fast_assign(
		const struct tcphdr *th = (const struct tcphdr *)skb->data;
		__entry->skbaddr = skb;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));

		TP_STORE_ADDR_PORTS_SKB(skb, th, __entry->saddr, __entry->daddr);
	),

	TP_printk("skbaddr=%p src=%pISpc dest=%pISpc",
		  __entry->skbaddr, __entry->saddr, __entry->daddr)
);

DEFINE_EVENT(tcp_event_skb, tcp_bad_csum,

	TP_PROTO(const struct sk_buff *skb),

	TP_ARGS(skb)
);

TRACE_EVENT(tcp_cong_state_set,

	TP_PROTO(struct sock *sk, const u8 ca_state),

	TP_ARGS(sk, ca_state),

	TP_STRUCT__entry(
		__field(const void *, skaddr)
		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)
		__array(__u8, saddr, 4)
		__array(__u8, daddr, 4)
		__array(__u8, saddr_v6, 16)
		__array(__u8, daddr_v6, 16)
		__field(__u8, cong_state)
	),

	TP_fast_assign(
		struct inet_sock *inet = inet_sk(sk);
		__be32 *p32;

		__entry->skaddr = sk;

		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		p32 = (__be32 *) __entry->saddr;
		*p32 = inet->inet_saddr;

		p32 = (__be32 *) __entry->daddr;
		*p32 =  inet->inet_daddr;

		TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
			   sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);

		__entry->cong_state = ca_state;
	),

	TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u",
		  show_family_name(__entry->family),
		  __entry->sport, __entry->dport,
		  __entry->saddr, __entry->daddr,
		  __entry->saddr_v6, __entry->daddr_v6,
		  __entry->cong_state)
);

DECLARE_EVENT_CLASS(tcp_hash_event,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),

	TP_ARGS(sk, skb),

	TP_STRUCT__entry(
		__field(__u64, net_cookie)
		__field(const void *, skbaddr)
		__field(const void *, skaddr)
		__field(int, state)

		/* sockaddr_in6 is always bigger than sockaddr_in */
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))
		__field(int, l3index)

		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)

		__field(bool, fin)
		__field(bool, syn)
		__field(bool, rst)
		__field(bool, psh)
		__field(bool, ack)
	),

	TP_fast_assign(
		const struct tcphdr *th = (const struct tcphdr *)skb->data;

		__entry->net_cookie = sock_net(sk)->net_cookie;
		__entry->skbaddr = skb;
		__entry->skaddr = sk;
		__entry->state = sk->sk_state;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
		TP_STORE_ADDR_PORTS_SKB(skb, th, __entry->saddr, __entry->daddr);
		__entry->l3index = inet_sdif(skb) ? inet_iif(skb) : 0;

		/* For filtering use */
		__entry->sport = ntohs(th->source);
		__entry->dport = ntohs(th->dest);
		__entry->family = sk->sk_family;

		__entry->fin = th->fin;
		__entry->syn = th->syn;
		__entry->rst = th->rst;
		__entry->psh = th->psh;
		__entry->ack = th->ack;
	),

	TP_printk("net=%llu state=%s family=%s src=%pISpc dest=%pISpc L3index=%d [%c%c%c%c%c]",
		  __entry->net_cookie,
		  show_tcp_state_name(__entry->state),
		  show_family_name(__entry->family),
		  __entry->saddr, __entry->daddr,
		  __entry->l3index,
		  __entry->fin ? 'F' : ' ',
		  __entry->syn ? 'S' : ' ',
		  __entry->rst ? 'R' : ' ',
		  __entry->psh ? 'P' : ' ',
		  __entry->ack ? '.' : ' ')
);

DEFINE_EVENT(tcp_hash_event, tcp_hash_bad_header,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
	TP_ARGS(sk, skb)
);

DEFINE_EVENT(tcp_hash_event, tcp_hash_md5_required,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
	TP_ARGS(sk, skb)
);

DEFINE_EVENT(tcp_hash_event, tcp_hash_md5_unexpected,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
	TP_ARGS(sk, skb)
);

DEFINE_EVENT(tcp_hash_event, tcp_hash_md5_mismatch,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
	TP_ARGS(sk, skb)
);

DEFINE_EVENT(tcp_hash_event, tcp_hash_ao_required,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
	TP_ARGS(sk, skb)
);

DECLARE_EVENT_CLASS(tcp_ao_event,

	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),

	TP_ARGS(sk, skb, keyid, rnext, maclen),

	TP_STRUCT__entry(
		__field(__u64, net_cookie)
		__field(const void *, skbaddr)
		__field(const void *, skaddr)
		__field(int, state)

		/* sockaddr_in6 is always bigger than sockaddr_in */
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))
		__field(int, l3index)

		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)

		__field(bool, fin)
		__field(bool, syn)
		__field(bool, rst)
		__field(bool, psh)
		__field(bool, ack)

		__field(__u8, keyid)
		__field(__u8, rnext)
		__field(__u8, maclen)
	),

	TP_fast_assign(
		const struct tcphdr *th = (const struct tcphdr *)skb->data;

		__entry->net_cookie = sock_net(sk)->net_cookie;
		__entry->skbaddr = skb;
		__entry->skaddr = sk;
		__entry->state = sk->sk_state;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
		TP_STORE_ADDR_PORTS_SKB(skb, th, __entry->saddr, __entry->daddr);
		__entry->l3index = inet_sdif(skb) ? inet_iif(skb) : 0;

		/* For filtering use */
		__entry->sport = ntohs(th->source);
		__entry->dport = ntohs(th->dest);
		__entry->family = sk->sk_family;

		__entry->fin = th->fin;
		__entry->syn = th->syn;
		__entry->rst = th->rst;
		__entry->psh = th->psh;
		__entry->ack = th->ack;

		__entry->keyid = keyid;
		__entry->rnext = rnext;
		__entry->maclen = maclen;
	),

	TP_printk("net=%llu state=%s family=%s src=%pISpc dest=%pISpc L3index=%d [%c%c%c%c%c] keyid=%u rnext=%u maclen=%u",
		  __entry->net_cookie,
		  show_tcp_state_name(__entry->state),
		  show_family_name(__entry->family),
		  __entry->saddr, __entry->daddr,
		  __entry->l3index,
		  __entry->fin ? 'F' : ' ',
		  __entry->syn ? 'S' : ' ',
		  __entry->rst ? 'R' : ' ',
		  __entry->psh ? 'P' : ' ',
		  __entry->ack ? '.' : ' ',
		  __entry->keyid, __entry->rnext, __entry->maclen)
);

DEFINE_EVENT(tcp_ao_event, tcp_ao_handshake_failure,
	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),
	TP_ARGS(sk, skb, keyid, rnext, maclen)
);

#ifdef CONFIG_TCP_AO
DEFINE_EVENT(tcp_ao_event, tcp_ao_wrong_maclen,
	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),
	TP_ARGS(sk, skb, keyid, rnext, maclen)
);

DEFINE_EVENT(tcp_ao_event, tcp_ao_mismatch,
	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),
	TP_ARGS(sk, skb, keyid, rnext, maclen)
);

DEFINE_EVENT(tcp_ao_event, tcp_ao_key_not_found,
	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),
	TP_ARGS(sk, skb, keyid, rnext, maclen)
);

DEFINE_EVENT(tcp_ao_event, tcp_ao_rnext_request,
	TP_PROTO(const struct sock *sk, const struct sk_buff *skb,
		 const __u8 keyid, const __u8 rnext, const __u8 maclen),
	TP_ARGS(sk, skb, keyid, rnext, maclen)
);

DECLARE_EVENT_CLASS(tcp_ao_event_sk,

	TP_PROTO(const struct sock *sk, const __u8 keyid, const __u8 rnext),

	TP_ARGS(sk, keyid, rnext),

	TP_STRUCT__entry(
		__field(__u64, net_cookie)
		__field(const void *, skaddr)
		__field(int, state)

		/* sockaddr_in6 is always bigger than sockaddr_in */
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))

		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)

		__field(__u8, keyid)
		__field(__u8, rnext)
	),

	TP_fast_assign(
		const struct inet_sock *inet = inet_sk(sk);

		__entry->net_cookie = sock_net(sk)->net_cookie;
		__entry->skaddr = sk;
		__entry->state = sk->sk_state;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
		TP_STORE_ADDR_PORTS(__entry, inet, sk);

		/* For filtering use */
		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		__entry->keyid = keyid;
		__entry->rnext = rnext;
	),

	TP_printk("net=%llu state=%s family=%s src=%pISpc dest=%pISpc keyid=%u rnext=%u",
		  __entry->net_cookie,
		  show_tcp_state_name(__entry->state),
		  show_family_name(__entry->family),
		  __entry->saddr, __entry->daddr,
		  __entry->keyid, __entry->rnext)
);

DEFINE_EVENT(tcp_ao_event_sk, tcp_ao_synack_no_key,
	TP_PROTO(const struct sock *sk, const __u8 keyid, const __u8 rnext),
	TP_ARGS(sk, keyid, rnext)
);

DECLARE_EVENT_CLASS(tcp_ao_event_sne,

	TP_PROTO(const struct sock *sk, __u32 new_sne),

	TP_ARGS(sk, new_sne),

	TP_STRUCT__entry(
		__field(__u64, net_cookie)
		__field(const void *, skaddr)
		__field(int, state)

		/* sockaddr_in6 is always bigger than sockaddr_in */
		__array(__u8, saddr, sizeof(struct sockaddr_in6))
		__array(__u8, daddr, sizeof(struct sockaddr_in6))

		__field(__u16, sport)
		__field(__u16, dport)
		__field(__u16, family)

		__field(__u32, new_sne)
	),

	TP_fast_assign(
		const struct inet_sock *inet = inet_sk(sk);

		__entry->net_cookie = sock_net(sk)->net_cookie;
		__entry->skaddr = sk;
		__entry->state = sk->sk_state;

		memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
		memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
		TP_STORE_ADDR_PORTS(__entry, inet, sk);

		/* For filtering use */
		__entry->sport = ntohs(inet->inet_sport);
		__entry->dport = ntohs(inet->inet_dport);
		__entry->family = sk->sk_family;

		__entry->new_sne = new_sne;
	),

	TP_printk("net=%llu state=%s family=%s src=%pISpc dest=%pISpc sne=%u",
		  __entry->net_cookie,
		  show_tcp_state_name(__entry->state),
		  show_family_name(__entry->family),
		  __entry->saddr, __entry->daddr,
		  __entry->new_sne)
);

DEFINE_EVENT(tcp_ao_event_sne, tcp_ao_snd_sne_update,
	TP_PROTO(const struct sock *sk, __u32 new_sne),
	TP_ARGS(sk, new_sne)
);

DEFINE_EVENT(tcp_ao_event_sne, tcp_ao_rcv_sne_update,
	TP_PROTO(const struct sock *sk, __u32 new_sne),
	TP_ARGS(sk, new_sne)
);
#endif /* CONFIG_TCP_AO */

#endif /* _TRACE_TCP_H */

/* This part must be outside protection */
#include <trace/define_trace.h>
