Linux 基础体系 · 第 67/85 篇。示例面向现代主流 Linux 发行版;发行版差异、权限和生产风险会明确说明。
Linux Bridge、VLAN、Bond 与 Team:二层网络、冗余和诊断
Linux 主机上的二层网络通常不是一个单独的“网卡配置”问题,而是多个内核对象组合后的结果:
物理网卡 eth0、eth1
│
▼
Bond/Team ← 链路冗余或聚合
│
▼
Linux Bridge ← 二层转发与交换
│
├── VLAN 10
├── VLAN 20
└── 物理/虚拟端口
也可以改变层次,例如:
物理网卡
│
Bond
│
VLAN 子接口
│
Bridge
这两种结构并不等价。理解 Linux 二层网络,关键不是记住若干命令,而是明确每个对象处理什么、报文在何处被修改、故障时哪一层负责切换,以及 IP 地址究竟属于哪个逻辑接口。
1. 先建立对象模型:设备、端口、转发域和地址
1.1 Linux 网络接口不是都代表一块物理网卡
Linux 中可以通过 ip link 看到多种接口:
ip -br link
可能得到:
lo UNKNOWN 127.0.0.1/8 ::1/128
enp1s0 UP
enp2s0 UP
bond0 UP
br0 UP
br0.10 UP
veth-host UP
这些接口所处层次不同:
enp1s0、enp2s0:物理以太网接口。bond0:内核 bonding 驱动创建的逻辑接口,下面可以挂多个物理从接口。br0:Linux bridge 创建的二层交换设备,下面可以挂物理接口、Bond、Team、VLAN 子接口、veth 等。br0.10:在br0上创建的 VLAN 子接口,代表某个 VLAN 的三层接口。veth-host:虚拟以太网对的一端,常用于 network namespace、容器或虚拟机连接。
“挂到 bridge 上”在内核中通常称为把接口设置为 bridge port。被加入 bridge 后,普通数据转发由 bridge 完成,IP 地址通常应配置在 bridge 自身或其 VLAN 子接口上,而不是继续配置在物理从接口上。
例如,以下结构中:
enp1s0 ─┐
├── br0 ── 本机 IP
enp1s1 ─┘
enp1s0 和 enp1s1 是 br0 的端口。若把主机地址配置在 enp1s0 而不是 br0,可能出现 ARP、源地址选择、入站报文交付和网络管理工具状态不一致的问题。配置方式应由网络管理系统统一管理,但逻辑归属不能混淆。
1.2 Linux Bridge 是二层转发设备
Bridge 在二层工作,依据目标 MAC 地址决定是否转发帧。它维护一个转发表,通常称为 FDB(Forwarding Database):
目标 MAC 端口
00:11:22:33:44:55 enp1s0
00:aa:bb:cc:dd:ee veth1234
Linux bridge 的基本行为可以抽象为:
- 收到帧;
- 从源 MAC 和入口端口学习源地址;
- 根据目标 MAC 查找转发表;
- 若目标在某个可转发端口上,则单播转发;
- 若目标未知,或目标是广播、组播,通常向同一 VLAN 的多个端口泛洪;
- 若目标端口就是入口端口,则不再从同一端口发出。
源 MAC 学习可以写成:
其中:
- 是 VLAN 标识,未启用 VLAN 过滤时可视为默认转发域;
- 是源 MAC;
- 是收到帧的端口。
目标查找可以写成:
其中 是目标 MAC。只有当该目标端口对 VLAN 有效时,查找结果才可用于转发。
如果目标 MAC 没有记录,bridge 无法判断出口,只能在同一二层广播域内泛洪。这解释了两个常见现象:
- 新设备刚上线时,可以看到广播和 ARP 先扩散;
- FDB 老化或链路切换后,短时间内可能出现未知单播泛洪。
查看 bridge 状态:
bridge link
bridge fdb show br br0
bridge -s link
bridge fdb show 中的 self、master 等标记反映 FDB 项由哪个对象管理。不同发行版和 iproute2 版本输出格式可能略有差异,但核心信息是 MAC、所属端口、VLAN 和状态。
1.3 Bridge 不等于路由器
Bridge 根据 MAC 转发,路由器根据 IP 前缀和路由表转发。假设主机 A 和主机 B 在同一 VLAN:
A 10.0.10.2/24 ── br0 ── B 10.0.10.3/24
A 发送给 B 时,先通过 ARP 得到 B 的 MAC,然后发送以太网帧。Linux bridge 只看 MAC,不理解 10.0.10.2/24 的前缀。
如果 A 访问 10.0.20.3,因为目标不在本地前缀内,A 会把帧交给默认网关。此时需要三层接口和路由处理,bridge 本身不会替代路由功能。
这与策略路由、VRF、反向路径检查等主题直接相关:bridge 负责“同一二层转发域内”,路由表负责“跨三层网络”。当一个主机同时承载多个 VLAN、多个 VRF 或多个 namespace 时,必须先判断问题发生在:
- VLAN 是否被允许;
- bridge 是否学习并转发;
- ARP/ND 是否成功;
- 路由和策略路由是否选择正确;
- 反向路径检查是否丢弃返回流量。
2. VLAN:标签、转发域和接口层次
2.1 802.1Q VLAN 的核心
802.1Q 在以太网帧中加入 VLAN 标签。标签中包含 VLAN ID,常用范围是 1 到 4094;VLAN 0 和 4095 有特殊用途,不能简单当作普通业务 VLAN 使用。
一个交换端口通常有两种抽象角色:
- Access:端口连接一个无标签终端,交换设备内部把它映射到一个 VLAN。
- Trunk:端口可承载多个 VLAN,通常以带标签帧传输。
Linux bridge 开启 VLAN 过滤后,也能表达类似关系。但“trunk”和“access”不是 Linux 内核中必须使用的唯一术语,实际配置通过每个 bridge port 的 VLAN membership、tagged/untagged、PVID 等属性实现。
2.2 Linux bridge 的 VLAN-aware 模式
创建 VLAN-aware bridge:
ip link add name br0 type bridge vlan_filtering 1
ip link set dev br0 up
将物理口加入 bridge:
ip link set dev enp1s0 master br0
ip link set dev enp1s1 master br0
配置 enp1s0 为 trunk,允许 VLAN 10 和 20,出方向保留标签:
bridge vlan add dev enp1s0 vid 10
bridge vlan add dev enp1s0 vid 20
配置 enp1s1 为 access VLAN 10,收到无标签帧时归入 VLAN 10,发送时去掉标签:
bridge vlan add dev enp1s1 vid 10 pvid untagged
查看结果:
bridge vlan show
典型输出类似:
port vlan-id
enp1s0 10
20
enp1s1 10 PVID Egress Untagged
br0 1 PVID Egress Untagged
具体默认项取决于内核、iproute2 和创建方式。生产配置不能仅凭示例中的默认 VLAN 推断安全边界,应显式检查并删除不需要的成员关系。
删除 VLAN 成员关系:
bridge vlan del dev enp1s0 vid 20
启用 VLAN 过滤后,转发条件不再只是“目标 MAC 在哪个端口”,而是:
对未知单播、广播或组播,目标端口集合也必须受 VLAN membership 约束:
其中 表示该帧所属 VLAN。
2.3 VLAN 的三种常见落点
方式一:VLAN-aware bridge
交换机 trunk
│
enp1s0
│
br0 vlan_filtering=1
├── 虚拟机端口 VLAN 10
└── 虚拟机端口 VLAN 20
这是虚拟化宿主机常用结构。bridge 统一管理多个 VLAN,虚拟机端口可以被限制到特定 VLAN。
方式二:bridge 上创建 VLAN 子接口
enp1s0 ── br0 ── br0.10 ── 主机 VLAN 10 IP
└──── br0.20 ── 主机 VLAN 20 IP
命令示例:
ip link add link br0 name br0.10 type vlan id 10
ip addr add 192.0.2.10/24 dev br0.10
ip link set dev br0.10 up
此时 br0.10 是主机在 VLAN 10 中的三层接口。它不是一个普通 bridge port,而是 bridge 自身的 VLAN 上层接口。
方式三:先创建 VLAN 子接口,再加入 bridge
enp1s0 ── enp1s0.10 ── br10
enp1s0 ── enp1s0.20 ── br20
命令示例:
ip link add link enp1s0 name enp1s0.10 type vlan id 10
ip link add name br10 type bridge
ip link set enp1s0.10 master br10
ip link set br10 up
ip link set enp1s0.10 up
这种方式把每个 VLAN 分成独立 bridge,结构直观,但当 VLAN 数量较多时,对象数量和管理复杂度会上升。
2.4 为什么“VLAN over bridge”和“bridge over VLAN”不能混为一谈
考虑两种结构:
A: 物理网卡 → bridge → bridge.10
B: 物理网卡 → eth.10 → bridge
A 中,bridge 先作为 VLAN-aware 二层交换域工作,br0.10 从 bridge 的 VLAN 视图中取出 VLAN 10 的流量。
B 中,VLAN 子接口先在单个下层接口上完成标签处理,之后 br10 只看到已经被分离的 VLAN 10 流量。
如果需要让多个虚拟机端口分别属于不同 VLAN,A 通常更自然;如果每个 VLAN 是一个独立二层网络,B 也可以成立。错误的关键不在名字,而在于:
- 标签在哪里被识别;
- 哪个对象拥有 VLAN membership;
- IP 地址配置在 bridge、VLAN 子接口还是物理接口;
- 上联交换机是否以预期方式发送 tagged/untagged 帧。
3. Bridge 的高级状态:FDB、STP、端口属性和环路
3.1 FDB 学习不是永久静态表
Linux bridge 会动态学习源 MAC。查看一条特定记录:
bridge fdb show br br0 | grep -i '00:11:22:33:44:55'
删除动态记录可以用于诊断:
bridge fdb del 00:11:22:33:44:55 dev enp1s0 master br0
删除前应确认 MAC 和端口,否则可能造成短时未知单播泛洪。动态 FDB 被清除后,下一批流量会重新触发学习。
同一个 MAC 在多个端口之间反复出现,通常表示:
- 二层环路;
- 虚拟机迁移或漂移;
- 上游交换机配置错误;
- Bond、Bridge 或 Team 层次重复;
- 某设备使用了不稳定或伪造的源 MAC。
内核日志有时会报告 MAC move 或 bridge 相关事件,但不能只依赖日志;需要同时检查 FDB、端口状态和抓包。
3.2 STP 解决环路,而不是提供链路聚合
启用生成树协议:
ip link set dev br0 type bridge stp_state 1
bridge link
STP 的目标是从冗余拓扑中选出无环转发树。发生拓扑变化时,某些端口可能从 Blocking、Listening、Learning 转为 Forwarding,期间业务会有收敛延迟。
STP 和 Bond/LACP 的职责不同:
- STP 处理多个二层路径造成的网络环路;
- Bond active-backup 处理同一个逻辑接口下的从链路切换;
- LACP 让两端把多条链路视为一个聚合组;
- Team runner 也可能使用 LACP。
把两条没有聚合的物理链路同时接到同一个上游交换网络,不能靠“bridge 会自动聪明地选择”来保证安全。若 bridge 形成环路,应使用 STP,或确保链路由 Bond/Team/LACP 正确封装成一个逻辑端口。
3.3 Bridge port 属性会改变转发
查看端口属性:
bridge link show
常见属性包括:
state:端口 STP 状态;hairpin:是否允许帧从入口端口再次发回同一端口;guard、root_block、fastleave:与 STP 或组播行为有关;learning、flood、mcast_flood:控制学习和泛洪。
Hairpin 模式常用于某些虚拟化或容器场景,例如多个逻辑端点通过同一个物理端口访问同一上游设备;但它也可能放大环路或重复报文问题:
bridge link set dev veth-host hairpin on
不能因为启用了 hairpin 就认为“同端口转发”普遍可用。它是一个改变默认转发约束的选项,应结合具体拓扑验证。
3.4 Bridge Netfilter 不是 Bridge 本身
Linux 可以通过 netfilter 处理桥接帧,相关 sysctl 常见于:
sysctl net.bridge
某些发行版会加载 br_netfilter 模块,使桥接流量经过部分 IPv4/IPv6 防火墙钩子。这样会出现一个容易误判的现象:
- bridge FDB、VLAN membership 看起来正确;
- 但 nftables/iptables 仍然丢弃了桥接流量。
是否启用、哪些协议经过何种钩子,受内核、模块和防火墙配置影响。诊断时应分别查看:
nft list ruleset
sysctl -a 2>/dev/null | grep '^net.bridge'
不要把“二层能转发”与“防火墙允许该帧上送或转发”视为同一件事。
4. Bond:一个逻辑链路下的多物理从接口
4.1 Bond 的目的和抽象
Bonding 驱动把多个从接口组合成一个逻辑接口:
enp1s0 ─┐
├── bond0 ── 上层 IP 或 bridge
enp2s0 ─┘
上层只看到 bond0。Bond 负责:
- 选择从接口发送;
- 监测链路或对端可达性;
- 在故障时切换;
- 某些模式下把流量分散到多个链路;
- 某些模式下与交换机通过 LACP 协商聚合。
Bond 不会凭空增加单个 TCP 流的带宽。以基于流的分担为例,一个流通常由哈希结果固定到一条链路:
其中 是可用从接口数。多流可以分布到不同链路,但单流吞吐受单条链路和哈希策略限制。
4.2 典型 Bond 模式
active-backup(mode 1)
只有一个从接口主动发送,其他接口备用:
发送:enp1s0
备用:enp2s0
链路故障后切换到备用接口。它对交换机通常不要求配置静态聚合,适合“两个独立交换端口提供冗余”的场景,但不能把两条链路带宽叠加给同一个流。
创建示例:
ip link add bond0 type bond mode active-backup
ip link set dev enp1s0 master bond0
ip link set dev enp2s0 master bond0
ip link set dev bond0 up
ip link set dev enp1s0 up
ip link set dev enp2s0 up
cat /proc/net/bonding/bond0
输出会包含当前 Active Slave、MII 状态、从接口列表等。
802.3ad(LACP)
Bond 与交换机通过 LACP 协商链路聚合:
ip link add bond0 type bond mode 802.3ad
两端必须形成同一个聚合组。交换机侧需要将对应端口配置为同一 LAG,并匹配速率、双工、VLAN、LACP 模式等。
LACP 解决的是“这些物理链路属于一个聚合逻辑链路”。它不等于“任意两台交换机的端口都能直接聚合”。如果两条链路分别接到不支持跨设备 MLAG、堆叠或虚拟机箱的独立交换机,通常无法形成有效的单一聚合组。
balance-xor(mode 2)
使用哈希选择发送从接口,需要上游交换机以兼容方式配置静态聚合或等效聚合。哈希策略决定流量分布,通常不能保证每条链路完全均匀。
balance-alb/tlb
这些模式包含更复杂的发送或接收分担机制,依赖驱动、ARP 行为和网络环境。它们不需要传统交换机聚合,但与虚拟化、网关、抓包和异常 MAC 学习的交互更复杂。生产中必须根据发行版支持和实际交换机行为验证,不应仅凭模式名判断可用性。
其他模式如 balance-rr、broadcast 也有特定行为和限制。balance-rr 可能造成乱序;broadcast 会在多个从接口复制发送,主要用于特殊可靠性需求而非普通带宽扩展。
查看 Bond 当前模式和参数:
ip -d link show bond0
cat /proc/net/bonding/bond0
4.3 Bond 的故障检测不是同一件事
Bond 可以使用链路状态检测,例如 MII/ethtool 类检测,也可以配置 ARP 监测。两者观察的故障范围不同:
- 物理链路检测能发现网卡 carrier 消失;
- 不能保证上游交换机、VLAN、远端网关仍可达;
- ARP 监测能观察某些三层邻居可达性;
- ARP 监测目标、源接口和 VLAN 设计错误时,可能误判。
因此,“网线没断”不等于“业务路径正常”。但反过来,使用业务网关作为监测目标也可能因网关维护、ACL 或 ARP 行为导致不必要切换。故障检测参数必须与实际拓扑匹配。
4.4 Bond 与 Bridge 的正确层次
常见安全结构是:
enp1s0 ─┐
├── bond0 ── br0 ── 虚拟机/主机三层接口
enp2s0 ─┘
对应的关键命令:
ip link add bond0 type bond mode active-backup
ip link set enp1s0 master bond0
ip link set enp2s0 master bond0
ip link add br0 type bridge
ip link set bond0 master br0
ip link set enp1s0 up
ip link set enp2s0 up
ip link set bond0 up
ip link set br0 up
主机地址应配置在 br0 或 br0.10 等上层接口,而不是 enp1s0、enp2s0 或通常不是 bond0。对于 VLAN-aware bridge,VLAN membership 通常配置在 bond0 这个 bridge port 上:
bridge vlan add dev bond0 vid 10
bridge vlan add dev bond0 vid 20
这里有一个重要边界:如果 Bond 的两个从接口本身分别被加入 bridge,且又存在 Bond 关系,拓扑就不是“两个从接口组成一个逻辑链路”,而可能形成错误或重复的二层路径。一个物理接口在某时刻只能按预期属于正确的上层关系,不能把 Bond 从接口同时当作普通 bridge 端口使用。
5. Team:用户空间管理器与内核 Team 接口
5.1 Team 与 Bond 的关系
Team 也是把多个物理接口呈现为一个逻辑网络接口,但其架构与传统 Bond 不同:
- Bond 的主要逻辑在内核 bonding 驱动中;
- Team 使用内核 team 驱动,并由用户空间的
teamd或其他管理组件配置和控制; - Team 的 runner、端口状态和事件处理更多通过用户空间管理;
- 实际可用性依赖发行版是否提供
teamd、NetworkManager 或其他集成。
Team 不是“Bond 的另一种模式名称”。两者都能提供 active-backup、负载分担或 LACP 类能力,但接口、配置工具、故障行为和发行版集成不同。
现代 Linux 发行版中,Bond 通常是更普遍、文档和自动化支持更广的选择;Team 并未在所有发行版和网络管理栈中保持同等地位。选择 Team 前应确认目标系统的 teamd、NetworkManager 版本和维护策略,而不能假设所有系统都预装。
5.2 Team 的组成
Team 的概念通常包括:
- team master:逻辑接口,例如
team0; - ports:物理从接口;
- runner:决定 active-backup、LACP、loadbalance 等行为;
- link watcher:检测端口链路状态;
teamd:用户空间守护进程,负责配置和控制。
一个 teamd 配置示例:
{
"device": "team0",
"runner": {
"name": "activebackup"
},
"link_watch": {
"name": "ethtool"
},
"ports": {
"enp1s0": {},
"enp2s0": {}
}
}
启动前需要系统已安装并支持 teamd:
teamd -f /etc/teamd/team0.conf -d
teamdctl team0 state
不同发行版可能使用 NetworkManager 配置 Team,而不是直接维护 teamd 进程。生产系统不能同时让多个管理器争抢同一接口,否则会出现配置被覆盖、端口反复加入/移除或守护进程互相重置状态。
Team 接口可以像 Bond 一样接入 bridge:
enp1s0 ─┐
├── team0 ── br0
enp2s0 ─┘
或由 Team 承载 VLAN:
team0 ── team0.10 ── 主机三层接口
配置 VLAN-aware bridge 时,team0 作为 bridge port 处理 VLAN membership:
bridge vlan add dev team0 vid 10
bridge vlan add dev team0 vid 20
5.3 Team 的 LACP 仍然需要交换机配合
Team 的 LACP runner 不能绕过交换机的聚合要求。若 Team 侧采用 LACP,而交换机侧端口没有加入同一 LAG,可能出现:
- LACP 协商不成功;
- 只有一条链路转发;
- MAC 在多个交换端口间抖动;
- 业务间歇性丢包;
- 广播或单播流量被错误转发。
因此 Bond 802.3ad 与 Team LACP 在拓扑约束上具有相同的基本事实:两端必须对“哪些端口属于同一个逻辑聚合组”达成一致。
6. 从报文角度推导三种典型结构
6.1 Bond active-backup + 普通 bridge
结构:
主机 A
│
├── enp1s0 ─┐
│ ├── bond0 ── br0 ── 另一台主机
└── enp2s0 ─┘
发送过程:
- 应用把 IP 数据交给主机协议栈;
- 路由表决定从
br0发出; - ARP/邻居表提供目标 MAC;
- bridge 选择
bond0这个端口; - Bond 选择当前 active slave,例如
enp1s0; - 物理网卡发送帧。
若 enp1s0 carrier 消失:
- Bond 的链路检测把
enp1s0标记为不可用; - Bond 选择
enp2s0; - 必要时通过 gratuitous ARP 或邻居更新让上游刷新 MAC 位置;
- bridge 的 FDB 仍可能认为目标 MAC 在
bond0,因为上层逻辑端口没有改变; - 外部交换机可能需要更新其对主机源 MAC 的端口学习。
这说明故障切换有多个状态表参与:
- Bond 从接口状态;
- bridge FDB;
- 上游交换机 FDB;
- 对端 ARP/ND 缓存;
- 连接跟踪和 TCP 状态。
某一层切换成功,不保证所有层已经立即收敛。
6.2 VLAN-aware bridge + Bond trunk
结构:
交换机 trunk
│ VLAN 10、20
bond0
│
br0
┌──┴──┐
br0.10 br0.20
从外部交换机到主机 VLAN 10 的报文:
- 交换机在 trunk 上发送带 VLAN 10 标签的帧;
- Bond 选择当前可用的从接口接收;
- bridge 识别 VLAN 10;
- bridge 查询 VLAN 10 作用域中的 FDB;
- 若目标是主机本身,帧交付到
br0.10; - 若目标是虚拟机端口,bridge 依据端口的 VLAN membership 转发;
- 若目标端口配置为
untagged,出端口时移除标签;若为 tagged,则保留标签。
如果 bond0 允许 VLAN 10,但目标虚拟机端口没有 VLAN 10,报文不会交付给该端口。反过来,虚拟机发送 VLAN 20 报文时,即使 bridge 本身存在 VLAN 20,若上联端口未允许 VLAN 20,报文也不会正常离开主机。
6.3 Bridge 与 namespace
Linux network namespace 拥有独立的接口、路由表、邻居表和端口。可以用 veth 将 namespace 接入 bridge:
ip netns add ns1
ip link add veth-host type veth peer name veth-ns
ip link set veth-ns netns ns1
ip link add br0 type bridge
ip link set br0 up
ip link set veth-host master br0
ip link set veth-host up
ip -n ns1 link set lo up
ip -n ns1 link set veth-ns name eth0
ip -n ns1 link set eth0 up
ip -n ns1 addr add 192.0.2.2/24 dev eth0
这里 br0 仍是宿主机 namespace 中的二层交换设备,ns1 只看到 eth0。若宿主机在同一 bridge 上有另一个接口 192.0.2.1/24,两者可以通过 ARP 直接通信;若要跨网段,则还需要宿主机路由或其他 namespace 中的路由器。
这也是容器网络排错的基础:必须分别进入正确的 namespace 查看:
ip netns exec ns1 ip addr
ip netns exec ns1 ip route
ip netns exec ns1 ip neigh
在宿主机执行 ip addr 看不到 namespace 内的接口,并不表示接口不存在。
7. 一个可回滚的实验拓扑
以下实验只在测试主机上执行。命令会创建 bridge、namespace 和 veth,不会修改物理交换机,但仍可能影响已有同名接口,因此先检查:
ip link show br-lab
ip netns list
创建两个 namespace 和一个 bridge:
ip netns add ns1
ip netns add ns2
ip link add br-lab type bridge vlan_filtering 1
ip link set br-lab up
ip link add veth1-host type veth peer name veth1-ns
ip link add veth2-host type veth peer name veth2-ns
ip link set veth1-ns netns ns1
ip link set veth2-ns netns ns2
ip link set veth1-host master br-lab
ip link set veth2-host master br-lab
ip link set veth1-host up
ip link set veth2-host up
将两个端口放入 VLAN 10,并把无标签帧映射到 VLAN 10:
bridge vlan add dev veth1-host vid 10 pvid untagged
bridge vlan add dev veth2-host vid 10 pvid untagged
配置 namespace:
ip -n ns1 link set lo up
ip -n ns1 link set veth1-ns name eth0
ip -n ns1 link set eth0 up
ip -n ns1 addr add 192.0.2.11/24 dev eth0
ip -n ns2 link set lo up
ip -n ns2 link set veth2-ns name eth0
ip -n ns2 link set eth0 up
ip -n ns2 addr add 192.0.2.12/24 dev eth0
测试:
ip netns exec ns1 ping -c 3 192.0.2.12
bridge vlan show
bridge fdb show br br-lab
预期结果是:
ns1和ns2的eth0都发送无标签帧;- 宿主机 bridge 将这两个端口归入 VLAN 10;
- ARP 广播只在 VLAN 10 的相关端口间传播;
ping成功后,FDB 中应能看到两端 MAC 与对应 veth host 端口的映射。
清理实验:
ip netns del ns1
ip netns del ns2
ip link del br-lab
删除 namespace 会连带删除其中的 veth 端;删除 bridge 前应确认没有其他生产接口挂载其上。
8. 诊断:先定位层次,再观察状态
二层故障最忌讳只执行一次 ping。应从接口、组合设备、VLAN、FDB、邻居和抓包逐层缩小范围。
8.1 第一层:接口和载体状态
ip -br link
ip -d link show enp1s0
ip -d link show bond0
ip -d link show br0
重点观察:
- 管理状态是否为
UP; LOWER_UP是否存在;- MTU 是否一致;
- 接口是否被设置为
master; - Bond 模式和参数是否符合预期;
- bridge 是否启用
vlan_filtering; - VLAN、Bond、Team 是否由正确的管理器接管。
UP 主要表示管理员启用了接口;LOWER_UP 更接近底层 carrier 正常。接口显示 UP 但没有 LOWER_UP,不能认为物理链路可用。
物理层进一步检查:
ethtool enp1s0
ethtool -S enp1s0
查看协商速率、双工、链路检测和驱动计数器。驱动统计名称不统一,rx_errors、CRC 错误、丢包、FIFO 错误等需要结合具体网卡解释。
8.2 第二层:Bond 或 Team 的成员状态
Bond:
cat /proc/net/bonding/bond0
ip -d link show bond0
需要核对:
- 当前 active slave;
- 各 slave 的 MII 状态;
- 聚合模式;
- LACP actor/partner 状态;
- 发送哈希策略;
- link failure count。
Team:
teamdctl team0 state
teamdctl team0 config dump
如果 teamdctl 无法连接,可能是:
teamd没有运行;- team 由 NetworkManager 等其他组件管理;
- 接口名称或权限不正确;
- 配置语法或 runner 不被当前版本支持。
LACP 问题还要在交换机上查看聚合组状态。仅在主机上看到两个链路 UP,不能证明 LACP 已经建立。
8.3 第三层:Bridge 端口、VLAN 和 FDB
bridge link show
bridge vlan show
bridge fdb show br br0
诊断逻辑可以形式化为:
- 入口端口是否存在且处于转发状态?
- 该端口是否允许目标 VLAN?
- 目标端口是否允许同一 VLAN?
- 目标 MAC 是否已学习到正确端口?
- 若未学习,广播/未知单播是否可以泛洪?
- 是否有 STP、端口隔离、bridge netfilter 或防火墙阻断?
例如,上联 trunk 上 VLAN 10 正常、VLAN 20 不通,优先比较:
bridge vlan show dev bond0
bridge vlan show dev br0
ip -d link show br0
如果 bond0 没有 VLAN 20 membership,问题发生在上联 bridge port;如果 bond0 有 VLAN 20 而 br0.20 没有地址或接口未启用,问题发生在主机三层交付;如果虚拟机端口没有 VLAN 20,问题发生在端口隔离边界。
8.4 第四层:邻居表、路由和地址归属
ip addr show
ip route show
ip neigh show
如果 ping 同网段地址失败:
ip neigh显示INCOMPLETE:通常是 ARP/ND 请求没有得到响应,需查 VLAN、bridge、对端接口或防火墙;- 邻居为
FAILED:内核多次解析失败; - 邻居已有 MAC 但仍不通:可能是 FDB、反向路径、防火墙或对端协议栈问题。
指定接口测试:
ping -I br0.10 -c 3 192.0.2.1
arping -I br0.10 -c 3 192.0.2.1
arping 只适用于 IPv4 ARP 场景;IPv6 应观察邻居发现和 ip -6 neigh。使用 -I 时必须选择真正承载该 VLAN 或地址的逻辑接口,不能随意指定一个 Bond 从接口。
8.5 第五层:抓包确认标签和路径
在物理接口抓包:
tcpdump -eni enp1s0 -vvv 'vlan 10 or arp'
在 bridge 或 VLAN 子接口抓包:
tcpdump -eni br0 -vvv 'vlan 10 or arp'
tcpdump -eni br0.10 -vvv 'arp or icmp'
抓包位置会影响看到的标签:
- 在 trunk 物理接口上,通常可看到 802.1Q 标签;
- 在 access 端口或被 VLAN 子接口剥离后,可能看不到标签;
- 硬件卸载可能使抓包结果与线上实际帧的观察角度不同;
- Bond 上层和具体 slave 上抓包,可能出现重复或不同层次的视图。
一个有效的诊断实验是同时在入口和出口抓包,比较:
- 报文是否进入主机;
- VLAN ID 是否正确;
- 是否从预期出口发出;
- 源和目的 MAC 是否变化;
- Bond 切换后报文是否改走另一物理接口。
8.6 事件和计数器
持续观察链路和地址变化:
ip monitor link addr route neigh
查看 bridge、Bond 和设备统计:
bridge -s link
ip -s link show enp1s0
ip -s link show bond0
ip -s link show br0
日志:
journalctl -k -f
journalctl -u NetworkManager -f
journalctl -u systemd-networkd -f
具体服务名称取决于发行版。NetworkManager、systemd-networkd、ifupdown、云初始化工具或虚拟化平台可能在启动、热插拔和链路变化时重写配置。诊断时应确认“谁是配置所有者”。
9. 常见失败模式及其因果链
9.1 把 IP 留在物理从接口上
错误结构:
enp1s0 ─┐
├── bond0 ── br0
enp2s0 ─┘
IP 配在 enp1s0
可能表现为:
- Bond 切换后 IP 路径不稳定;
- ARP 从错误接口发出;
ip route get选择不符合预期;- 网络管理器反复调整地址;
- 抓包看到请求发出但响应未交付给应用。
修复原则是让 IP 属于逻辑三层接口:普通 bridge 场景配置在 br0,多 VLAN 场景配置在 br0.10、br0.20 等;Bond 从接口只作为链路成员。
9.2 VLAN ID 两端不一致
假设交换机 trunk 发送 VLAN 20,但 Linux 上联 port 只允许 VLAN 10。报文可能在物理层到达,但 bridge VLAN filtering 在入口处将其丢弃或不转发。反过来,Linux 发送 VLAN 20,而交换机端口未允许 VLAN 20,也会在上游被丢弃。
因此,必须同时核对:
交换机端口 VLAN membership
↕
Linux bridge port VLAN membership
↕
虚拟端口或 VLAN 子接口配置
“物理网卡能看到报文”只能证明报文到达某个观察点,不能证明它经过了完整转发路径。
9.3 把 Bond 两端接入不支持跨设备聚合的交换机
active-backup 可以把两个端口接到独立交换机,但 LACP/static aggregation 通常要求它们属于同一个逻辑交换设备。错误使用 802.3ad 的典型症状包括:
- LACP partner 不完整;
- 一条链路被标记为 standby 或 individual;
- MAC 在交换机端口间漂移;
- 连接偶发超时而不是完全不通。
修复方向只有两个:使用交换机支持的 MLAG/堆叠等跨设备聚合,或改用不要求对端聚合的 active-backup 等模式。
9.4 误以为两条链路一定把带宽相加
在两个 1 Gbit/s 物理链路上,基于流哈希的聚合可能使多个独立流合计接近两条链路的总能力,但一个五元组固定的 TCP 流通常不会同时使用两条链路。负载不均还可能由哈希输入、流数量和通信对象决定。
因此性能测试应区分:
- 单连接吞吐;
- 多连接吞吐;
- 双向流量;
- 小包 PPS;
- 故障切换期间的丢包和恢复时间。
不能用一个 iperf3 单连接结果证明聚合链路“没有生效”。
9.5 忽略 MTU
VLAN 标签本身增加帧头开销;某些硬件路径还涉及隧道、虚拟化封装或桥接卸载。若路径中一端 MTU 不匹配,可能出现:
- 小包正常、大包失败;
- TCP 建连成功但传输卡住;
- IPv4 依赖分片而 IPv6 直接失败;
- PMTU 发现因 ICMP 被阻断而表现为黑洞。
检查:
ip link show
ip route get 198.51.100.10
tracepath 198.51.100.10
MTU 应按整条路径验证,不能只看主机 br0 的数值。
9.6 只看 carrier,不看业务可达性
LOWER_UP 只能说明网卡认为链路层载波存在。它不能证明:
- 交换机端口在正确 VLAN;
- LACP 已协商;
- bridge VLAN 过滤允许报文;
- 对端 ARP/ND 正常;
- 防火墙允许流量;
- 路由和策略路由正确。
故障检测机制也有同样边界。硬件链路检测和 ARP 检测观察的是不同故障域,不能互相替代。
10. 生产配置中的生命周期和恢复
10.1 临时命令与持久配置是两套问题
ip 和 bridge 命令直接修改当前内核状态,重启后通常消失。生产系统还需要由某个网络管理器持久化:
- NetworkManager connection profile;
- systemd-networkd 的
.netdev、.network、.netdev/.network组合; - Debian/Ubuntu 某些环境中的 ifupdown;
- 云平台或虚拟化平台的网络配置;
- 发行版特定的配置文件。
不能把不同管理器的配置语法混用。例如手工创建 bond0 后,NetworkManager 可能在重新加载连接时删除或重建它;systemd-networkd 也可能根据声明式配置改变 master/slave 关系。
上线前应明确:
- 谁创建 Bond 或 Team;
- 谁将其加入 bridge;
- 谁设置 VLAN filtering 和 VLAN membership;
- 谁配置 IP、默认路由和 DNS;
- 链路变化时由谁执行切换;
- 远程操作失败时如何通过控制台恢复。
10.2 远程修改二层拓扑的风险
把当前 SSH 所依赖的接口加入 bridge、Bond 或修改 VLAN,可能立刻断开连接。风险来自多个瞬间状态:
- IP 地址暂时仍在旧接口;
- bridge 尚未启用;
- VLAN membership 未完成;
- Bond active slave 尚未选出;
- 上游交换机尚未刷新 MAC;
- NetworkManager 重载后撤销手工状态。
推荐使用带外控制台、远程 KVM 或预设自动回滚任务。示意性的恢复保护可以是:
# 仅示意,生产环境应使用受控的 systemd timer 或运维编排
at now + 5 minutes <<'EOF'
ip link set dev br0 down
EOF
但这种简单回滚并不一定能恢复原有 IP、路由和管理器状态。可靠恢复应保存变更前的:
ip addr
ip route
ip rule
ip link
bridge vlan show
并准备完整的反向配置,而不是只关闭一个 bridge。
10.3 网络管理器状态应作为证据的一部分
当手工命令看起来正确,但几分钟后恢复原状,通常不是内核随机行为,而是某个管理器重新应用了声明式配置。应查看:
nmcli device status
nmcli connection show
networkctl status
具体命令取决于系统。还要查看:
systemctl --type=service | grep -Ei 'NetworkManager|networkd|teamd|wicked'
多个服务同时管理同一接口是高风险状态。网络对象的生命周期必须有唯一清晰的控制者。
11. 如何选择 Bridge、VLAN、Bond 和 Team
这些对象不是互斥替代品,而是解决不同问题:
| 对象 | 主要职责 | 处理对象 |
|---|---|---|
| Bridge | 二层交换和端口连接 | MAC、FDB、VLAN、STP |
| VLAN | 划分逻辑二层广播域 | 802.1Q 标签和 VLAN membership |
| Bond | 多物理接口组合 | 从接口选择、冗余、LACP |
| Team | 由用户空间管理的多接口组合 | runner、端口状态、冗余、LACP |
典型选择逻辑如下:
- 需要让多个虚拟端口或物理端口处于同一二层网络:使用 Bridge。
- 需要在一条 trunk 上承载多个广播域:使用 VLAN-aware Bridge 或多个 VLAN 子接口。
- 需要一条逻辑链路的物理冗余:通常使用 Bond active-backup。
- 需要多链路聚合:使用 Bond 802.3ad 或 Team 的 LACP runner,并配置交换机对应 LAG。
- 需要 network namespace 或容器接入二层网络:通常通过 veth 接入 Bridge。
- 需要跨 VLAN 通信、多个路由表或隔离三层转发:还要使用路由、策略路由或 VRF;Bridge 和 VLAN 本身不会完成这些三层决策。
最后可以用一条完整路径验证设计是否自洽:
应用
→ 路由表/邻居表
→ br0 或 br0.10
→ Bridge VLAN membership 与 FDB
→ bond0 或 team0
→ active slave / LACP 哈希
→ 物理链路
→ 交换机端口 VLAN 与聚合状态
只要沿这条路径逐段检查“接口是否存在、状态是否允许、VLAN 是否一致、MAC 是否学习、下一层是否收到”,大多数 Linux 二层故障都能从“网络不通”还原为一个明确的状态或配置错误。
系列导航与关联阅读
- 系列入口:Linux 完整学习路线:从内核与文件系统到网络、性能和生产运维
- 上一篇:Linux 路由深入:多表、策略路由、ECMP、VRF 和反向路径检查
- 下一篇:Linux Network Namespace 与 veth:容器网络、路由和 NAT 实验
- 延伸:Linux namespaces 深入:PID、Mount、Network、User 和隔离组合
官方资料
本文依据 Linux 内核、systemd 与主流发行版官方文档重新梳理;正文与实验由 WR BLOG 编写。

评论
0 条讨论