rx.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /* Copyright (C) 2024 Intel Corporation */
  3. #ifndef __LIBETH_RX_H
  4. #define __LIBETH_RX_H
  5. #include <linux/if_vlan.h>
  6. #include <net/page_pool/helpers.h>
  7. #include <net/xdp.h>
  8. /* Rx buffer management */
  9. /* Space reserved in front of each frame */
  10. #define LIBETH_SKB_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
  11. /* Maximum headroom for worst-case calculations */
  12. #define LIBETH_MAX_HEADROOM LIBETH_SKB_HEADROOM
  13. /* Link layer / L2 overhead: Ethernet, 2 VLAN tags (C + S), FCS */
  14. #define LIBETH_RX_LL_LEN (ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN)
  15. /* Maximum supported L2-L4 header length */
  16. #define LIBETH_MAX_HEAD roundup_pow_of_two(max(MAX_HEADER, 256))
  17. /* Always use order-0 pages */
  18. #define LIBETH_RX_PAGE_ORDER 0
  19. /* Pick a sane buffer stride and align to a cacheline boundary */
  20. #define LIBETH_RX_BUF_STRIDE SKB_DATA_ALIGN(128)
  21. /* HW-writeable space in one buffer: truesize - headroom/tailroom, aligned */
  22. #define LIBETH_RX_PAGE_LEN(hr) \
  23. ALIGN_DOWN(SKB_MAX_ORDER(hr, LIBETH_RX_PAGE_ORDER), \
  24. LIBETH_RX_BUF_STRIDE)
  25. /**
  26. * struct libeth_fqe - structure representing an Rx buffer (fill queue element)
  27. * @page: page holding the buffer
  28. * @offset: offset from the page start (to the headroom)
  29. * @truesize: total space occupied by the buffer (w/ headroom and tailroom)
  30. *
  31. * Depending on the MTU, API switches between one-page-per-frame and shared
  32. * page model (to conserve memory on bigger-page platforms). In case of the
  33. * former, @offset is always 0 and @truesize is always ```PAGE_SIZE```.
  34. */
  35. struct libeth_fqe {
  36. struct page *page;
  37. u32 offset;
  38. u32 truesize;
  39. } __aligned_largest;
  40. /**
  41. * enum libeth_fqe_type - enum representing types of Rx buffers
  42. * @LIBETH_FQE_MTU: buffer size is determined by MTU
  43. * @LIBETH_FQE_SHORT: buffer size is smaller than MTU, for short frames
  44. * @LIBETH_FQE_HDR: buffer size is ```LIBETH_MAX_HEAD```-sized, for headers
  45. */
  46. enum libeth_fqe_type {
  47. LIBETH_FQE_MTU = 0U,
  48. LIBETH_FQE_SHORT,
  49. LIBETH_FQE_HDR,
  50. };
  51. /**
  52. * struct libeth_fq - structure representing a buffer (fill) queue
  53. * @fp: hotpath part of the structure
  54. * @pp: &page_pool for buffer management
  55. * @fqes: array of Rx buffers
  56. * @truesize: size to allocate per buffer, w/overhead
  57. * @count: number of descriptors/buffers the queue has
  58. * @type: type of the buffers this queue has
  59. * @hsplit: flag whether header split is enabled
  60. * @buf_len: HW-writeable length per each buffer
  61. * @nid: ID of the closest NUMA node with memory
  62. */
  63. struct libeth_fq {
  64. struct_group_tagged(libeth_fq_fp, fp,
  65. struct page_pool *pp;
  66. struct libeth_fqe *fqes;
  67. u32 truesize;
  68. u32 count;
  69. );
  70. /* Cold fields */
  71. enum libeth_fqe_type type:2;
  72. bool hsplit:1;
  73. u32 buf_len;
  74. int nid;
  75. };
  76. int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct *napi);
  77. void libeth_rx_fq_destroy(struct libeth_fq *fq);
  78. /**
  79. * libeth_rx_alloc - allocate a new Rx buffer
  80. * @fq: fill queue to allocate for
  81. * @i: index of the buffer within the queue
  82. *
  83. * Return: DMA address to be passed to HW for Rx on successful allocation,
  84. * ```DMA_MAPPING_ERROR``` otherwise.
  85. */
  86. static inline dma_addr_t libeth_rx_alloc(const struct libeth_fq_fp *fq, u32 i)
  87. {
  88. struct libeth_fqe *buf = &fq->fqes[i];
  89. buf->truesize = fq->truesize;
  90. buf->page = page_pool_dev_alloc(fq->pp, &buf->offset, &buf->truesize);
  91. if (unlikely(!buf->page))
  92. return DMA_MAPPING_ERROR;
  93. return page_pool_get_dma_addr(buf->page) + buf->offset +
  94. fq->pp->p.offset;
  95. }
  96. void libeth_rx_recycle_slow(struct page *page);
  97. /**
  98. * libeth_rx_sync_for_cpu - synchronize or recycle buffer post DMA
  99. * @fqe: buffer to process
  100. * @len: frame length from the descriptor
  101. *
  102. * Process the buffer after it's written by HW. The regular path is to
  103. * synchronize DMA for CPU, but in case of no data it will be immediately
  104. * recycled back to its PP.
  105. *
  106. * Return: true when there's data to process, false otherwise.
  107. */
  108. static inline bool libeth_rx_sync_for_cpu(const struct libeth_fqe *fqe,
  109. u32 len)
  110. {
  111. struct page *page = fqe->page;
  112. /* Very rare, but possible case. The most common reason:
  113. * the last fragment contained FCS only, which was then
  114. * stripped by the HW.
  115. */
  116. if (unlikely(!len)) {
  117. libeth_rx_recycle_slow(page);
  118. return false;
  119. }
  120. page_pool_dma_sync_for_cpu(page->pp, page, fqe->offset, len);
  121. return true;
  122. }
  123. /* Converting abstract packet type numbers into a software structure with
  124. * the packet parameters to do O(1) lookup on Rx.
  125. */
  126. enum {
  127. LIBETH_RX_PT_OUTER_L2 = 0U,
  128. LIBETH_RX_PT_OUTER_IPV4,
  129. LIBETH_RX_PT_OUTER_IPV6,
  130. };
  131. enum {
  132. LIBETH_RX_PT_NOT_FRAG = 0U,
  133. LIBETH_RX_PT_FRAG,
  134. };
  135. enum {
  136. LIBETH_RX_PT_TUNNEL_IP_NONE = 0U,
  137. LIBETH_RX_PT_TUNNEL_IP_IP,
  138. LIBETH_RX_PT_TUNNEL_IP_GRENAT,
  139. LIBETH_RX_PT_TUNNEL_IP_GRENAT_MAC,
  140. LIBETH_RX_PT_TUNNEL_IP_GRENAT_MAC_VLAN,
  141. };
  142. enum {
  143. LIBETH_RX_PT_TUNNEL_END_NONE = 0U,
  144. LIBETH_RX_PT_TUNNEL_END_IPV4,
  145. LIBETH_RX_PT_TUNNEL_END_IPV6,
  146. };
  147. enum {
  148. LIBETH_RX_PT_INNER_NONE = 0U,
  149. LIBETH_RX_PT_INNER_UDP,
  150. LIBETH_RX_PT_INNER_TCP,
  151. LIBETH_RX_PT_INNER_SCTP,
  152. LIBETH_RX_PT_INNER_ICMP,
  153. LIBETH_RX_PT_INNER_TIMESYNC,
  154. };
  155. #define LIBETH_RX_PT_PAYLOAD_NONE PKT_HASH_TYPE_NONE
  156. #define LIBETH_RX_PT_PAYLOAD_L2 PKT_HASH_TYPE_L2
  157. #define LIBETH_RX_PT_PAYLOAD_L3 PKT_HASH_TYPE_L3
  158. #define LIBETH_RX_PT_PAYLOAD_L4 PKT_HASH_TYPE_L4
  159. struct libeth_rx_pt {
  160. u32 outer_ip:2;
  161. u32 outer_frag:1;
  162. u32 tunnel_type:3;
  163. u32 tunnel_end_prot:2;
  164. u32 tunnel_end_frag:1;
  165. u32 inner_prot:3;
  166. enum pkt_hash_types payload_layer:2;
  167. u32 pad:2;
  168. enum xdp_rss_hash_type hash_type:16;
  169. };
  170. void libeth_rx_pt_gen_hash_type(struct libeth_rx_pt *pt);
  171. /**
  172. * libeth_rx_pt_get_ip_ver - get IP version from a packet type structure
  173. * @pt: packet type params
  174. *
  175. * Wrapper to compile out the IPv6 code from the drivers when not supported
  176. * by the kernel.
  177. *
  178. * Return: @pt.outer_ip or stub for IPv6 when not compiled-in.
  179. */
  180. static inline u32 libeth_rx_pt_get_ip_ver(struct libeth_rx_pt pt)
  181. {
  182. #if !IS_ENABLED(CONFIG_IPV6)
  183. switch (pt.outer_ip) {
  184. case LIBETH_RX_PT_OUTER_IPV4:
  185. return LIBETH_RX_PT_OUTER_IPV4;
  186. default:
  187. return LIBETH_RX_PT_OUTER_L2;
  188. }
  189. #else
  190. return pt.outer_ip;
  191. #endif
  192. }
  193. /* libeth_has_*() can be used to quickly check whether the HW metadata is
  194. * available to avoid further expensive processing such as descriptor reads.
  195. * They already check for the corresponding netdev feature to be enabled,
  196. * thus can be used as drop-in replacements.
  197. */
  198. static inline bool libeth_rx_pt_has_checksum(const struct net_device *dev,
  199. struct libeth_rx_pt pt)
  200. {
  201. /* Non-zero _INNER* is only possible when _OUTER_IPV* is set,
  202. * it is enough to check only for the L4 type.
  203. */
  204. return likely(pt.inner_prot > LIBETH_RX_PT_INNER_NONE &&
  205. (dev->features & NETIF_F_RXCSUM));
  206. }
  207. static inline bool libeth_rx_pt_has_hash(const struct net_device *dev,
  208. struct libeth_rx_pt pt)
  209. {
  210. return likely(pt.payload_layer > LIBETH_RX_PT_PAYLOAD_NONE &&
  211. (dev->features & NETIF_F_RXHASH));
  212. }
  213. /**
  214. * libeth_rx_pt_set_hash - fill in skb hash value basing on the PT
  215. * @skb: skb to fill the hash in
  216. * @hash: 32-bit hash value from the descriptor
  217. * @pt: packet type
  218. */
  219. static inline void libeth_rx_pt_set_hash(struct sk_buff *skb, u32 hash,
  220. struct libeth_rx_pt pt)
  221. {
  222. skb_set_hash(skb, hash, pt.payload_layer);
  223. }
  224. #endif /* __LIBETH_RX_H */