요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
====================================
Netfilter's flowtable infrastructure
====================================
This documentation describes the Netfilter flowtable infrastructure which allows
you to define a fastpath through the flowtable datapath. This infrastructure
also provides hardware offload support. The flowtable supports for the layer 3
IPv4 and IPv6 and the layer 4 TCP and UDP protocols.
Overview
--------
Once the first packet of the flow successfully goes through the IP forwarding
path, from the second packet on, you might decide to offload the flow to the
flowtable through your ruleset. The flowtable infrastructure provides a rule
action that allows you to specify when to add a flow to the flowtable.
A packet that finds a matching entry in the flowtable (ie. flowtable hit) is
transmitted to the output netdevice via neigh_xmit(), hence, packets bypass the
classic IP forwarding path (the visible effect is that you do not see these
packets from any of the Netfilter hooks coming after ingress). In case that
there is no matching entry in the flowtable (ie. flowtable miss), the packet
follows the classic IP forwarding path.
The flowtable uses a resizable hashtable. Lookups are based on the following
n-tuple selectors: layer 2 protocol encapsulation (VLAN and PPPoE), layer 3
source and destination, layer 4 source and destination ports and the input
interface (useful in case there are several conntrack zones in place).
The 'flow add' action allows you to populate the flowtable, the user selectively
specifies what flows are placed into the flowtable. Hence, packets follow the
classic IP forwarding path unless the user explicitly instruct flows to use this
new alternative forwarding path via policy.
The flowtable datapath is represented in Fig.1, which describes the classic IP
forwarding path including the Netfilter hooks and the flowtable fastpath bypass.
::
userspace process
^ |
| |
_____|____ ____\/___
/ \ / \
| input | | output |
\__________/ \_________/
^ |
| |
_________ __________ --------- _____\/_____
/ \ / \ |Routing | / \
--> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit
\_________/ \__________/ ---------- \____________/ ^
| ^ | ^ |
flowtable | ____\/___ | |
| | / \ | |
__\/___ | | forward |------------ |
|-----| | \_________/ |
|-----| | 'flow offload' rule |
|-----| | adds entry to |
|_____| | flowtable |
| | |
/ \ | |
/hit\_no_| |
\ ? / |
\ / |
|__yes_________________fastpath bypass ____________________________|
Fig.1 Netfilter hooks and flowtable interactions
The flowtable entry also stores the NAT configuration, so all packets are
mangled according to the NAT policy that is specified from the classic IP
forwarding path. The TTL is decremented before calling neigh_xmit(). Fragmented
traffic is passed up to follow the classic IP forwarding path given that the
transport header is missing, in this case, flowtable lookups are not possible.
TCP RST and FIN packets are also passed up to the classic IP forwarding path to
release the flow gracefully. Packets that exceed the MTU are also passed up to
the classic forwarding path to report packet-too-big ICMP errors to the sender.
Example configuration
---------------------
Enabling the flowtable bypass is relatively easy, you only need to create a
flowtable and add one rule to your forward chain::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
}
chain y {
type filter hook forward priority 0; policy accept;
ip protocol tcp flow add @f
counter packets 0 bytes 0
}
}
This example adds the flowtable 'f' to the ingress hook of the eth0 and eth1
netdevices. You can create as many flowtables as you want in case you need to
perform resource partitioning. The flowtable priority defines the order in which
hooks are run in the pipeline, this is convenient in case you already have a
nftables ingress chain (make sure the flowtable priority is smaller than the
nftables ingress chain hence the flowtable runs before in the pipeline).
The 'flow offload' action from the forward chain 'y' adds an entry to the
flowtable for the TCP syn-ack packet coming in the reply direction. Once the
flow is offloaded, you will observe that the counter rule in the example above
does not get updated for the packets that are being forwarded through the
forwarding bypass.
You can identify offloaded flows through the [OFFLOAD] tag when listing your
connection tracking table.
::
# conntrack -L
tcp 6 src=10.141.10.2 dst=192.168.10.2 sport=52728 dport=5201 src=192.168.10.2 dst=192.168.10.1 sport=5201 dport=52728 [OFFLOAD] mark=0 use=2
Layer 2 encapsulation
---------------------
Since Linux kernel 5.13, the flowtable infrastructure discovers the real
netdevice behind VLAN and PPPoE netdevices. The flowtable software datapath
parses the VLAN and PPPoE layer 2 headers to extract the ethertype and the
VLAN ID / PPPoE session ID which are used for the flowtable lookups. The
flowtable datapath also deals with layer 2 decapsulation.
You do not need to add the PPPoE and the VLAN devices to your flowtable,
instead the real device is sufficient for the flowtable to track your flows.
Bridge and IP forwarding
------------------------
Since Linux kernel 5.13, you can add bridge ports to the flowtable. The
flowtable infrastructure discovers the topology behind the bridge device. This
allows the flowtable to define a fastpath bypass between the bridge ports
(represented as eth1 and eth2 in the example figure below) and the gateway
device (represented as eth0) in your switch/router.
::
fastpath bypass
.-------------------------.
/ \
| IP forwarding |
| / \ \/
| br0 eth0 ..... eth0
. / \ *host B*
-> eth1 eth2
. *switch/router*
.
.
eth0
*host A*
The flowtable infrastructure also supports for bridge VLAN filtering actions
such as PVID and untagged. You can also stack a classic VLAN device on top of
your bridge port.
If you would like that your flowtable defines a fastpath between your bridge
ports and your IP forwarding path, you have to add your bridge ports (as
represented by the real netdevice) to your flowtable definition.
Counters
--------
The flowtable can synchronize packet and byte counters with the existing
connection tracking entry by specifying the counter statement in your flowtable
definition, e.g.
::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
counter
}
}
Counter support is available since Linux kernel 5.7.
Hardware offload
----------------
If your network device provides hardware offload support, you can turn it on by
means of the 'offload' flag in your flowtable definition, e.g.
::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
flags offload;
}
}
There is a workqueue that adds the flows to the hardware. Note that a few
packets might still run over the flowtable software path until the workqueue has
a chance to offload the flow to the network device.
You can identify hardware offloaded flows through the [HW_OFFLOAD] tag when
listing your connection tracking table. Please, note that the [OFFLOAD] tag
refers to the software offload mode, so there is a distinction between [OFFLOAD]
which refers to the software flowtable fastpath and [HW_OFFLOAD] which refers
to the hardware offload datapath being used by the flow.
The flowtable hardware offload infrastructure also supports for the DSA
(Distributed Switch Architecture).
Limitations
-----------
The flowtable behaves like a cache. The flowtable entries might get stale if
either the destination MAC address or the egress netdevice that is used for
transmission changes.
This might be a problem if:
- You run the flowtable in software mode and you combine bridge and IP
forwarding in your setup.
- Hardware offload is enabled.
More reading
------------
This documentation is based on the LWN.net articles [1]_\ [2]_. Rafal Milecki
also made a very complete and comprehensive summary called "A state of network
acceleration" that describes how things were before this infrastructure was
mainlined [3]_ and it also makes a rough summary of this work [4]_.
.. [1] https://lwn.net/Articles/738214/
.. [2] https://lwn.net/Articles/742164/
.. [3] http://lists.infradead.org/pipermail/lede-dev/2018-January/010830.html
.. [4] http://lists.infradead.org/pipermail/lede-dev/2018-January/010829.html
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Fastpath와 지원 protocol
1-12Netfilter flowtable은 별도의 datapath fastpath를 정의하고 hardware offload까지 지원합니다. Layer 3은 IPv4·IPv6, layer 4는 TCP·UDP flow를 처리합니다.
.. SPDX-License-Identifier: GPL-2.0
====================================
Netfilter's flowtable infrastructure
====================================
This documentation describes the Netfilter flowtable infrastructure which allows
you to define a fastpath through the flowtable datapath. This infrastructure
also provides hardware offload support. The flowtable supports for the layer 3
IPv4 and IPv6 and the layer 4 TCP and UDP protocols.
Overview
Hit, miss와 classic forwarding bypass
13-81Flow의 첫 packet이 일반 IP forwarding path를 성공적으로 지난 뒤 ruleset의 `flow add` action으로 flowtable에 넣을 수 있습니다. 사용자가 policy로 명시한 flow만 offload되며 그 밖의 packet은 계속 classic path를 따릅니다.
Flowtable hit packet은 `neigh_xmit()`으로 output netdevice에 바로 전송되어 ingress 뒤의 prerouting, forward, postrouting 같은 Netfilter hook을 우회합니다. Entry가 없는 miss packet은 classic IP forwarding path로 이동합니다.
Flowtable은 크기를 조절할 수 있는 hashtable을 사용합니다. Lookup selector는 VLAN·PPPoE layer 2 encapsulation, layer 3 source·destination, layer 4 source·destination port, 그리고 여러 conntrack zone을 구분하는 input interface로 구성된 n-tuple입니다.
Entry에는 classic forwarding path에서 정한 NAT 구성도 저장되어 모든 packet에 같은 NAT policy를 적용합니다. `neigh_xmit()` 전에는 TTL을 감소시킵니다. Fragment는 transport header가 없어 lookup할 수 없으므로 classic path로 보냅니다. TCP RST·FIN도 flow를 정상 종료하도록 classic path로 올리고, MTU를 넘는 packet도 sender에게 packet-too-big ICMP를 보고하도록 일반 경로를 사용합니다.
원문의 Netfilter hook ASCII 그림을 hit와 miss 경로로 재구성했습니다.
--------
Once the first packet of the flow successfully goes through the IP forwarding
path, from the second packet on, you might decide to offload the flow to the
flowtable through your ruleset. The flowtable infrastructure provides a rule
action that allows you to specify when to add a flow to the flowtable.
A packet that finds a matching entry in the flowtable (ie. flowtable hit) is
transmitted to the output netdevice via neigh_xmit(), hence, packets bypass the
classic IP forwarding path (the visible effect is that you do not see these
packets from any of the Netfilter hooks coming after ingress). In case that
there is no matching entry in the flowtable (ie. flowtable miss), the packet
follows the classic IP forwarding path.
The flowtable uses a resizable hashtable. Lookups are based on the following
n-tuple selectors: layer 2 protocol encapsulation (VLAN and PPPoE), layer 3
source and destination, layer 4 source and destination ports and the input
interface (useful in case there are several conntrack zones in place).
The 'flow add' action allows you to populate the flowtable, the user selectively
specifies what flows are placed into the flowtable. Hence, packets follow the
classic IP forwarding path unless the user explicitly instruct flows to use this
new alternative forwarding path via policy.
The flowtable datapath is represented in Fig.1, which describes the classic IP
forwarding path including the Netfilter hooks and the flowtable fastpath bypass.
::
userspace process
^ |
| |
_____|____ ____\/___
/ \ / \
| input | | output |
\__________/ \_________/
^ |
| |
_________ __________ --------- _____\/_____
/ \ / \ |Routing | / \
--> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit
\_________/ \__________/ ---------- \____________/ ^
| ^ | ^ |
flowtable | ____\/___ | |
| | / \ | |
__\/___ | | forward |------------ |
|-----| | \_________/ |
|-----| | 'flow offload' rule |
|-----| | adds entry to |
|_____| | flowtable |
| | |
/ \ | |
/hit\_no_| |
\ ? / |
\ / |
|__yes_________________fastpath bypass ____________________________|
Fig.1 Netfilter hooks and flowtable interactions
The flowtable entry also stores the NAT configuration, so all packets are
mangled according to the NAT policy that is specified from the classic IP
forwarding path. The TTL is decremented before calling neigh_xmit(). Fragmented
traffic is passed up to follow the classic IP forwarding path given that the
transport header is missing, in this case, flowtable lookups are not possible.
TCP RST and FIN packets are also passed up to the classic IP forwarding path to
release the flow gracefully. Packets that exceed the MTU are also passed up to
the classic forwarding path to report packet-too-big ICMP errors to the sender.
Example configuration
nftables 구성과 OFFLOAD 확인
82-120우회 경로를 켜려면 flowtable을 만들고 forward chain에 rule 하나를 추가합니다. 예제의 inet table `x`는 ingress priority 0인 flowtable `f`를 `eth0`, `eth1`에 붙이고, forward chain `y`에서 TCP packet에 `flow add @f`를 실행합니다.
Resource partitioning이 필요하면 flowtable을 여러 개 만들 수 있습니다. Priority는 pipeline에서 hook 실행 순서를 정합니다. 이미 nftables ingress chain이 있다면 flowtable priority를 더 작은 값으로 두어 먼저 실행되게 해야 합니다.
Forward chain의 offload action은 reply 방향 TCP SYN-ACK에서 entry를 추가합니다. 이후 우회되는 packet은 뒤의 counter rule을 지나지 않으므로 counter가 증가하지 않습니다. `conntrack -L` 출력의 `[OFFLOAD]` tag로 software flowtable에 올라간 flow를 확인할 수 있습니다.
---------------------
Enabling the flowtable bypass is relatively easy, you only need to create a
flowtable and add one rule to your forward chain::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
}
chain y {
type filter hook forward priority 0; policy accept;
ip protocol tcp flow add @f
counter packets 0 bytes 0
}
}
This example adds the flowtable 'f' to the ingress hook of the eth0 and eth1
netdevices. You can create as many flowtables as you want in case you need to
perform resource partitioning. The flowtable priority defines the order in which
hooks are run in the pipeline, this is convenient in case you already have a
nftables ingress chain (make sure the flowtable priority is smaller than the
nftables ingress chain hence the flowtable runs before in the pipeline).
The 'flow offload' action from the forward chain 'y' adds an entry to the
flowtable for the TCP syn-ack packet coming in the reply direction. Once the
flow is offloaded, you will observe that the counter rule in the example above
does not get updated for the packets that are being forwarded through the
forwarding bypass.
You can identify offloaded flows through the [OFFLOAD] tag when listing your
connection tracking table.
::
# conntrack -L
tcp 6 src=10.141.10.2 dst=192.168.10.2 sport=52728 dport=5201 src=192.168.10.2 dst=192.168.10.1 sport=5201 dport=52728 [OFFLOAD] mark=0 use=2
Layer 2 encapsulation
VLAN과 PPPoE encapsulation
121-132Linux 5.13부터 flowtable은 VLAN과 PPPoE netdevice 뒤의 실제 netdevice를 찾습니다. Software datapath가 layer 2 header를 해석하여 lookup용 ethertype와 VLAN ID 또는 PPPoE session ID를 추출하고 decapsulation도 처리합니다. Flowtable에는 VLAN·PPPoE 장치 자체를 추가할 필요 없이 실제 장치만 넣으면 됩니다.
---------------------
Since Linux kernel 5.13, the flowtable infrastructure discovers the real
netdevice behind VLAN and PPPoE netdevices. The flowtable software datapath
parses the VLAN and PPPoE layer 2 headers to extract the ethertype and the
VLAN ID / PPPoE session ID which are used for the flowtable lookups. The
flowtable datapath also deals with layer 2 decapsulation.
You do not need to add the PPPoE and the VLAN devices to your flowtable,
instead the real device is sufficient for the flowtable to track your flows.
Bridge and IP forwarding
Bridge와 IP forwarding fastpath
133-165Linux 5.13부터 bridge port를 flowtable에 추가할 수 있고 infrastructure가 bridge 뒤 topology를 탐색합니다. 문서 예제에서는 host A가 붙은 `eth1`·`eth2` bridge port와 gateway `eth0` 사이에 switch/router 내부 fastpath가 생깁니다.
Bridge VLAN filtering의 PVID와 untagged action도 지원하며 bridge port 위에 일반 VLAN device를 쌓을 수도 있습니다. Bridge port와 IP forwarding path 사이의 fastpath를 원한다면 flowtable 정의에 bridge 장치가 아니라 실제 netdevice로 표현된 port를 추가해야 합니다.
원문의 네트워크 ASCII 그림을 실제 장치 관계로 옮겼습니다.
------------------------
Since Linux kernel 5.13, you can add bridge ports to the flowtable. The
flowtable infrastructure discovers the topology behind the bridge device. This
allows the flowtable to define a fastpath bypass between the bridge ports
(represented as eth1 and eth2 in the example figure below) and the gateway
device (represented as eth0) in your switch/router.
::
fastpath bypass
.-------------------------.
/ \
| IP forwarding |
| / \ \/
| br0 eth0 ..... eth0
. / \ *host B*
-> eth1 eth2
. *switch/router*
.
.
eth0
*host A*
The flowtable infrastructure also supports for bridge VLAN filtering actions
such as PVID and untagged. You can also stack a classic VLAN device on top of
your bridge port.
If you would like that your flowtable defines a fastpath between your bridge
ports and your IP forwarding path, you have to add your bridge ports (as
represented by the real netdevice) to your flowtable definition.
Counters
Conntrack counter 동기화
166-183Flowtable 정의에 `counter` statement를 넣으면 packet·byte counter를 기존 conntrack entry와 동기화할 수 있습니다. Counter 지원은 Linux 5.7부터 제공됩니다.
--------
The flowtable can synchronize packet and byte counters with the existing
connection tracking entry by specifying the counter statement in your flowtable
definition, e.g.
::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
counter
}
}
Counter support is available since Linux kernel 5.7.
Hardware offload
Hardware offload
184-211장치가 hardware offload를 지원하면 flowtable 정의에 `flags offload`를 넣어 활성화합니다. Workqueue가 flow를 hardware에 추가하므로 작업이 실행되기 전 몇 packet은 software flowtable path로 갈 수 있습니다.
Conntrack 목록의 `[HW_OFFLOAD]` tag는 실제 hardware datapath를 뜻합니다. `[OFFLOAD]`는 software flowtable fastpath이므로 둘을 구분해야 합니다. Hardware offload infrastructure는 DSA도 지원합니다.
conntrack 목록에서 보이는 두 가속 경로입니다.
----------------
If your network device provides hardware offload support, you can turn it on by
means of the 'offload' flag in your flowtable definition, e.g.
::
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
flags offload;
}
}
There is a workqueue that adds the flows to the hardware. Note that a few
packets might still run over the flowtable software path until the workqueue has
a chance to offload the flow to the network device.
You can identify hardware offloaded flows through the [HW_OFFLOAD] tag when
listing your connection tracking table. Please, note that the [OFFLOAD] tag
refers to the software offload mode, so there is a distinction between [OFFLOAD]
which refers to the software flowtable fastpath and [HW_OFFLOAD] which refers
to the hardware offload datapath being used by the flow.
The flowtable hardware offload infrastructure also supports for the DSA
(Distributed Switch Architecture).
Limitations
Cache stale 문제
212-224Flowtable은 cache처럼 동작하므로 송신에 사용하는 destination MAC 또는 egress netdevice가 바뀌면 entry가 stale해질 수 있습니다. Software mode에서 bridge와 IP forwarding을 결합한 구성, 또는 hardware offload를 켠 구성에서 특히 문제가 될 수 있습니다.
-----------
The flowtable behaves like a cache. The flowtable entries might get stale if
either the destination MAC address or the egress netdevice that is used for
transmission changes.
This might be a problem if:
- You run the flowtable in software mode and you combine bridge and IP
forwarding in your setup.
- Hardware offload is enabled.
More reading
추가 자료
225-235이 문서는 두 LWN.net 글을 바탕으로 합니다. Rafal Milecki의 'A state of network acceleration' 요약은 infrastructure가 mainline에 들어오기 전의 상태와 이 작업의 개요를 함께 설명합니다. 원문 끝의 네 URL을 참고 자료로 보존합니다.
------------
This documentation is based on the LWN.net articles [1]_\ [2]_. Rafal Milecki
also made a very complete and comprehensive summary called "A state of network
acceleration" that describes how things were before this infrastructure was
mainlined [3]_ and it also makes a rough summary of this work [4]_.
.. [1] https://lwn.net/Articles/738214/
.. [2] https://lwn.net/Articles/742164/
.. [3] http://lists.infradead.org/pipermail/lede-dev/2018-January/010830.html
.. [4] http://lists.infradead.org/pipermail/lede-dev/2018-January/010829.html
요약·해설
nf_flowtable.rst:1-235첫 packet으로 conntrack·NAT 상태를 만든 뒤 선택한 flow의 후속 packet을 ingress lookup에서 output device로 직접 보내며 예외 packet은 classic path로 돌려보냅니다.
Hit와 miss의 분기입니다.