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