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 thebus_dma_segmentof 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 oldpidxvalue from the newpidxvalue. math girlies rise πipi_flags(uint16_t) β flags defined on a per-packet basis.ipi_pidx(uint32_t) β the value of the firstpidxsent to theisc_encapfunction for encapsulation and subsequent transmission.ipi_new_pidx(uint32_t) β the value set after theisc_encapfunction terminates. this value becomes the firstpidxsent to theisc-encapthe 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 thestruct ether_vlan_header.ipi_ehrdlen(uint8_t) β length of the Ethernet Header.ipi_ip_hlen(uint8_t) β length of the TCP Headeripi_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 bothipi_ip_hlenandipi_tcp_hlenare 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 thembuf(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>= 0then 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. theif_pkt_infodata structure is carrying the data information fields that describe the packet. this function returns0if 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 afterisc_txd_encaptransmits a packet. it updates the hardware producer index, or increments the descriptors used, topidx_or_creditsin the queue designated by theqidnumber. 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 byidx. and then it returns that value. short, sweet, returns a number πisc_rxd_refill()starting with the physical addresspaddrs, the function reads a packet into the rx_ring until it hits the value designated bycount.vaddrsis 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 listflidin queue set numberqidtopidx, 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 byriis returned in the data structureif_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
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms