Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/intel/libeth/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  rx.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2024-2025 Intel Corporation */

#define DEFAULT_SYMBOL_NAMESPACE "LIBETH"

#include <linux/export.h>

#include <net/libeth/rx.h>

/* Rx buffer management */

/**
 * libeth_rx_hw_len_mtu - get the actual buffer size to be passed to HW
 * @pp: &page_pool_params of the netdev to calculate the size for
 * @max_len: maximum buffer size for a single descriptor
 *
 * Return: HW-writeable length per one buffer to pass it to the HW accounting:
 * MTU the @dev has, HW required alignment, minimum and maximum allowed values,
 * and system's page size.
 */

static u32 libeth_rx_hw_len_mtu(const struct page_pool_params *pp, u32 max_len)
{
 u32 len;

 len = READ_ONCE(pp->netdev->mtu) + LIBETH_RX_LL_LEN;
 len = ALIGN(len, LIBETH_RX_BUF_STRIDE);
 len = min3(len, ALIGN_DOWN(max_len ? : U32_MAX, LIBETH_RX_BUF_STRIDE),
     pp->max_len);

 return len;
}

/**
 * libeth_rx_hw_len_truesize - get the short buffer size to be passed to HW
 * @pp: &page_pool_params of the netdev to calculate the size for
 * @max_len: maximum buffer size for a single descriptor
 * @truesize: desired truesize for the buffers
 *
 * Return: HW-writeable length per one buffer to pass it to the HW ignoring the
 * MTU and closest to the passed truesize. Can be used for "short" buffer
 * queues to fragment pages more efficiently.
 */

static u32 libeth_rx_hw_len_truesize(const struct page_pool_params *pp,
         u32 max_len, u32 truesize)
{
 u32 min, len;

 min = SKB_HEAD_ALIGN(pp->offset + LIBETH_RX_BUF_STRIDE);
 truesize = clamp(roundup_pow_of_two(truesize), roundup_pow_of_two(min),
    PAGE_SIZE << LIBETH_RX_PAGE_ORDER);

 len = SKB_WITH_OVERHEAD(truesize - pp->offset);
 len = ALIGN_DOWN(len, LIBETH_RX_BUF_STRIDE) ? : LIBETH_RX_BUF_STRIDE;
 len = min3(len, ALIGN_DOWN(max_len ? : U32_MAX, LIBETH_RX_BUF_STRIDE),
     pp->max_len);

 return len;
}

/**
 * libeth_rx_page_pool_params - calculate params with the stack overhead
 * @fq: buffer queue to calculate the size for
 * @pp: &page_pool_params of the netdev
 *
 * Set the PP params to will all needed stack overhead (headroom, tailroom) and
 * both the HW buffer length and the truesize for all types of buffers. For
 * "short" buffers, truesize never exceeds the "wanted" one; for the rest,
 * it can be up to the page size.
 *
 * Return: true on success, false on invalid input params.
 */

static bool libeth_rx_page_pool_params(struct libeth_fq *fq,
           struct page_pool_params *pp)
{
 pp->offset = fq->xdp ? LIBETH_XDP_HEADROOM : LIBETH_SKB_HEADROOM;
 /* HW-writeable / syncable length per one page */
 pp->max_len = LIBETH_RX_PAGE_LEN(pp->offset);

 /* HW-writeable length per buffer */
 switch (fq->type) {
 case LIBETH_FQE_MTU:
  fq->buf_len = libeth_rx_hw_len_mtu(pp, fq->buf_len);
  break;
 case LIBETH_FQE_SHORT:
  fq->buf_len = libeth_rx_hw_len_truesize(pp, fq->buf_len,
       fq->truesize);
  break;
 case LIBETH_FQE_HDR:
  fq->buf_len = ALIGN(LIBETH_MAX_HEAD, LIBETH_RX_BUF_STRIDE);
  break;
 default:
  return false;
 }

 /* Buffer size to allocate */
 fq->truesize = roundup_pow_of_two(SKB_HEAD_ALIGN(pp->offset +
        fq->buf_len));

 return true;
}

/**
 * libeth_rx_page_pool_params_zc - calculate params without the stack overhead
 * @fq: buffer queue to calculate the size for
 * @pp: &page_pool_params of the netdev
 *
 * Set the PP params to exclude the stack overhead and both the buffer length
 * and the truesize, which are equal for the data buffers. Note that this
 * requires separate header buffers to be always active and account the
 * overhead.
 * With the MTU == ``PAGE_SIZE``, this allows the kernel to enable the zerocopy
 * mode.
 *
 * Return: true on success, false on invalid input params.
 */

static bool libeth_rx_page_pool_params_zc(struct libeth_fq *fq,
       struct page_pool_params *pp)
{
 u32 mtu, max;

 pp->offset = 0;
 pp->max_len = PAGE_SIZE << LIBETH_RX_PAGE_ORDER;

 switch (fq->type) {
 case LIBETH_FQE_MTU:
  mtu = READ_ONCE(pp->netdev->mtu);
  break;
 case LIBETH_FQE_SHORT:
  mtu = fq->truesize;
  break;
 default:
  return false;
 }

 mtu = roundup_pow_of_two(mtu);
 max = min(rounddown_pow_of_two(fq->buf_len ? : U32_MAX),
    pp->max_len);

 fq->buf_len = clamp(mtu, LIBETH_RX_BUF_STRIDE, max);
 fq->truesize = fq->buf_len;

 return true;
}

/**
 * libeth_rx_fq_create - create a PP with the default libeth settings
 * @fq: buffer queue struct to fill
 * @napi: &napi_struct covering this PP (no usage outside its poll loops)
 *
 * Return: %0 on success, -%errno on failure.
 */

int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct *napi)
{
 struct page_pool_params pp = {
  .flags  = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
  .order  = LIBETH_RX_PAGE_ORDER,
  .pool_size = fq->count,
  .nid  = fq->nid,
  .dev  = napi->dev->dev.parent,
  .netdev  = napi->dev,
  .napi  = napi,
 };
 struct libeth_fqe *fqes;
 struct page_pool *pool;
 int ret;

 pp.dma_dir = fq->xdp ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;

 if (!fq->hsplit)
  ret = libeth_rx_page_pool_params(fq, &pp);
 else
  ret = libeth_rx_page_pool_params_zc(fq, &pp);
 if (!ret)
  return -EINVAL;

 pool = page_pool_create(&pp);
 if (IS_ERR(pool))
  return PTR_ERR(pool);

 fqes = kvcalloc_node(fq->count, sizeof(*fqes), GFP_KERNEL, fq->nid);
 if (!fqes) {
  ret = -ENOMEM;
  goto err_buf;
 }

 ret = xdp_reg_page_pool(pool);
 if (ret)
  goto err_mem;

 fq->fqes = fqes;
 fq->pp = pool;

 return 0;

err_mem:
 kvfree(fqes);
err_buf:
 page_pool_destroy(pool);

 return ret;
}
EXPORT_SYMBOL_GPL(libeth_rx_fq_create);

/**
 * libeth_rx_fq_destroy - destroy a &page_pool created by libeth
 * @fq: buffer queue to process
 */

void libeth_rx_fq_destroy(struct libeth_fq *fq)
{
 xdp_unreg_page_pool(fq->pp);
 kvfree(fq->fqes);
 page_pool_destroy(fq->pp);
}
EXPORT_SYMBOL_GPL(libeth_rx_fq_destroy);

/**
 * libeth_rx_recycle_slow - recycle libeth netmem
 * @netmem: network memory to recycle
 *
 * To be used on exceptions or rare cases not requiring fast inline recycling.
 */

void __cold libeth_rx_recycle_slow(netmem_ref netmem)
{
 page_pool_put_full_netmem(netmem_get_pp(netmem), netmem, false);
}
EXPORT_SYMBOL_GPL(libeth_rx_recycle_slow);

/* Converting abstract packet type numbers into a software structure with
 * the packet parameters to do O(1) lookup on Rx.
 */


static const u16 libeth_rx_pt_xdp_oip[] = {
 [LIBETH_RX_PT_OUTER_L2]  = XDP_RSS_TYPE_NONE,
 [LIBETH_RX_PT_OUTER_IPV4] = XDP_RSS_L3_IPV4,
 [LIBETH_RX_PT_OUTER_IPV6] = XDP_RSS_L3_IPV6,
};

static const u16 libeth_rx_pt_xdp_iprot[] = {
 [LIBETH_RX_PT_INNER_NONE] = XDP_RSS_TYPE_NONE,
 [LIBETH_RX_PT_INNER_UDP] = XDP_RSS_L4_UDP,
 [LIBETH_RX_PT_INNER_TCP] = XDP_RSS_L4_TCP,
 [LIBETH_RX_PT_INNER_SCTP] = XDP_RSS_L4_SCTP,
 [LIBETH_RX_PT_INNER_ICMP] = XDP_RSS_L4_ICMP,
 [LIBETH_RX_PT_INNER_TIMESYNC] = XDP_RSS_TYPE_NONE,
};

static const u16 libeth_rx_pt_xdp_pl[] = {
 [LIBETH_RX_PT_PAYLOAD_NONE] = XDP_RSS_TYPE_NONE,
 [LIBETH_RX_PT_PAYLOAD_L2] = XDP_RSS_TYPE_NONE,
 [LIBETH_RX_PT_PAYLOAD_L3] = XDP_RSS_TYPE_NONE,
 [LIBETH_RX_PT_PAYLOAD_L4] = XDP_RSS_L4,
};

/**
 * libeth_rx_pt_gen_hash_type - generate an XDP RSS hash type for a PT
 * @pt: PT structure to evaluate
 *
 * Generates ```hash_type``` field with XDP RSS type values from the parsed
 * packet parameters if they're obtained dynamically at runtime.
 */

void libeth_rx_pt_gen_hash_type(struct libeth_rx_pt *pt)
{
 pt->hash_type = 0;
 pt->hash_type |= libeth_rx_pt_xdp_oip[pt->outer_ip];
 pt->hash_type |= libeth_rx_pt_xdp_iprot[pt->inner_prot];
 pt->hash_type |= libeth_rx_pt_xdp_pl[pt->payload_layer];
}
EXPORT_SYMBOL_GPL(libeth_rx_pt_gen_hash_type);

/* Module */

MODULE_DESCRIPTION("Common Ethernet library");
MODULE_LICENSE("GPL");

Messung V0.5
C=97 H=92 G=94

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.