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_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 70 struct 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 80 struct tcp_opt { 81 __u8 kind; 82 __u8 len; 83 union { 84 __u8 data[4]; 85 __u32 data32; 86 }; 87 } __attribute__((packed)); 88 89 struct { 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 96 static inline unsigned int tcp_hdrlen(const struct tcphdr *th) 97 { 98 return th->doff << 2; 99 } 100 101 static inline __u8 skops_tcp_flags(const struct bpf_sock_ops *skops) 102 { 103 return skops->skb_tcp_flags; 104 } 105 106 static 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 114 static 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 } 122 static inline void 123 clear_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 130 static inline void 131 set_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