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 { 72*f417dc28SMichael 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 100ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a) 101ad69f35dSMichael S. Tsirkin { 102ad69f35dSMichael S. Tsirkin return ptr_ring_consume(&a->ring); 103ad69f35dSMichael S. Tsirkin } 104ad69f35dSMichael S. Tsirkin 1053528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a, 1063528c1a5SJason Wang struct sk_buff **array, int n) 1073528c1a5SJason Wang { 1083528c1a5SJason Wang return ptr_ring_consume_batched(&a->ring, (void **)array, n); 1093528c1a5SJason Wang } 1103528c1a5SJason Wang 111ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 112ad69f35dSMichael S. Tsirkin { 113ad69f35dSMichael S. Tsirkin return ptr_ring_consume_irq(&a->ring); 114ad69f35dSMichael S. Tsirkin } 115ad69f35dSMichael S. Tsirkin 1163528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a, 1173528c1a5SJason Wang struct sk_buff **array, int n) 1183528c1a5SJason Wang { 1193528c1a5SJason Wang return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n); 1203528c1a5SJason Wang } 1213528c1a5SJason Wang 122ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 123ad69f35dSMichael S. Tsirkin { 124ad69f35dSMichael S. Tsirkin return ptr_ring_consume_any(&a->ring); 125ad69f35dSMichael S. Tsirkin } 126ad69f35dSMichael S. Tsirkin 1273528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a, 1283528c1a5SJason Wang struct sk_buff **array, int n) 1293528c1a5SJason Wang { 1303528c1a5SJason Wang return ptr_ring_consume_batched_any(&a->ring, (void **)array, n); 1313528c1a5SJason Wang } 1323528c1a5SJason Wang 1333528c1a5SJason Wang 134ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 135ad69f35dSMichael S. Tsirkin { 136ad69f35dSMichael S. Tsirkin return ptr_ring_consume_bh(&a->ring); 137ad69f35dSMichael S. Tsirkin } 138ad69f35dSMichael S. Tsirkin 1393528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a, 1403528c1a5SJason Wang struct sk_buff **array, int n) 1413528c1a5SJason Wang { 1423528c1a5SJason Wang return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n); 1433528c1a5SJason Wang } 1443528c1a5SJason Wang 145ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb) 146ad69f35dSMichael S. Tsirkin { 147ad69f35dSMichael S. Tsirkin if (likely(skb)) { 148ad69f35dSMichael S. Tsirkin int len = skb->len; 149ad69f35dSMichael S. Tsirkin 150ad69f35dSMichael S. Tsirkin if (skb_vlan_tag_present(skb)) 151ad69f35dSMichael S. Tsirkin len += VLAN_HLEN; 152ad69f35dSMichael S. Tsirkin 153ad69f35dSMichael S. Tsirkin return len; 154ad69f35dSMichael S. Tsirkin } else { 155ad69f35dSMichael S. Tsirkin return 0; 156ad69f35dSMichael S. Tsirkin } 157ad69f35dSMichael S. Tsirkin } 158ad69f35dSMichael S. Tsirkin 159ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a) 160ad69f35dSMichael S. Tsirkin { 161ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 162ad69f35dSMichael S. Tsirkin } 163ad69f35dSMichael S. Tsirkin 164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a) 165ad69f35dSMichael S. Tsirkin { 166ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 167ad69f35dSMichael S. Tsirkin } 168ad69f35dSMichael S. Tsirkin 169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a) 170ad69f35dSMichael S. Tsirkin { 171ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 172ad69f35dSMichael S. Tsirkin } 173ad69f35dSMichael S. Tsirkin 174ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a) 175ad69f35dSMichael S. Tsirkin { 176ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 177ad69f35dSMichael S. Tsirkin } 178ad69f35dSMichael S. Tsirkin 179ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp) 180ad69f35dSMichael S. Tsirkin { 181ad69f35dSMichael S. Tsirkin return ptr_ring_init(&a->ring, size, gfp); 182ad69f35dSMichael S. Tsirkin } 183ad69f35dSMichael S. Tsirkin 184fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr) 1857d7072e3SMichael S. Tsirkin { 1867d7072e3SMichael S. Tsirkin kfree_skb(ptr); 1877d7072e3SMichael S. Tsirkin } 1887d7072e3SMichael S. Tsirkin 1893acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a, 1903acb6960SJason Wang struct sk_buff **skbs, int n) 1913acb6960SJason Wang { 1923acb6960SJason Wang ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); 1933acb6960SJason Wang } 1943acb6960SJason Wang 195fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 1967d7072e3SMichael S. Tsirkin { 1977d7072e3SMichael S. Tsirkin return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 1987d7072e3SMichael S. Tsirkin } 1997d7072e3SMichael S. Tsirkin 200bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings, 20181fbfe8aSEric Dumazet int nrings, unsigned int size, 20281fbfe8aSEric Dumazet gfp_t gfp) 203bf900b3dSJason Wang { 204bf900b3dSJason Wang BUILD_BUG_ON(offsetof(struct skb_array, ring)); 205bf900b3dSJason Wang return ptr_ring_resize_multiple((struct ptr_ring **)rings, 206bf900b3dSJason Wang nrings, size, gfp, 207bf900b3dSJason Wang __skb_array_destroy_skb); 208bf900b3dSJason Wang } 209bf900b3dSJason Wang 210ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a) 211ad69f35dSMichael S. Tsirkin { 2127d7072e3SMichael S. Tsirkin ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 213ad69f35dSMichael S. Tsirkin } 214ad69f35dSMichael S. Tsirkin 215ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H */ 216