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 7 struct bpf_test_option { 8 __u8 flags; 9 __u8 max_delack_ms; 10 __u8 rand; 11 } __attribute__((packed)); 12 13 enum { 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 */ 29 struct 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 36 struct 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_WINDOW 3 54 #define TCPOPT_EXP 254 55 56 #define TCP_BPF_EXPOPT_BASE_LEN 4 57 #define MAX_TCP_HDR_LEN 60 58 #define MAX_TCP_OPTION_SPACE 40 59 60 #ifdef BPF_PROG_TEST_TCP_HDR_OPTIONS 61 62 #define CG_OK 1 63 #define CG_ERR 0 64 65 #ifndef SOL_TCP 66 #define SOL_TCP 6 67 #endif 68 69 struct tcp_exprm_opt { 70 __u8 kind; 71 __u8 len; 72 __u16 magic; 73 union { 74 __u8 data[4]; 75 __u32 data32; 76 }; 77 } __attribute__((packed)); 78 79 struct tcp_opt { 80 __u8 kind; 81 __u8 len; 82 union { 83 __u8 data[4]; 84 __u32 data32; 85 }; 86 } __attribute__((packed)); 87 88 struct { 89 __uint(type, BPF_MAP_TYPE_HASH); 90 __uint(max_entries, 2); 91 __type(key, int); 92 __type(value, struct linum_err); 93 } lport_linum_map SEC(".maps"); 94 95 static inline unsigned int tcp_hdrlen(const struct tcphdr *th) 96 { 97 return th->doff << 2; 98 } 99 100 static inline __u8 skops_tcp_flags(const struct bpf_sock_ops *skops) 101 { 102 return skops->skb_tcp_flags; 103 } 104 105 static inline void clear_hdr_cb_flags(struct bpf_sock_ops *skops) 106 { 107 bpf_sock_ops_cb_flags_set(skops, 108 skops->bpf_sock_ops_cb_flags & 109 ~(BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG | 110 BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG)); 111 } 112 113 static inline void set_hdr_cb_flags(struct bpf_sock_ops *skops, __u32 extra) 114 { 115 bpf_sock_ops_cb_flags_set(skops, 116 skops->bpf_sock_ops_cb_flags | 117 BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG | 118 BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG | 119 extra); 120 } 121 static inline void 122 clear_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops) 123 { 124 bpf_sock_ops_cb_flags_set(skops, 125 skops->bpf_sock_ops_cb_flags & 126 ~BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG); 127 } 128 129 static inline void 130 set_parse_all_hdr_cb_flags(struct bpf_sock_ops *skops) 131 { 132 bpf_sock_ops_cb_flags_set(skops, 133 skops->bpf_sock_ops_cb_flags | 134 BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG); 135 } 136 137 #define RET_CG_ERR(__err) ({ \ 138 struct linum_err __linum_err; \ 139 int __lport; \ 140 \ 141 __linum_err.linum = __LINE__; \ 142 __linum_err.err = __err; \ 143 __lport = skops->local_port; \ 144 bpf_map_update_elem(&lport_linum_map, &__lport, &__linum_err, BPF_NOEXIST); \ 145 clear_hdr_cb_flags(skops); \ 146 clear_parse_all_hdr_cb_flags(skops); \ 147 return CG_ERR; \ 148 }) 149 150 #endif /* BPF_PROG_TEST_TCP_HDR_OPTIONS */ 151 152 #endif /* _TEST_TCP_HDR_OPTIONS_H */ 153