요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
=====================
Segmentation Offloads
=====================
Introduction
============
This document describes a set of techniques in the Linux networking stack
to take advantage of segmentation offload capabilities of various NICs.
The following technologies are described:
* TCP Segmentation Offload - TSO
* UDP Fragmentation Offload - UFO
* IPIP, SIT, GRE, and UDP Tunnel Offloads
* Generic Segmentation Offload - GSO
* Generic Receive Offload - GRO
* Partial Generic Segmentation Offload - GSO_PARTIAL
* SCTP acceleration with GSO - GSO_BY_FRAGS
TCP Segmentation Offload
========================
TCP segmentation allows a device to segment a single frame into multiple
frames with a data payload size specified in skb_shinfo()->gso_size.
When TCP segmentation requested the bit for either SKB_GSO_TCPV4 or
SKB_GSO_TCPV6 should be set in skb_shinfo()->gso_type and
skb_shinfo()->gso_size should be set to a non-zero value.
TCP segmentation is dependent on support for the use of partial checksum
offload. For this reason TSO is normally disabled if the Tx checksum
offload for a given device is disabled.
In order to support TCP segmentation offload it is necessary to populate
the network and transport header offsets of the skbuff so that the device
drivers will be able determine the offsets of the IP or IPv6 header and the
TCP header. In addition as CHECKSUM_PARTIAL is required csum_start should
also point to the TCP header of the packet.
For IPv4 segmentation we support one of two types in terms of the IP ID.
The default behavior is to increment the IP ID with every segment. If the
GSO type SKB_GSO_TCP_FIXEDID is specified then we will not increment the IP
ID and all segments will use the same IP ID.
For encapsulated packets, SKB_GSO_TCP_FIXEDID refers only to the outer header.
SKB_GSO_TCP_FIXEDID_INNER can be used to specify the same for the inner header.
Any combination of these two GSO types is allowed.
If a device has NETIF_F_TSO_MANGLEID set then the IP ID can be ignored when
performing TSO and we will either increment the IP ID for all frames, or leave
it at a static value based on driver preference. For encapsulated packets,
NETIF_F_TSO_MANGLEID is relevant for both outer and inner headers, unless the
DF bit is not set on the outer header, in which case the device driver must
guarantee that the IP ID field is incremented in the outer header with every
segment.
UDP Fragmentation Offload
=========================
UDP fragmentation offload allows a device to fragment an oversized UDP
datagram into multiple IPv4 fragments. Many of the requirements for UDP
fragmentation offload are the same as TSO. However the IPv4 ID for
fragments should not increment as a single IPv4 datagram is fragmented.
UFO is deprecated: modern kernels will no longer generate UFO skbs, but can
still receive them from tuntap and similar devices. Offload of UDP-based
tunnel protocols is still supported.
IPIP, SIT, GRE, UDP Tunnel, and Remote Checksum Offloads
========================================================
In addition to the offloads described above it is possible for a frame to
contain additional headers such as an outer tunnel. In order to account
for such instances an additional set of segmentation offload types were
introduced including SKB_GSO_IPXIP4, SKB_GSO_IPXIP6, SKB_GSO_GRE, and
SKB_GSO_UDP_TUNNEL. These extra segmentation types are used to identify
cases where there are more than just 1 set of headers. For example in the
case of IPIP and SIT we should have the network and transport headers moved
from the standard list of headers to "inner" header offsets.
Currently only two levels of headers are supported. The convention is to
refer to the tunnel headers as the outer headers, while the encapsulated
data is normally referred to as the inner headers. Below is the list of
calls to access the given headers:
IPIP/SIT Tunnel::
Outer Inner
MAC skb_mac_header
Network skb_network_header skb_inner_network_header
Transport skb_transport_header
UDP/GRE Tunnel::
Outer Inner
MAC skb_mac_header skb_inner_mac_header
Network skb_network_header skb_inner_network_header
Transport skb_transport_header skb_inner_transport_header
In addition to the above tunnel types there are also SKB_GSO_GRE_CSUM and
SKB_GSO_UDP_TUNNEL_CSUM. These two additional tunnel types reflect the
fact that the outer header also requests to have a non-zero checksum
included in the outer header.
Finally there is SKB_GSO_TUNNEL_REMCSUM which indicates that a given tunnel
header has requested a remote checksum offload. In this case the inner
headers will be left with a partial checksum and only the outer header
checksum will be computed.
Generic Segmentation Offload
============================
Generic segmentation offload is a pure software offload that is meant to
deal with cases where device drivers cannot perform the offloads described
above. What occurs in GSO is that a given skbuff will have its data broken
out over multiple skbuffs that have been resized to match the MSS provided
via skb_shinfo()->gso_size.
Before enabling any hardware segmentation offload a corresponding software
offload is required in GSO. Otherwise it becomes possible for a frame to
be re-routed between devices and end up being unable to be transmitted.
Generic Receive Offload
=======================
Generic receive offload is the complement to GSO. Ideally any frame
assembled by GRO should be segmented to create an identical sequence of
frames using GSO, and any sequence of frames segmented by GSO should be
able to be reassembled back to the original by GRO.
Partial Generic Segmentation Offload
====================================
Partial generic segmentation offload is a hybrid between TSO and GSO. What
it effectively does is take advantage of certain traits of TCP and tunnels
so that instead of having to rewrite the packet headers for each segment
only the inner-most transport header and possibly the outer-most network
header need to be updated. This allows devices that do not support tunnel
offloads or tunnel offloads with checksum to still make use of segmentation.
With the partial offload what occurs is that all headers excluding the
inner transport header are updated such that they will contain the correct
values for if the header was simply duplicated. The one exception to this
is the outer IPv4 ID field. It is up to the device drivers to guarantee
that the IPv4 ID field is incremented in the case that a given header does
not have the DF bit set.
SCTP acceleration with GSO
===========================
SCTP - despite the lack of hardware support - can still take advantage of
GSO to pass one large packet through the network stack, rather than
multiple small packets.
This requires a different approach to other offloads, as SCTP packets
cannot be just segmented to (P)MTU. Rather, the chunks must be contained in
IP segments, padding respected. So unlike regular GSO, SCTP can't just
generate a big skb, set gso_size to the fragmentation point and deliver it
to IP layer.
Instead, the SCTP protocol layer builds an skb with the segments correctly
padded and stored as chained skbs, and skb_segment() splits based on those.
To signal this, gso_size is set to the special value GSO_BY_FRAGS.
Therefore, any code in the core networking stack must be aware of the
possibility that gso_size will be GSO_BY_FRAGS and handle that case
appropriately.
There are some helpers to make this easier:
- skb_is_gso(skb) && skb_is_gso_sctp(skb) is the best way to see if
an skb is an SCTP GSO skb.
- For size checks, the skb_gso_validate_*_len family of helpers correctly
considers GSO_BY_FRAGS.
- For manipulating packets, skb_increase_gso_size and skb_decrease_gso_size
will check for GSO_BY_FRAGS and WARN if asked to manipulate these skbs.
This also affects drivers with the NETIF_F_FRAGLIST & NETIF_F_GSO_SCTP bits
set. Note also that NETIF_F_GSO_SCTP is included in NETIF_F_GSO_SOFTWARE.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
분할 offload 기술의 범위
1-21이 문서는 다양한 NIC의 segmentation offload 기능을 Linux 네트워킹 스택에서 사용하는 방법을 설명합니다. 범위는 TCP Segmentation Offload(TSO), UDP Fragmentation Offload(UFO), IPIP·SIT·GRE·UDP tunnel offload, software GSO, GRO, GSO_PARTIAL, SCTP용 GSO_BY_FRAGS입니다.
송신 분할, 수신 결합과 tunnel·SCTP 예외를 구분합니다.
.. SPDX-License-Identifier: GPL-2.0
=====================
Segmentation Offloads
=====================
Introduction
============
This document describes a set of techniques in the Linux networking stack
to take advantage of segmentation offload capabilities of various NICs.
The following technologies are described:
* TCP Segmentation Offload - TSO
* UDP Fragmentation Offload - UFO
* IPIP, SIT, GRE, and UDP Tunnel Offloads
* Generic Segmentation Offload - GSO
* Generic Receive Offload - GRO
* Partial Generic Segmentation Offload - GSO_PARTIAL
* SCTP acceleration with GSO - GSO_BY_FRAGS
TCP Segmentation Offload
22-59TSO는 하나의 frame을 `skb_shinfo()->gso_size`에 지정한 payload 크기의 여러 frame으로 NIC가 나누게 합니다. IPv4 또는 IPv6 TCP 분할을 요청할 때 `skb_shinfo()->gso_type`에 `SKB_GSO_TCPV4` 또는 `SKB_GSO_TCPV6` bit를 설정하고 `gso_size`를 0이 아닌 값으로 둡니다.
TCP segmentation은 partial checksum offload에 의존하므로 장치의 Tx checksum offload를 끄면 TSO도 보통 꺼집니다. 드라이버가 IP/IPv6와 TCP header offset을 찾을 수 있도록 skbuff의 network header와 transport header offset을 채워야 하며, `CHECKSUM_PARTIAL`을 위해 `csum_start`도 TCP header를 가리켜야 합니다.
IPv4 기본 동작은 segment마다 IP ID를 증가시키는 것입니다. `SKB_GSO_TCP_FIXEDID`를 지정하면 모든 segment가 같은 outer IP ID를 사용합니다. encapsulated packet에서 inner header에도 같은 정책을 적용하려면 `SKB_GSO_TCP_FIXEDID_INNER`를 사용하며 두 type을 함께 설정할 수 있습니다.
장치에 `NETIF_F_TSO_MANGLEID`가 있으면 TSO 중 IP ID를 무시하고 드라이버 선택에 따라 모든 frame에서 증가시키거나 고정할 수 있습니다. encapsulated packet에서는 outer와 inner 모두에 적용됩니다. 다만 outer header의 DF bit가 꺼져 있으면 드라이버는 매 segment마다 outer IPv4 ID를 증가시켜야 합니다.
큰 TCP skb가 NIC에서 올바른 segment로 나뉘기 위한 metadata입니다.
TCP Segmentation Offload
========================
TCP segmentation allows a device to segment a single frame into multiple
frames with a data payload size specified in skb_shinfo()->gso_size.
When TCP segmentation requested the bit for either SKB_GSO_TCPV4 or
SKB_GSO_TCPV6 should be set in skb_shinfo()->gso_type and
skb_shinfo()->gso_size should be set to a non-zero value.
TCP segmentation is dependent on support for the use of partial checksum
offload. For this reason TSO is normally disabled if the Tx checksum
offload for a given device is disabled.
In order to support TCP segmentation offload it is necessary to populate
the network and transport header offsets of the skbuff so that the device
drivers will be able determine the offsets of the IP or IPv6 header and the
TCP header. In addition as CHECKSUM_PARTIAL is required csum_start should
also point to the TCP header of the packet.
For IPv4 segmentation we support one of two types in terms of the IP ID.
The default behavior is to increment the IP ID with every segment. If the
GSO type SKB_GSO_TCP_FIXEDID is specified then we will not increment the IP
ID and all segments will use the same IP ID.
For encapsulated packets, SKB_GSO_TCP_FIXEDID refers only to the outer header.
SKB_GSO_TCP_FIXEDID_INNER can be used to specify the same for the inner header.
Any combination of these two GSO types is allowed.
If a device has NETIF_F_TSO_MANGLEID set then the IP ID can be ignored when
performing TSO and we will either increment the IP ID for all frames, or leave
it at a static value based on driver preference. For encapsulated packets,
NETIF_F_TSO_MANGLEID is relevant for both outer and inner headers, unless the
DF bit is not set on the outer header, in which case the device driver must
guarantee that the IP ID field is incremented in the outer header with every
segment.
UDP Fragmentation Offload
60-73UFO는 oversized UDP datagram을 여러 IPv4 fragment로 장치가 나누게 합니다. 요구 조건 대부분은 TSO와 같지만 한 IPv4 datagram을 fragment로 나누는 것이므로 fragment마다 IPv4 ID를 증가시키면 안 됩니다.
UFO는 deprecated입니다. 현대 kernel은 새 UFO skb를 만들지 않지만 tuntap 같은 장치에서 받은 UFO skb는 계속 처리할 수 있습니다. UDP 기반 tunnel protocol의 offload는 여전히 지원됩니다.
UDP Fragmentation Offload
=========================
UDP fragmentation offload allows a device to fragment an oversized UDP
datagram into multiple IPv4 fragments. Many of the requirements for UDP
fragmentation offload are the same as TSO. However the IPv4 ID for
fragments should not increment as a single IPv4 datagram is fragmented.
UFO is deprecated: modern kernels will no longer generate UFO skbs, but can
still receive them from tuntap and similar devices. Offload of UDP-based
tunnel protocols is still supported.
Tunnel과 remote checksum offload
74-121frame에 outer tunnel header가 추가된 경우를 나타내기 위해 `SKB_GSO_IPXIP4`, `SKB_GSO_IPXIP6`, `SKB_GSO_GRE`, `SKB_GSO_UDP_TUNNEL` type을 사용합니다. IPIP와 SIT에서는 일반 header 위치에 있던 network·transport 의미를 inner header offset으로 옮겨 해석합니다.
현재 지원하는 header 계층은 outer tunnel과 encapsulated inner data의 두 단계입니다. IPIP/SIT에서 outer MAC은 `skb_mac_header`, outer network는 `skb_network_header`, outer transport는 `skb_transport_header`입니다. inner network는 `skb_inner_network_header`이고 별도 inner MAC·transport accessor는 표에서 사용하지 않습니다.
UDP/GRE tunnel에서는 outer MAC/network/transport가 각각 `skb_mac_header`, `skb_network_header`, `skb_transport_header`이고 inner MAC/network/transport는 `skb_inner_mac_header`, `skb_inner_network_header`, `skb_inner_transport_header`입니다.
`SKB_GSO_GRE_CSUM`과 `SKB_GSO_UDP_TUNNEL_CSUM`은 outer header에도 0이 아닌 checksum을 넣어야 함을 뜻합니다. `SKB_GSO_TUNNEL_REMCSUM`은 remote checksum offload 요청입니다. 이 경우 inner header는 partial checksum 상태로 남기고 outer header checksum만 계산합니다.
outer와 inner 두 header 계층을 접근하는 함수입니다.
IPIP, SIT, GRE, UDP Tunnel, and Remote Checksum Offloads
========================================================
In addition to the offloads described above it is possible for a frame to
contain additional headers such as an outer tunnel. In order to account
for such instances an additional set of segmentation offload types were
introduced including SKB_GSO_IPXIP4, SKB_GSO_IPXIP6, SKB_GSO_GRE, and
SKB_GSO_UDP_TUNNEL. These extra segmentation types are used to identify
cases where there are more than just 1 set of headers. For example in the
case of IPIP and SIT we should have the network and transport headers moved
from the standard list of headers to "inner" header offsets.
Currently only two levels of headers are supported. The convention is to
refer to the tunnel headers as the outer headers, while the encapsulated
data is normally referred to as the inner headers. Below is the list of
calls to access the given headers:
IPIP/SIT Tunnel::
Outer Inner
MAC skb_mac_header
Network skb_network_header skb_inner_network_header
Transport skb_transport_header
UDP/GRE Tunnel::
Outer Inner
MAC skb_mac_header skb_inner_mac_header
Network skb_network_header skb_inner_network_header
Transport skb_transport_header skb_inner_transport_header
In addition to the above tunnel types there are also SKB_GSO_GRE_CSUM and
SKB_GSO_UDP_TUNNEL_CSUM. These two additional tunnel types reflect the
fact that the outer header also requests to have a non-zero checksum
included in the outer header.
Finally there is SKB_GSO_TUNNEL_REMCSUM which indicates that a given tunnel
header has requested a remote checksum offload. In this case the inner
headers will be left with a partial checksum and only the outer header
checksum will be computed.
Generic Segmentation Offload
============================
Generic segmentation offload is a pure software offload that is meant to
deal with cases where device drivers cannot perform the offloads described
above. What occurs in GSO is that a given skbuff will have its data broken
Generic Segmentation Offload
122-139GSO는 장치 드라이버가 하드웨어 offload를 수행할 수 없을 때 사용하는 순수 software offload입니다. 하나의 skbuff 데이터를 여러 skbuff로 나누고 각 크기를 `skb_shinfo()->gso_size`가 제공한 MSS에 맞춥니다.
하드웨어 segmentation offload를 활성화하려면 먼저 대응하는 software GSO 구현이 있어야 합니다. 그렇지 않으면 큰 frame이 offload를 지원하지 않는 다른 장치로 reroute됐을 때 송신할 수 없게 됩니다.
out over multiple skbuffs that have been resized to match the MSS provided
via skb_shinfo()->gso_size.
Before enabling any hardware segmentation offload a corresponding software
offload is required in GSO. Otherwise it becomes possible for a frame to
be re-routed between devices and end up being unable to be transmitted.
Generic Receive Offload
=======================
Generic receive offload is the complement to GSO. Ideally any frame
assembled by GRO should be segmented to create an identical sequence of
frames using GSO, and any sequence of frames segmented by GSO should be
able to be reassembled back to the original by GRO.
Partial Generic Segmentation Offload
Generic Receive Offload
140-149GRO는 GSO의 반대 동작입니다. 이상적으로 GRO가 합친 frame은 GSO로 분할했을 때 원래와 동일한 frame sequence를 만들어야 하고, GSO가 나눈 sequence는 GRO가 원본으로 다시 조립할 수 있어야 합니다.
분할과 결합은 서로 역연산에 가까운 결과를 내야 합니다.
====================================
Partial generic segmentation offload is a hybrid between TSO and GSO. What
it effectively does is take advantage of certain traits of TCP and tunnels
so that instead of having to rewrite the packet headers for each segment
only the inner-most transport header and possibly the outer-most network
header need to be updated. This allows devices that do not support tunnel
offloads or tunnel offloads with checksum to still make use of segmentation.
With the partial offload what occurs is that all headers excluding the
Partial GSO
150-169GSO_PARTIAL은 TSO와 GSO의 혼합입니다. TCP와 tunnel의 특성을 이용해 segment마다 모든 header를 다시 쓰지 않고 가장 안쪽 transport header와 경우에 따라 가장 바깥 network header만 갱신합니다. 따라서 tunnel offload나 checksum 포함 tunnel offload를 직접 지원하지 않는 장치도 segmentation을 활용할 수 있습니다.
inner transport header를 제외한 header들은 단순 복제했을 때 올바른 값이 되도록 미리 갱신합니다. 예외는 outer IPv4 ID입니다. 해당 header의 DF bit가 꺼져 있으면 장치 드라이버가 IPv4 ID를 segment마다 증가시켜야 합니다.
inner transport header are updated such that they will contain the correct
values for if the header was simply duplicated. The one exception to this
is the outer IPv4 ID field. It is up to the device drivers to guarantee
that the IPv4 ID field is incremented in the case that a given header does
not have the DF bit set.
SCTP acceleration with GSO
===========================
SCTP - despite the lack of hardware support - can still take advantage of
GSO to pass one large packet through the network stack, rather than
multiple small packets.
This requires a different approach to other offloads, as SCTP packets
cannot be just segmented to (P)MTU. Rather, the chunks must be contained in
IP segments, padding respected. So unlike regular GSO, SCTP can't just
generate a big skb, set gso_size to the fragmentation point and deliver it
to IP layer.
SCTP의 GSO_BY_FRAGS
170-190SCTP는 전용 하드웨어 지원이 없어도 GSO를 이용해 여러 작은 packet 대신 하나의 큰 packet을 네트워크 스택에 통과시킬 수 있습니다. 그러나 SCTP chunk는 padding을 지킨 채 IP segment 안에 들어가야 하므로 일반 GSO처럼 큰 skb 하나와 PMTU 기준 `gso_size`만 지정할 수 없습니다.
SCTP 계층은 올바르게 padding한 segment를 chained skb로 저장하고 `skb_segment()`가 그 경계를 따라 나눕니다. 이를 표시하려고 `gso_size`에 특수 값 `GSO_BY_FRAGS`를 넣습니다. core networking code는 `gso_size`가 일반 숫자가 아니라 이 값일 가능성을 처리해야 합니다.
SCTP GSO 여부는 `skb_is_gso(skb) && skb_is_gso_sctp(skb)`로 검사하는 것이 가장 좋습니다. 길이 검사는 `skb_gso_validate_*_len` helper가 `GSO_BY_FRAGS`를 올바르게 고려합니다. `skb_increase_gso_size`와 `skb_decrease_gso_size`는 이 skb의 크기 조작을 요청하면 검사 후 WARN합니다.
이 규칙은 `NETIF_F_FRAGLIST`와 `NETIF_F_GSO_SCTP` bit를 가진 드라이버에도 영향을 줍니다. `NETIF_F_GSO_SCTP`는 `NETIF_F_GSO_SOFTWARE`에 포함됩니다.
protocol layer가 chunk와 padding 경계를 만든 뒤 skb_segment가 그 경계를 사용합니다.
Instead, the SCTP protocol layer builds an skb with the segments correctly
padded and stored as chained skbs, and skb_segment() splits based on those.
To signal this, gso_size is set to the special value GSO_BY_FRAGS.
Therefore, any code in the core networking stack must be aware of the
possibility that gso_size will be GSO_BY_FRAGS and handle that case
appropriately.
There are some helpers to make this easier:
- skb_is_gso(skb) && skb_is_gso_sctp(skb) is the best way to see if
an skb is an SCTP GSO skb.
- For size checks, the skb_gso_validate_*_len family of helpers correctly
considers GSO_BY_FRAGS.
- For manipulating packets, skb_increase_gso_size and skb_decrease_gso_size
will check for GSO_BY_FRAGS and WARN if asked to manipulate these skbs.
This also affects drivers with the NETIF_F_FRAGLIST & NETIF_F_GSO_SCTP bits
set. Note also that NETIF_F_GSO_SCTP is included in NETIF_F_GSO_SOFTWARE.
요약·해설
segmentation-offloads.rst:1-190TSO, UFO, tunnel offload, GSO, GRO, GSO_PARTIAL과 SCTP GSO_BY_FRAGS를 설명합니다.