Skip to content

第一百二十四章:虚拟之船

问道期

涉及内核源码:

林小源在港口看到了一些奇怪的船——它们没有船体,没有桅杆,只有一根连接两端的绳索。

"这些是什么?"

"veth。"一个年轻的声音回答。

林小源看到一个穿着工装的年轻人蹲在码头边,正在检查那些奇怪的"船"。年轻人的衣服上绣着虚拟网络设备的图样——veth、bridge、tun/tap、vlan。

"虚拟网络设备。"年轻人说,"它们不是物理网卡,但行为类似。veth 是最简单的一种——虚拟以太网对。一端发送的数据,从另一端接收。"

"就像一根管道。"

"对,但更准确地说,是一根虚拟网线。"年轻人拿起一根 veth,两端各有一个接口,"一端放在命名空间 A,另一端放在命名空间 B。数据从 A 进去,从 B 出来。"

"除了 veth,还有哪些虚拟设备?"林小源问。

年轻人指向码头中央的一个巨大平台:"看到那个了吗?bridge——虚拟交换机。它连接多个网络设备,根据 MAC 地址转发数据包。"

林小源看着那个平台——无数 veth pair 的一端连接在上面,数据包在平台内部根据 MAC 地址表被转发到正确的端口。

"bridge 学习 MAC 地址。"年轻人说,"收到一个数据包,记住源 MAC 和端口的对应关系。下次要转发到那个 MAC,直接从对应的端口发出去。和物理交换机一样。"

"tun/tap 呢?"

年轻人从口袋里掏出两个小装置:"tun 是三层设备——用户空间程序可以读写 IP 包。tap 是二层设备——可以读写以太网帧。VPN 软件常用 tun——OpenVPN、WireGuard。用户空间程序通过 /dev/net/tun 读写数据包。"

"用户空间也能处理网络数据?"

"对。"年轻人说,"tun/tap 是用户空间和内核网络栈之间的桥梁。VPN 程序在用户空间加密数据,通过 tun 发给内核,内核再通过物理网卡发出去。"

"还有 vlan。"年轻人指向码头的另一侧。

林小源看到码头被分成了几个区域,每个区域用不同颜色的旗帜标记。

"虚拟局域网。"年轻人说,在一个物理网络上隔离流量。ip link add link eth0 name eth0.100 type vlan id 100——这会在 eth0 上创建一个 vlan 100 的子接口。不同 vlan 的流量互不可见。"

"macvlan 呢?"

"在一个物理接口上创建多个虚拟接口,每个有独立的 MAC 地址。"年轻人说,"和 bridge 不同,macvlan 不需要学习——每个虚拟接口直接有固定的 MAC。适合容器网络——每个容器一个 macvlan 接口,直接和物理网络通信,不需要 bridge。"

林小源看着码头上各种各样的虚拟设备,忽然明白了——容器和虚拟化网络的基础就是这些虚拟设备。veth 连接命名空间,bridge 交换流量,tun/tap 连接用户空间,vlan 隔离网络。

"它们都不是物理设备。"年轻人说,"但对内核来说,它们和物理网卡没有区别——都实现了 接口,都有 。内核不关心你是物理的还是虚拟的——只要实现了接口,就是网络设备。"

c
/*
 * 虚拟网络设备:
 *
 * 1. veth
 *    虚拟以太网对
 *    一端发送,另一端接收
 *    连接不同命名空间
 *
 * 2. bridge
 *    虚拟交换机
 *    连接多个网络设备
 *    学习 MAC 地址
 *
 * 3. tun/tap
 *    tun: 三层设备(IP 包)
 *    tap: 二层设备(以太网帧)
 *    用户空间可以读写
 *
 * 4. vlan
 *    虚拟局域网
 *    在物理网络上隔离流量
 *
 * 5. macvlan
 *    在一个物理接口上创建多个虚拟接口
 *    每个有独立的 MAC 地址
 */

printf("=== 虚拟网络设备 — 不是船的\"\" ===\n\n");

printf("虚拟网络设备:\n\n");

printf("1. veth:\n");
printf("   虚拟以太网对\n");
printf("   一端发送,另一端接收\n");
printf("   连接不同命名空间\n\n");

printf("2. bridge:\n");
printf("   虚拟交换机\n");
printf("   连接多个网络设备\n");
printf("   学习 MAC 地址\n\n");

printf("3. tun/tap:\n");
printf("   tun: 三层设备(IP 包)\n");
printf("   tap: 二层设备(以太网帧)\n");
printf("   用户空间可以读写\n\n");

printf("4. vlan:\n");
printf("   虚拟局域网\n");
printf("   在物理网络上隔离流量\n\n");

printf("--- 容器网络拓扑 ---\n");
printf("  容器 1        容器 2\n");
printf("  ┌────┐       ┌────┐\n");
printf("  │eth0│       │eth0│\n");
printf("  └─┬──┘       └─┬──┘\n");
printf("    │             │\n");
printf("  veth0        veth1\n");
printf("    │             │\n");
printf("    └──────┬──────┘\n");
printf("         br0\n");
printf("           │\n");
printf("         eth0\n");
printf("           │\n");
printf("        物理网络\n\n");

printf("--- 创建虚拟设备 ---\n");
printf("veth:\n");
printf("  ip link add veth0 type veth peer name veth1\n\n");
printf("bridge:\n");
printf("  ip link add br0 type bridge\n");
printf("  ip link set veth0 master br0\n\n");
printf("vlan:\n");
printf("  ip link add link eth0 name eth0.100 type vlan id 100\n\n");

printf("--- tun/tap ---\n");
printf("VPN 使用 tun:\n");
printf("  用户空间读写 /dev/net/tun\n");
printf("  数据包经过 tun 设备\n");

道藏笔记

内核启示

虚拟网络设备是容器和虚拟化网络的基础。

虚拟网络设备:

  • veth — 虚拟以太网对,连接命名空间
  • bridge — 虚拟交换机,连接多个设备
  • tun/tap — 用户空间收发数据包
  • vlan — 虚拟局域网,隔离流量

容器网络拓扑:

  • 容器通过 veth pair 连接到 bridge
  • bridge 连接到物理网络

虚拟网络设备是"虚拟之船"——在虚拟世界中航行。


破关试炼

虚拟网络设备之试

物理网卡、veth、bridge 等设备在内核中共同抽象成哪种网络设备结构?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道