IFLIBTXTX(9)

πŸ’– NAME πŸ’–

okay bestie, welcome to iflibtxrx(9) β€” the Device Dependent Transmit and Receive Functions. this is the page for when you're writing a driver and you gotta tell iflib how your specific hardware does the whole send-a-packet / get-a-packet thing. no cap, this is core driver territory πŸ’…


✨ SYNOPSIS ✨

#include <ifdi_if.h>

Interface Manipulation Functions

int
isc_txd_encap(void *sc, if_pkt_into_t pi);

void
isc_txd_flush(void *sc, uint16_t qid, uint32_t _pidx_or_credits_);

int
isc_txd_credits_update(void *sc, uint16_t qid, bool clear);

int
isc_rxd_available(void *sc, uint16_t qsid, uint32_t cidx);

void
isc_rxd_refill(void *sc, uint16_t qsid, uint8_t flid, uint32_t pidx,
    uint64_t *paddrs, caddr_t *vaddrs, uint16_t count);

void
isc_rxd_flush(void *sc, uint16_t qsid, uint8_t flid, uint32_t pidx);

int
isc_rxd_pkt_get(void *sc, if_rxd_info_t ri);

Global Variables

extern struct if_txrx

πŸŽ€ DATA STRUCTURES πŸŽ€

so the device dependent mechanisms for handling packet transmit and receive are, like, primarily defined by those functions up there ⬆️. the if_pkt_info data structure is holding all the stats and identifying info you need to actually send a packet. and the receive-side twin of that is the if_rxd_info structure. they're a matched set, your honor 🫢

The if_pkt_info Structure

the fields of struct if_pkt_info are, in order, slay by slay:

  • ipi_len (uint32_t) β€” the size of the packet being sent on the transmit queue.
  • ipi_segs (bus_dma_segment_t *) β€” a pointer to the bus_dma_segment of the device independent transfer queue defined in iflib.
  • ipi_qsidx β€” a unique index value, assigned sequentially to each transmit queue. it's how you reference the queue that's currently transmitting.
  • ipi_nsegs (uint16_t) β€” how many descriptors are gonna be read into the device dependent transfer descriptors.
  • ipi_ndescs (uint16_t) β€” number of descriptors in use. you get this by subtracting the old pidx value from the new pidx value. math girlies rise πŸ™Œ
  • ipi_flags (uint16_t) β€” flags defined on a per-packet basis.
  • ipi_pidx (uint32_t) β€” the value of the first pidx sent to the isc_encap function for encapsulation and subsequent transmission.
  • ipi_new_pidx (uint32_t) β€” the value set after the isc_encap function terminates. this value becomes the first pidx sent to the isc-encap the next time the function gets called. it's giving "passing the baton" πŸƒβ™€οΈ

The Following Fields Are Used For Offload Handling

  • ipi_csum_flags (uint64_t) β€” flags describing the checksum values, used on a per-packet basis.
  • ipi_tso_segsz (uint16_t) β€” size of the TSO Segment Size.
  • ipi_mflags (uint16_t) β€” flags describing the operational parameters of the mbuf.
  • ipi_vtag (uint16_t) β€” contains the VLAN information in the Ethernet Frame.
  • ipi_etype (uint16_t) β€” type of ethernet header protocol, as contained by the struct ether_vlan_header.
  • ipi_ehrdlen (uint8_t) β€” length of the Ethernet Header.
  • ipi_ip_hlen (uint8_t) β€” length of the TCP Header
  • ipi_tcp_hlen (uint8_t) β€” length of the TCP Header.
  • ipi_tcp_hflags (uint8_t) β€” flags describing the operational parameters of the TCP Header.
  • ipi_ipproto (uint8_t) β€” specifies the type of IP Protocol in use. example: TCP, UDP, or SCTP.
not me pointing out that both ipi_ip_hlen and ipi_tcp_hlen are documented as "Length of the TCP Header" πŸ’€ that's literally what the page says, i'm just the messenger, don't come for me

The if_rxd_info Structure

the fields of struct if_rxd_info go a little something like this:

  • iri_qsidx (uint16_t) β€” a unique index value assigned sequentially to each receive queue. used to reference the currently receiving queue.
  • iri_vtag (uint16_t) β€” contains the VLAN information in the Ethernet Frame.
  • iri_len (uint16_t) β€” the size of a received packet.
  • iri_next_offset (uint16_t) β€” the offset value for the next packet to be receive. a Null value signifies the end of packet.
  • iri_cidx (uint32_t) β€” the index value of the packet currently being processed in the consumer queue.
  • iri_flowid (uint32_t) β€” the value of the RSS hash for the packet.
  • iri_flags (uint) β€” flags describing the operational parameters of the mbuf contained in the receive packet.
  • iri_csum_flags (uint32_t) β€” flags describing the checksum value contained in the receive packet.
  • iri_csum_data (uint32_t) β€” checksum data contained in the mbuf(9) packet header.
  • iri_m (struct mbuf *) β€” an mbuf for drivers that manage their own receive queues.
  • iri_ifp (struct ifnet *) β€” a link back to the interface structure. utilized by drivers that have multiple interface per softc.
  • iri_rsstype (uint8_t) β€” the value of the RSS hash type.
  • iri_pad (uint8_t) β€” the length of any padding contained by the received data.
  • iri_qidx (uint8_t) β€” represents the type of queue event. if value >= 0 then it is the freelist id, otherwise it is a completion queue event.

πŸ”₯ FUNCTIONS πŸ”₯

every single one of these function calls is associated exclusively with either packet transmission or packet receipt β€” pick a lane, bestie. and that void *sc passed as the first argument to all of them? that's the driver's softc. the main character of the whole operation, honestly πŸ‘‘

Transmit Packet Functions

  • isc_txd_encap() the transmit function that sends a packet on an interface. the if_pkt_info data structure is carrying the data information fields that describe the packet. this function returns 0 if it's successful, otherwise an error value gets returned. (so like, check the return, fr fr 😀)
  • isc_txd_flush() the flush function, and it gets called immediately after isc_txd_encap transmits a packet. it updates the hardware producer index, or increments the descriptors used, to pidx_or_credits in the queue designated by the qid number. this is often referred to as poking the doorbell register. πŸ”” iconic behavior.
  • isc_txd_credits_update() the credit function advances the buffer ring and calculates the credits (descriptors) processed. until the I/O is complete it cleans the range in case of multisegments and updates the count of processed packets. the function returns the number of processed credits. yes she's doing several things at once, she's multitasking, we love her πŸ’…

Receive Packet Functions

  • isc_rxd_available() this function calculates the remaining number of descriptors from a position given by idx. and then it returns that value. short, sweet, returns a number πŸ“
  • isc_rxd_refill() starting with the physical address paddrs, the function reads a packet into the rx_ring until it hits the value designated by count. vaddrs is typically not needed β€” it's provided for devices that place their own metadata in the packet header.
  • isc_rxd_flush() this flush function updates the producer pointer on the free list flid in queue set number qid to pidx, to reflect the presence of new buffers. new buffers = new era ✨
  • isc_rxd_pkt_get() processes a single software descriptor. rxr->rx_base[i] contains a descriptor that describes a received packet. hardware specific information about the buffer referred to by ri is returned in the data structure if_rxd_info. (note: no semicolon on that last sentence in the original, we're keeping the vibe authentic 🫢)

🌈 SEE ALSO 🌈


πŸ‘‘ AUTHORS πŸ‘‘

this manual page was written by Nicole Graziano. absolute legend, thank you for your service πŸ«‘πŸ’–


and that's the whole page bestie, you ate that reading assignment. this was from the IFLIBTXTX(9) page, the Kernel Developer's Manual, Debian, dated April 16, 2019 β€” go forth and write your driver, you've got this πŸ’œβœ¨

πŸ“¦ where this page comes from