xsk_queue.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* XDP user-space ring structure
  3. * Copyright(c) 2018 Intel Corporation.
  4. */
  5. #include <linux/log2.h>
  6. #include <linux/slab.h>
  7. #include <linux/overflow.h>
  8. #include <linux/vmalloc.h>
  9. #include <net/xdp_sock_drv.h>
  10. #include "xsk_queue.h"
  11. static size_t xskq_get_ring_size(struct xsk_queue *q, bool umem_queue)
  12. {
  13. struct xdp_umem_ring *umem_ring;
  14. struct xdp_rxtx_ring *rxtx_ring;
  15. if (umem_queue)
  16. return struct_size(umem_ring, desc, q->nentries);
  17. return struct_size(rxtx_ring, desc, q->nentries);
  18. }
  19. struct xsk_queue *xskq_create(u32 nentries, bool umem_queue)
  20. {
  21. struct xsk_queue *q;
  22. size_t size;
  23. q = kzalloc_obj(*q);
  24. if (!q)
  25. return NULL;
  26. q->nentries = nentries;
  27. q->ring_mask = nentries - 1;
  28. size = xskq_get_ring_size(q, umem_queue);
  29. /* size which is overflowing or close to SIZE_MAX will become 0 in
  30. * PAGE_ALIGN(), checking SIZE_MAX is enough due to the previous
  31. * is_power_of_2(), the rest will be handled by vmalloc_user()
  32. */
  33. if (unlikely(size == SIZE_MAX)) {
  34. kfree(q);
  35. return NULL;
  36. }
  37. size = PAGE_ALIGN(size);
  38. q->ring = vmalloc_user(size);
  39. if (!q->ring) {
  40. kfree(q);
  41. return NULL;
  42. }
  43. q->ring_vmalloc_size = size;
  44. return q;
  45. }
  46. void xskq_destroy(struct xsk_queue *q)
  47. {
  48. if (!q)
  49. return;
  50. vfree(q->ring);
  51. kfree(q);
  52. }