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 1003528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a, 1013528c1a5SJason Wang struct sk_buff **array, int n) 1023528c1a5SJason Wang { 1033528c1a5SJason Wang return ptr_ring_consume_batched(&a->ring, (void **)array, n); 1043528c1a5SJason Wang } 1053528c1a5SJason Wang 106ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 107ad69f35dSMichael S. Tsirkin { 108ad69f35dSMichael S. Tsirkin return ptr_ring_consume_irq(&a->ring); 109ad69f35dSMichael S. Tsirkin } 110ad69f35dSMichael S. Tsirkin 1113528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a, 1123528c1a5SJason Wang struct sk_buff **array, int n) 1133528c1a5SJason Wang { 1143528c1a5SJason Wang return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n); 1153528c1a5SJason Wang } 1163528c1a5SJason Wang 117ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 118ad69f35dSMichael S. Tsirkin { 119ad69f35dSMichael S. Tsirkin return ptr_ring_consume_any(&a->ring); 120ad69f35dSMichael S. Tsirkin } 121ad69f35dSMichael S. Tsirkin 1223528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a, 1233528c1a5SJason Wang struct sk_buff **array, int n) 1243528c1a5SJason Wang { 1253528c1a5SJason Wang return ptr_ring_consume_batched_any(&a->ring, (void **)array, n); 1263528c1a5SJason Wang } 1273528c1a5SJason Wang 1283528c1a5SJason Wang 129ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 130ad69f35dSMichael S. Tsirkin { 131ad69f35dSMichael S. Tsirkin return ptr_ring_consume_bh(&a->ring); 132ad69f35dSMichael S. Tsirkin } 133ad69f35dSMichael S. Tsirkin 1343528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a, 1353528c1a5SJason Wang struct sk_buff **array, int n) 1363528c1a5SJason Wang { 1373528c1a5SJason Wang return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n); 1383528c1a5SJason Wang } 1393528c1a5SJason Wang 140ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb) 141ad69f35dSMichael S. Tsirkin { 142ad69f35dSMichael S. Tsirkin if (likely(skb)) { 143ad69f35dSMichael S. Tsirkin int len = skb->len; 144ad69f35dSMichael S. Tsirkin 145ad69f35dSMichael S. Tsirkin if (skb_vlan_tag_present(skb)) 146ad69f35dSMichael S. Tsirkin len += VLAN_HLEN; 147ad69f35dSMichael S. Tsirkin 148ad69f35dSMichael S. Tsirkin return len; 149ad69f35dSMichael S. Tsirkin } else { 150ad69f35dSMichael S. Tsirkin return 0; 151ad69f35dSMichael S. Tsirkin } 152ad69f35dSMichael S. Tsirkin } 153ad69f35dSMichael S. Tsirkin 154ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a) 155ad69f35dSMichael S. Tsirkin { 156ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 157ad69f35dSMichael S. Tsirkin } 158ad69f35dSMichael S. Tsirkin 159ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a) 160ad69f35dSMichael S. Tsirkin { 161ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 162ad69f35dSMichael S. Tsirkin } 163ad69f35dSMichael S. Tsirkin 164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a) 165ad69f35dSMichael S. Tsirkin { 166ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 167ad69f35dSMichael S. Tsirkin } 168ad69f35dSMichael S. Tsirkin 169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a) 170ad69f35dSMichael S. Tsirkin { 171ad69f35dSMichael S. Tsirkin return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 172ad69f35dSMichael S. Tsirkin } 173ad69f35dSMichael S. Tsirkin 174ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp) 175ad69f35dSMichael S. Tsirkin { 176ad69f35dSMichael S. Tsirkin return ptr_ring_init(&a->ring, size, gfp); 177ad69f35dSMichael S. Tsirkin } 178ad69f35dSMichael S. Tsirkin 179fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr) 1807d7072e3SMichael S. Tsirkin { 1817d7072e3SMichael S. Tsirkin kfree_skb(ptr); 1827d7072e3SMichael S. Tsirkin } 1837d7072e3SMichael S. Tsirkin 1843acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a, 1853acb6960SJason Wang struct sk_buff **skbs, int n) 1863acb6960SJason Wang { 1873acb6960SJason Wang ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); 1883acb6960SJason Wang } 1893acb6960SJason Wang 190fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 1917d7072e3SMichael S. Tsirkin { 1927d7072e3SMichael S. Tsirkin return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 1937d7072e3SMichael S. Tsirkin } 1947d7072e3SMichael S. Tsirkin 195bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings, 196*81fbfe8aSEric Dumazet int nrings, unsigned int size, 197*81fbfe8aSEric Dumazet gfp_t gfp) 198bf900b3dSJason Wang { 199bf900b3dSJason Wang BUILD_BUG_ON(offsetof(struct skb_array, ring)); 200bf900b3dSJason Wang return ptr_ring_resize_multiple((struct ptr_ring **)rings, 201bf900b3dSJason Wang nrings, size, gfp, 202bf900b3dSJason Wang __skb_array_destroy_skb); 203bf900b3dSJason Wang } 204bf900b3dSJason Wang 205ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a) 206ad69f35dSMichael S. Tsirkin { 2077d7072e3SMichael S. Tsirkin ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 208ad69f35dSMichael S. Tsirkin } 209ad69f35dSMichael S. Tsirkin 210ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H */ 211