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 { 72ad69f35dSMichael S. Tsirkin return !__ptr_ring_peek(&a->ring); 73ad69f35dSMichael S. Tsirkin } 74ad69f35dSMichael S. Tsirkin 75ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a) 76ad69f35dSMichael S. Tsirkin { 77ad69f35dSMichael S. Tsirkin return ptr_ring_empty(&a->ring); 78ad69f35dSMichael S. Tsirkin } 79ad69f35dSMichael S. Tsirkin 807d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a) 817d7072e3SMichael S. Tsirkin { 827d7072e3SMichael S. Tsirkin return ptr_ring_empty_bh(&a->ring); 837d7072e3SMichael S. Tsirkin } 847d7072e3SMichael S. Tsirkin 857d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a) 867d7072e3SMichael S. Tsirkin { 877d7072e3SMichael S. Tsirkin return ptr_ring_empty_irq(&a->ring); 887d7072e3SMichael S. Tsirkin } 897d7072e3SMichael S. Tsirkin 907d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a) 917d7072e3SMichael S. Tsirkin { 927d7072e3SMichael S. Tsirkin return ptr_ring_empty_any(&a->ring); 937d7072e3SMichael S. Tsirkin } 947d7072e3SMichael S. Tsirkin 95ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a) 96ad69f35dSMichael S. Tsirkin { 97ad69f35dSMichael S. Tsirkin return ptr_ring_consume(&a->ring); 98ad69f35dSMichael S. Tsirkin } 99ad69f35dSMichael S. Tsirkin 100ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 101ad69f35dSMichael S. Tsirkin { 102ad69f35dSMichael S. Tsirkin return ptr_ring_consume_irq(&a->ring); 103ad69f35dSMichael S. Tsirkin } 104ad69f35dSMichael S. Tsirkin 105ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 106ad69f35dSMichael S. Tsirkin { 107ad69f35dSMichael S. Tsirkin return ptr_ring_consume_any(&a->ring); 108ad69f35dSMichael S. Tsirkin } 109ad69f35dSMichael S. Tsirkin 110ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 111ad69f35dSMichael S. Tsirkin { 112ad69f35dSMichael S. Tsirkin return ptr_ring_consume_bh(&a->ring); 113ad69f35dSMichael S. Tsirkin } 114ad69f35dSMichael S. Tsirkin 115ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb) 116ad69f35dSMichael S. Tsirkin { 117ad69f35dSMichael S. Tsirkin if (likely(skb)) { 118ad69f35dSMichael S. Tsirkin int len = skb->len; 119ad69f35dSMichael S. Tsirkin 120ad69f35dSMichael S. Tsirkin if (skb_vlan_tag_present(skb)) 121ad69f35dSMichael S. Tsirkin len += VLAN_HLEN; 122ad69f35dSMichael S. Tsirkin 123ad69f35dSMichael S. Tsirkin return len; 124ad69f35dSMichael S. Tsirkin } else { 125ad69f35dSMichael S. Tsirkin return 0; 126ad69f35dSMichael S. Tsirkin } 127ad69f35dSMichael S. Tsirkin } 128ad69f35dSMichael S. Tsirkin 129ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a) 130ad69f35dSMichael S. Tsirkin { 131ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 132ad69f35dSMichael S. Tsirkin } 133ad69f35dSMichael S. Tsirkin 134ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a) 135ad69f35dSMichael S. Tsirkin { 136ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 137ad69f35dSMichael S. Tsirkin } 138ad69f35dSMichael S. Tsirkin 139ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a) 140ad69f35dSMichael S. Tsirkin { 141ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 142ad69f35dSMichael S. Tsirkin } 143ad69f35dSMichael S. Tsirkin 144ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a) 145ad69f35dSMichael S. Tsirkin { 146ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 147ad69f35dSMichael S. Tsirkin } 148ad69f35dSMichael S. Tsirkin 149ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp) 150ad69f35dSMichael S. Tsirkin { 151ad69f35dSMichael S. Tsirkin return ptr_ring_init(&a->ring, size, gfp); 152ad69f35dSMichael S. Tsirkin } 153ad69f35dSMichael S. Tsirkin 154fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr) 1557d7072e3SMichael S. Tsirkin { 1567d7072e3SMichael S. Tsirkin kfree_skb(ptr); 1577d7072e3SMichael S. Tsirkin } 1587d7072e3SMichael S. Tsirkin 159fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 1607d7072e3SMichael S. Tsirkin { 1617d7072e3SMichael S. Tsirkin return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 1627d7072e3SMichael S. Tsirkin } 1637d7072e3SMichael S. Tsirkin 164*bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings, 165*bf900b3dSJason Wang int nrings, int size, gfp_t gfp) 166*bf900b3dSJason Wang { 167*bf900b3dSJason Wang BUILD_BUG_ON(offsetof(struct skb_array, ring)); 168*bf900b3dSJason Wang return ptr_ring_resize_multiple((struct ptr_ring **)rings, 169*bf900b3dSJason Wang nrings, size, gfp, 170*bf900b3dSJason Wang __skb_array_destroy_skb); 171*bf900b3dSJason Wang } 172*bf900b3dSJason Wang 173ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a) 174ad69f35dSMichael S. Tsirkin { 1757d7072e3SMichael S. Tsirkin ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 176ad69f35dSMichael S. Tsirkin } 177ad69f35dSMichael S. Tsirkin 178ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H */ 179