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 17604326b4SDaniel Borkmann 18604326b4SDaniel Borkmann enum __sk_action { 19604326b4SDaniel Borkmann __SK_DROP = 0, 20604326b4SDaniel Borkmann __SK_PASS, 21604326b4SDaniel Borkmann __SK_REDIRECT, 22604326b4SDaniel Borkmann __SK_NONE, 23604326b4SDaniel Borkmann }; 24604326b4SDaniel Borkmann 25604326b4SDaniel Borkmann struct sk_msg_sg { 26604326b4SDaniel Borkmann u32 start; 27604326b4SDaniel Borkmann u32 curr; 28604326b4SDaniel Borkmann u32 end; 29604326b4SDaniel Borkmann u32 size; 30604326b4SDaniel Borkmann u32 copybreak; 31604326b4SDaniel Borkmann bool copy[MAX_MSG_FRAGS]; 32d3b18ad3SJohn Fastabend /* The extra element is used for chaining the front and sections when 33d3b18ad3SJohn Fastabend * the list becomes partitioned (e.g. end < start). The crypto APIs 34d3b18ad3SJohn Fastabend * require the chaining. 35d3b18ad3SJohn Fastabend */ 36d3b18ad3SJohn Fastabend struct scatterlist data[MAX_MSG_FRAGS + 1]; 37604326b4SDaniel Borkmann }; 38604326b4SDaniel Borkmann 397a69c0f2SJohn Fastabend /* UAPI in filter.c depends on struct sk_msg_sg being first element. */ 40604326b4SDaniel Borkmann struct sk_msg { 41604326b4SDaniel Borkmann struct sk_msg_sg sg; 42604326b4SDaniel Borkmann void *data; 43604326b4SDaniel Borkmann void *data_end; 44604326b4SDaniel Borkmann u32 apply_bytes; 45604326b4SDaniel Borkmann u32 cork_bytes; 46604326b4SDaniel Borkmann u32 flags; 47604326b4SDaniel Borkmann struct sk_buff *skb; 48604326b4SDaniel Borkmann struct sock *sk_redir; 49604326b4SDaniel Borkmann struct sock *sk; 50604326b4SDaniel Borkmann struct list_head list; 51604326b4SDaniel Borkmann }; 52604326b4SDaniel Borkmann 53604326b4SDaniel Borkmann struct sk_psock_progs { 54604326b4SDaniel Borkmann struct bpf_prog *msg_parser; 55604326b4SDaniel Borkmann struct bpf_prog *skb_parser; 56604326b4SDaniel Borkmann struct bpf_prog *skb_verdict; 57604326b4SDaniel Borkmann }; 58604326b4SDaniel Borkmann 59604326b4SDaniel Borkmann enum sk_psock_state_bits { 60604326b4SDaniel Borkmann SK_PSOCK_TX_ENABLED, 61604326b4SDaniel Borkmann }; 62604326b4SDaniel Borkmann 63604326b4SDaniel Borkmann struct sk_psock_link { 64604326b4SDaniel Borkmann struct list_head list; 65604326b4SDaniel Borkmann struct bpf_map *map; 66604326b4SDaniel Borkmann void *link_raw; 67604326b4SDaniel Borkmann }; 68604326b4SDaniel Borkmann 69604326b4SDaniel Borkmann struct sk_psock_parser { 70604326b4SDaniel Borkmann struct strparser strp; 71604326b4SDaniel Borkmann bool enabled; 72604326b4SDaniel Borkmann void (*saved_data_ready)(struct sock *sk); 73604326b4SDaniel Borkmann }; 74604326b4SDaniel Borkmann 75604326b4SDaniel Borkmann struct sk_psock_work_state { 76604326b4SDaniel Borkmann struct sk_buff *skb; 77604326b4SDaniel Borkmann u32 len; 78604326b4SDaniel Borkmann u32 off; 79604326b4SDaniel Borkmann }; 80604326b4SDaniel Borkmann 81604326b4SDaniel Borkmann struct sk_psock { 82604326b4SDaniel Borkmann struct sock *sk; 83604326b4SDaniel Borkmann struct sock *sk_redir; 84604326b4SDaniel Borkmann u32 apply_bytes; 85604326b4SDaniel Borkmann u32 cork_bytes; 86604326b4SDaniel Borkmann u32 eval; 87604326b4SDaniel Borkmann struct sk_msg *cork; 88604326b4SDaniel Borkmann struct sk_psock_progs progs; 89604326b4SDaniel Borkmann struct sk_psock_parser parser; 90604326b4SDaniel Borkmann struct sk_buff_head ingress_skb; 91604326b4SDaniel Borkmann struct list_head ingress_msg; 92604326b4SDaniel Borkmann unsigned long state; 93604326b4SDaniel Borkmann struct list_head link; 94604326b4SDaniel Borkmann spinlock_t link_lock; 95604326b4SDaniel Borkmann refcount_t refcnt; 96604326b4SDaniel Borkmann void (*saved_unhash)(struct sock *sk); 97604326b4SDaniel Borkmann void (*saved_close)(struct sock *sk, long timeout); 98604326b4SDaniel Borkmann void (*saved_write_space)(struct sock *sk); 99604326b4SDaniel Borkmann struct proto *sk_proto; 100604326b4SDaniel Borkmann struct sk_psock_work_state work_state; 101604326b4SDaniel Borkmann struct work_struct work; 102604326b4SDaniel Borkmann union { 103604326b4SDaniel Borkmann struct rcu_head rcu; 104604326b4SDaniel Borkmann struct work_struct gc; 105604326b4SDaniel Borkmann }; 106604326b4SDaniel Borkmann }; 107604326b4SDaniel Borkmann 108604326b4SDaniel Borkmann int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len, 109604326b4SDaniel Borkmann int elem_first_coalesce); 110d829e9c4SDaniel Borkmann int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src, 111d829e9c4SDaniel Borkmann u32 off, u32 len); 112604326b4SDaniel Borkmann void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len); 113604326b4SDaniel Borkmann int sk_msg_free(struct sock *sk, struct sk_msg *msg); 114604326b4SDaniel Borkmann int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg); 115604326b4SDaniel Borkmann void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes); 116604326b4SDaniel Borkmann void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg, 117604326b4SDaniel Borkmann u32 bytes); 118604326b4SDaniel Borkmann 119604326b4SDaniel Borkmann void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes); 120d3b18ad3SJohn Fastabend void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes); 121604326b4SDaniel Borkmann 122604326b4SDaniel Borkmann int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from, 123604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 124604326b4SDaniel Borkmann int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from, 125604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 126604326b4SDaniel Borkmann 127604326b4SDaniel Borkmann static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes) 128604326b4SDaniel Borkmann { 129604326b4SDaniel Borkmann WARN_ON(i == msg->sg.end && bytes); 130604326b4SDaniel Borkmann } 131604326b4SDaniel Borkmann 132604326b4SDaniel Borkmann static inline void sk_msg_apply_bytes(struct sk_psock *psock, u32 bytes) 133604326b4SDaniel Borkmann { 134604326b4SDaniel Borkmann if (psock->apply_bytes) { 135604326b4SDaniel Borkmann if (psock->apply_bytes < bytes) 136604326b4SDaniel Borkmann psock->apply_bytes = 0; 137604326b4SDaniel Borkmann else 138604326b4SDaniel Borkmann psock->apply_bytes -= bytes; 139604326b4SDaniel Borkmann } 140604326b4SDaniel Borkmann } 141604326b4SDaniel Borkmann 142604326b4SDaniel Borkmann #define sk_msg_iter_var_prev(var) \ 143604326b4SDaniel Borkmann do { \ 144604326b4SDaniel Borkmann if (var == 0) \ 145604326b4SDaniel Borkmann var = MAX_MSG_FRAGS - 1; \ 146604326b4SDaniel Borkmann else \ 147604326b4SDaniel Borkmann var--; \ 148604326b4SDaniel Borkmann } while (0) 149604326b4SDaniel Borkmann 150604326b4SDaniel Borkmann #define sk_msg_iter_var_next(var) \ 151604326b4SDaniel Borkmann do { \ 152604326b4SDaniel Borkmann var++; \ 153604326b4SDaniel Borkmann if (var == MAX_MSG_FRAGS) \ 154604326b4SDaniel Borkmann var = 0; \ 155604326b4SDaniel Borkmann } while (0) 156604326b4SDaniel Borkmann 157604326b4SDaniel Borkmann #define sk_msg_iter_prev(msg, which) \ 158604326b4SDaniel Borkmann sk_msg_iter_var_prev(msg->sg.which) 159604326b4SDaniel Borkmann 160604326b4SDaniel Borkmann #define sk_msg_iter_next(msg, which) \ 161604326b4SDaniel Borkmann sk_msg_iter_var_next(msg->sg.which) 162604326b4SDaniel Borkmann 163604326b4SDaniel Borkmann static inline void sk_msg_clear_meta(struct sk_msg *msg) 164604326b4SDaniel Borkmann { 165604326b4SDaniel Borkmann memset(&msg->sg, 0, offsetofend(struct sk_msg_sg, copy)); 166604326b4SDaniel Borkmann } 167604326b4SDaniel Borkmann 168604326b4SDaniel Borkmann static inline void sk_msg_init(struct sk_msg *msg) 169604326b4SDaniel Borkmann { 170d3b18ad3SJohn Fastabend BUILD_BUG_ON(ARRAY_SIZE(msg->sg.data) - 1 != MAX_MSG_FRAGS); 171604326b4SDaniel Borkmann memset(msg, 0, sizeof(*msg)); 172d3b18ad3SJohn Fastabend sg_init_marker(msg->sg.data, MAX_MSG_FRAGS); 173604326b4SDaniel Borkmann } 174604326b4SDaniel Borkmann 175604326b4SDaniel Borkmann static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src, 176604326b4SDaniel Borkmann int which, u32 size) 177604326b4SDaniel Borkmann { 178604326b4SDaniel Borkmann dst->sg.data[which] = src->sg.data[which]; 179604326b4SDaniel Borkmann dst->sg.data[which].length = size; 1803f4c3127SJohn Fastabend dst->sg.size += size; 181604326b4SDaniel Borkmann src->sg.data[which].length -= size; 182604326b4SDaniel Borkmann src->sg.data[which].offset += size; 183604326b4SDaniel Borkmann } 184604326b4SDaniel Borkmann 185d3b18ad3SJohn Fastabend static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src) 186d3b18ad3SJohn Fastabend { 187d3b18ad3SJohn Fastabend memcpy(dst, src, sizeof(*src)); 188d3b18ad3SJohn Fastabend sk_msg_init(src); 189d3b18ad3SJohn Fastabend } 190d3b18ad3SJohn Fastabend 191604326b4SDaniel Borkmann static inline bool sk_msg_full(const struct sk_msg *msg) 192604326b4SDaniel Borkmann { 193604326b4SDaniel Borkmann return (msg->sg.end == msg->sg.start) && msg->sg.size; 194604326b4SDaniel Borkmann } 195604326b4SDaniel Borkmann 1968734a162SJohn Fastabend static inline u32 sk_msg_elem_used(const struct sk_msg *msg) 1978734a162SJohn Fastabend { 1988734a162SJohn Fastabend if (sk_msg_full(msg)) 1998734a162SJohn Fastabend return MAX_MSG_FRAGS; 2008734a162SJohn Fastabend 2018734a162SJohn Fastabend return msg->sg.end >= msg->sg.start ? 2028734a162SJohn Fastabend msg->sg.end - msg->sg.start : 2038734a162SJohn Fastabend msg->sg.end + (MAX_MSG_FRAGS - msg->sg.start); 2048734a162SJohn Fastabend } 2058734a162SJohn Fastabend 206604326b4SDaniel Borkmann static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which) 207604326b4SDaniel Borkmann { 208604326b4SDaniel Borkmann return &msg->sg.data[which]; 209604326b4SDaniel Borkmann } 210604326b4SDaniel Borkmann 2116fff607eSJohn Fastabend static inline struct scatterlist sk_msg_elem_cpy(struct sk_msg *msg, int which) 2126fff607eSJohn Fastabend { 2136fff607eSJohn Fastabend return msg->sg.data[which]; 2146fff607eSJohn Fastabend } 2156fff607eSJohn Fastabend 216604326b4SDaniel Borkmann static inline struct page *sk_msg_page(struct sk_msg *msg, int which) 217604326b4SDaniel Borkmann { 218604326b4SDaniel Borkmann return sg_page(sk_msg_elem(msg, which)); 219604326b4SDaniel Borkmann } 220604326b4SDaniel Borkmann 221604326b4SDaniel Borkmann static inline bool sk_msg_to_ingress(const struct sk_msg *msg) 222604326b4SDaniel Borkmann { 223604326b4SDaniel Borkmann return msg->flags & BPF_F_INGRESS; 224604326b4SDaniel Borkmann } 225604326b4SDaniel Borkmann 226604326b4SDaniel Borkmann static inline void sk_msg_compute_data_pointers(struct sk_msg *msg) 227604326b4SDaniel Borkmann { 228604326b4SDaniel Borkmann struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start); 229604326b4SDaniel Borkmann 230604326b4SDaniel Borkmann if (msg->sg.copy[msg->sg.start]) { 231604326b4SDaniel Borkmann msg->data = NULL; 232604326b4SDaniel Borkmann msg->data_end = NULL; 233604326b4SDaniel Borkmann } else { 234604326b4SDaniel Borkmann msg->data = sg_virt(sge); 235604326b4SDaniel Borkmann msg->data_end = msg->data + sge->length; 236604326b4SDaniel Borkmann } 237604326b4SDaniel Borkmann } 238604326b4SDaniel Borkmann 239604326b4SDaniel Borkmann static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page, 240604326b4SDaniel Borkmann u32 len, u32 offset) 241604326b4SDaniel Borkmann { 242604326b4SDaniel Borkmann struct scatterlist *sge; 243604326b4SDaniel Borkmann 244604326b4SDaniel Borkmann get_page(page); 245604326b4SDaniel Borkmann sge = sk_msg_elem(msg, msg->sg.end); 246604326b4SDaniel Borkmann sg_set_page(sge, page, len, offset); 247604326b4SDaniel Borkmann sg_unmark_end(sge); 248604326b4SDaniel Borkmann 249604326b4SDaniel Borkmann msg->sg.copy[msg->sg.end] = true; 250604326b4SDaniel Borkmann msg->sg.size += len; 251604326b4SDaniel Borkmann sk_msg_iter_next(msg, end); 252604326b4SDaniel Borkmann } 253604326b4SDaniel Borkmann 254d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state) 255d3b18ad3SJohn Fastabend { 256d3b18ad3SJohn Fastabend do { 257d3b18ad3SJohn Fastabend msg->sg.copy[i] = copy_state; 258d3b18ad3SJohn Fastabend sk_msg_iter_var_next(i); 259d3b18ad3SJohn Fastabend if (i == msg->sg.end) 260d3b18ad3SJohn Fastabend break; 261d3b18ad3SJohn Fastabend } while (1); 262d3b18ad3SJohn Fastabend } 263d3b18ad3SJohn Fastabend 264d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start) 265d3b18ad3SJohn Fastabend { 266d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, true); 267d3b18ad3SJohn Fastabend } 268d3b18ad3SJohn Fastabend 269d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_clear(struct sk_msg *msg, u32 start) 270d3b18ad3SJohn Fastabend { 271d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, false); 272d3b18ad3SJohn Fastabend } 273d3b18ad3SJohn Fastabend 274604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock(const struct sock *sk) 275604326b4SDaniel Borkmann { 276604326b4SDaniel Borkmann return rcu_dereference_sk_user_data(sk); 277604326b4SDaniel Borkmann } 278604326b4SDaniel Borkmann 279604326b4SDaniel Borkmann static inline void sk_psock_queue_msg(struct sk_psock *psock, 280604326b4SDaniel Borkmann struct sk_msg *msg) 281604326b4SDaniel Borkmann { 282604326b4SDaniel Borkmann list_add_tail(&msg->list, &psock->ingress_msg); 283604326b4SDaniel Borkmann } 284604326b4SDaniel Borkmann 285d3b18ad3SJohn Fastabend static inline bool sk_psock_queue_empty(const struct sk_psock *psock) 286d3b18ad3SJohn Fastabend { 287d3b18ad3SJohn Fastabend return psock ? list_empty(&psock->ingress_msg) : true; 288d3b18ad3SJohn Fastabend } 289d3b18ad3SJohn Fastabend 290604326b4SDaniel Borkmann static inline void sk_psock_report_error(struct sk_psock *psock, int err) 291604326b4SDaniel Borkmann { 292604326b4SDaniel Borkmann struct sock *sk = psock->sk; 293604326b4SDaniel Borkmann 294604326b4SDaniel Borkmann sk->sk_err = err; 295604326b4SDaniel Borkmann sk->sk_error_report(sk); 296604326b4SDaniel Borkmann } 297604326b4SDaniel Borkmann 298604326b4SDaniel Borkmann struct sk_psock *sk_psock_init(struct sock *sk, int node); 299604326b4SDaniel Borkmann 300604326b4SDaniel Borkmann int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock); 301604326b4SDaniel Borkmann void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock); 302604326b4SDaniel Borkmann void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock); 303604326b4SDaniel Borkmann 304604326b4SDaniel Borkmann int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, 305604326b4SDaniel Borkmann struct sk_msg *msg); 306604326b4SDaniel Borkmann 307604326b4SDaniel Borkmann static inline struct sk_psock_link *sk_psock_init_link(void) 308604326b4SDaniel Borkmann { 309604326b4SDaniel Borkmann return kzalloc(sizeof(struct sk_psock_link), 310604326b4SDaniel Borkmann GFP_ATOMIC | __GFP_NOWARN); 311604326b4SDaniel Borkmann } 312604326b4SDaniel Borkmann 313604326b4SDaniel Borkmann static inline void sk_psock_free_link(struct sk_psock_link *link) 314604326b4SDaniel Borkmann { 315604326b4SDaniel Borkmann kfree(link); 316604326b4SDaniel Borkmann } 317604326b4SDaniel Borkmann 318604326b4SDaniel Borkmann struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock); 319604326b4SDaniel Borkmann #if defined(CONFIG_BPF_STREAM_PARSER) 320604326b4SDaniel Borkmann void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link); 321604326b4SDaniel Borkmann #else 322604326b4SDaniel Borkmann static inline void sk_psock_unlink(struct sock *sk, 323604326b4SDaniel Borkmann struct sk_psock_link *link) 324604326b4SDaniel Borkmann { 325604326b4SDaniel Borkmann } 326604326b4SDaniel Borkmann #endif 327604326b4SDaniel Borkmann 328604326b4SDaniel Borkmann void __sk_psock_purge_ingress_msg(struct sk_psock *psock); 329604326b4SDaniel Borkmann 330604326b4SDaniel Borkmann static inline void sk_psock_cork_free(struct sk_psock *psock) 331604326b4SDaniel Borkmann { 332604326b4SDaniel Borkmann if (psock->cork) { 333604326b4SDaniel Borkmann sk_msg_free(psock->sk, psock->cork); 334604326b4SDaniel Borkmann kfree(psock->cork); 335604326b4SDaniel Borkmann psock->cork = NULL; 336604326b4SDaniel Borkmann } 337604326b4SDaniel Borkmann } 338604326b4SDaniel Borkmann 339604326b4SDaniel Borkmann static inline void sk_psock_update_proto(struct sock *sk, 340604326b4SDaniel Borkmann struct sk_psock *psock, 341604326b4SDaniel Borkmann struct proto *ops) 342604326b4SDaniel Borkmann { 343604326b4SDaniel Borkmann psock->saved_unhash = sk->sk_prot->unhash; 344604326b4SDaniel Borkmann psock->saved_close = sk->sk_prot->close; 345604326b4SDaniel Borkmann psock->saved_write_space = sk->sk_write_space; 346604326b4SDaniel Borkmann 347604326b4SDaniel Borkmann psock->sk_proto = sk->sk_prot; 348604326b4SDaniel Borkmann sk->sk_prot = ops; 349604326b4SDaniel Borkmann } 350604326b4SDaniel Borkmann 351604326b4SDaniel Borkmann static inline void sk_psock_restore_proto(struct sock *sk, 352604326b4SDaniel Borkmann struct sk_psock *psock) 353604326b4SDaniel Borkmann { 354*186bcc3dSJakub Sitnicki sk->sk_write_space = psock->saved_write_space; 355*186bcc3dSJakub Sitnicki 356604326b4SDaniel Borkmann if (psock->sk_proto) { 357604326b4SDaniel Borkmann sk->sk_prot = psock->sk_proto; 358604326b4SDaniel Borkmann psock->sk_proto = NULL; 359604326b4SDaniel Borkmann } 360604326b4SDaniel Borkmann } 361604326b4SDaniel Borkmann 362604326b4SDaniel Borkmann static inline void sk_psock_set_state(struct sk_psock *psock, 363604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 364604326b4SDaniel Borkmann { 365604326b4SDaniel Borkmann set_bit(bit, &psock->state); 366604326b4SDaniel Borkmann } 367604326b4SDaniel Borkmann 368604326b4SDaniel Borkmann static inline void sk_psock_clear_state(struct sk_psock *psock, 369604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 370604326b4SDaniel Borkmann { 371604326b4SDaniel Borkmann clear_bit(bit, &psock->state); 372604326b4SDaniel Borkmann } 373604326b4SDaniel Borkmann 374604326b4SDaniel Borkmann static inline bool sk_psock_test_state(const struct sk_psock *psock, 375604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 376604326b4SDaniel Borkmann { 377604326b4SDaniel Borkmann return test_bit(bit, &psock->state); 378604326b4SDaniel Borkmann } 379604326b4SDaniel Borkmann 3805032d079SJohn Fastabend static inline struct sk_psock *sk_psock_get_checked(struct sock *sk) 3815032d079SJohn Fastabend { 3825032d079SJohn Fastabend struct sk_psock *psock; 3835032d079SJohn Fastabend 3845032d079SJohn Fastabend rcu_read_lock(); 3855032d079SJohn Fastabend psock = sk_psock(sk); 3865032d079SJohn Fastabend if (psock) { 3875032d079SJohn Fastabend if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { 3885032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 3895032d079SJohn Fastabend goto out; 3905032d079SJohn Fastabend } 3915032d079SJohn Fastabend 3925032d079SJohn Fastabend if (!refcount_inc_not_zero(&psock->refcnt)) 3935032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 3945032d079SJohn Fastabend } 3955032d079SJohn Fastabend out: 3965032d079SJohn Fastabend rcu_read_unlock(); 3975032d079SJohn Fastabend return psock; 3985032d079SJohn Fastabend } 3995032d079SJohn Fastabend 400604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock_get(struct sock *sk) 401604326b4SDaniel Borkmann { 402604326b4SDaniel Borkmann struct sk_psock *psock; 403604326b4SDaniel Borkmann 404604326b4SDaniel Borkmann rcu_read_lock(); 405604326b4SDaniel Borkmann psock = sk_psock(sk); 406604326b4SDaniel Borkmann if (psock && !refcount_inc_not_zero(&psock->refcnt)) 407604326b4SDaniel Borkmann psock = NULL; 408604326b4SDaniel Borkmann rcu_read_unlock(); 409604326b4SDaniel Borkmann return psock; 410604326b4SDaniel Borkmann } 411604326b4SDaniel Borkmann 412604326b4SDaniel Borkmann void sk_psock_stop(struct sock *sk, struct sk_psock *psock); 413604326b4SDaniel Borkmann void sk_psock_destroy(struct rcu_head *rcu); 414604326b4SDaniel Borkmann void sk_psock_drop(struct sock *sk, struct sk_psock *psock); 415604326b4SDaniel Borkmann 416604326b4SDaniel Borkmann static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock) 417604326b4SDaniel Borkmann { 418604326b4SDaniel Borkmann if (refcount_dec_and_test(&psock->refcnt)) 419604326b4SDaniel Borkmann sk_psock_drop(sk, psock); 420604326b4SDaniel Borkmann } 421604326b4SDaniel Borkmann 422552de910SJohn Fastabend static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock) 423552de910SJohn Fastabend { 424552de910SJohn Fastabend if (psock->parser.enabled) 425552de910SJohn Fastabend psock->parser.saved_data_ready(sk); 426552de910SJohn Fastabend else 427552de910SJohn Fastabend sk->sk_data_ready(sk); 428552de910SJohn Fastabend } 429552de910SJohn Fastabend 430604326b4SDaniel Borkmann static inline void psock_set_prog(struct bpf_prog **pprog, 431604326b4SDaniel Borkmann struct bpf_prog *prog) 432604326b4SDaniel Borkmann { 433604326b4SDaniel Borkmann prog = xchg(pprog, prog); 434604326b4SDaniel Borkmann if (prog) 435604326b4SDaniel Borkmann bpf_prog_put(prog); 436604326b4SDaniel Borkmann } 437604326b4SDaniel Borkmann 438604326b4SDaniel Borkmann static inline void psock_progs_drop(struct sk_psock_progs *progs) 439604326b4SDaniel Borkmann { 440604326b4SDaniel Borkmann psock_set_prog(&progs->msg_parser, NULL); 441604326b4SDaniel Borkmann psock_set_prog(&progs->skb_parser, NULL); 442604326b4SDaniel Borkmann psock_set_prog(&progs->skb_verdict, NULL); 443604326b4SDaniel Borkmann } 444604326b4SDaniel Borkmann 445604326b4SDaniel Borkmann #endif /* _LINUX_SKMSG_H */ 446