/* 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 */