Bridge

bridge一般叫网桥,它也是一种虚拟网络设备,所以具有虚拟网络设备的特征,可以配置 IP、MAC 地址等。与其他虚拟网络设备不同的是,bridge 是一个虚拟交换机,和物理交换机有类似的功能。bridge 一端连接着协议栈,另外一端有多个端口,数据在各个端口间转发是基于 MAC 地址。

bridge 可以工作在二层(链路层),也可以工作在三层(IP 网路层)。默认工作在二层。默认情况下,其工作在二层,可以在同一子网内的的不同主机间转发以太网报文;当给 bridge 分配了 IP 地址,也就开启了该 bridge 的三层工作模式。在 Linux 下,你可以用iproute2brctl命令对 bridge 进行管理。

创建 bridge 与创建其他虚拟网络设备类似,只需要制定 type 为 bridge:

1
2
# ip link add br0 type bridge
# ip link set br0 up

但是这样创建出来的 bridge 一端连接着协议栈,其他端口什么也没有连接,因此我们需要将其他设备连接到该 bridge 才能有实际的功能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# ip link add veth0 type veth peer name veth1
# ip addr add 20.1.0.10/24 dev veth0
# ip addr add 20.1.0.11/24 dev veth1
# ip link set veth0 up
# ip link set veth1 up
# 将veth0连接到br0
# ip link set dev veth0 master br0
# 通过 bridge link 命令可以看到bridge上连接了哪些设备
# bridge link
6: veth0 state UP : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2

network-device-bridge-2.jpg
network-device-bridge-2.jpg

事实上,一旦 br0 和 veth0 连接后,它们之间将变成双向通道,但是内核协议栈和 veth0 之间变成了单通道,协议栈能发数据给 veth0,但 veth0 从外面收到的数据不会转发给协议栈 ,同时 br0 的 MAC 地址变成了 veth0 的 MAC 地址。我们可以验证一下:

1
2
3
4
5
6
# ping -c 1 -I veth0 20.1.0.11
PING 20.1.0.11 (20.1.0.11) from 20.1.0.10 veth0: 56(84) bytes of data.
From 20.1.0.10 icmp_seq=1 Destination Host Unreachable

--- 20.1.0.11 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

如果我们使用 tcpdump 在 br0 上抓包就会发现:

1
2
3
4
# tcpdump -n -i br0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:45:48.225459 ARP, Reply 20.1.0.10 is-at a2:85:26:b3:72:6c, length 28

可以看到 veth0 收到应答包后没有给协议栈,而是直接转发给 br0,这样协议栈得不到 veth1 的 mac 地址,从而 ping 不通。br0 在 veth0 和协议栈之间数据包给拦截了。但是如果我们给 br 配置 IP,会怎么样呢?

1
2
# ip addr del 20.1.0.10/24 dev veth0
# ip addr add 20.1.0.10/24 dev br0

这样,网络结构就变成了下面这样:

network-device-bridge-3.jpg
network-device-bridge-3.jpg

这时候再通过 br0 来 ping 一下 veth1,会发现结果可以通:

1
2
3
4
5
6
7
# ping -c 1 -I br0 20.1.0.11
PING 20.1.0.11 (20.1.0.11) from 20.1.0.10 br0: 56(84) bytes of data.
64 bytes from 20.1.0.11: icmp_seq=1 ttl=64 time=0.121 ms

--- 20.1.0.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.121/0.121/0.121/0.000 ms

其实当去掉 veth0 的 IP 地址,而给 br0 配置了 IP 之后,协议栈在路由的时候不会将数据包发给 veth0,为了表达更直观,我们协议栈和 veth0 之间的连接线去掉,这时候的 veth0 相当于一根网线。

在现实中,bridge 常用的使用场景:

虚拟机

典型的虚拟机网络实现就是通过 TUN/TAP 将虚拟机内的网卡同宿主机的 br0 连接起来,这时 br0 和物理交换机的效果类似,虚拟机发出去的数据包先到达 br0,然后由 br0 交给 eth0 发送出去,这样做数据包都不需要经过 host 机器的协议栈,运行效率非常高。

network-device-vm.jpg
network-device-vm.jpg

容器

而对于容器网络来说,每个容器的网络设备单独的网络命名空间中,所以很好地不同容器的协议栈,我们在接下来的笔记中进一步讨论不同的容器实现。

network-device-docker.jpg
network-device-docker.jpg

参考资料