12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 2ad69f35dSMichael S. Tsirkin /* 3ad69f35dSMichael S. Tsirkin * Definitions for the 'struct skb_array' datastructure. 4ad69f35dSMichael S. Tsirkin * 5ad69f35dSMichael S. Tsirkin * Author: 6ad69f35dSMichael S. Tsirkin * Michael S. Tsirkin <[email protected]> 7ad69f35dSMichael S. Tsirkin * 8ad69f35dSMichael S. Tsirkin * Copyright (C) 2016 Red Hat, Inc. 9ad69f35dSMichael S. Tsirkin * 10ad69f35dSMichael S. Tsirkin * Limited-size FIFO of skbs. Can be used more or less whenever 11ad69f35dSMichael S. Tsirkin * sk_buff_head can be used, except you need to know the queue size in 12ad69f35dSMichael S. Tsirkin * advance. 13ad69f35dSMichael S. Tsirkin * Implemented as a type-safe wrapper around ptr_ring. 14ad69f35dSMichael S. Tsirkin */ 15ad69f35dSMichael S. Tsirkin 16ad69f35dSMichael S. Tsirkin #ifndef _LINUX_SKB_ARRAY_H 17ad69f35dSMichael S. Tsirkin #define _LINUX_SKB_ARRAY_H 1 18ad69f35dSMichael S. Tsirkin 19ad69f35dSMichael S. Tsirkin #ifdef __KERNEL__ 20ad69f35dSMichael S. Tsirkin #include <linux/ptr_ring.h> 21ad69f35dSMichael S. Tsirkin #include <linux/skbuff.h> 22ad69f35dSMichael S. Tsirkin #include <linux/if_vlan.h> 23ad69f35dSMichael S. Tsirkin #endif 24ad69f35dSMichael S. Tsirkin 25ad69f35dSMichael S. Tsirkin struct skb_array { 26ad69f35dSMichael S. Tsirkin struct ptr_ring ring; 27ad69f35dSMichael S. Tsirkin }; 28ad69f35dSMichael S. Tsirkin 29ad69f35dSMichael S. Tsirkin /* Might be slightly faster than skb_array_full below, but callers invoking 30ad69f35dSMichael S. Tsirkin * this in a loop must use a compiler barrier, for example cpu_relax(). 31ad69f35dSMichael S. Tsirkin */ 32ad69f35dSMichael S. Tsirkin static inline bool __skb_array_full(struct skb_array *a) 33ad69f35dSMichael S. Tsirkin { 34ad69f35dSMichael S. Tsirkin return __ptr_ring_full(&a->ring); 35ad69f35dSMichael S. Tsirkin } 36ad69f35dSMichael S. Tsirkin 37ad69f35dSMichael S. Tsirkin static inline bool skb_array_full(struct skb_array *a) 38ad69f35dSMichael S. Tsirkin { 39ad69f35dSMichael S. Tsirkin return ptr_ring_full(&a->ring); 40ad69f35dSMichael S. Tsirkin } 41ad69f35dSMichael S. Tsirkin 42ad69f35dSMichael S. Tsirkin static inline int skb_array_produce(struct skb_array *a, struct sk_buff *skb) 43ad69f35dSMichael S. Tsirkin { 44ad69f35dSMichael S. Tsirkin return ptr_ring_produce(&a->ring, skb); 45ad69f35dSMichael S. Tsirkin } 46ad69f35dSMichael S. Tsirkin 47ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_irq(struct skb_array *a, struct sk_buff *skb) 48ad69f35dSMichael S. Tsirkin { 49ad69f35dSMichael S. Tsirkin return ptr_ring_produce_irq(&a->ring, skb); 50ad69f35dSMichael S. Tsirkin } 51ad69f35dSMichael S. Tsirkin 52ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_bh(struct skb_array *a, struct sk_buff *skb) 53ad69f35dSMichael S. Tsirkin { 54ad69f35dSMichael S. Tsirkin return ptr_ring_produce_bh(&a->ring, skb); 55ad69f35dSMichael S. Tsirkin } 56ad69f35dSMichael S. Tsirkin 57ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_any(struct skb_array *a, struct sk_buff *skb) 58ad69f35dSMichael S. Tsirkin { 59ad69f35dSMichael S. Tsirkin return ptr_ring_produce_any(&a->ring, skb); 60ad69f35dSMichael S. Tsirkin } 61ad69f35dSMichael S. Tsirkin 627d7072e3SMichael S. Tsirkin /* Might be slightly faster than skb_array_empty below, but only safe if the 637d7072e3SMichael S. Tsirkin * array is never resized. Also, callers invoking this in a loop must take care 647d7072e3SMichael S. Tsirkin * to use a compiler barrier, for example cpu_relax(). 65ad69f35dSMichael S. Tsirkin */ 66ad69f35dSMichael S. Tsirkin static inline bool __skb_array_empty(struct skb_array *a) 67ad69f35dSMichael S. Tsirkin { 68f417dc28SMichael S. Tsirkin return __ptr_ring_empty(&a->ring); 69ad69f35dSMichael S. Tsirkin } 70ad69f35dSMichael S. Tsirkin 714a86a4cfSJohn Fastabend static inline struct sk_buff *__skb_array_peek(struct skb_array *a) 724a86a4cfSJohn Fastabend { 734a86a4cfSJohn Fastabend return __ptr_ring_peek(&a->ring); 744a86a4cfSJohn Fastabend } 754a86a4cfSJohn Fastabend 76ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a) 77ad69f35dSMichael S. Tsirkin { 78ad69f35dSMichael S. Tsirkin return ptr_ring_empty(&a->ring); 79ad69f35dSMichael S. Tsirkin } 80ad69f35dSMichael S. Tsirkin 817d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a) 827d7072e3SMichael S. Tsirkin { 837d7072e3SMichael S. Tsirkin return ptr_ring_empty_bh(&a->ring); 847d7072e3SMichael S. Tsirkin } 857d7072e3SMichael S. Tsirkin 867d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a) 877d7072e3SMichael S. Tsirkin { 887d7072e3SMichael S. Tsirkin return ptr_ring_empty_irq(&a->ring); 897d7072e3SMichael S. Tsirkin } 907d7072e3SMichael S. Tsirkin 917d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a) 927d7072e3SMichael S. Tsirkin { 937d7072e3SMichael S. Tsirkin return ptr_ring_empty_any(&a->ring); 947d7072e3SMichael S. Tsirkin } 957d7072e3SMichael S. Tsirkin 96021a17edSPaolo Abeni static inline struct sk_buff *__skb_array_consume(struct skb_array *a) 97021a17edSPaolo Abeni { 98021a17edSPaolo Abeni return __ptr_ring_consume(&a->ring); 99021a17edSPaolo Abeni } 100021a17edSPaolo Abeni 101ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a) 102ad69f35dSMichael S. Tsirkin { 103ad69f35dSMichael S. Tsirkin return ptr_ring_consume(&a->ring); 104ad69f35dSMichael S. Tsirkin } 105ad69f35dSMichael S. Tsirkin 1063528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a, 1073528c1a5SJason Wang struct sk_buff **array, int n) 1083528c1a5SJason Wang { 1093528c1a5SJason Wang return ptr_ring_consume_batched(&a->ring, (void **)array, n); 1103528c1a5SJason Wang } 1113528c1a5SJason Wang 112ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 113ad69f35dSMichael S. Tsirkin { 114ad69f35dSMichael S. Tsirkin return ptr_ring_consume_irq(&a->ring); 115ad69f35dSMichael S. Tsirkin } 116ad69f35dSMichael S. Tsirkin 1173528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a, 1183528c1a5SJason Wang struct sk_buff **array, int n) 1193528c1a5SJason Wang { 1203528c1a5SJason Wang return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n); 1213528c1a5SJason Wang } 1223528c1a5SJason Wang 123ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 124ad69f35dSMichael S. Tsirkin { 125ad69f35dSMichael S. Tsirkin return ptr_ring_consume_any(&a->ring); 126ad69f35dSMichael S. Tsirkin } 127ad69f35dSMichael S. Tsirkin 1283528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a, 1293528c1a5SJason Wang struct sk_buff **array, int n) 1303528c1a5SJason Wang { 1313528c1a5SJason Wang return ptr_ring_consume_batched_any(&a->ring, (void **)array, n); 1323528c1a5SJason Wang } 1333528c1a5SJason Wang 1343528c1a5SJason Wang 135ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 136ad69f35dSMichael S. Tsirkin { 137ad69f35dSMichael S. Tsirkin return ptr_ring_consume_bh(&a->ring); 138ad69f35dSMichael S. Tsirkin } 139ad69f35dSMichael S. Tsirkin 1403528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a, 1413528c1a5SJason Wang struct sk_buff **array, int n) 1423528c1a5SJason Wang { 1433528c1a5SJason Wang return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n); 1443528c1a5SJason Wang } 1453528c1a5SJason Wang 146ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb) 147ad69f35dSMichael S. Tsirkin { 148ad69f35dSMichael S. Tsirkin if (likely(skb)) { 149ad69f35dSMichael S. Tsirkin int len = skb->len; 150ad69f35dSMichael S. Tsirkin 151ad69f35dSMichael S. Tsirkin if (skb_vlan_tag_present(skb)) 152ad69f35dSMichael S. Tsirkin len += VLAN_HLEN; 153ad69f35dSMichael S. Tsirkin 154ad69f35dSMichael S. Tsirkin return len; 155ad69f35dSMichael S. Tsirkin } else { 156ad69f35dSMichael S. Tsirkin return 0; 157ad69f35dSMichael S. Tsirkin } 158ad69f35dSMichael S. Tsirkin } 159ad69f35dSMichael S. Tsirkin 160ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a) 161ad69f35dSMichael S. Tsirkin { 162ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 163ad69f35dSMichael S. Tsirkin } 164ad69f35dSMichael S. Tsirkin 165ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a) 166ad69f35dSMichael S. Tsirkin { 167ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 168ad69f35dSMichael S. Tsirkin } 169ad69f35dSMichael S. Tsirkin 170ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a) 171ad69f35dSMichael S. Tsirkin { 172ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 173ad69f35dSMichael S. Tsirkin } 174ad69f35dSMichael S. Tsirkin 175ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a) 176ad69f35dSMichael S. Tsirkin { 177ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 178ad69f35dSMichael S. Tsirkin } 179ad69f35dSMichael S. Tsirkin 180*2c321f3fSSuren Baghdasaryan static inline int skb_array_init_noprof(struct skb_array *a, int size, gfp_t gfp) 181ad69f35dSMichael S. Tsirkin { 182*2c321f3fSSuren Baghdasaryan return ptr_ring_init_noprof(&a->ring, size, gfp); 183ad69f35dSMichael S. Tsirkin } 184*2c321f3fSSuren Baghdasaryan #define skb_array_init(...) alloc_hooks(skb_array_init_noprof(__VA_ARGS__)) 185ad69f35dSMichael S. Tsirkin 186fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr) 1877d7072e3SMichael S. Tsirkin { 1887d7072e3SMichael S. Tsirkin kfree_skb(ptr); 1897d7072e3SMichael S. Tsirkin } 1907d7072e3SMichael S. Tsirkin 1913acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a, 1923acb6960SJason Wang struct sk_buff **skbs, int n) 1933acb6960SJason Wang { 1943acb6960SJason Wang ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); 1953acb6960SJason Wang } 1963acb6960SJason Wang 197fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 1987d7072e3SMichael S. Tsirkin { 1997d7072e3SMichael S. Tsirkin return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 2007d7072e3SMichael S. Tsirkin } 2017d7072e3SMichael S. Tsirkin 202*2c321f3fSSuren Baghdasaryan static inline int skb_array_resize_multiple_noprof(struct skb_array **rings, 20381fbfe8aSEric Dumazet int nrings, unsigned int size, 20481fbfe8aSEric Dumazet gfp_t gfp) 205bf900b3dSJason Wang { 206bf900b3dSJason Wang BUILD_BUG_ON(offsetof(struct skb_array, ring)); 207*2c321f3fSSuren Baghdasaryan return ptr_ring_resize_multiple_noprof((struct ptr_ring **)rings, 208bf900b3dSJason Wang nrings, size, gfp, 209bf900b3dSJason Wang __skb_array_destroy_skb); 210bf900b3dSJason Wang } 211*2c321f3fSSuren Baghdasaryan #define skb_array_resize_multiple(...) \ 212*2c321f3fSSuren Baghdasaryan alloc_hooks(skb_array_resize_multiple_noprof(__VA_ARGS__)) 213bf900b3dSJason Wang 214ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a) 215ad69f35dSMichael S. Tsirkin { 2167d7072e3SMichael S. Tsirkin ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 217ad69f35dSMichael S. Tsirkin } 218ad69f35dSMichael S. Tsirkin 219ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H */ 220