Skip to content

Support segmentation offload #1861

@cagatay-y

Description

@cagatay-y

VIRTIO has support for drivers to offload the segmentation of large packets to MTU sized frames to the device. This can help reduce the descriptor table pressure by reducing the number of buffers that need to be provided and also relieves the CPU of some work. There is some prior work in #834 related to this. The feature requires support from the smol-tcp side.

Notes

Some of the information below is not relevant for virtio-net but are here as they will be relevant for the changes that will be proposed for smoltcp.

  • There are separate send side segmentation features for each combination in {IPv4, IPv6} × {TCP, UDP} TCP with IPv4, TCP with IPv6, UDP with either (at least for virtio-net).
    • on Linux [7]
    • on Windows [8, 9]
      Furthermore, UDP packets can be segmented (where they are sent as unfragmented IPv4 packets each with their own UDP header) or fragmented (where they are sent as fragmented IPv4 packets of a single UDP packet). The latter seems to be deprecated for the Linux kernel [1].
  • For receive offloads, the structure is not symmetrical.
    • virtio separates UDP offload into one for IPv4 and one for IPv6 on the receive side [11 (VIRTIO_NET_F_GUEST_USO4 and VIRTIO_NET_F_GUEST_USO6 in the v1.3 draft].
    • Linux does not seem to separate even TCP and UDP on the receive side [12]. There is LRO and GRO, and they seem similar [15].
    • Windows distinguishes between TCP and UDP coalescing [13] and IPv4/IPv6 for TCP [14].
  • Different drivers may support different payload sizes to be segmented
    • virtio-net doesn't seem to specify the size for send but it is specified as 65536 (maximum TCP packet size) for receive offload [2 (section 5.1.6.3)].
    • At least some Mellanox cards seem to support payloads four times as large [3 (max_tso parameter)]. Mellanox Infiniband driver on the Linux kernel also references a max_tso parameter [6] and seems to be in the context of Ethernet networking.
    • One piece of Intel documentation specifies the maximum TCP payload size as 64,000 bytes [4] but it may be a case of 64 KiB accidentally turning into 64 KB. The same documentation specifies "64 K" (emphasis mine) as the limit for UDP segmentation [5].
    • Windows drivers support reporting the maximum offload size, which may be larger than 64K [10].

smoltcp to-do (incomplete, in no particular order)

  • Communicate gso_size (the size of the segments to be created by the device) information to the device (probably through PacketMeta)
  • Implement new Fragmenter that doesn't fragment IP packets
  • Figure out if smoltcp needs to know about the large receive offload (a.k.a. receive segment coalescing)
    Probably, on Windows some out-of-band information needs to be provided [16].
  • Deduplicate the segment size calculation in seq_to_transmit and dispatch (EDIT: seems to be unnecessary)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions