1604326b4SDaniel Borkmann /* SPDX-License-Identifier: GPL-2.0 */ 2604326b4SDaniel Borkmann /* Copyright (c) 2017 - 2018 Covalent IO, Inc. http://covalent.io */ 3604326b4SDaniel Borkmann 4604326b4SDaniel Borkmann #ifndef _LINUX_SKMSG_H 5604326b4SDaniel Borkmann #define _LINUX_SKMSG_H 6604326b4SDaniel Borkmann 7604326b4SDaniel Borkmann #include <linux/bpf.h> 8604326b4SDaniel Borkmann #include <linux/filter.h> 9604326b4SDaniel Borkmann #include <linux/scatterlist.h> 10604326b4SDaniel Borkmann #include <linux/skbuff.h> 11604326b4SDaniel Borkmann 12604326b4SDaniel Borkmann #include <net/sock.h> 13604326b4SDaniel Borkmann #include <net/tcp.h> 14604326b4SDaniel Borkmann #include <net/strparser.h> 15604326b4SDaniel Borkmann 16604326b4SDaniel Borkmann #define MAX_MSG_FRAGS MAX_SKB_FRAGS 17031097d9SJakub Kicinski #define NR_MSG_FRAG_IDS (MAX_MSG_FRAGS + 1) 18604326b4SDaniel Borkmann 19604326b4SDaniel Borkmann enum __sk_action { 20604326b4SDaniel Borkmann __SK_DROP = 0, 21604326b4SDaniel Borkmann __SK_PASS, 22604326b4SDaniel Borkmann __SK_REDIRECT, 23604326b4SDaniel Borkmann __SK_NONE, 24604326b4SDaniel Borkmann }; 25604326b4SDaniel Borkmann 26604326b4SDaniel Borkmann struct sk_msg_sg { 27604326b4SDaniel Borkmann u32 start; 28604326b4SDaniel Borkmann u32 curr; 29604326b4SDaniel Borkmann u32 end; 30604326b4SDaniel Borkmann u32 size; 31604326b4SDaniel Borkmann u32 copybreak; 32163ab96bSJakub Kicinski unsigned long copy; 33031097d9SJakub Kicinski /* The extra two elements: 34031097d9SJakub Kicinski * 1) used for chaining the front and sections when the list becomes 35031097d9SJakub Kicinski * partitioned (e.g. end < start). The crypto APIs require the 36031097d9SJakub Kicinski * chaining; 37031097d9SJakub Kicinski * 2) to chain tailer SG entries after the message. 38d3b18ad3SJohn Fastabend */ 39031097d9SJakub Kicinski struct scatterlist data[MAX_MSG_FRAGS + 2]; 40604326b4SDaniel Borkmann }; 41031097d9SJakub Kicinski static_assert(BITS_PER_LONG >= NR_MSG_FRAG_IDS); 42604326b4SDaniel Borkmann 437a69c0f2SJohn Fastabend /* UAPI in filter.c depends on struct sk_msg_sg being first element. */ 44604326b4SDaniel Borkmann struct sk_msg { 45604326b4SDaniel Borkmann struct sk_msg_sg sg; 46604326b4SDaniel Borkmann void *data; 47604326b4SDaniel Borkmann void *data_end; 48604326b4SDaniel Borkmann u32 apply_bytes; 49604326b4SDaniel Borkmann u32 cork_bytes; 50604326b4SDaniel Borkmann u32 flags; 51604326b4SDaniel Borkmann struct sk_buff *skb; 52604326b4SDaniel Borkmann struct sock *sk_redir; 53604326b4SDaniel Borkmann struct sock *sk; 54604326b4SDaniel Borkmann struct list_head list; 55604326b4SDaniel Borkmann }; 56604326b4SDaniel Borkmann 57604326b4SDaniel Borkmann struct sk_psock_progs { 58604326b4SDaniel Borkmann struct bpf_prog *msg_parser; 59604326b4SDaniel Borkmann struct bpf_prog *skb_parser; 60604326b4SDaniel Borkmann struct bpf_prog *skb_verdict; 61604326b4SDaniel Borkmann }; 62604326b4SDaniel Borkmann 63604326b4SDaniel Borkmann enum sk_psock_state_bits { 64604326b4SDaniel Borkmann SK_PSOCK_TX_ENABLED, 65604326b4SDaniel Borkmann }; 66604326b4SDaniel Borkmann 67604326b4SDaniel Borkmann struct sk_psock_link { 68604326b4SDaniel Borkmann struct list_head list; 69604326b4SDaniel Borkmann struct bpf_map *map; 70604326b4SDaniel Borkmann void *link_raw; 71604326b4SDaniel Borkmann }; 72604326b4SDaniel Borkmann 73604326b4SDaniel Borkmann struct sk_psock_parser { 74604326b4SDaniel Borkmann struct strparser strp; 75604326b4SDaniel Borkmann bool enabled; 76604326b4SDaniel Borkmann void (*saved_data_ready)(struct sock *sk); 77604326b4SDaniel Borkmann }; 78604326b4SDaniel Borkmann 79604326b4SDaniel Borkmann struct sk_psock_work_state { 80604326b4SDaniel Borkmann struct sk_buff *skb; 81604326b4SDaniel Borkmann u32 len; 82604326b4SDaniel Borkmann u32 off; 83604326b4SDaniel Borkmann }; 84604326b4SDaniel Borkmann 85604326b4SDaniel Borkmann struct sk_psock { 86604326b4SDaniel Borkmann struct sock *sk; 87604326b4SDaniel Borkmann struct sock *sk_redir; 88604326b4SDaniel Borkmann u32 apply_bytes; 89604326b4SDaniel Borkmann u32 cork_bytes; 90604326b4SDaniel Borkmann u32 eval; 91604326b4SDaniel Borkmann struct sk_msg *cork; 92604326b4SDaniel Borkmann struct sk_psock_progs progs; 93604326b4SDaniel Borkmann struct sk_psock_parser parser; 94604326b4SDaniel Borkmann struct sk_buff_head ingress_skb; 95604326b4SDaniel Borkmann struct list_head ingress_msg; 96604326b4SDaniel Borkmann unsigned long state; 97604326b4SDaniel Borkmann struct list_head link; 98604326b4SDaniel Borkmann spinlock_t link_lock; 99604326b4SDaniel Borkmann refcount_t refcnt; 100604326b4SDaniel Borkmann void (*saved_unhash)(struct sock *sk); 101604326b4SDaniel Borkmann void (*saved_close)(struct sock *sk, long timeout); 102604326b4SDaniel Borkmann void (*saved_write_space)(struct sock *sk); 103604326b4SDaniel Borkmann struct proto *sk_proto; 104604326b4SDaniel Borkmann struct sk_psock_work_state work_state; 105604326b4SDaniel Borkmann struct work_struct work; 106604326b4SDaniel Borkmann union { 107604326b4SDaniel Borkmann struct rcu_head rcu; 108604326b4SDaniel Borkmann struct work_struct gc; 109604326b4SDaniel Borkmann }; 110604326b4SDaniel Borkmann }; 111604326b4SDaniel Borkmann 112604326b4SDaniel Borkmann int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len, 113604326b4SDaniel Borkmann int elem_first_coalesce); 114d829e9c4SDaniel Borkmann int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src, 115d829e9c4SDaniel Borkmann u32 off, u32 len); 116604326b4SDaniel Borkmann void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len); 117604326b4SDaniel Borkmann int sk_msg_free(struct sock *sk, struct sk_msg *msg); 118604326b4SDaniel Borkmann int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg); 119604326b4SDaniel Borkmann void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes); 120604326b4SDaniel Borkmann void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg, 121604326b4SDaniel Borkmann u32 bytes); 122604326b4SDaniel Borkmann 123604326b4SDaniel Borkmann void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes); 124d3b18ad3SJohn Fastabend void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes); 125604326b4SDaniel Borkmann 126604326b4SDaniel Borkmann int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from, 127604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 128604326b4SDaniel Borkmann int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from, 129604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 130604326b4SDaniel Borkmann 131604326b4SDaniel Borkmann static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes) 132604326b4SDaniel Borkmann { 133604326b4SDaniel Borkmann WARN_ON(i == msg->sg.end && bytes); 134604326b4SDaniel Borkmann } 135604326b4SDaniel Borkmann 136604326b4SDaniel Borkmann static inline void sk_msg_apply_bytes(struct sk_psock *psock, u32 bytes) 137604326b4SDaniel Borkmann { 138604326b4SDaniel Borkmann if (psock->apply_bytes) { 139604326b4SDaniel Borkmann if (psock->apply_bytes < bytes) 140604326b4SDaniel Borkmann psock->apply_bytes = 0; 141604326b4SDaniel Borkmann else 142604326b4SDaniel Borkmann psock->apply_bytes -= bytes; 143604326b4SDaniel Borkmann } 144604326b4SDaniel Borkmann } 145604326b4SDaniel Borkmann 146683916f6SJakub Kicinski static inline u32 sk_msg_iter_dist(u32 start, u32 end) 147683916f6SJakub Kicinski { 148031097d9SJakub Kicinski return end >= start ? end - start : end + (NR_MSG_FRAG_IDS - start); 149683916f6SJakub Kicinski } 150683916f6SJakub Kicinski 151604326b4SDaniel Borkmann #define sk_msg_iter_var_prev(var) \ 152604326b4SDaniel Borkmann do { \ 153604326b4SDaniel Borkmann if (var == 0) \ 154031097d9SJakub Kicinski var = NR_MSG_FRAG_IDS - 1; \ 155604326b4SDaniel Borkmann else \ 156604326b4SDaniel Borkmann var--; \ 157604326b4SDaniel Borkmann } while (0) 158604326b4SDaniel Borkmann 159604326b4SDaniel Borkmann #define sk_msg_iter_var_next(var) \ 160604326b4SDaniel Borkmann do { \ 161604326b4SDaniel Borkmann var++; \ 162031097d9SJakub Kicinski if (var == NR_MSG_FRAG_IDS) \ 163604326b4SDaniel Borkmann var = 0; \ 164604326b4SDaniel Borkmann } while (0) 165604326b4SDaniel Borkmann 166604326b4SDaniel Borkmann #define sk_msg_iter_prev(msg, which) \ 167604326b4SDaniel Borkmann sk_msg_iter_var_prev(msg->sg.which) 168604326b4SDaniel Borkmann 169604326b4SDaniel Borkmann #define sk_msg_iter_next(msg, which) \ 170604326b4SDaniel Borkmann sk_msg_iter_var_next(msg->sg.which) 171604326b4SDaniel Borkmann 172604326b4SDaniel Borkmann static inline void sk_msg_clear_meta(struct sk_msg *msg) 173604326b4SDaniel Borkmann { 174604326b4SDaniel Borkmann memset(&msg->sg, 0, offsetofend(struct sk_msg_sg, copy)); 175604326b4SDaniel Borkmann } 176604326b4SDaniel Borkmann 177604326b4SDaniel Borkmann static inline void sk_msg_init(struct sk_msg *msg) 178604326b4SDaniel Borkmann { 179031097d9SJakub Kicinski BUILD_BUG_ON(ARRAY_SIZE(msg->sg.data) - 1 != NR_MSG_FRAG_IDS); 180604326b4SDaniel Borkmann memset(msg, 0, sizeof(*msg)); 181031097d9SJakub Kicinski sg_init_marker(msg->sg.data, NR_MSG_FRAG_IDS); 182604326b4SDaniel Borkmann } 183604326b4SDaniel Borkmann 184604326b4SDaniel Borkmann static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src, 185604326b4SDaniel Borkmann int which, u32 size) 186604326b4SDaniel Borkmann { 187604326b4SDaniel Borkmann dst->sg.data[which] = src->sg.data[which]; 188604326b4SDaniel Borkmann dst->sg.data[which].length = size; 1893f4c3127SJohn Fastabend dst->sg.size += size; 190604326b4SDaniel Borkmann src->sg.data[which].length -= size; 191604326b4SDaniel Borkmann src->sg.data[which].offset += size; 192604326b4SDaniel Borkmann } 193604326b4SDaniel Borkmann 194d3b18ad3SJohn Fastabend static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src) 195d3b18ad3SJohn Fastabend { 196d3b18ad3SJohn Fastabend memcpy(dst, src, sizeof(*src)); 197d3b18ad3SJohn Fastabend sk_msg_init(src); 198d3b18ad3SJohn Fastabend } 199d3b18ad3SJohn Fastabend 200604326b4SDaniel Borkmann static inline bool sk_msg_full(const struct sk_msg *msg) 201604326b4SDaniel Borkmann { 202031097d9SJakub Kicinski return sk_msg_iter_dist(msg->sg.start, msg->sg.end) == MAX_MSG_FRAGS; 203604326b4SDaniel Borkmann } 204604326b4SDaniel Borkmann 2058734a162SJohn Fastabend static inline u32 sk_msg_elem_used(const struct sk_msg *msg) 2068734a162SJohn Fastabend { 207683916f6SJakub Kicinski return sk_msg_iter_dist(msg->sg.start, msg->sg.end); 2088734a162SJohn Fastabend } 2098734a162SJohn Fastabend 210604326b4SDaniel Borkmann static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which) 211604326b4SDaniel Borkmann { 212604326b4SDaniel Borkmann return &msg->sg.data[which]; 213604326b4SDaniel Borkmann } 214604326b4SDaniel Borkmann 2156fff607eSJohn Fastabend static inline struct scatterlist sk_msg_elem_cpy(struct sk_msg *msg, int which) 2166fff607eSJohn Fastabend { 2176fff607eSJohn Fastabend return msg->sg.data[which]; 2186fff607eSJohn Fastabend } 2196fff607eSJohn Fastabend 220604326b4SDaniel Borkmann static inline struct page *sk_msg_page(struct sk_msg *msg, int which) 221604326b4SDaniel Borkmann { 222604326b4SDaniel Borkmann return sg_page(sk_msg_elem(msg, which)); 223604326b4SDaniel Borkmann } 224604326b4SDaniel Borkmann 225604326b4SDaniel Borkmann static inline bool sk_msg_to_ingress(const struct sk_msg *msg) 226604326b4SDaniel Borkmann { 227604326b4SDaniel Borkmann return msg->flags & BPF_F_INGRESS; 228604326b4SDaniel Borkmann } 229604326b4SDaniel Borkmann 230604326b4SDaniel Borkmann static inline void sk_msg_compute_data_pointers(struct sk_msg *msg) 231604326b4SDaniel Borkmann { 232604326b4SDaniel Borkmann struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start); 233604326b4SDaniel Borkmann 234163ab96bSJakub Kicinski if (test_bit(msg->sg.start, &msg->sg.copy)) { 235604326b4SDaniel Borkmann msg->data = NULL; 236604326b4SDaniel Borkmann msg->data_end = NULL; 237604326b4SDaniel Borkmann } else { 238604326b4SDaniel Borkmann msg->data = sg_virt(sge); 239604326b4SDaniel Borkmann msg->data_end = msg->data + sge->length; 240604326b4SDaniel Borkmann } 241604326b4SDaniel Borkmann } 242604326b4SDaniel Borkmann 243604326b4SDaniel Borkmann static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page, 244604326b4SDaniel Borkmann u32 len, u32 offset) 245604326b4SDaniel Borkmann { 246604326b4SDaniel Borkmann struct scatterlist *sge; 247604326b4SDaniel Borkmann 248604326b4SDaniel Borkmann get_page(page); 249604326b4SDaniel Borkmann sge = sk_msg_elem(msg, msg->sg.end); 250604326b4SDaniel Borkmann sg_set_page(sge, page, len, offset); 251604326b4SDaniel Borkmann sg_unmark_end(sge); 252604326b4SDaniel Borkmann 253163ab96bSJakub Kicinski __set_bit(msg->sg.end, &msg->sg.copy); 254604326b4SDaniel Borkmann msg->sg.size += len; 255604326b4SDaniel Borkmann sk_msg_iter_next(msg, end); 256604326b4SDaniel Borkmann } 257604326b4SDaniel Borkmann 258d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state) 259d3b18ad3SJohn Fastabend { 260d3b18ad3SJohn Fastabend do { 261163ab96bSJakub Kicinski if (copy_state) 262163ab96bSJakub Kicinski __set_bit(i, &msg->sg.copy); 263163ab96bSJakub Kicinski else 264163ab96bSJakub Kicinski __clear_bit(i, &msg->sg.copy); 265d3b18ad3SJohn Fastabend sk_msg_iter_var_next(i); 266d3b18ad3SJohn Fastabend if (i == msg->sg.end) 267d3b18ad3SJohn Fastabend break; 268d3b18ad3SJohn Fastabend } while (1); 269d3b18ad3SJohn Fastabend } 270d3b18ad3SJohn Fastabend 271d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start) 272d3b18ad3SJohn Fastabend { 273d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, true); 274d3b18ad3SJohn Fastabend } 275d3b18ad3SJohn Fastabend 276d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_clear(struct sk_msg *msg, u32 start) 277d3b18ad3SJohn Fastabend { 278d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, false); 279d3b18ad3SJohn Fastabend } 280d3b18ad3SJohn Fastabend 281604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock(const struct sock *sk) 282604326b4SDaniel Borkmann { 283604326b4SDaniel Borkmann return rcu_dereference_sk_user_data(sk); 284604326b4SDaniel Borkmann } 285604326b4SDaniel Borkmann 286604326b4SDaniel Borkmann static inline void sk_psock_queue_msg(struct sk_psock *psock, 287604326b4SDaniel Borkmann struct sk_msg *msg) 288604326b4SDaniel Borkmann { 289604326b4SDaniel Borkmann list_add_tail(&msg->list, &psock->ingress_msg); 290604326b4SDaniel Borkmann } 291604326b4SDaniel Borkmann 292d3b18ad3SJohn Fastabend static inline bool sk_psock_queue_empty(const struct sk_psock *psock) 293d3b18ad3SJohn Fastabend { 294d3b18ad3SJohn Fastabend return psock ? list_empty(&psock->ingress_msg) : true; 295d3b18ad3SJohn Fastabend } 296d3b18ad3SJohn Fastabend 297604326b4SDaniel Borkmann static inline void sk_psock_report_error(struct sk_psock *psock, int err) 298604326b4SDaniel Borkmann { 299604326b4SDaniel Borkmann struct sock *sk = psock->sk; 300604326b4SDaniel Borkmann 301604326b4SDaniel Borkmann sk->sk_err = err; 302604326b4SDaniel Borkmann sk->sk_error_report(sk); 303604326b4SDaniel Borkmann } 304604326b4SDaniel Borkmann 305604326b4SDaniel Borkmann struct sk_psock *sk_psock_init(struct sock *sk, int node); 306604326b4SDaniel Borkmann 307604326b4SDaniel Borkmann int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock); 308604326b4SDaniel Borkmann void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock); 309604326b4SDaniel Borkmann void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock); 310604326b4SDaniel Borkmann 311604326b4SDaniel Borkmann int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, 312604326b4SDaniel Borkmann struct sk_msg *msg); 313604326b4SDaniel Borkmann 314604326b4SDaniel Borkmann static inline struct sk_psock_link *sk_psock_init_link(void) 315604326b4SDaniel Borkmann { 316604326b4SDaniel Borkmann return kzalloc(sizeof(struct sk_psock_link), 317604326b4SDaniel Borkmann GFP_ATOMIC | __GFP_NOWARN); 318604326b4SDaniel Borkmann } 319604326b4SDaniel Borkmann 320604326b4SDaniel Borkmann static inline void sk_psock_free_link(struct sk_psock_link *link) 321604326b4SDaniel Borkmann { 322604326b4SDaniel Borkmann kfree(link); 323604326b4SDaniel Borkmann } 324604326b4SDaniel Borkmann 325604326b4SDaniel Borkmann struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock); 326604326b4SDaniel Borkmann #if defined(CONFIG_BPF_STREAM_PARSER) 327604326b4SDaniel Borkmann void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link); 328604326b4SDaniel Borkmann #else 329604326b4SDaniel Borkmann static inline void sk_psock_unlink(struct sock *sk, 330604326b4SDaniel Borkmann struct sk_psock_link *link) 331604326b4SDaniel Borkmann { 332604326b4SDaniel Borkmann } 333604326b4SDaniel Borkmann #endif 334604326b4SDaniel Borkmann 335604326b4SDaniel Borkmann void __sk_psock_purge_ingress_msg(struct sk_psock *psock); 336604326b4SDaniel Borkmann 337604326b4SDaniel Borkmann static inline void sk_psock_cork_free(struct sk_psock *psock) 338604326b4SDaniel Borkmann { 339604326b4SDaniel Borkmann if (psock->cork) { 340604326b4SDaniel Borkmann sk_msg_free(psock->sk, psock->cork); 341604326b4SDaniel Borkmann kfree(psock->cork); 342604326b4SDaniel Borkmann psock->cork = NULL; 343604326b4SDaniel Borkmann } 344604326b4SDaniel Borkmann } 345604326b4SDaniel Borkmann 346604326b4SDaniel Borkmann static inline void sk_psock_update_proto(struct sock *sk, 347604326b4SDaniel Borkmann struct sk_psock *psock, 348604326b4SDaniel Borkmann struct proto *ops) 349604326b4SDaniel Borkmann { 350604326b4SDaniel Borkmann psock->saved_unhash = sk->sk_prot->unhash; 351604326b4SDaniel Borkmann psock->saved_close = sk->sk_prot->close; 352604326b4SDaniel Borkmann psock->saved_write_space = sk->sk_write_space; 353604326b4SDaniel Borkmann 354604326b4SDaniel Borkmann psock->sk_proto = sk->sk_prot; 355604326b4SDaniel Borkmann sk->sk_prot = ops; 356604326b4SDaniel Borkmann } 357604326b4SDaniel Borkmann 358604326b4SDaniel Borkmann static inline void sk_psock_restore_proto(struct sock *sk, 359604326b4SDaniel Borkmann struct sk_psock *psock) 360604326b4SDaniel Borkmann { 361*4da6a196SJohn Fastabend sk->sk_prot->unhash = psock->saved_unhash; 362186bcc3dSJakub Sitnicki sk->sk_write_space = psock->saved_write_space; 363186bcc3dSJakub Sitnicki 364604326b4SDaniel Borkmann if (psock->sk_proto) { 36595fa1454SJohn Fastabend struct inet_connection_sock *icsk = inet_csk(sk); 36695fa1454SJohn Fastabend bool has_ulp = !!icsk->icsk_ulp_data; 36795fa1454SJohn Fastabend 36895fa1454SJohn Fastabend if (has_ulp) 36995fa1454SJohn Fastabend tcp_update_ulp(sk, psock->sk_proto); 37095fa1454SJohn Fastabend else 371604326b4SDaniel Borkmann sk->sk_prot = psock->sk_proto; 372604326b4SDaniel Borkmann psock->sk_proto = NULL; 373604326b4SDaniel Borkmann } 374604326b4SDaniel Borkmann } 375604326b4SDaniel Borkmann 376604326b4SDaniel Borkmann static inline void sk_psock_set_state(struct sk_psock *psock, 377604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 378604326b4SDaniel Borkmann { 379604326b4SDaniel Borkmann set_bit(bit, &psock->state); 380604326b4SDaniel Borkmann } 381604326b4SDaniel Borkmann 382604326b4SDaniel Borkmann static inline void sk_psock_clear_state(struct sk_psock *psock, 383604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 384604326b4SDaniel Borkmann { 385604326b4SDaniel Borkmann clear_bit(bit, &psock->state); 386604326b4SDaniel Borkmann } 387604326b4SDaniel Borkmann 388604326b4SDaniel Borkmann static inline bool sk_psock_test_state(const struct sk_psock *psock, 389604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 390604326b4SDaniel Borkmann { 391604326b4SDaniel Borkmann return test_bit(bit, &psock->state); 392604326b4SDaniel Borkmann } 393604326b4SDaniel Borkmann 3945032d079SJohn Fastabend static inline struct sk_psock *sk_psock_get_checked(struct sock *sk) 3955032d079SJohn Fastabend { 3965032d079SJohn Fastabend struct sk_psock *psock; 3975032d079SJohn Fastabend 3985032d079SJohn Fastabend rcu_read_lock(); 3995032d079SJohn Fastabend psock = sk_psock(sk); 4005032d079SJohn Fastabend if (psock) { 4015032d079SJohn Fastabend if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { 4025032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 4035032d079SJohn Fastabend goto out; 4045032d079SJohn Fastabend } 4055032d079SJohn Fastabend 4065032d079SJohn Fastabend if (!refcount_inc_not_zero(&psock->refcnt)) 4075032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 4085032d079SJohn Fastabend } 4095032d079SJohn Fastabend out: 4105032d079SJohn Fastabend rcu_read_unlock(); 4115032d079SJohn Fastabend return psock; 4125032d079SJohn Fastabend } 4135032d079SJohn Fastabend 414604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock_get(struct sock *sk) 415604326b4SDaniel Borkmann { 416604326b4SDaniel Borkmann struct sk_psock *psock; 417604326b4SDaniel Borkmann 418604326b4SDaniel Borkmann rcu_read_lock(); 419604326b4SDaniel Borkmann psock = sk_psock(sk); 420604326b4SDaniel Borkmann if (psock && !refcount_inc_not_zero(&psock->refcnt)) 421604326b4SDaniel Borkmann psock = NULL; 422604326b4SDaniel Borkmann rcu_read_unlock(); 423604326b4SDaniel Borkmann return psock; 424604326b4SDaniel Borkmann } 425604326b4SDaniel Borkmann 426604326b4SDaniel Borkmann void sk_psock_stop(struct sock *sk, struct sk_psock *psock); 427604326b4SDaniel Borkmann void sk_psock_destroy(struct rcu_head *rcu); 428604326b4SDaniel Borkmann void sk_psock_drop(struct sock *sk, struct sk_psock *psock); 429604326b4SDaniel Borkmann 430604326b4SDaniel Borkmann static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock) 431604326b4SDaniel Borkmann { 432604326b4SDaniel Borkmann if (refcount_dec_and_test(&psock->refcnt)) 433604326b4SDaniel Borkmann sk_psock_drop(sk, psock); 434604326b4SDaniel Borkmann } 435604326b4SDaniel Borkmann 436552de910SJohn Fastabend static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock) 437552de910SJohn Fastabend { 438552de910SJohn Fastabend if (psock->parser.enabled) 439552de910SJohn Fastabend psock->parser.saved_data_ready(sk); 440552de910SJohn Fastabend else 441552de910SJohn Fastabend sk->sk_data_ready(sk); 442552de910SJohn Fastabend } 443552de910SJohn Fastabend 444604326b4SDaniel Borkmann static inline void psock_set_prog(struct bpf_prog **pprog, 445604326b4SDaniel Borkmann struct bpf_prog *prog) 446604326b4SDaniel Borkmann { 447604326b4SDaniel Borkmann prog = xchg(pprog, prog); 448604326b4SDaniel Borkmann if (prog) 449604326b4SDaniel Borkmann bpf_prog_put(prog); 450604326b4SDaniel Borkmann } 451604326b4SDaniel Borkmann 452604326b4SDaniel Borkmann static inline void psock_progs_drop(struct sk_psock_progs *progs) 453604326b4SDaniel Borkmann { 454604326b4SDaniel Borkmann psock_set_prog(&progs->msg_parser, NULL); 455604326b4SDaniel Borkmann psock_set_prog(&progs->skb_parser, NULL); 456604326b4SDaniel Borkmann psock_set_prog(&progs->skb_verdict, NULL); 457604326b4SDaniel Borkmann } 458604326b4SDaniel Borkmann 459604326b4SDaniel Borkmann #endif /* _LINUX_SKMSG_H */ 460