[译] Introduction to Linux interfaces for virtual networking (Hangbin, 2017)

Virtual Networking

TOC

Linux 具有丰富的虚拟网络功能,这些功能是构建虚拟机、容器以及云环境的基础。本文将从用法的角度简要地介绍 Linux 中常见的虚拟网络设备,而不涉及代码层面的分析。如果你有一些关于计算机网络的背景知识,你可能会对本文非常感兴趣;如果你想获取虚拟网络接口的列表,可以使用 ip link help 命令。

本文将涉及以下常用的接口,请注意,其中某些接口之间常常会产生一些混淆:(见 TOC)

阅读本文后,您将会了解这些虚拟网络设备是什么,它们之间存在哪些区别,何时使用以及如何创建它们。

Bridge

Linux Bridge 的行为非常像交换机,它可以在其上连接的接口之间转发数据包。Bridge 通常被用于在路由器,网关或主机上的虚拟机以及网络名称空间(network namespace)之间转发数据包。此外,它还支持 STP、VLAN 的过滤器以及多播侦听功能。

bridge

如果你需要在虚拟机、容器以或宿主机之间建立通信,Bridge 将会是一个可用的方案。创建 Bridge 的具体方式如下:

1ip link add br0 type bridge
2ip link set eth0 master br0
3ip link set tap1 master br0
4ip link set tap2 master br0
5ip link set veth1 master br0

以上命令将创建一个 Bridge(br0)设备,并将两个 TAP 设备(tap1tap2),一个 VETH 设备(veth1)一个物理设备 eth0 设为 br0 的从设备(slave),具体如上图所示。

Bonded interface

Linux 的 Bonded 接口提供了一种方式,可以将多个网络接口在逻辑上聚合成单个“被绑定”在一起的接口。被聚合出的接口的具体行为取决于其工作模式,常用的工作模式包括热待机(hot standby)以及负载均衡(load balancing)等。

bond

你可以使用 Bonded 接口来提高你的链接速度,或实现故障转移。创建 Bonded 接口的方式如下:

1ip link add bond1 type bond miimon 100 mode active-backup
2ip link set eth0 master bond1
3ip link set eth1 master bond1

以上命令将创建一个工作在 active-backup 模式下的 bonded 接口(bond1)。你可以在 Linux 内核文档 中找到其他模式的信息。

Team device

类似于 Bonded 接口,team 设备的目的是提供一种机制,来将多个网卡(nic)在链路层(L2 layer)分组为同一个逻辑网卡 (team device)。

team

首先要认识到,team 设备的存在意义并不是为了模仿或者复制 bonded 接口,使用了另一种不同的方式来解决同样的问题,如使用 RCU TX/RX 路径和模块化设计。

译注:RCU 是 Linux 内核中的一种同步机制,它是一种读 - 拷贝 - 更新的技术,用于保护共享数据结构。RCU 的基本思想是先创建一个旧数据的副本,然后 writer 更新这个副本,最后再用新的数据替换掉旧的数据。这种机制的优点是读者不需要获得任何锁就可以访问共享数据结构,而写者在访问共享数据结构时首先拷贝一个副本,然后对副本进行修改,最后使用一个回调机制在适当的时机把指向原来的数据结构的指针指向新的数据结构。

创建 team 设备的方式如下:

1teamd -o -n -U -d -t team0 -c '{"runner": {"name": "activebackup"},"link_watch": {"name": "ethtool"}}'
2ip link set eth0 down
3ip link set eth1 down
4teamdctl team0 port add eth0
5teamdctl team0 port add eth1

以上命令将创建一个 active-backup 模式的 team 设备(team0),并将 eth0eth1 做为 team0 的子设备。

VLAN

VLAN(virtual LAN)通过向网络数据包添加标签来分隔广播域。VLAN 允许网络管理员对相同或不同交换机下的主机进行分组。 VLAN 的数据头如下所示:

vlan01

译注:图中 820.1Q 应为 802.1Q。

当您想在虚拟机、命名空间或主机中区分子网时,可以使用 VLAN 来实现。创建 VLAN 的方式如下:

1ip link add link eth0 name eth0.2 type vlan id 2
2ip link add link eth0 name eth0.3 type vlan id 3

以上命令将创建 VLAN2(eth0.2)和 VLAN3(eth0.3),其拓扑结构如下所示:

vlan02

注意,当配置 VLAN 时,您需要确保连接到主机的交换机能够处理 VLAN 标签。

VXLAN

VXLAN (Virtual eXtensible Local Area Network,虚拟可扩展局域网) 是一种隧道协议,旨在解决 IEEE 802.1q 中 VLAN id 数量受限(4,096)的问题,它描述于 IETF RFC 7348

VXLAN 的网络标识符 VNI 使用了 24 位,因此可以支持 16,777,216 个虚拟局域网。VXLAN 将带有 VXLAN 协议标头的 2 层帧封装到 UDP-IP 数据包中,其结构如下图所示:

vxlan01

VXLAN 通常部署在数据中心中,用于连接不同机架上的虚拟主机,其结构如下:

vxlan02

你可以这样创建 VXLAN:

1ip link add vx0 type vxlan id 100 local 1.1.1.1 remote 2.2.2.2 dev eth0 dstport 4789

更详细的用法可以参考 VXLAN kernel documentation 或者 VXLAN introduction

MACVLAN

VLAN 可以在单个接口上创建多个虚拟接口,其工作方式是使用 VLAN tag 对数据进行过滤。而 MACVLAN 则可以在单个接口上创建多个拥有独立二层地址(Ethernet MAC)的虚拟接口。 在 MACVLAN 出现之前,从虚拟机或命名空间连接到物理网络的方式是创建 TAP 或 VETH 设备,并将其连接到与物理网络连接的网桥上,如下图所示:

br_ns
而使用 MACVLAN,可以在不使用网桥的情况下,将与 MACVLAN 相关联的物理接口直接绑定到名称空间或虚拟机。
macvlan
MACVLAN 有 5 种不同的类型,分别为:

  1. Private:即使外部交换机支持发夹(hairpin)模式,也不允许同一物理接口上的 MACVLAN 实例之间进行通信。
    macvlan_01
  2. VEPA:可通过物理接口将数据从一个 MACVLAN 实例传输到同一物理接口上的另一个 MACVLAN 实例,与之连接的交换机必须支持发夹模式。该模式为默认模式
    macvlan_02
  3. Bridge:在该模式下,所有的接口都可以直接相互连接,而不需要物理接口的对端进行重定向。
    macvlan_03
  4. Passthru:在该模式下,同一个物理接口上只与允许存在一个虚拟接口,且所有的流量都将被转发至虚拟接口。默认情况下,该模式会将底层接口强制设为混杂模式,传递 nopromisc 表示可以防止这种情况。
    macvlan_04
  5. Source:该模式允许设置一个 source mac 地址列表来对数据进行过滤,可以用于创建基于 mac 地址,而非 id 的 VLAN。更详细的说明可以参考 commit message

IPVLAN

IPVLAN 与 MACVLAN 类似,但其虚拟接口具有相同的 MAC 地址。

ipvlan
IPVLAN 支持 L2 和 L3 模式。L2 模式下,IPVLAN 的行为与 bridge 模式下的 MACVLAN 类似,其底层物理接口将充当一个交换机或网桥的角色。
ipvlan_01
而 L3 模式下,其底层物理接口的作用类似于路由器,可以将数据包在虚拟接口之间路由,从而提供了更好的可扩展性。
ipvlan_02

有关何时应该使用 IPVLAN,可以参考 IPVLAN kernel documentation。创建 IPVLAN 的方式如下:

1ip netns add ns0
2ip link add name ipvl0 link eth0 type ipvlan mode l2
3ip link set dev ipvl0 netns ns0

以上命令将创建一个名为 ns0 的命名空间,并在该命名空间中创建一个 L2 层的 IPVLAN 接口(ipvl0)。

MACVTAP/IPVTAP

MACVTAP/IPVTAP是一种新的设备驱动程序,旨在简化虚拟化桥接网络。当在物理接口之上创建MACVTAP/IPVTAP实例时,内核还创建了一个字符设备/dev/tapX,可以像 TUN/TAP 设备一样,供 KVM/QEMU 直接使用。 你可以使用单个的 MACVTAP/IPVTAP 模块替换 TUN/TAP 和 bridge 的组合:

macvtap
MACVLAN/IPVLAN 可以使与主机相连的交换机可以同时感知到 Guest 和 Host。MACVTAP 与 IPVTAP 之间的区别与 MACVLAN/IPVLAN 基本相同。

创建 MACVTAP 实例的方式如下:

1ip link add link eth0 name macvtap0 type macvtap

MACsec

MACsec (Media Access Control Security) 是有线以太网局域网中安全性相关的 IEEE 标准。与 IPsec 类似,作为第 2 层规范,MACsec 同时保护 IP、ARP 以及 DHCP 等协议的流量。MACsec 的标头大致如下:

macsec_01
MACsec 的主要应用场景是保护 LAN 中的所有消息,包括 ARP,NS 和 DHCP。
macsec
配置 MACsec 的方式如下:

1ip link add macsec0 link eth1 type macsec

注意,该命令仅完成了对 MACsec 接口的创建工作,对于更详细的配置,请参考 MACsec introduction by Sabrina Dubroca.

VETH

VETH (virtual Ethernet) 设备是本一种地以太网隧道。该设备总是被成对创建的,如下图所示。在一对设备中的任意一端传入的数据包时,另一端将立刻接收。同时,当任一端关闭时,该设备对的链路状态也为关闭。

veth
VETH 可以在不同网络名称空间之间通信时使用,其配置方法如下:

1ip netns add net1
2ip netns add net2
3ip link add veth1 netns net1 type veth peer name veth2 netns net2

以上命令将创建两个网络名称空间(net1net2),以及一对 VETH 设备(veth1veth2)。其中,veth1 位于 net1 中,veth2 位于 net2 中。为这两个设备分配 IP 地址后,即可在两个名称空间之间进行 ping 或通信。

VCAN

与网络环回设备(lo)类似,VCAN (virtual CAN) 驱动程序提供了虚拟本地 CAN (Controller Area Network) 接口,因此用户可以通过 VCAN 接口发送/接收 can 消息。如今,CAN 主要用于汽车领域。有关更多 CAN 协议信息,请参阅 kernel CAN documentation。 当你需要在本地机器上测试一个 CAN 协议实现的时候,可以使用 VCAN,创建方式如下:

1ip link add dev vcan1 type vcan

VXCAN

与 VETH 驱动类似,VXCAN (虚拟 CAN 隧道) 在两个 VCAN 网络设备之间实现了本地 CAN 流量的隧道。创建 VXCAN 实例时,两个 VXCAN 设备将作为一对创建。当一端发送数据包时,另一端将立刻接收,反之亦然。VXCAN 可以用于跨网络命名空间的通信。设置 VXCAN 实例的方式如下:

1ip netns add net1
2ip netns add net2
3ip link add vxcan1 netns net1 type vxcan peer name vxcan2 netns net2

IPOIB

IPOIB 设备支持 IP-over-InfiniBand 协议。该设备通过 InfiniBand (IB) 传输 IP 数据包,因此你可以将 IB 设备当作一个高速 NIC 来使用。

PoIB 驱动程序支持两种操作模式:datagram 和 connected.。在 datagram 模式下,该设备使用 IB UD (Unreliable Datagram) 传输方式。而在 connected 模式下,使用 IB RC (Reliable Connected) 传输方式。Connected 模式利用了 IB 传输的连接特性,并允许使用 MTU 高达 64k 的 IP 数据包。

有关更多详细信息,可以参阅 IPOIB 内核文档。

当你拥有 IB 设备并希望使用 IP 与远程主机通信时,可以使用 IPOIB 设备。以下为 IPOIB 设备的创建方式:

1ip link add ib0 name ipoib0 type ipoib pkey IB_PKEY mode connected

NLMON

NLMON 是一种 Netlink 监控设备。当需要监视系统 Netlink 消息时,可以使用该设备。创建方式如下:

1ip link add nlmon0 type nlmon
2ip link set nlmon0 up
3tcpdump -i nlmon0 -w nlmsg.pcap

这将创建并启动一个 NLMON 设备,然后使用 tcpdump 命令捕获 Netlink 消息。WireShark 的最新版本可以对 Netlink 消息进行解码。

Dummy interface

Dummy 接口是一种完全虚拟接口,例如环回设备 lo。此类虚拟接口常用于路由数据,而非实际传输。用于测试和调试。使用 dummy 接口可以使不活动的 SLIP(Serial Line Internet Protocol)地址表现得像某个本地程序的真实地址。目前,dummy 接口主要用于测试与调试。其创建方式如下:

1ip link add dummy1 type dummy
2ip addr add 1.1.1.1/24 dev dummy1
3ip link set dummy1 up

IFB

IFB (Intermediate Functional Block) 设备用于集中多源流量,并提供了流量整形(sharping)功能 IFB 设备的创建方式如下:

1ip link add ifb0 type ifb
2ip link set ifb0 up
3tc qdisc add dev ifb0 root sfq
4tc qdisc add dev eth0 handle ffff: ingress
5tc filter add dev eth0 parent ffff: u32 match u32 0 0 action mirred egress redirect dev ifb0

以上命令将创建一个 IFB 设备(ifb0),并将其 root qdisc(Queuing Disciplines)调度器替换为 SFQ(Stochastic Fairness Queueing),这是一种无类别的队列调度算法。然后它在 eth0 接口上添加了一个 ingress qdisc 调度程序,并将所有 ingress 流量重定向到 ifb0。

有关更多 IFB qdisc 的使用方法,可以参考 Linux Foundation wiki

Netdevsim interface

Netdevsim 是一种用于测试各种网络 API 的模拟网络设备。目前,主要专注于测试硬件卸载(offloading)、tc/XDP BPF 以及 SR-IOV。Netdevsim 设备的创建方式如下:

1ip link add dev sim0 type netdevsim
2ip link set dev sim0 up

启用 tc 卸载

1ethtool -K sim0 hw-tc-offload on

载入 XDP BPF 程序

1ip link set dev sim0 xdpoffload obj prog.o

新增用于 SR-IOV 测试的 VFs:

1echo 3 > /sys/class/net/sim0/device/sriov_numvfs
2ip link set sim0 vf 0 mac 

要更改 vf 编号,需要先完全禁用它们:

1echo 0 > /sys/class/net/sim0/device/sriov_numvfs
2echo 5 > /sys/class/net/sim0/device/sriov_numvfs