虚拟网络、路由与队列

本页目录

小包可以通过,稍大的包却卡住;veth 有流量,物理口没有。虚拟设备、二层域、路由、封装与排队需要沿同一条实际路径逐层解释。

查阅目标阅读位置
bridge、VLAN 与 bond第 1~2 节
封装尺寸与策略路由第 3~4 节
排队、namespace 与 TUN/TAP第 5~7 节
同一报文可经过多层虚拟设备 容器 / VM 独立网络视图 veth / TAP 连接端点 bridge / VLAN 二层域与转发 路由 / 出口 三层与队列 FDB 查询目的 MAC;FIB 查询 IP 前缀;qdisc 管排队 各层解决的问题不同,创建接口不等于整条路径已连通 图为一种组合,容器网络也可以采用直接路由、其他接口或 BPF 数据路径。

1. Bridge:FDB 不等于路由表

bridge 根据源 MAC 学习端口,查询目的 MAC 对应的 FDB 表项。已知单播转发到相应端口;未知单播、广播和组播按配置采取泛洪、组播侦听等处理。它不根据 IP 最长前缀选择下一跳。

设 VM A、B 接在 br0 两个 TAP 端口,位于同一二层域。A 先通过 ARP/NDP 获得 B 的链路层地址,再发送目的 MAC 为 B 的帧。bridge 的学习与转发不要求 br0 自己有 IP;给 br0 配 IP 是让宿主也参与该三层网络,而不是打开桥功能的必要条件。

二层环路可能引起广播风暴,需要正确拓扑及 STP 等机制。VLAN filtering 打开后,端口成员、PVID 与 tagged/untagged 出口规则一起决定转发域;仅创建 VLAN ID 不代表所有端口都允许该 VLAN。见 bridge 文档。

2. VLAN 与 bonding 不增加同一种能力

VLAN 在共享物理链路上区分逻辑二层域。VLAN 子接口通常使上层看到独立 net_device,硬件 offload 可能把 tag 保存在元数据或由硬件插入/剥除,所以抓包是否看到 tag 取决于位置。

bonding 将多个下层链路组织成一个逻辑接口:

模式典型用途限制
active-backup链路切换不把单流吞吐叠加成多条链路总和
balance-xor按 hash 分流需要正确对端配置,hash 字段影响均衡
802.3adLACP 协商聚合交换机支持、成员条件与 hashing 必须匹配
balance-rr按轮转方式分配发送可能导致报文乱序,并非通用优选

两条 10 Gbit/s 链路组成 LACP,不代表单个 TCP 连接一定达到 20 Gbit/s;为保序,同一 flow 通常仍映射到一条成员链路。链路检测也不等于端到端服务健康检测。见 bonding 文档。

3. 隧道:先算封装,再配置 MTU

IPIP 将 IP 放入外层 IP;GRE 增加 GRE 头并可承载相应协议;VXLAN 常把二层帧封装到 UDP/IP,VNI 标识逻辑网络。VNI 比 VLAN ID 更大,不代表它提供加密或访问认证。

假设 underlay 的 IPv4 MTU 为 1500,普通 VXLAN 无额外选项:

封装内容字节数
外层 IPv420
UDP8
VXLAN8
内层 Ethernet14
合计50
留给内层 IP 包1500 − 50 = 1450

外层改为 IPv6 基本头时,多用 20 字节,结果约 1430。内层 VLAN 或额外头部还需继续计入。

这是根据明确封装计算的上限,不是所有 VXLAN 的固定 MTU。underlay MTU 按其 IP 载荷边界定义,上述计算没有再次扣除外层以太网头;混用层次会多减或少减。

路径中 MTU 不一致、ICMP Packet Too Big 等被过滤,可能形成小包正常而大包卡住的现象。隧道 key/VNI、远端地址、FDB/控制平面和返回路径也都需正确。WireGuard 等提供加密隧道,但它们与明文 VXLAN 的安全属性不同。见 VXLAN 文档。

把各层开销放回同一长度轴:外层 IP、UDP、VXLAN、内层以太网头与应用数据都占用预算。改变外层 IPv4/IPv6 或 VLAN 后,能容纳的数据上限随之移动。

MTU 从外层 IP 包起算,H_tunnel 包含外层 IP/UDP/VXLAN 与内层以太网头;外层以太网头不计入 IP MTU。

正在呈现知识画面
每加一层头部,内层还能放多少?

VXLAN 的外层 IP、UDP、VXLAN 和内层 Ethernet 都占用 underlay IP MTU;内层 IP/TCP 头还会继续占用内层数据预算。

4. 策略路由先选规则,再查对应表

路由策略数据库按 rule 的优先级检查源地址、mark、接口等条件,并执行查表等动作。一条 lookup 规则选中的表若未得到终止结果,可能继续后续规则;不是第一次匹配条件就无条件停止。

同一张表内,路由通常优先最长前缀,再按候选项属性选择。10.2.3.9 同时匹配 10.0.0.0/8 与 10.2.0.0/16,若其他条件正常,后者更具体。不能据 IPv4 FIB 使用 trie 就承诺任何负载下严格 O(log n)。

from ipaddress import ip_address, ip_network

address = ip_address('10.2.3.9')
routes = [ip_network(s) for s in ('0.0.0.0/0', '10.0.0.0/8', '10.2.0.0/16')]
best = max((r for r in routes if address in r), key=lambda r: r.prefixlen)
assert str(best) == '10.2.0.0/16'
print(best)

此例只演示一张表的前缀匹配,未模拟 policy rule、ECMP、路由类型及邻居解析。ip route get 也要带上问题相关的源地址、mark 或接口信息,才能接近实际查找条件。参见 ip-rule。

5. qdisc:排队、调度、整形和 AQM

功能核心动作
排队保存暂时不能发送的 skb
调度从队列中选择下一包
整形延迟发送以控制速率
policing对超出条件的包丢弃或采取动作
AQM按队列状态提前丢弃或 ECN 标记,反馈拥塞

它们可以组合,但不意味着一个接口自动提供全部功能。

fq_codel 结合流队列与 CoDel,CAKE 组合整形、公平和队列管理,HTB 支持分层带宽安排。系统默认 qdisc 受配置和设备影响,不能统一声称 fq_codel 一定是默认。

控制排队位置:本地 AQM 管不到所有远端缓冲

如果真实瓶颈在调制解调器/运营商缓冲区,主机本地队列可能始终很短,本地 AQM 无法直接控制远端队列。把可控整形速率设在适当瓶颈之前,才有机会让排队发生在自己管理的位置,但具体速率需测量链路开销和变化。

ingress/clsact 提供入口过滤位置,并不是普通可长期排队的接收整形队列;需要排队整形时可结合 IFB 等方式。BQL 调节驱动层在途字节,作用又不同于流级拥塞控制与 qdisc AQM。

6. Namespace、veth、TUN/TAP

network namespace 隔离设备列表、路由、端口绑定等网络状态。它共享同一个内核,不自动创建出口、DNS 服务或带宽保障。一个普通 net_device 在某时刻属于一个 namespace,veth pair 的两端可以放入不同 namespace。

veth 提供成对的内核网络端点;TUN/TAP 则让用户态经文件描述符读写网络数据。TUN 提供三层包,TAP 提供二层帧。用户态读 fd 得到内核发往该接口的数据,写 fd 则向内核注入接收数据,方向要按这个视角理解。

数据是否带额外 packet information 或 virtio-net header 取决于 flags,不是永远从第一个字节就是 IP/以太网头。VM 常用 TAP,部分用户态 VPN 使用 TUN;主线内核 WireGuard 自身实现 net_device,不能笼统说所有 WireGuard 都依赖 /dev/net/tun。见 TUN/TAP。

7. 只读查阅完整路径

ip -d link show
ip rule show
ip route show table all
bridge link show
bridge vlan show
tc -s qdisc show

先确认设备和 namespace,再检查二层域、地址与路由,随后确认 MTU、过滤规则与队列。流量出现在 veth 上而物理口没有,不足以直接判定丢包:它可能被本机交付、桥内转发、封装到另一出口,或提前被策略拒绝。

关联阅读:协议栈概述、Netfilter 与 BPF/XDP。