1ad2f8eb0SMartin KaFai Lau /* SPDX-License-Identifier: GPL-2.0 */
2ad2f8eb0SMartin KaFai Lau /* Copyright (c) 2020 Facebook */
3ad2f8eb0SMartin KaFai Lau
4ad2f8eb0SMartin KaFai Lau #ifndef _TEST_TCP_HDR_OPTIONS_H
5ad2f8eb0SMartin KaFai Lau #define _TEST_TCP_HDR_OPTIONS_H
6ad2f8eb0SMartin KaFai Lau
7ad2f8eb0SMartin KaFai Lau struct bpf_test_option {
8ad2f8eb0SMartin KaFai Lau __u8 flags;
9ad2f8eb0SMartin KaFai Lau __u8 max_delack_ms;
10ad2f8eb0SMartin KaFai Lau __u8 rand;
11ad2f8eb0SMartin KaFai Lau } __attribute__((packed));
12ad2f8eb0SMartin KaFai Lau
13ad2f8eb0SMartin KaFai Lau enum {
14ad2f8eb0SMartin KaFai Lau OPTION_RESEND,
15ad2f8eb0SMartin KaFai Lau OPTION_MAX_DELACK_MS,
16ad2f8eb0SMartin KaFai Lau OPTION_RAND,
17ad2f8eb0SMartin KaFai Lau __NR_OPTION_FLAGS,
18ad2f8eb0SMartin KaFai Lau };
19ad2f8eb0SMartin KaFai Lau
20ad2f8eb0SMartin KaFai Lau #define OPTION_F_RESEND (1 << OPTION_RESEND)
21ad2f8eb0SMartin KaFai Lau #define OPTION_F_MAX_DELACK_MS (1 << OPTION_MAX_DELACK_MS)
22ad2f8eb0SMartin KaFai Lau #define OPTION_F_RAND (1 << OPTION_RAND)
23ad2f8eb0SMartin KaFai Lau #define OPTION_MASK ((1 << __NR_OPTION_FLAGS) - 1)
24ad2f8eb0SMartin KaFai Lau
25ad2f8eb0SMartin KaFai Lau #define TEST_OPTION_FLAGS(flags, option) (1 & ((flags) >> (option)))
26ad2f8eb0SMartin KaFai Lau #define SET_OPTION_FLAGS(flags, option) ((flags) |= (1 << (option)))
27ad2f8eb0SMartin KaFai Lau
28ad2f8eb0SMartin KaFai Lau /* Store in bpf_sk_storage */
29ad2f8eb0SMartin KaFai Lau struct hdr_stg {
30ad2f8eb0SMartin KaFai Lau bool active;
31ad2f8eb0SMartin KaFai Lau bool resend_syn; /* active side only */
32ad2f8eb0SMartin KaFai Lau bool syncookie; /* passive side only */
33ad2f8eb0SMartin KaFai Lau bool fastopen; /* passive side only */
34ad2f8eb0SMartin KaFai Lau };
35ad2f8eb0SMartin KaFai Lau
36ad2f8eb0SMartin KaFai Lau struct linum_err {
37ad2f8eb0SMartin KaFai Lau unsigned int linum;
38ad2f8eb0SMartin KaFai Lau int err;
39ad2f8eb0SMartin KaFai Lau };
40ad2f8eb0SMartin KaFai Lau
41ad2f8eb0SMartin KaFai Lau #define TCPHDR_FIN 0x01
42ad2f8eb0SMartin KaFai Lau #define TCPHDR_SYN 0x02
43ad2f8eb0SMartin KaFai Lau #define TCPHDR_RST 0x04
44ad2f8eb0SMartin KaFai Lau #define TCPHDR_PSH 0x08
45ad2f8eb0SMartin KaFai Lau #define TCPHDR_ACK 0x10
46ad2f8eb0SMartin KaFai Lau #define TCPHDR_URG 0x20
47ad2f8eb0SMartin KaFai Lau #define TCPHDR_ECE 0x40
48ad2f8eb0SMartin KaFai Lau #define TCPHDR_CWR 0x80
49ad2f8eb0SMartin KaFai Lau #define TCPHDR_SYNACK (TCPHDR_SYN | TCPHDR_ACK)
50ad2f8eb0SMartin KaFai Lau
51ad2f8eb0SMartin KaFai Lau #define TCPOPT_EOL 0
52ad2f8eb0SMartin KaFai Lau #define TCPOPT_NOP 1
53*cfa7b011SJoanne Koong #define TCPOPT_MSS 2
54ad2f8eb0SMartin KaFai Lau #define TCPOPT_WINDOW 3
55ad2f8eb0SMartin KaFai Lau #define TCPOPT_EXP 254
56ad2f8eb0SMartin KaFai Lau
57ad2f8eb0SMartin KaFai Lau #define TCP_BPF_EXPOPT_BASE_LEN 4
58ad2f8eb0SMartin KaFai Lau #define MAX_TCP_HDR_LEN 60
59ad2f8eb0SMartin KaFai Lau #define MAX_TCP_OPTION_SPACE 40
60ad2f8eb0SMartin KaFai Lau
61ad2f8eb0SMartin KaFai Lau #ifdef BPF_PROG_TEST_TCP_HDR_OPTIONS
62ad2f8eb0SMartin KaFai Lau
63ad2f8eb0SMartin KaFai Lau #define CG_OK 1
64ad2f8eb0SMartin KaFai Lau #define CG_ERR 0
65ad2f8eb0SMartin KaFai Lau
66ad2f8eb0SMartin KaFai Lau #ifndef SOL_TCP
67ad2f8eb0SMartin KaFai Lau #define SOL_TCP 6
68ad2f8eb0SMartin KaFai Lau #endif
69ad2f8eb0SMartin KaFai Lau
70ad2f8eb0SMartin KaFai Lau struct tcp_exprm_opt {
71ad2f8eb0SMartin KaFai Lau __u8 kind;
72ad2f8eb0SMartin KaFai Lau __u8 len;
73ad2f8eb0SMartin KaFai Lau __u16 magic;
74ad2f8eb0SMartin KaFai Lau union {
75ad2f8eb0SMartin KaFai Lau __u8 data[4];
76ad2f8eb0SMartin KaFai Lau __u32 data32;
77ad2f8eb0SMartin KaFai Lau };
78ad2f8eb0SMartin KaFai Lau } __attribute__((packed));
79ad2f8eb0SMartin KaFai Lau
80ad2f8eb0SMartin KaFai Lau struct tcp_opt {
81ad2f8eb0SMartin KaFai Lau __u8 kind;
82ad2f8eb0SMartin KaFai Lau __u8 len;
83ad2f8eb0SMartin KaFai Lau union {
84ad2f8eb0SMartin KaFai Lau __u8 data[4];
85ad2f8eb0SMartin KaFai Lau __u32 data32;
86ad2f8eb0SMartin KaFai Lau };
87ad2f8eb0SMartin KaFai Lau } __attribute__((packed));
88ad2f8eb0SMartin KaFai Lau
89ad2f8eb0SMartin KaFai Lau struct {
90ad2f8eb0SMartin KaFai Lau __uint(type, BPF_MAP_TYPE_HASH);
91ad2f8eb0SMartin KaFai Lau __uint(max_entries, 2);
92ad2f8eb0SMartin KaFai Lau __type(key, int);
93ad2f8eb0SMartin KaFai Lau __type(value, struct linum_err);
94ad2f8eb0SMartin KaFai Lau } lport_linum_map SEC(".maps");
95ad2f8eb0SMartin KaFai Lau
tcp_hdrlen(const struct tcphdr * th)96ad2f8eb0SMartin KaFai Lau static inline unsigned int tcp_hdrlen(const struct tcphdr *th)
97ad2f8eb0SMartin KaFai Lau {
98ad2f8eb0SMartin KaFai Lau return th->doff << 2;
99ad2f8eb0SMartin KaFai Lau }
100ad2f8eb0SMartin KaFai Lau
skops_tcp_flags(const struct bpf_sock_ops * skops)101ad2f8eb0SMartin KaFai Lau static inline __u8 skops_tcp_flags(const struct bpf_sock_ops *skops)
102ad2f8eb0SMartin KaFai Lau {
103ad2f8eb0SMartin KaFai Lau return skops->skb_tcp_flags;
104ad2f8eb0SMartin KaFai Lau }
105ad2f8eb0SMartin KaFai Lau
clear_hdr_cb_flags(struct bpf_sock_ops * skops)106ad2f8eb0SMartin KaFai Lau static inline void clear_hdr_cb_flags(struct bpf_sock_ops *skops)
107ad2f8eb0SMartin KaFai Lau {
108ad2f8eb0SMartin KaFai Lau bpf_sock_ops_cb_flags_set(skops,
109ad2f8eb0SMartin KaFai Lau skops->bpf_sock_ops_cb_flags &
110ad2f8eb0SMartin KaFai Lau ~(BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG |
111ad2f8eb0SMartin KaFai Lau BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG));
112ad2f8eb0SMartin KaFai Lau }
113ad2f8eb0SMartin KaFai Lau
set_hdr_cb_flags(struct bpf_sock_ops * skops,__u32 extra)11496d46c50SMartin KaFai Lau static inline void set_hdr_cb_flags(struct bpf_sock_ops *skops, __u32 extra)
115ad2f8eb0SMartin KaFai Lau {
116ad2f8eb0SMartin KaFai Lau bpf_sock_ops_cb_flags_set(skops,
117ad2f8eb0SMartin KaFai Lau skops->bpf_sock_ops_cb_flags |
118ad2f8eb0SMartin KaFai Lau BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG |
11996d46c50SMartin KaFai Lau BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG |
12096d46c50SMartin KaFai Lau extra);
121ad2f8eb0SMartin KaFai Lau }
122ad2f8eb0SMartin KaFai Lau static inline void
clear_parse_all_hdr_cb_flags(struct bpf_sock_ops * skops)123ad2f8eb0SMartin KaFai Lau clear_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops)
124ad2f8eb0SMartin KaFai Lau {
125ad2f8eb0SMartin KaFai Lau bpf_sock_ops_cb_flags_set(skops,
126ad2f8eb0SMartin KaFai Lau skops->bpf_sock_ops_cb_flags &
127ad2f8eb0SMartin KaFai Lau ~BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
128ad2f8eb0SMartin KaFai Lau }
129ad2f8eb0SMartin KaFai Lau
130ad2f8eb0SMartin KaFai Lau static inline void
set_parse_all_hdr_cb_flags(struct bpf_sock_ops * skops)131ad2f8eb0SMartin KaFai Lau set_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops)
132ad2f8eb0SMartin KaFai Lau {
133ad2f8eb0SMartin KaFai Lau bpf_sock_ops_cb_flags_set(skops,
134ad2f8eb0SMartin KaFai Lau skops->bpf_sock_ops_cb_flags |
135ad2f8eb0SMartin KaFai Lau BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
136ad2f8eb0SMartin KaFai Lau }
137ad2f8eb0SMartin KaFai Lau
138ad2f8eb0SMartin KaFai Lau #define RET_CG_ERR(__err) ({ \
139ad2f8eb0SMartin KaFai Lau struct linum_err __linum_err; \
140ad2f8eb0SMartin KaFai Lau int __lport; \
141ad2f8eb0SMartin KaFai Lau \
142ad2f8eb0SMartin KaFai Lau __linum_err.linum = __LINE__; \
143ad2f8eb0SMartin KaFai Lau __linum_err.err = __err; \
144ad2f8eb0SMartin KaFai Lau __lport = skops->local_port; \
145ad2f8eb0SMartin KaFai Lau bpf_map_update_elem(&lport_linum_map, &__lport, &__linum_err, BPF_NOEXIST); \
146ad2f8eb0SMartin KaFai Lau clear_hdr_cb_flags(skops); \
147ad2f8eb0SMartin KaFai Lau clear_parse_all_hdr_cb_flags(skops); \
148ad2f8eb0SMartin KaFai Lau return CG_ERR; \
149ad2f8eb0SMartin KaFai Lau })
150ad2f8eb0SMartin KaFai Lau
151ad2f8eb0SMartin KaFai Lau #endif /* BPF_PROG_TEST_TCP_HDR_OPTIONS */
152ad2f8eb0SMartin KaFai Lau
153ad2f8eb0SMartin KaFai Lau #endif /* _TEST_TCP_HDR_OPTIONS_H */
154