The DPDK programmers guide explains mbufs to be
"free buffers that may be used by the DPDK application to store message buffers. A rte_mbuf struct generally carries
network packet buffers, but it can actually be any data (control data, events, …). The rte_mbuf header structure is
kept as small as possible and currently uses just two cache lines, with the most frequently used fields being on the first of the
two cache lines."
While the rte_mbuf is in reality only 128 bytes large, it only serves as
data descriptor, with fields like pkt_len, which is the total
length of the package over all segments and data_len, which is the amount of data that is inside the segment buffer of
this specific rte_mbuf. Because rte_mbufs can be chained together with their
rte_mbuf* next field, in order to accommodate larger packages.
The content of the package (e.g. the Ethernet frame) is stored at the void *buf_addr; field of the rte_mbuf.
This is also the first field of rte_mbuf, so they are pointer interconvertible. The data can thus be accessed
via (char *)mbuf->buf_addr + mbuf->data_off . The DPDK provides a macro for this called rte_pktmbuf_mtod.
Even though the desired type can be passed to rte_pktmbuf_mtod, it uses C-style cast, so you should only actually pass
char* or std::byte*, so it doesn't result in undefined behavior. This
A NIC can have one or multiple female 8P8C connectors (commonly referred to as RJ-45). These are called physical ports. A NIC with more than one physical ports is called multi-port NIC, a NIC with four ports is called quad-port, like this Quad-Port Ethernet adapter. With Single-root I/O virtualization, multiple virtual ports can be mapped to a single physical port, so multiple virtual machines on a server can share a single physical NIC port.
PCI devices like NICs are identified using the
BDF (bus/device/function) notation, with 8
bit for the bus, 5 bit for the device and 3 bit for the function number
[source]. DPDK has to use these numbers to
address NIC ports internally, but abstracts this from the user by assigning each NIC port a
port_id. All functions that are exported by the PMD (pollmode driver) API use the port_id to identify the NIC port.[source]
The DPDK API documentation states: "In all functions of the Ethernet API, the Ethernet device is designated by an integer >= 0 named the device port identifier."
Examples for functions that use port_id:
int rte_eth_dev_start(uint16_t port_id);
starts the Ethernet device.
int rte_eth_macaddr_get(uint16_t port_id, struct rte_ether_addr *mac_addr); fetches the MAC address of the NIC port
port_id.