iPXE
io_buffer Struct Reference

A persistent I/O buffer. More...

#include <iobuf.h>

Data Fields

struct list_head list
 List of which this buffer is a member.
struct dma_mapping map
 DMA mapping.
void * head
 Start of the buffer.
void * data
 Start of data.
void * tail
 End of data.
void * end
 End of the buffer.

Detailed Description

A persistent I/O buffer.

This data structure encapsulates a long-lived I/O buffer. The buffer may be passed between multiple owners, queued for possible retransmission, etc.

The datapath model uses a zero-copy fast path for both transmit and receive directions. Headers and footers are appended/prepended and stripped in situ as the buffer is passed between layers of the network stack. Adding or stripping a header or footer is merely a pointer update: no existing data is ever moved.

The buffer content is delineated by four pointers, which satisfy the invariant:

head <= data <= tail <= end

The head and end pointers are set when the buffer is first allocated and are never changed. The data and tail pointers represent the current data region within the buffer, and are modified by the accessor functions iob_push(), iob_pull(), iob_put(), iob_unput() etc.

The current length of the data region may be obtained using iob_len(). The space currently between the head and data pointers is the available headroom and its length may be obtained using iob_headroom(). Similarly, the space currently between the tail and end pointers is the available tailroom and its length may be obtained using iob_tailroom().

It is the responsibility of the allocator of the I/O buffer to ensure that sufficient headroom and tailroom exists for all subsequent users of the I/O buffer. For example: a transmit buffer allocated by the TCP layer must ensure that there is sufficient headroom for the TCP headers, the network-layer (IPv4/IPv6) headers, and the longest possible link-layer header. The lower layers are permitted to assume that sufficient headroom exists and may call iob_push() to prepend their headers without performing any further checks.

On the receive datapath, I/O buffers are typically allocated by the device driver. Some care must be taken to ensure that received buffers that end up being reflected and transmitted (e.g. responses to ARP requests) contain sufficient headroom. For most devices, transmit and receive buffers are symmetric and so any receive buffer will always have sufficient headroom for this purpose. Devices that require additional transmit headers (such as the Asix USB NICs) must ensure that additional headroom is allocated in receive buffers to allow for this reflection.

Received I/O buffers should always be treated as containing untrusted data. Device drivers may assume that DMA-capable hardware will not report erroneous lengths (e.g. a received length greater than the original allocation length), but all other consumers must validate the buffer length before accessing its contents or stripping headers or footers.

The accessor functions iob_push(), iob_pull(), iob_unput() etc include assertion checks but do not perform any runtime checks that the pointer invariant is maintained. In particular, using iob_pull() or iob_unput() to strip a header without first using iob_len() to check the available length will result in an invariant violation that causes the iob_len() calculation to underflow and report an extremely large buffer length (which is then likely to cause a false positive for any subsequent buffer length checks).

Definition at line 98 of file iobuf.h.

Field Documentation

◆ list

◆ map

struct dma_mapping io_buffer::map

◆ head

void* io_buffer::head

Start of the buffer.

Definition at line 111 of file iobuf.h.

Referenced by alloc_iob_okx(), alloc_iob_raw(), free_iob(), iob_headroom(), iob_populate(), and net80211_probe_step().

◆ data

void* io_buffer::data

Start of data.

Definition at line 113 of file iobuf.h.

Referenced by a3c90x_prepare_rx_desc(), a3c90x_transmit(), acm_control_receive(), acm_control_transmit(), acm_intr_complete(), acm_transmit(), af_packet_nic_poll(), af_packet_nic_transmit(), alloc_iob_okx(), alloc_iob_raw(), aoe_rx(), aoecmd_rx(), aoecmd_tx(), arbel_complete(), arbel_fill_mlx_send_wqe(), arbel_fill_rc_send_wqe(), arbel_fill_ud_send_wqe(), arbel_post_recv(), arp_rx(), ath5k_rx_iob_alloc(), ath5k_txbuf_setup(), ath_rx_init(), ath_tx_setup_buffer(), atl1e_clean_rx_irq(), atl1e_tx_map(), axge_in_complete(), axge_intr_complete(), b44_process_rx_packets(), b44_rx_refill(), b44_transmit(), bnxt_add_vlan(), bnxt_rx_drop(), bnxt_rx_process(), bnxt_tx(), bnxt_tx_adjust_pkt(), bnxt_tx_complete(), ccmp_decrypt(), ccmp_encrypt(), cgem_refill_rx(), cgem_transmit(), dhcp_deliver(), dhcp_tx(), dhcpv6_rx(), dm96xx_in_complete(), dm96xx_intr_complete(), dns_xfer_deliver(), dwmac_refill_rx(), dwmac_transmit(), eapol_eap_rx(), eapol_key_rx(), eapol_rx(), ecm_intr_complete(), efab_fill_rx_queue(), efab_receive(), efab_transmit(), efi_download_deliver_iob(), efi_local_step(), efi_pxe_udp_read(), efi_snp_receive(), efi_usb_async_complete(), efi_usb_sync_transfer(), efx_hunt_build_rx_desc(), efx_hunt_build_tx_desc(), efx_hunt_receive(), efx_hunt_rxq_fill(), efx_hunt_transmit(), ehci_endpoint_message(), ehci_endpoint_stream(), ena_refill_rx(), ena_transmit(), eoib_complete_recv(), eoib_duplicate(), eoib_transmit(), eth_pull(), eth_slow_lacp_dump(), eth_slow_lacp_rx(), eth_slow_marker_dump(), eth_slow_marker_rx(), eth_slow_rx(), exanic_transmit(), falcon_build_rx_desc(), falcon_build_tx_desc(), fc_els_rx(), fc_ns_query_deliver(), fc_port_deliver(), fc_xchg_rx(), fcoe_deliver(), fcoe_fip_rx(), fcoe_rx(), fcpcmd_recv_rddata(), fcpcmd_recv_rsp(), fcpcmd_recv_unknown(), fcpcmd_recv_xfer_rdy(), flexboot_nodnic_post_recv(), forcedeth_transmit(), fragment_reassemble(), free_iob(), ftp_control_deliver(), gdbudp_recv(), get_hw_packet_type(), golan_post_recv(), golan_post_send(), gve_transmit(), hermon_fill_eth_send_wqe(), hermon_fill_mlx_send_wqe(), hermon_fill_rc_send_wqe(), hermon_fill_ud_send_wqe(), hermon_post_recv(), http_rx_linebuf(), hub_complete(), hunt_mcdi_copyin(), hunt_mcdi_copyout(), hunt_mcdi_request_poll(), ib_cmrc_complete_recv(), ib_cmrc_xfer_deliver(), ib_mi_complete_recv(), ib_pull(), ib_push(), icmp_rx_echo_reply(), icmp_rx_echo_request(), icmp_tx_echo(), icmp_tx_echo_reply(), icmp_tx_echo_request(), icmpv4_rx(), icmpv6_rx(), icplus_refill_rx(), icplus_transmit(), ifec_net_transmit(), igbvf_refill_rx_ring(), igbvf_setup_rx_resources(), igbvf_transmit(), imux_in_complete(), imux_rx_tcp(), imux_tx(), imux_tx_tcp(), intel_refill_rx(), intel_transmit(), intelxl_refill_rx(), intelxl_transmit(), iob_concatenate(), iob_dma(), iob_empty(), iob_headroom(), iob_len(), iob_map(), iob_pad(), iob_populate(), iob_pull(), iob_push(), iob_reserve(), iob_split(), ipair_deliver(), iphone_in_complete(), ipoib_complete_recv(), ipoib_translate_rx_arp(), ipoib_translate_tx_arp(), ipoib_transmit(), ipv4_fragment_offset(), ipv4_is_fragment(), ipv4_more_fragments(), ipv4_pshdr_chksum(), ipv4_rx(), ipv6_fragment_offset(), ipv6_is_fragment(), ipv6_more_fragments(), ipv6_rx(), iscsi_socket_deliver(), iscsi_tx_login_request(), jme_fill_tx_desc(), jme_set_clean_rxdesc(), jme_tx_clean(), legacy_poll(), legacy_transmit(), linda_post_recv(), linda_post_send(), lldp_rx(), loopback_wait(), mnpnet_transmit(), myri10ge_net_transmit(), myri10ge_post_receive(), myson_refill_rx(), myson_transmit(), natsemi_refill_rx(), natsemi_transmit(), ncm_in_complete(), ncm_intr_complete(), ndp_rx_neighbour(), ndp_rx_router_advertisement(), ndp_tx_ll_addr(), neighbour_tx_queue(), net80211_accum_frags(), net80211_handle_assoc_reply(), net80211_handle_auth(), net80211_handle_mgmt(), net80211_ll_pull(), net80211_netdev_transmit(), net80211_prepare_assoc(), net80211_probe_step(), net80211_rx(), net80211_rx_frag(), net80211_send_assoc(), net80211_update_link_quality(), net_poll(), netdev_rx(), netdev_tx(), netfront_poll_rx(), netfront_refill_rx(), netfront_transmit(), netvsc_transmit(), nfs_get_read_reply(), nfs_get_readlink_reply(), nfs_iob_get_fh(), nii_transmit(), ntp_deliver(), oncrpc_iob_get_cred(), pcnet32_transmit(), peerblk_raw_rx(), peerblk_retrieval_rx(), peerdisc_socket_rx(), phantom_refill_rx_ring(), phantom_transmit(), ping_rx(), pinger_deliver(), pnic_poll(), pnic_transmit(), pxe_tftp_xfer_deliver(), pxenv_udp_read(), pxenv_undi_isr(), qib7322_post_recv(), qib7322_post_send(), rdc_refill_rx(), read(), realtek_refill_rx(), realtek_transmit(), rhine_refill_rx(), rhine_transmit(), rndis_rx(), rndis_rx_data(), rndis_rx_initialise(), rndis_rx_message(), rndis_rx_query_oid(), rndis_rx_set_oid(), rndis_rx_status(), rndis_tx_complete_err(), rndis_tx_defer(), rtl818x_handle_rx(), rtl818x_init_rx_ring(), rtl818x_tx(), sec80211_detect(), shomron_fill_eth_send_wqe(), sis190_alloc_rx_iob(), sis190_process_rx(), sis190_transmit(), skge_rx_setup(), skge_xmit_frame(), sky2_rx_map_iob(), sky2_xmit_frame(), slam_pull_header(), slam_pull_value(), slam_socket_deliver(), slirp_transmit(), smsc75xx_in_complete(), smsc95xx_in_complete(), smscusb_intr_complete(), snpnet_transmit(), srp_login(), srpdev_deliver(), stp_rx(), tap_poll(), tap_transmit(), tcp_process_rx_queue(), tcp_process_tx_queue(), tcp_rx(), tcp_rx_enqueue(), tcp_sack_block(), tcp_xmit_reset(), tcp_xmit_sack(), tftp_rx(), tftp_rx_data(), tkip_decrypt(), tkip_encrypt(), tls_cipherstream_deliver(), tls_hmac_list(), tls_new_alert(), tls_new_change_cipher(), tls_new_ciphertext(), tls_new_handshake(), tls_send_record(), tls_verify_padding(), txnic_refill_rq(), txnic_send(), udp_rx(), uhci_endpoint_message(), uhci_endpoint_stream(), uhci_enqueue(), undinet_transmit(), usb_control(), usb_message(), usbblk_in_complete(), usbio_bulk_in_poll(), usbio_bulk_out_poll(), usbio_control_poll(), usbio_interrupt_poll(), usbkbd_complete(), velocity_poll_rx(), velocity_transmit(), virtio_net_submit(), vlan_rx(), vmbus_send_data(), vmxnet3_refill_rx(), vmxnet3_transmit(), vxge_hw_fifo_txdl_buffer_set(), vxge_hw_ring_rxd_1b_set(), vxge_hw_vpath_poll_rx(), wep_decrypt(), wep_encrypt(), wpa_make_rsn_ie(), wpa_send_2_of_4(), wpa_send_eapol(), wpa_send_final(), wpa_start(), xcm_deliver(), xferbuf_deliver(), and xhci_endpoint_message().

◆ tail

◆ end

void* io_buffer::end

End of the buffer.

Definition at line 117 of file iobuf.h.

Referenced by alloc_iob_okx(), alloc_iob_raw(), free_iob(), iob_populate(), and iob_tailroom().


The documentation for this struct was generated from the following file: