Netfilter 的 flowtable 基础设施¶
本文档描述了 Netfilter flowtable 基础设施,它允许您通过 flowtable 数据路径定义快速通道。此基础设施还提供硬件卸载支持。flowtable 支持第 3 层 IPv4 和 IPv6 以及第 4 层 TCP 和 UDP 协议。
概述¶
一旦流的第一个数据包成功通过 IP 转发路径,从第二个数据包开始,您可以决定通过您的规则集将该流卸载到 flowtable。 flowtable 基础设施提供了一个规则操作,允许您指定何时将流添加到 flowtable。
在 flowtable 中找到匹配条目的数据包(即 flowtable 命中)通过 neigh_xmit() 传输到输出网络设备,因此,数据包绕过传统的 IP 转发路径(可见的效果是您无法在入口后出现的任何 Netfilter 钩子中看到这些数据包)。 如果 flowtable 中没有匹配的条目(即 flowtable 未命中),则数据包遵循传统的 IP 转发路径。
flowtable 使用可调整大小的哈希表。 查找基于以下 n 元组选择器:第 2 层协议封装(VLAN 和 PPPoE)、第 3 层源和目标、第 4 层源和目标端口以及输入接口(如果存在多个 conntrack 区域,则很有用)。
“flow add”操作允许您填充 flowtable,用户有选择地指定哪些流被放入 flowtable。 因此,除非用户明确指示流通过策略使用这种新的替代转发路径,否则数据包将遵循传统的 IP 转发路径。
flowtable 数据路径在图 1 中表示,该图描述了经典的 IP 转发路径,包括 Netfilter 钩子和 flowtable 快速通道绕过。
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
flowtable 条目还存储 NAT 配置,因此所有数据包都根据从经典 IP 转发路径指定的 NAT 策略进行处理。 TTL 在调用 neigh_xmit() 之前递减。 由于缺少传输标头,碎片化的流量会传递到经典的 IP 转发路径,在这种情况下,无法进行 flowtable 查找。 TCP RST 和 FIN 数据包也会传递到经典的 IP 转发路径,以便优雅地释放流。 超过 MTU 的数据包也会传递到经典的转发路径,以便向发送者报告数据包过大 ICMP 错误。
示例配置¶
启用 flowtable 绕过相对容易,您只需要创建一个 flowtable 并在您的转发链中添加一个规则
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
}
}
此示例将 flowtable “f” 添加到 eth0 和 eth1 网络设备的入口钩子。 如果您需要执行资源分区,您可以根据需要创建任意数量的 flowtable。 flowtable 优先级定义了钩子在管道中运行的顺序,如果您已经有一个 nftables 入口链,这将非常方便(确保 flowtable 优先级小于 nftables 入口链,因此 flowtable 在管道中先运行)。
转发链 “y” 中的 “flow offload” 操作会将一个条目添加到 flowtable,用于来自回复方向的 TCP syn-ack 数据包。 一旦流被卸载,您将观察到,对于通过转发绕过转发的数据包,上述示例中的计数器规则不会被更新。
当列出您的连接跟踪表时,您可以通过 [OFFLOAD] 标签来识别卸载的流。
# 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
第 2 层封装¶
自从 Linux 内核 5.13 以来,flowtable 基础设施发现了 VLAN 和 PPPoE 网络设备背后的真实网络设备。 flowtable 软件数据路径解析 VLAN 和 PPPoE 第 2 层标头以提取以太网类型和 VLAN ID / PPPoE 会话 ID,这些信息用于 flowtable 查找。 flowtable 数据路径还处理第 2 层解封装。
您不需要将 PPPoE 和 VLAN 设备添加到您的 flowtable,相反,真实设备足以让 flowtable 跟踪您的流。
桥接和 IP 转发¶
自从 Linux 内核 5.13 以来,您可以将桥接端口添加到 flowtable。 flowtable 基础设施发现了桥接设备背后的拓扑结构。 这允许 flowtable 在您的交换机/路由器中的桥接端口(在下面的示例图中表示为 eth1 和 eth2)和网关设备(表示为 eth0)之间定义一个快速通道绕过。
fastpath bypass
.-------------------------.
/ \
| IP forwarding |
| / \ \/
| br0 eth0 ..... eth0
. / \ *host B*
-> eth1 eth2
. *switch/router*
.
.
eth0
*host A*
flowtable 基础设施还支持桥接 VLAN 过滤操作,例如 PVID 和 untagged。 您还可以在桥接端口之上堆叠一个经典的 VLAN 设备。
如果您希望您的 flowtable 在桥接端口和 IP 转发路径之间定义一个快速通道,您必须将您的桥接端口(由真实网络设备表示)添加到您的 flowtable 定义中。
计数器¶
flowtable 可以通过在您的 flowtable 定义中指定计数器语句来与现有的连接跟踪条目同步数据包和字节计数器,例如
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
counter
}
}
自从 Linux 内核 5.7 以来,计数器支持可用。
硬件卸载¶
如果您的网络设备提供硬件卸载支持,您可以通过在您的 flowtable 定义中使用 “offload” 标志来启用它,例如
table inet x {
flowtable f {
hook ingress priority 0; devices = { eth0, eth1 };
flags offload;
}
}
有一个工作队列将流添加到硬件。 请注意,在工作队列有机会将流卸载到网络设备之前,一些数据包可能仍然在 flowtable 软件路径上运行。
当列出您的连接跟踪表时,您可以通过 [HW_OFFLOAD] 标签来识别硬件卸载的流。 请注意,[OFFLOAD] 标签是指软件卸载模式,因此 [OFFLOAD](指软件 flowtable 快速通道)和 [HW_OFFLOAD](指流正在使用的硬件卸载数据路径)之间存在区别。
flowtable 硬件卸载基础设施还支持 DSA(分布式交换机架构)。
限制¶
flowtable 的行为类似于缓存。 如果用于传输的目标 MAC 地址或出口网络设备发生更改,则 flowtable 条目可能会变得过时。
如果出现以下情况,这可能会成为一个问题:
您在软件模式下运行 flowtable,并且您在您的设置中组合了桥接和 IP 转发。
硬件卸载已启用。
更多阅读¶
本文档基于 LWN.net 文章 [1][2]。 Rafal Milecki 还编写了一个非常完整和全面的摘要,称为“网络加速状态”,描述了该基础设施被主线化之前的情况 [3],并且它还对这项工作做了一个粗略的总结 [4]。