JasonWang's Blog

MACVLAN详解

字数统计: 2k阅读时长: 8 min
2026/01/17

MACVLAN(MAC Virtual LAN)是Linux内核提供的一种L2层的网络虚拟化技术,它允许在单个物理接口上创建多个虚拟子接口,每个子接口拥有独立的 MAC地址。与Linux Bridge相比,MACVLAN 减少了数据包处理层级,提供了更简洁的网络架构和更好的性能。MACVLAN通常用于容器网络、虚拟机网络等场景,为容器和虚拟机提供访问外部网络的能力。

本文结合实际的业务场景,基于Linux 5.15内核源码,深入分析MACVLAN的实现原理和工作机制。

MACVLAN 简介

MACVLAN允许在单个物理网络接口(父接口)上创建多个虚拟子接口。每个子接口拥有独立的 MAC 地址,对网络中的其他设备而言,它们就像是独立的物理设备。相对其他网络虚拟化技术,MACVLAN具有如下几个优势:

  • 独立 MAC 地址: 每个子接口拥有唯一的 MAC 地址,可被网络独立识别
  • 多种工作模式: 支持私有、VEPA、桥接、直通、源地址五种模式
  • 高性能 : 数据包无需经过额外的桥接层,减少处理开销
  • 简化拓扑 : 无需创建 Linux Bridge,直接通过物理接口通信

MACVLAN实现原理

Linux内核中,对应有MACVLAN的网络驱动,核心代码位于drivers/net/macvlan.c文件中,主要提供了如下两个关键的数据结构:

  • struct macvlan_dev: MACVLAN设备,用于表示一个MACVLAN子设备,包含了MACVLAN设备、MACVLAN端口等信息
  • struct macvlan_port: MACVLAN端口,表示一个MACVLAN端口,包含了MACVLAN子设备的列表和MAC地址哈希表等信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// drivers/net/macvlan.c
struct macvlan_dev {
struct net_device *dev; // MACVLAN设备
struct net_device *lowerdev; // 物理父设备
struct macvlan_port *port; // 所属的端口
struct hlist_node hlist; // 哈希链表节点
struct list_head list; // 设备链表节点
enum macvlan_mode mode; // 工作模式
u16 flags; // 设备标志
struct macvlan_source_entry __rcu *source_list;
unsigned int macaddr_count;
};

struct macvlan_port {
struct net_device *dev; // 物理父设备
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; // MAC地址哈希表
struct list_head vlans; // MACVLAN设备链表
struct rcu_head rcu; // RCU保护
bool passthru; // 是否直通模式
int count; // MACVLAN设备数量
};

MACVLAN虚拟网卡来说,主要的处理都集中在数据链路层(L2),我们以MACVLAN设备注册与数据包发送为例说明MACVLAN的实现原理。

MACVLAN 的注册流程

MACVLAN设备的创建和注册过程如下,主要包括如下几个步骤:

  • 查找并验证父设备:检查父设备是否存在、是否支持MACVLAN
  • 初始化 MACVLAN 设备:创建 MACVLAN 设备、初始化MACVLAN端口等
  • 注册 MACVLAN 设备:将 MACVLAN 设备注册到内核网络设备列表中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// drivers/net/macvlan.c
static int macvlan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev;
struct macvlan_port *port;
int err;

// 1. 查找并验证父设备
if (!tb[IFLA_LINK])
return -EINVAL;
lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
if (!lowerdev)
return -ENODEV;

// 2. 检查父设备是否支持 MACVLAN
if (!macvlan_port_exists(lowerdev)) {
// 首次在此设备上创建 MACVLAN,初始化端口
err = macvlan_port_create(lowerdev);
if (err)
return err;
}
port = macvlan_port_get_rtnl(lowerdev);

// 3. 初始化 MACVLAN 设备
vlan->lowerdev = lowerdev;
vlan->dev = dev;
vlan->port = port;
vlan->mode = MACVLAN_MODE_VEPA; // 默认 VEPA 模式

// 4. 设置 MAC 地址
if (tb[IFLA_ADDRESS])
eth_hw_addr_set(dev, nla_data(tb[IFLA_ADDRESS]));
else
eth_hw_addr_random(dev);

// 5. 将设备加入端口列表
list_add_tail_rcu(&vlan->list, &port->vlans);
macvlan_hash_add(vlan);
port->count++;

// 6. 注册网络设备
err = register_netdevice(dev);
if (err)
goto cleanup;

return 0;

cleanup:
macvlan_delete(vlan);
return err;
}

数据包接收流程

当物理接口接收到数据包时,一般会通过网络软中断进行处理,然后再发送到MACVLAN设备,MACVLAN的处理流程如下:

  • 获取MACVLAN端口结构:通过skb->dev获取MACVLAN端口结构
  • 处理多播/广播包:MACVLAN端口处理多播/广播包的逻辑
  • 源地址检查:防止 MAC 地址欺骗
  • 处理数据包:MACVLAN端口处理数据包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// drivers/net/macvlan.c
static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
{
struct macvlan_port *port;
struct sk_buff *skb = *pskb;
const struct ethhdr *eth = eth_hdr(skb);
const struct macvlan_dev *vlan;

// 获取 MACVLAN 端口结构
port = macvlan_port_get_rcu(skb->dev);
if (!port)
return RX_HANDLER_PASS;

// 处理多播/广播包
if (is_multicast_ether_addr(eth->h_dest)) {
return macvlan_handle_multicast(pskb, port, eth);
}

// 源地址检查(防止 MAC 地址欺骗)
macvlan_forward_source(skb, port, eth->h_source);

// 直通模式:使用第一个 MACVLAN 设备
if (macvlan_passthru(port))
vlan = list_first_or_null_rcu(&port->vlans, struct macvlan_dev, list);
else
vlan = macvlan_hash_lookup(port, eth->h_dest);

if (!vlan || vlan->mode == MACVLAN_MODE_SOURCE)
return RX_HANDLER_PASS;

// 将数据包交给对应的 MACVLAN 设备处理
skb->dev = vlan->dev;
skb->pkt_type = PACKET_HOST;

return RX_HANDLER_ANOTHER;
}

数据的发送流程主要在macvlan_queue_xmit函数中,不再赘述,有兴趣的可以自己研究下。

工作模式

MACVLAN 支持五种工作模式,使用位掩码定义:

  • MACVLAN_MODE_PRIVATE: 私有模式,同一父设备下的虚拟子网卡之间完全隔离,且子网卡与父接口所在主机也完全隔离,所有子网卡仅能与外部网络通信,数据包无需在主机内做任何转发
  • MACVLAN_MODE_VEPA: 虚拟以太网端口聚合模式,禁止同 MACVLAN实例的子网卡之间直接通信,所有子网卡的数据包(包括同组互访)都必须通过物理网卡转发到外部交换机,由交换机完成数据包的转发 / 过滤 / 隔离,再回传给目标子网卡
  • MACVLAN_MODE_BRIDGE: 桥接模式,同父设备下的 MACVLAN 可直接通信,组成一个虚拟的网络,子网卡之间的数据可以直接通过内核转发,无需经过物理网卡与外部交换机
  • MACVLAN_MODE_PASSTHRU: 一个物理网卡仅能创建一个虚拟子网卡,子网卡直接 “直通”物理父接口的二层特性,可复用父接口的 MAC 地址(或指定专属 MAC),子网卡的二层流量直接映射到物理网卡,内核仅做简单的数据包透传
  • MACVLAN_MODE_SOURCE: 基于源MAC地址过滤网络报文
1
2
3
4
5
6
7
8
// include/uapi/linux/if_macvlan.h
enum macvlan_mode {
MACVLAN_MODE_PRIVATE = 1,
MACVLAN_MODE_VEPA = 2,
MACVLAN_MODE_BRIDGE = 4,
MACVLAN_MODE_PASSTHRU = 8,
MACVLAN_MODE_SOURCE = 16,
};

应用场景

MACVLAN作为Linux下轻量级的网络虚拟化技术,在容器、虚拟机、虚拟化网络等场景中得到了广泛的应用。

容器网络

让容器直接连接到物理网络,获得独立 IP:

1
2
3
4
5
6
7
8
9
10
11
# 创建MACVLAN网络
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
macvlan_net

# 运行容器并连接到MACVLAN网络
docker run --network macvlan_net \
--ip=192.168.1.100 \
-it ubuntu:latest

虚拟机网络

为 KVM/QEMU 虚拟机提供直接网络访问:

1
2
3
4
5
# 创建MACVLAN接口
ip link add macvlan0 link eth0 type macvlan mode bridge
ip link set macvlan0 address 00:11:22:33:44:55
ip link set macvlan0 up
ip addr add 192.168.1.200/24 dev macvlan0

网络隔离

为不同服务创建独立的网络接口,实现服务间隔离:

1
2
3
4
5
6
7
8
9
# 为不同服务创建独立的MACVLAN接口
ip link add web-vlan link eth0 type macvlan mode private
ip link add db-vlan link eth0 type macvlan mode private
ip link add cache-vlan link eth0 type macvlan mode private

# 配置IP地址
ip addr add 10.0.1.10/24 dev web-vlan
ip addr add 10.0.1.20/24 dev db-vlan
ip addr add 10.0.1.30/24 dev cache-vlan

总结

MACVLAN 是一种轻量级的网络虚拟化技术,通过在单个物理接口上虚拟出多个独立 MAC 地址的子接口,每个网卡都共享父接口的网络链路与物理带宽。相比 Linux Bridge,它减少了数据包处理层级,在性能和简洁性上都具有优势。支持五种不同的工作模式(PRIVATE、VEPA、BRIDGE、PASSTHRU、SOURCE)适应了不同的隔离和通信需求,使其在容器网络、虚拟机网络、服务隔离等场景中得到广泛应用。理解其内核实现机制,有助于在实际部署中做出更合理的网络架构设计。

参考文献

  1. Linux内核源码: https://github.com/torvalds/linux/tree/master/drivers/net/macvlan.c
  2. MACVLAN内核文档: https://www.kernel.org/doc/Documentation/networking/macvlan.txt
  3. Docker MACVLAN文档: https://docs.docker.com/network/macvlan/
  4. Linux IP link

原文作者:Jason Wang

更新日期:2026-01-30, 19:07:07

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

CATALOG
  1. 1. MACVLAN 简介
  2. 2. MACVLAN实现原理
    1. 2.1. MACVLAN 的注册流程
    2. 2.2. 数据包接收流程
    3. 2.3. 工作模式
  3. 3. 应用场景
    1. 3.1. 容器网络
    2. 3.2. 虚拟机网络
    3. 3.3. 网络隔离
  4. 4. 总结
  5. 5. 参考文献