4、Linux Bridge:虚拟交换机原理与配置

Linux Bridge 是内核实现的一个虚拟二层交换机,它基于标准 IEEE 802.1D 协议,能够将多个网络接口(物理或虚拟)桥接在一起,形成一个广播域。在容器网络和虚拟化场景中,Linux Bridge 是连接容器命名空间与宿主机网络的核心组件,也是 DPDK KNI 与 Tun/Tap 设备协同工作的关键桥梁。

4.1 核心原理:MAC 地址学习与转发

Linux Bridge 的工作机制与传统硬件交换机完全一致,核心流程包括:

  • MAC 地址学习:当数据帧从某个端口进入 Bridge 时,Bridge 会记录源 MAC 地址与该端口的映射关系,并写入 FDB(Forwarding Database,转发数据库)。
  • 查表转发:对于目标 MAC 地址,Bridge 查询 FDB 表:若命中则单播转发到对应端口;若未命中则向所有端口(除入端口外)泛洪。
  • 广播与多播:广播帧(FF:FF:FF:FF:FF:FF)和多播帧会被泛洪到所有端口。
  • STP(生成树协议):防止环路,默认启用(可通过 brctl stp 或 ip link set 控制)。
关键概念: FDB 表是 Bridge 的核心数据结构,可通过 bridge fdb show 命令查看。每个条目包含 MAC 地址、所属端口、是否自学习(self)以及老化时间(默认 300 秒)。
Linux Bridge 内部转发流程 Linux Bridge (br0) FDB 转发数据库 MAC_A → Port1 MAC_B → Port2 MAC_C → Port3 Port1 (eth0) Port2 (tap0) Port3 (veth1) 数据帧:目标 MAC_B 查表命中 → 单播 转发决策: 1. 查 FDB → 命中 MAC_B → 仅转发到 Port2 2. 查 FDB → 未命中 → 泛洪到所有端口(除入端口)

4.2 创建与管理 Linux Bridge

Linux Bridge 的管理工具主要有两种:传统的 brctl(bridge-utils 包)和现代的 ip 命令(iproute2 包)。推荐使用 ip 命令,功能更强大且与网络命名空间集成更好。

4.2.1 使用 ip 命令创建 Bridge

# 1. 创建 Bridge 设备
ip link add name br0 type bridge

# 2. 启用 Bridge
ip link set br0 up

# 3. 添加接口到 Bridge(以 eth0 和 tap0 为例)
ip link set eth0 master br0
ip link set tap0 master br0

# 4. 查看 Bridge 状态
ip link show br0
bridge link show
bridge fdb show

4.2.2 使用 brctl 命令(传统方式)

# 安装 bridge-utils(如未安装)
apt-get install bridge-utils   # Debian/Ubuntu
yum install bridge-utils       # CentOS/RHEL

# 创建 Bridge
brctl addbr br0

# 启用
ip link set br0 up

# 添加接口
brctl addif br0 eth0
brctl addif br0 tap0

# 查看
brctl show
brctl showmacs br0
最佳实践: 在容器网络场景中,建议统一使用 ip 命令管理 Bridge,因为它天然支持网络命名空间(ip netns)和 VETH 对,且语法更一致。

4.3 Bridge 与网络命名空间的集成

Linux Bridge 是连接宿主机网络与容器网络命名空间的核心枢纽。典型的拓扑结构如下:

  • 宿主机侧:Bridge 设备(如 br0)位于默认命名空间,通常配置一个 IP 地址作为网关。
  • 容器侧:每个容器拥有独立的网络命名空间,通过 VETH 对(veth pair)的一端连接到 Bridge。
  • 数据路径:容器发出的数据帧 → VETH 对 → Bridge → 查 FDB → 转发到目标端口(可能是另一个容器、宿主机或物理网卡)。
Bridge + 网络命名空间拓扑 默认命名空间(Root NS) br0 (Linux Bridge) eth0 (物理网卡) veth0 (宿主侧) veth1 (宿主侧) 容器 1 NS eth0@veth0 IP: 10.0.0.2/24 容器 2 NS eth0@veth1 IP: 10.0.0.3/24 容器间通信

4.4 Bridge 的关键配置参数

参数 命令示例 说明
STP(生成树协议) ip link set br0 type bridge stp_state 1 启用 STP 防止环路,默认关闭(0)
MAC 地址老化时间 ip link set br0 type bridge ageing_time 60000 单位:厘秒(centiseconds),默认 30000(300 秒)
转发延迟 ip link set br0 type bridge forward_delay 400 STP 状态切换延迟,单位:厘秒,默认 2000
最大 MAC 地址数 ip link set br0 type bridge max_fdb_entries 1024 限制 FDB 表大小,防止内存溢出
多播侦听 ip link set br0 type bridge mcast_snooping 1 启用 IGMP/MLD 侦听,优化多播转发
VLAN 过滤 ip link set br0 type bridge vlan_filtering 1 启用 802.1Q VLAN 过滤,默认关闭
注意: 在容器网络场景中,通常不需要启用 STP,因为容器网络拓扑是树形结构,不存在环路。启用 STP 反而会增加端口收敛时间(30-50 秒),导致容器启动后网络不可用。

4.5 Bridge 的 VLAN 过滤功能

从 Linux 3.8 内核开始,Bridge 支持 VLAN 过滤(802.1Q),可以将 Bridge 配置为 VLAN 感知交换机。这在多租户容器网络隔离中非常有用。

4.5.1 启用 VLAN 过滤

# 创建 Bridge 并启用 VLAN 过滤
ip link add name br0 type bridge vlan_filtering 1
ip link set br0 up

# 添加端口并配置 VLAN
ip link set eth0 master br0
ip link set tap0 master br0

# 配置端口 VLAN 成员关系
bridge vlan add vid 10 dev eth0 pvid untagged
bridge vlan add vid 10 dev tap0 pvid untagged

# 查看 VLAN 配置
bridge vlan show

4.5.2 VLAN 隔离示例

端口 PVID 允许的 VLAN 说明
eth0(上行) 1 10, 20 Trunk 端口,承载多个 VLAN
tap0(容器 A) 10 10 Access 端口,VLAN 10
tap1(容器 B) 20 20 Access 端口,VLAN 20

配置后,容器 A 和容器 B 处于不同的广播域,无法直接二层通信,实现了租户隔离。

4.6 Bridge 与 DPDK KNI 的协同

在 DPDK 场景中,KNI 设备可以作为 Bridge 的一个端口,将 DPDK 处理的数据包注入内核网络栈,再通过 Bridge 转发到容器或其他网络设备。

# 1. 创建 KNI 设备(DPDK 侧操作)
# rte_kni_create("kni0", ...)

# 2. 将 KNI 设备添加到 Bridge
ip link set kni0 master br0

# 3. 配置 Bridge IP(作为网关)
ip addr add 10.0.0.1/24 dev br0
ip link set br0 up

# 4. 数据流:DPDK → KNI → Bridge → 容器
性能提示: KNI 设备在内核态和用户态之间通过 mbuf 共享内存传递数据,避免了数据拷贝。但相比直接使用物理网卡,KNI 仍然存在一次内核态到用户态的上下文切换开销。在高速转发场景(>10Gbps)中,建议评估是否真的需要经过内核 Bridge。

4.7 常见问题与排查

  • 容器无法通信:检查 Bridge 的 FDB 表是否学习到 MAC 地址;确认容器内的默认网关指向 Bridge IP。
  • STP 导致端口阻塞:在容器网络中关闭 STP(stp_state 0)。
  • VLAN 过滤不生效:确认内核版本 ≥ 3.8;检查 vlan_filtering 是否已启用。
  • Bridge 转发性能低:检查是否启用了 iptables 的 bridge-nf-call 功能(sysctl net.bridge.bridge-nf-call-iptables=0)。
# 快速排查命令集
# 1. 查看 Bridge 状态
bridge link show
bridge fdb show

# 2. 查看端口 MAC 学习情况
brctl showmacs br0

# 3. 检查 iptables 对 Bridge 的影响
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables

# 4. 抓包分析(在 Bridge 上)
tcpdump -i br0 -e -n