aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/test_tcp_hdr_options.h
blob: 6118e3ab61fc302f2fb83a449af15ffb11e4cf34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Facebook */

#ifndef _TEST_TCP_HDR_OPTIONS_H
#define _TEST_TCP_HDR_OPTIONS_H

struct bpf_test_option {
	__u8 flags;
	__u8 max_delack_ms;
	__u8 rand;
} __attribute__((packed));

enum {
	OPTION_RESEND,
	OPTION_MAX_DELACK_MS,
	OPTION_RAND,
	__NR_OPTION_FLAGS,
};

#define OPTION_F_RESEND		(1 << OPTION_RESEND)
#define OPTION_F_MAX_DELACK_MS	(1 << OPTION_MAX_DELACK_MS)
#define OPTION_F_RAND		(1 << OPTION_RAND)
#define OPTION_MASK		((1 << __NR_OPTION_FLAGS) - 1)

#define TEST_OPTION_FLAGS(flags, option) (1 & ((flags) >> (option)))
#define SET_OPTION_FLAGS(flags, option)	((flags) |= (1 << (option)))

/* Store in bpf_sk_storage */
struct hdr_stg {
	bool active;
	bool resend_syn; /* active side only */
	bool syncookie;  /* passive side only */
	bool fastopen;	/* passive side only */
};

struct linum_err {
	unsigned int linum;
	int err;
};

#define TCPHDR_FIN 0x01
#define TCPHDR_SYN 0x02
#define TCPHDR_RST 0x04
#define TCPHDR_PSH 0x08
#define TCPHDR_ACK 0x10
#define TCPHDR_URG 0x20
#define TCPHDR_ECE 0x40
#define TCPHDR_CWR 0x80
#define TCPHDR_SYNACK (TCPHDR_SYN | TCPHDR_ACK)

#define TCPOPT_EOL		0
#define TCPOPT_NOP		1
#define TCPOPT_WINDOW		3
#define TCPOPT_EXP		254

#define TCP_BPF_EXPOPT_BASE_LEN 4
#define MAX_TCP_HDR_LEN		60
#define MAX_TCP_OPTION_SPACE	40

#ifdef BPF_PROG_TEST_TCP_HDR_OPTIONS

#define CG_OK	1
#define CG_ERR	0

#ifndef SOL_TCP
#define SOL_TCP 6
#endif

struct tcp_exprm_opt {
	__u8 kind;
	__u8 len;
	__u16 magic;
	union {
		__u8 data[4];
		__u32 data32;
	};
} __attribute__((packed));

struct tcp_opt {
	__u8 kind;
	__u8 len;
	union {
		__u8 data[4];
		__u32 data32;
	};
} __attribute__((packed));

struct {
	__uint(type, BPF_MAP_TYPE_HASH);
	__uint(max_entries, 2);
	__type(key, int);
	__type(value, struct linum_err);
} lport_linum_map SEC(".maps");

static inline unsigned int tcp_hdrlen(const struct tcphdr *th)
{
	return th->doff << 2;
}

static inline __u8 skops_tcp_flags(const struct bpf_sock_ops *skops)
{
	return skops->skb_tcp_flags;
}

static inline void clear_hdr_cb_flags(struct bpf_sock_ops *skops)
{
	bpf_sock_ops_cb_flags_set(skops,
				  skops->bpf_sock_ops_cb_flags &
				  ~(BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG |
				    BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG));
}

static inline void set_hdr_cb_flags(struct bpf_sock_ops *skops, __u32 extra)
{
	bpf_sock_ops_cb_flags_set(skops,
				  skops->bpf_sock_ops_cb_flags |
				  BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG |
				  BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG |
				  extra);
}
static inline void
clear_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops)
{
	bpf_sock_ops_cb_flags_set(skops,
				  skops->bpf_sock_ops_cb_flags &
				  ~BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
}

static inline void
set_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops)
{
	bpf_sock_ops_cb_flags_set(skops,
				  skops->bpf_sock_ops_cb_flags |
				  BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
}

#define RET_CG_ERR(__err) ({			\
	struct linum_err __linum_err;		\
	int __lport;				\
						\
	__linum_err.linum = __LINE__;		\
	__linum_err.err = __err;		\
	__lport = skops->local_port;		\
	bpf_map_update_elem(&lport_linum_map, &__lport, &__linum_err, BPF_NOEXIST); \
	clear_hdr_cb_flags(skops);					\
	clear_parse_all_hdr_cb_flags(skops);				\
	return CG_ERR;							\
})

#endif /* BPF_PROG_TEST_TCP_HDR_OPTIONS */

#endif /* _TEST_TCP_HDR_OPTIONS_H */