Generic segmentation offload (GSO) is a SW technique to segment large packets into small ones. The packet types are various (e.g. TCP, UDP). Like TSO, GSO gains performance by reducing per-packet overhead for applications. Therefore, we propose to support GSO in DPDK.
DPDK GSO is designed as an application-used library. Applications directly use GSO API to perform GSO. There are two reasons to implement GSO as a standalone library. First, an application-used library enables flexibility to applications. Applications are able to perform own operations on GSO segments, like vxlan encapsulation. Note that we call the small packets that are GSOed from large packets as GSO segments. Second, applications can easily control GSO segments. Since applications are aware of the number of GSO segments that are transmitted, if not all GSO segments are sent successfully, applications can choose to resend these unsent segments or choose to drop them. But if we implement GSO in ethdev layer or inside each driver, it's hard to decide how to process these unsent GSO segments. Besides, the number of packets that are sent successfully may also confuse applications. This is because the number of packets after been GSOed may be quite larger than the number of packets that applications pass to rte_eth_tx_burst. Therefore, DPDK GSO is designed as a standalone library. To segment a packet is to divide the packet payload into small parts, and each paylaod part adds the packet header to form a GSO segment. Simply, we can copy each payload part and the packet header to form a GSO segment. But this simple way requires two memory copies to form a segment (i.e. copy header and copy payload part). For better performance, we should avoid unnecessary memory copies. But we can't avoid copying the packet header, since each GSO segment has own header values, like ipv4_hdr->total_length. In DPDK GSO, we avoid copying packet payload by using 2-segment mbuf to organize a GSO segment. A 2-segment mbuf is two chained mbuf. The first mbuf is a normal mbuf which stores packet header. The second mbuf is an indirect mbuf, which points to a packet payload part. With 2-segment mbuf, to perform GSO on a packet, which can be divided into three GSO segments, requires four steps: 1. Allocate three 2-segment mbufs. Each 2-segment mbuf is used to keep a GSO segment; 2. For each 2-segment mbuf, copy packet header to the first mbuf, and point the second mbuf to a corresponding packet payload part; 3. Update packet header for each 2-segment mbuf. For example, update packet length in IPv4 header; 4. The refcnt of each 2-segment mbuf reduces 1. As we can see, if GSO segments are successfully sent by NICs, the original packets will be freed automatically. If not all GSO segments are sent successfully, applications can choose to resent them or free their mbuf space. If these GSO segments are freed, the original packets will be freed too. DPDK GSO assumes all inputted packets have correct checksums. Besides, DPDK GSO won't re-calculate checksums for GSO segments. To support 2-segment mbuf, DPDK GSO demands TX functions to support multi-segment packets.