1ad69f35dSMichael S. Tsirkin /* 2ad69f35dSMichael S. Tsirkin * Definitions for the 'struct skb_array' datastructure. 3ad69f35dSMichael S. Tsirkin * 4ad69f35dSMichael S. Tsirkin * Author: 5ad69f35dSMichael S. Tsirkin * Michael S. Tsirkin <[email protected]> 6ad69f35dSMichael S. Tsirkin * 7ad69f35dSMichael S. Tsirkin * Copyright (C) 2016 Red Hat, Inc. 8ad69f35dSMichael S. Tsirkin * 9ad69f35dSMichael S. Tsirkin * This program is free software; you can redistribute it and/or modify it 10ad69f35dSMichael S. Tsirkin * under the terms of the GNU General Public License as published by the 11ad69f35dSMichael S. Tsirkin * Free Software Foundation; either version 2 of the License, or (at your 12ad69f35dSMichael S. Tsirkin * option) any later version. 13ad69f35dSMichael S. Tsirkin * 14ad69f35dSMichael S. Tsirkin * Limited-size FIFO of skbs. Can be used more or less whenever 15ad69f35dSMichael S. Tsirkin * sk_buff_head can be used, except you need to know the queue size in 16ad69f35dSMichael S. Tsirkin * advance. 17ad69f35dSMichael S. Tsirkin * Implemented as a type-safe wrapper around ptr_ring. 18ad69f35dSMichael S. Tsirkin */ 19ad69f35dSMichael S. Tsirkin 20ad69f35dSMichael S. Tsirkin #ifndef _LINUX_SKB_ARRAY_H 21ad69f35dSMichael S. Tsirkin #define _LINUX_SKB_ARRAY_H 1 22ad69f35dSMichael S. Tsirkin 23ad69f35dSMichael S. Tsirkin #ifdef __KERNEL__ 24ad69f35dSMichael S. Tsirkin #include <linux/ptr_ring.h> 25ad69f35dSMichael S. Tsirkin #include <linux/skbuff.h> 26ad69f35dSMichael S. Tsirkin #include <linux/if_vlan.h> 27ad69f35dSMichael S. Tsirkin #endif 28ad69f35dSMichael S. Tsirkin 29ad69f35dSMichael S. Tsirkin struct skb_array { 30ad69f35dSMichael S. Tsirkin struct ptr_ring ring; 31ad69f35dSMichael S. Tsirkin }; 32ad69f35dSMichael S. Tsirkin 33ad69f35dSMichael S. Tsirkin /* Might be slightly faster than skb_array_full below, but callers invoking 34ad69f35dSMichael S. Tsirkin * this in a loop must use a compiler barrier, for example cpu_relax(). 35ad69f35dSMichael S. Tsirkin */ 36ad69f35dSMichael S. Tsirkin static inline bool __skb_array_full(struct skb_array *a) 37ad69f35dSMichael S. Tsirkin { 38ad69f35dSMichael S. Tsirkin return __ptr_ring_full(&a->ring); 39ad69f35dSMichael S. Tsirkin } 40ad69f35dSMichael S. Tsirkin 41ad69f35dSMichael S. Tsirkin static inline bool skb_array_full(struct skb_array *a) 42ad69f35dSMichael S. Tsirkin { 43ad69f35dSMichael S. Tsirkin return ptr_ring_full(&a->ring); 44ad69f35dSMichael S. Tsirkin } 45ad69f35dSMichael S. Tsirkin 46ad69f35dSMichael S. Tsirkin static inline int skb_array_produce(struct skb_array *a, struct sk_buff *skb) 47ad69f35dSMichael S. Tsirkin { 48ad69f35dSMichael S. Tsirkin return ptr_ring_produce(&a->ring, skb); 49ad69f35dSMichael S. Tsirkin } 50ad69f35dSMichael S. Tsirkin 51ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_irq(struct skb_array *a, struct sk_buff *skb) 52ad69f35dSMichael S. Tsirkin { 53ad69f35dSMichael S. Tsirkin return ptr_ring_produce_irq(&a->ring, skb); 54ad69f35dSMichael S. Tsirkin } 55ad69f35dSMichael S. Tsirkin 56ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_bh(struct skb_array *a, struct sk_buff *skb) 57ad69f35dSMichael S. Tsirkin { 58ad69f35dSMichael S. Tsirkin return ptr_ring_produce_bh(&a->ring, skb); 59ad69f35dSMichael S. Tsirkin } 60ad69f35dSMichael S. Tsirkin 61ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_any(struct skb_array *a, struct sk_buff *skb) 62ad69f35dSMichael S. Tsirkin { 63ad69f35dSMichael S. Tsirkin return ptr_ring_produce_any(&a->ring, skb); 64ad69f35dSMichael S. Tsirkin } 65ad69f35dSMichael S. Tsirkin 667d7072e3SMichael S. Tsirkin /* Might be slightly faster than skb_array_empty below, but only safe if the 677d7072e3SMichael S. Tsirkin * array is never resized. Also, callers invoking this in a loop must take care 687d7072e3SMichael S. Tsirkin * to use a compiler barrier, for example cpu_relax(). 69ad69f35dSMichael S. Tsirkin */ 70ad69f35dSMichael S. Tsirkin static inline bool __skb_array_empty(struct skb_array *a) 71ad69f35dSMichael S. Tsirkin { 72f417dc28SMichael S. Tsirkin return __ptr_ring_empty(&a->ring); 73ad69f35dSMichael S. Tsirkin } 74ad69f35dSMichael S. Tsirkin 754a86a4cfSJohn Fastabend static inline struct sk_buff *__skb_array_peek(struct skb_array *a) 764a86a4cfSJohn Fastabend { 774a86a4cfSJohn Fastabend return __ptr_ring_peek(&a->ring); 784a86a4cfSJohn Fastabend } 794a86a4cfSJohn Fastabend 80ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a) 81ad69f35dSMichael S. Tsirkin { 82ad69f35dSMichael S. Tsirkin return ptr_ring_empty(&a->ring); 83ad69f35dSMichael S. Tsirkin } 84ad69f35dSMichael S. Tsirkin 857d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a) 867d7072e3SMichael S. Tsirkin { 877d7072e3SMichael S. Tsirkin return ptr_ring_empty_bh(&a->ring); 887d7072e3SMichael S. Tsirkin } 897d7072e3SMichael S. Tsirkin 907d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a) 917d7072e3SMichael S. Tsirkin { 927d7072e3SMichael S. Tsirkin return ptr_ring_empty_irq(&a->ring); 937d7072e3SMichael S. Tsirkin } 947d7072e3SMichael S. Tsirkin 957d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a) 967d7072e3SMichael S. Tsirkin { 977d7072e3SMichael S. Tsirkin return ptr_ring_empty_any(&a->ring); 987d7072e3SMichael S. Tsirkin } 997d7072e3SMichael S. Tsirkin 100*021a17edSPaolo Abeni static inline struct sk_buff *__skb_array_consume(struct skb_array *a) 101*021a17edSPaolo Abeni { 102*021a17edSPaolo Abeni return __ptr_ring_consume(&a->ring); 103*021a17edSPaolo Abeni } 104*021a17edSPaolo Abeni 105ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a) 106ad69f35dSMichael S. Tsirkin { 107ad69f35dSMichael S. Tsirkin return ptr_ring_consume(&a->ring); 108ad69f35dSMichael S. Tsirkin } 109ad69f35dSMichael S. Tsirkin 1103528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a, 1113528c1a5SJason Wang struct sk_buff **array, int n) 1123528c1a5SJason Wang { 1133528c1a5SJason Wang return ptr_ring_consume_batched(&a->ring, (void **)array, n); 1143528c1a5SJason Wang } 1153528c1a5SJason Wang 116ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 117ad69f35dSMichael S. Tsirkin { 118ad69f35dSMichael S. Tsirkin return ptr_ring_consume_irq(&a->ring); 119ad69f35dSMichael S. Tsirkin } 120ad69f35dSMichael S. Tsirkin 1213528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a, 1223528c1a5SJason Wang struct sk_buff **array, int n) 1233528c1a5SJason Wang { 1243528c1a5SJason Wang return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n); 1253528c1a5SJason Wang } 1263528c1a5SJason Wang 127ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 128ad69f35dSMichael S. Tsirkin { 129ad69f35dSMichael S. Tsirkin return ptr_ring_consume_any(&a->ring); 130ad69f35dSMichael S. Tsirkin } 131ad69f35dSMichael S. Tsirkin 1323528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a, 1333528c1a5SJason Wang struct sk_buff **array, int n) 1343528c1a5SJason Wang { 1353528c1a5SJason Wang return ptr_ring_consume_batched_any(&a->ring, (void **)array, n); 1363528c1a5SJason Wang } 1373528c1a5SJason Wang 1383528c1a5SJason Wang 139ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 140ad69f35dSMichael S. Tsirkin { 141ad69f35dSMichael S. Tsirkin return ptr_ring_consume_bh(&a->ring); 142ad69f35dSMichael S. Tsirkin } 143ad69f35dSMichael S. Tsirkin 1443528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a, 1453528c1a5SJason Wang struct sk_buff **array, int n) 1463528c1a5SJason Wang { 1473528c1a5SJason Wang return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n); 1483528c1a5SJason Wang } 1493528c1a5SJason Wang 150ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb) 151ad69f35dSMichael S. Tsirkin { 152ad69f35dSMichael S. Tsirkin if (likely(skb)) { 153ad69f35dSMichael S. Tsirkin int len = skb->len; 154ad69f35dSMichael S. Tsirkin 155ad69f35dSMichael S. Tsirkin if (skb_vlan_tag_present(skb)) 156ad69f35dSMichael S. Tsirkin len += VLAN_HLEN; 157ad69f35dSMichael S. Tsirkin 158ad69f35dSMichael S. Tsirkin return len; 159ad69f35dSMichael S. Tsirkin } else { 160ad69f35dSMichael S. Tsirkin return 0; 161ad69f35dSMichael S. Tsirkin } 162ad69f35dSMichael S. Tsirkin } 163ad69f35dSMichael S. Tsirkin 164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a) 165ad69f35dSMichael S. Tsirkin { 166ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 167ad69f35dSMichael S. Tsirkin } 168ad69f35dSMichael S. Tsirkin 169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a) 170ad69f35dSMichael S. Tsirkin { 171ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 172ad69f35dSMichael S. Tsirkin } 173ad69f35dSMichael S. Tsirkin 174ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a) 175ad69f35dSMichael S. Tsirkin { 176ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 177ad69f35dSMichael S. Tsirkin } 178ad69f35dSMichael S. Tsirkin 179ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a) 180ad69f35dSMichael S. Tsirkin { 181ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 182ad69f35dSMichael S. Tsirkin } 183ad69f35dSMichael S. Tsirkin 184ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp) 185ad69f35dSMichael S. Tsirkin { 186ad69f35dSMichael S. Tsirkin return ptr_ring_init(&a->ring, size, gfp); 187ad69f35dSMichael S. Tsirkin } 188ad69f35dSMichael S. Tsirkin 189fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr) 1907d7072e3SMichael S. Tsirkin { 1917d7072e3SMichael S. Tsirkin kfree_skb(ptr); 1927d7072e3SMichael S. Tsirkin } 1937d7072e3SMichael S. Tsirkin 1943acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a, 1953acb6960SJason Wang struct sk_buff **skbs, int n) 1963acb6960SJason Wang { 1973acb6960SJason Wang ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); 1983acb6960SJason Wang } 1993acb6960SJason Wang 200fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 2017d7072e3SMichael S. Tsirkin { 2027d7072e3SMichael S. Tsirkin return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 2037d7072e3SMichael S. Tsirkin } 2047d7072e3SMichael S. Tsirkin 205bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings, 20681fbfe8aSEric Dumazet int nrings, unsigned int size, 20781fbfe8aSEric Dumazet gfp_t gfp) 208bf900b3dSJason Wang { 209bf900b3dSJason Wang BUILD_BUG_ON(offsetof(struct skb_array, ring)); 210bf900b3dSJason Wang return ptr_ring_resize_multiple((struct ptr_ring **)rings, 211bf900b3dSJason Wang nrings, size, gfp, 212bf900b3dSJason Wang __skb_array_destroy_skb); 213bf900b3dSJason Wang } 214bf900b3dSJason Wang 215ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a) 216ad69f35dSMichael S. Tsirkin { 2177d7072e3SMichael S. Tsirkin ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 218ad69f35dSMichael S. Tsirkin } 219ad69f35dSMichael S. Tsirkin 220ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H */ 221