/* Space reserved in front of each frame */ #define LIBETH_SKB_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN) #define LIBETH_XDP_HEADROOM (ALIGN(XDP_PACKET_HEADROOM, NET_SKB_PAD) + \
NET_IP_ALIGN) /* Maximum headroom for worst-case calculations */ #define LIBETH_MAX_HEADROOM LIBETH_XDP_HEADROOM /* Link layer / L2 overhead: Ethernet, 2 VLAN tags (C + S), FCS */ #define LIBETH_RX_LL_LEN (ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN) /* Maximum supported L2-L4 header length */ #define LIBETH_MAX_HEAD roundup_pow_of_two(max(MAX_HEADER, 256))
/* Always use order-0 pages */ #define LIBETH_RX_PAGE_ORDER 0 /* Pick a sane buffer stride and align to a cacheline boundary */ #define LIBETH_RX_BUF_STRIDE SKB_DATA_ALIGN(128) /* HW-writeable space in one buffer: truesize - headroom/tailroom, aligned */ #define LIBETH_RX_PAGE_LEN(hr) \
ALIGN_DOWN(SKB_MAX_ORDER(hr, LIBETH_RX_PAGE_ORDER), \
LIBETH_RX_BUF_STRIDE)
/** * struct libeth_fqe - structure representing an Rx buffer (fill queue element) * @netmem: network memory reference holding the buffer * @offset: offset from the page start (to the headroom) * @truesize: total space occupied by the buffer (w/ headroom and tailroom) * * Depending on the MTU, API switches between one-page-per-frame and shared * page model (to conserve memory on bigger-page platforms). In case of the * former, @offset is always 0 and @truesize is always ```PAGE_SIZE```.
*/ struct libeth_fqe {
netmem_ref netmem;
u32 offset;
u32 truesize;
} __aligned_largest;
/** * enum libeth_fqe_type - enum representing types of Rx buffers * @LIBETH_FQE_MTU: buffer size is determined by MTU * @LIBETH_FQE_SHORT: buffer size is smaller than MTU, for short frames * @LIBETH_FQE_HDR: buffer size is ```LIBETH_MAX_HEAD```-sized, for headers
*/ enum libeth_fqe_type {
LIBETH_FQE_MTU = 0U,
LIBETH_FQE_SHORT,
LIBETH_FQE_HDR,
};
/** * struct libeth_fq - structure representing a buffer (fill) queue * @fp: hotpath part of the structure * @pp: &page_pool for buffer management * @fqes: array of Rx buffers * @truesize: size to allocate per buffer, w/overhead * @count: number of descriptors/buffers the queue has * @type: type of the buffers this queue has * @hsplit: flag whether header split is enabled * @xdp: flag indicating whether XDP is enabled * @buf_len: HW-writeable length per each buffer * @nid: ID of the closest NUMA node with memory
*/ struct libeth_fq {
struct_group_tagged(libeth_fq_fp, fp, struct page_pool *pp; struct libeth_fqe *fqes;
/** * libeth_rx_alloc - allocate a new Rx buffer * @fq: fill queue to allocate for * @i: index of the buffer within the queue * * Return: DMA address to be passed to HW for Rx on successful allocation, * ```DMA_MAPPING_ERROR``` otherwise.
*/ staticinline dma_addr_t libeth_rx_alloc(conststruct libeth_fq_fp *fq, u32 i)
{ struct libeth_fqe *buf = &fq->fqes[i];
/** * libeth_rx_sync_for_cpu - synchronize or recycle buffer post DMA * @fqe: buffer to process * @len: frame length from the descriptor * * Process the buffer after it's written by HW. The regular path is to * synchronize DMA for CPU, but in case of no data it will be immediately * recycled back to its PP. * * Return: true when there's data to process, false otherwise.
*/ staticinlinebool libeth_rx_sync_for_cpu(conststruct libeth_fqe *fqe,
u32 len)
{
netmem_ref netmem = fqe->netmem;
/* Very rare, but possible case. The most common reason: * the last fragment contained FCS only, which was then * stripped by the HW.
*/ if (unlikely(!len)) {
libeth_rx_recycle_slow(netmem); returnfalse;
}
/** * struct libeth_rx_csum - checksum offload bits decoded from the Rx descriptor * @l3l4p: detectable L3 and L4 integrity check is processed by the hardware * @ipe: IP checksum error * @eipe: external (outermost) IP header (only for tunels) * @eudpe: external (outermost) UDP checksum error (only for tunels) * @ipv6exadd: IPv6 header with extension headers * @l4e: L4 integrity error * @pprs: set for packets that skip checksum calculation in the HW pre parser * @nat: the packet is a UDP tunneled packet * @raw_csum_valid: set if raw checksum is valid * @pad: padding to naturally align raw_csum field * @raw_csum: raw checksum
*/ struct libeth_rx_csum {
u32 l3l4p:1;
u32 ipe:1;
u32 eipe:1;
u32 eudpe:1;
u32 ipv6exadd:1;
u32 l4e:1;
u32 pprs:1;
u32 nat:1;
/** * struct libeth_rqe_info - receive queue element info * @len: packet length * @ptype: packet type based on types programmed into the device * @eop: whether it's the last fragment of the packet * @rxe: MAC errors: CRC, Alignment, Oversize, Undersizes, Length error * @vlan: C-VLAN or S-VLAN tag depending on the VLAN offload configuration
*/ struct libeth_rqe_info {
u32 len;
/** * libeth_rx_pt_get_ip_ver - get IP version from a packet type structure * @pt: packet type params * * Wrapper to compile out the IPv6 code from the drivers when not supported * by the kernel. * * Return: @pt.outer_ip or stub for IPv6 when not compiled-in.
*/ staticinline u32 libeth_rx_pt_get_ip_ver(struct libeth_rx_pt pt)
{ #if !IS_ENABLED(CONFIG_IPV6) switch (pt.outer_ip) { case LIBETH_RX_PT_OUTER_IPV4: return LIBETH_RX_PT_OUTER_IPV4; default: return LIBETH_RX_PT_OUTER_L2;
} #else return pt.outer_ip; #endif
}
/* libeth_has_*() can be used to quickly check whether the HW metadata is * available to avoid further expensive processing such as descriptor reads. * They already check for the corresponding netdev feature to be enabled, * thus can be used as drop-in replacements.
*/
staticinlinebool libeth_rx_pt_has_checksum(conststruct net_device *dev, struct libeth_rx_pt pt)
{ /* Non-zero _INNER* is only possible when _OUTER_IPV* is set, * it is enough to check only for the L4 type.
*/ return likely(pt.inner_prot > LIBETH_RX_PT_INNER_NONE &&
(dev->features & NETIF_F_RXCSUM));
}
/** * libeth_rx_pt_set_hash - fill in skb hash value basing on the PT * @skb: skb to fill the hash in * @hash: 32-bit hash value from the descriptor * @pt: packet type
*/ staticinlinevoid libeth_rx_pt_set_hash(struct sk_buff *skb, u32 hash, struct libeth_rx_pt pt)
{
skb_set_hash(skb, hash, pt.payload_layer);
}
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.