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; 19081aabbb9SJohn Fastabend src->sg.size -= size; 191604326b4SDaniel Borkmann src->sg.data[which].length -= size; 192604326b4SDaniel Borkmann src->sg.data[which].offset += size; 193604326b4SDaniel Borkmann } 194604326b4SDaniel Borkmann 195d3b18ad3SJohn Fastabend static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src) 196d3b18ad3SJohn Fastabend { 197d3b18ad3SJohn Fastabend memcpy(dst, src, sizeof(*src)); 198d3b18ad3SJohn Fastabend sk_msg_init(src); 199d3b18ad3SJohn Fastabend } 200d3b18ad3SJohn Fastabend 201604326b4SDaniel Borkmann static inline bool sk_msg_full(const struct sk_msg *msg) 202604326b4SDaniel Borkmann { 203031097d9SJakub Kicinski return sk_msg_iter_dist(msg->sg.start, msg->sg.end) == MAX_MSG_FRAGS; 204604326b4SDaniel Borkmann } 205604326b4SDaniel Borkmann 2068734a162SJohn Fastabend static inline u32 sk_msg_elem_used(const struct sk_msg *msg) 2078734a162SJohn Fastabend { 208683916f6SJakub Kicinski return sk_msg_iter_dist(msg->sg.start, msg->sg.end); 2098734a162SJohn Fastabend } 2108734a162SJohn Fastabend 211604326b4SDaniel Borkmann static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which) 212604326b4SDaniel Borkmann { 213604326b4SDaniel Borkmann return &msg->sg.data[which]; 214604326b4SDaniel Borkmann } 215604326b4SDaniel Borkmann 2166fff607eSJohn Fastabend static inline struct scatterlist sk_msg_elem_cpy(struct sk_msg *msg, int which) 2176fff607eSJohn Fastabend { 2186fff607eSJohn Fastabend return msg->sg.data[which]; 2196fff607eSJohn Fastabend } 2206fff607eSJohn Fastabend 221604326b4SDaniel Borkmann static inline struct page *sk_msg_page(struct sk_msg *msg, int which) 222604326b4SDaniel Borkmann { 223604326b4SDaniel Borkmann return sg_page(sk_msg_elem(msg, which)); 224604326b4SDaniel Borkmann } 225604326b4SDaniel Borkmann 226604326b4SDaniel Borkmann static inline bool sk_msg_to_ingress(const struct sk_msg *msg) 227604326b4SDaniel Borkmann { 228604326b4SDaniel Borkmann return msg->flags & BPF_F_INGRESS; 229604326b4SDaniel Borkmann } 230604326b4SDaniel Borkmann 231604326b4SDaniel Borkmann static inline void sk_msg_compute_data_pointers(struct sk_msg *msg) 232604326b4SDaniel Borkmann { 233604326b4SDaniel Borkmann struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start); 234604326b4SDaniel Borkmann 235163ab96bSJakub Kicinski if (test_bit(msg->sg.start, &msg->sg.copy)) { 236604326b4SDaniel Borkmann msg->data = NULL; 237604326b4SDaniel Borkmann msg->data_end = NULL; 238604326b4SDaniel Borkmann } else { 239604326b4SDaniel Borkmann msg->data = sg_virt(sge); 240604326b4SDaniel Borkmann msg->data_end = msg->data + sge->length; 241604326b4SDaniel Borkmann } 242604326b4SDaniel Borkmann } 243604326b4SDaniel Borkmann 244604326b4SDaniel Borkmann static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page, 245604326b4SDaniel Borkmann u32 len, u32 offset) 246604326b4SDaniel Borkmann { 247604326b4SDaniel Borkmann struct scatterlist *sge; 248604326b4SDaniel Borkmann 249604326b4SDaniel Borkmann get_page(page); 250604326b4SDaniel Borkmann sge = sk_msg_elem(msg, msg->sg.end); 251604326b4SDaniel Borkmann sg_set_page(sge, page, len, offset); 252604326b4SDaniel Borkmann sg_unmark_end(sge); 253604326b4SDaniel Borkmann 254163ab96bSJakub Kicinski __set_bit(msg->sg.end, &msg->sg.copy); 255604326b4SDaniel Borkmann msg->sg.size += len; 256604326b4SDaniel Borkmann sk_msg_iter_next(msg, end); 257604326b4SDaniel Borkmann } 258604326b4SDaniel Borkmann 259d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state) 260d3b18ad3SJohn Fastabend { 261d3b18ad3SJohn Fastabend do { 262163ab96bSJakub Kicinski if (copy_state) 263163ab96bSJakub Kicinski __set_bit(i, &msg->sg.copy); 264163ab96bSJakub Kicinski else 265163ab96bSJakub Kicinski __clear_bit(i, &msg->sg.copy); 266d3b18ad3SJohn Fastabend sk_msg_iter_var_next(i); 267d3b18ad3SJohn Fastabend if (i == msg->sg.end) 268d3b18ad3SJohn Fastabend break; 269d3b18ad3SJohn Fastabend } while (1); 270d3b18ad3SJohn Fastabend } 271d3b18ad3SJohn Fastabend 272d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start) 273d3b18ad3SJohn Fastabend { 274d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, true); 275d3b18ad3SJohn Fastabend } 276d3b18ad3SJohn Fastabend 277d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_clear(struct sk_msg *msg, u32 start) 278d3b18ad3SJohn Fastabend { 279d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, false); 280d3b18ad3SJohn Fastabend } 281d3b18ad3SJohn Fastabend 282604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock(const struct sock *sk) 283604326b4SDaniel Borkmann { 284604326b4SDaniel Borkmann return rcu_dereference_sk_user_data(sk); 285604326b4SDaniel Borkmann } 286604326b4SDaniel Borkmann 287604326b4SDaniel Borkmann static inline void sk_psock_queue_msg(struct sk_psock *psock, 288604326b4SDaniel Borkmann struct sk_msg *msg) 289604326b4SDaniel Borkmann { 290604326b4SDaniel Borkmann list_add_tail(&msg->list, &psock->ingress_msg); 291604326b4SDaniel Borkmann } 292604326b4SDaniel Borkmann 293d3b18ad3SJohn Fastabend static inline bool sk_psock_queue_empty(const struct sk_psock *psock) 294d3b18ad3SJohn Fastabend { 295d3b18ad3SJohn Fastabend return psock ? list_empty(&psock->ingress_msg) : true; 296d3b18ad3SJohn Fastabend } 297d3b18ad3SJohn Fastabend 298604326b4SDaniel Borkmann static inline void sk_psock_report_error(struct sk_psock *psock, int err) 299604326b4SDaniel Borkmann { 300604326b4SDaniel Borkmann struct sock *sk = psock->sk; 301604326b4SDaniel Borkmann 302604326b4SDaniel Borkmann sk->sk_err = err; 303604326b4SDaniel Borkmann sk->sk_error_report(sk); 304604326b4SDaniel Borkmann } 305604326b4SDaniel Borkmann 306604326b4SDaniel Borkmann struct sk_psock *sk_psock_init(struct sock *sk, int node); 307604326b4SDaniel Borkmann 308604326b4SDaniel Borkmann int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock); 309604326b4SDaniel Borkmann void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock); 310604326b4SDaniel Borkmann void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock); 311604326b4SDaniel Borkmann 312604326b4SDaniel Borkmann int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, 313604326b4SDaniel Borkmann struct sk_msg *msg); 314604326b4SDaniel Borkmann 315604326b4SDaniel Borkmann static inline struct sk_psock_link *sk_psock_init_link(void) 316604326b4SDaniel Borkmann { 317604326b4SDaniel Borkmann return kzalloc(sizeof(struct sk_psock_link), 318604326b4SDaniel Borkmann GFP_ATOMIC | __GFP_NOWARN); 319604326b4SDaniel Borkmann } 320604326b4SDaniel Borkmann 321604326b4SDaniel Borkmann static inline void sk_psock_free_link(struct sk_psock_link *link) 322604326b4SDaniel Borkmann { 323604326b4SDaniel Borkmann kfree(link); 324604326b4SDaniel Borkmann } 325604326b4SDaniel Borkmann 326604326b4SDaniel Borkmann struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock); 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 { 3431a2e2013SLorenz Bauer /* Initialize saved callbacks and original proto only once, since this 3441a2e2013SLorenz Bauer * function may be called multiple times for a psock, e.g. when 3451a2e2013SLorenz Bauer * psock->progs.msg_parser is updated. 3461a2e2013SLorenz Bauer * 3471a2e2013SLorenz Bauer * Since we've not installed the new proto, psock is not yet in use and 3481a2e2013SLorenz Bauer * we can initialize it without synchronization. 3491a2e2013SLorenz Bauer */ 3501a2e2013SLorenz Bauer if (!psock->sk_proto) { 3511a2e2013SLorenz Bauer struct proto *orig = READ_ONCE(sk->sk_prot); 3521a2e2013SLorenz Bauer 3531a2e2013SLorenz Bauer psock->saved_unhash = orig->unhash; 3541a2e2013SLorenz Bauer psock->saved_close = orig->close; 355604326b4SDaniel Borkmann psock->saved_write_space = sk->sk_write_space; 356604326b4SDaniel Borkmann 3571a2e2013SLorenz Bauer psock->sk_proto = orig; 3581a2e2013SLorenz Bauer } 3591a2e2013SLorenz Bauer 360b8e202d1SJakub Sitnicki /* Pairs with lockless read in sk_clone_lock() */ 361b8e202d1SJakub Sitnicki WRITE_ONCE(sk->sk_prot, ops); 362604326b4SDaniel Borkmann } 363604326b4SDaniel Borkmann 364604326b4SDaniel Borkmann static inline void sk_psock_restore_proto(struct sock *sk, 365604326b4SDaniel Borkmann struct sk_psock *psock) 366604326b4SDaniel Borkmann { 3674da6a196SJohn Fastabend sk->sk_prot->unhash = psock->saved_unhash; 3687b70973dSLorenz Bauer if (inet_csk_has_ulp(sk)) { 369a4393861SJakub Sitnicki tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); 3707b70973dSLorenz Bauer } else { 3717b70973dSLorenz Bauer sk->sk_write_space = psock->saved_write_space; 3727b70973dSLorenz Bauer /* Pairs with lockless read in sk_clone_lock() */ 3737b70973dSLorenz Bauer WRITE_ONCE(sk->sk_prot, psock->sk_proto); 3747b70973dSLorenz Bauer } 375604326b4SDaniel Borkmann } 376604326b4SDaniel Borkmann 377604326b4SDaniel Borkmann static inline void sk_psock_set_state(struct sk_psock *psock, 378604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 379604326b4SDaniel Borkmann { 380604326b4SDaniel Borkmann set_bit(bit, &psock->state); 381604326b4SDaniel Borkmann } 382604326b4SDaniel Borkmann 383604326b4SDaniel Borkmann static inline void sk_psock_clear_state(struct sk_psock *psock, 384604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 385604326b4SDaniel Borkmann { 386604326b4SDaniel Borkmann clear_bit(bit, &psock->state); 387604326b4SDaniel Borkmann } 388604326b4SDaniel Borkmann 389604326b4SDaniel Borkmann static inline bool sk_psock_test_state(const struct sk_psock *psock, 390604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 391604326b4SDaniel Borkmann { 392604326b4SDaniel Borkmann return test_bit(bit, &psock->state); 393604326b4SDaniel Borkmann } 394604326b4SDaniel Borkmann 395604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock_get(struct sock *sk) 396604326b4SDaniel Borkmann { 397604326b4SDaniel Borkmann struct sk_psock *psock; 398604326b4SDaniel Borkmann 399604326b4SDaniel Borkmann rcu_read_lock(); 400604326b4SDaniel Borkmann psock = sk_psock(sk); 401604326b4SDaniel Borkmann if (psock && !refcount_inc_not_zero(&psock->refcnt)) 402604326b4SDaniel Borkmann psock = NULL; 403604326b4SDaniel Borkmann rcu_read_unlock(); 404604326b4SDaniel Borkmann return psock; 405604326b4SDaniel Borkmann } 406604326b4SDaniel Borkmann 407604326b4SDaniel Borkmann void sk_psock_stop(struct sock *sk, struct sk_psock *psock); 408604326b4SDaniel Borkmann void sk_psock_destroy(struct rcu_head *rcu); 409604326b4SDaniel Borkmann void sk_psock_drop(struct sock *sk, struct sk_psock *psock); 410604326b4SDaniel Borkmann 411604326b4SDaniel Borkmann static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock) 412604326b4SDaniel Borkmann { 413604326b4SDaniel Borkmann if (refcount_dec_and_test(&psock->refcnt)) 414604326b4SDaniel Borkmann sk_psock_drop(sk, psock); 415604326b4SDaniel Borkmann } 416604326b4SDaniel Borkmann 417552de910SJohn Fastabend static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock) 418552de910SJohn Fastabend { 419552de910SJohn Fastabend if (psock->parser.enabled) 420552de910SJohn Fastabend psock->parser.saved_data_ready(sk); 421552de910SJohn Fastabend else 422552de910SJohn Fastabend sk->sk_data_ready(sk); 423552de910SJohn Fastabend } 424552de910SJohn Fastabend 425604326b4SDaniel Borkmann static inline void psock_set_prog(struct bpf_prog **pprog, 426604326b4SDaniel Borkmann struct bpf_prog *prog) 427604326b4SDaniel Borkmann { 428604326b4SDaniel Borkmann prog = xchg(pprog, prog); 429604326b4SDaniel Borkmann if (prog) 430604326b4SDaniel Borkmann bpf_prog_put(prog); 431604326b4SDaniel Borkmann } 432604326b4SDaniel Borkmann 433*bb0de313SLorenz Bauer static inline int psock_replace_prog(struct bpf_prog **pprog, 434*bb0de313SLorenz Bauer struct bpf_prog *prog, 435*bb0de313SLorenz Bauer struct bpf_prog *old) 436*bb0de313SLorenz Bauer { 437*bb0de313SLorenz Bauer if (cmpxchg(pprog, old, prog) != old) 438*bb0de313SLorenz Bauer return -ENOENT; 439*bb0de313SLorenz Bauer 440*bb0de313SLorenz Bauer if (old) 441*bb0de313SLorenz Bauer bpf_prog_put(old); 442*bb0de313SLorenz Bauer 443*bb0de313SLorenz Bauer return 0; 444*bb0de313SLorenz Bauer } 445*bb0de313SLorenz Bauer 446604326b4SDaniel Borkmann static inline void psock_progs_drop(struct sk_psock_progs *progs) 447604326b4SDaniel Borkmann { 448604326b4SDaniel Borkmann psock_set_prog(&progs->msg_parser, NULL); 449604326b4SDaniel Borkmann psock_set_prog(&progs->skb_parser, NULL); 450604326b4SDaniel Borkmann psock_set_prog(&progs->skb_verdict, NULL); 451604326b4SDaniel Borkmann } 452604326b4SDaniel Borkmann 453e91de6afSJohn Fastabend int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb); 454e91de6afSJohn Fastabend 455e91de6afSJohn Fastabend static inline bool sk_psock_strp_enabled(struct sk_psock *psock) 456e91de6afSJohn Fastabend { 457e91de6afSJohn Fastabend if (!psock) 458e91de6afSJohn Fastabend return false; 459e91de6afSJohn Fastabend return psock->parser.enabled; 460e91de6afSJohn Fastabend } 461604326b4SDaniel Borkmann #endif /* _LINUX_SKMSG_H */ 462