第11篇:VLAN 管理的实现
第11篇:VLAN 管理的实现
VLAN:虚拟的隔离墙
如果把交换机比作一栋办公楼,VLAN 就是楼里的隔断墙。物理上所有人都在同一栋楼,但逻辑上你把财务部和研发部隔开了——两个部门的广播互不干扰。
在数据中心里 VLAN 的核心价值:
- 广播域隔离:一个 VLAN 内的广播不会扩散到其他 VLAN
- 安全边界:不同租户/业务的流量天然隔离
- 灵活分组:同一个物理端口可以同时属于多个 VLAN(Trunk 模式)
SONiC 支持 IEEE 802.1Q 标准 VLAN,VLAN ID 范围 1-4094。实现上分为两个层面:Linux 内核层(用于 CPU 流量)和 ASIC 硬件层(用于数据面转发)。两者必须保持一致。
数据模型:VLAN 和 VLAN_MEMBER
SONiC 用两张 CONFIG_DB 表来描述 VLAN 配置:
VLAN 表:定义 VLAN 本身
{
"VLAN|Vlan100": {
"vlanid": "100",
"admin_status": "up",
"mtu": "9100"
},
"VLAN|Vlan200": {
"vlanid": "200",
"admin_status": "up"
}
}
关键字段:
vlanid:802.1Q VLAN IDadmin_status:管理状态mtu:最大传输单元,影响该 VLAN 所有成员接口
VLAN_MEMBER 表:定义哪些端口属于哪个 VLAN
{
"VLAN_MEMBER|Vlan100|Ethernet4": {
"tagging_mode": "untagged"
},
"VLAN_MEMBER|Vlan100|Ethernet8": {
"tagging_mode": "tagged"
},
"VLAN_MEMBER|Vlan200|Ethernet8": {
"tagging_mode": "tagged"
}
}
tagging_mode 决定了帧进出端口时 VLAN tag 的处理方式(后面详细讲)。
VLAN_INTERFACE 表:给 VLAN 分配 IP
当 VLAN 需要三层路由功能时,给它配 IP 地址:
{
"VLAN_INTERFACE|Vlan100": {},
"VLAN_INTERFACE|Vlan100|10.0.100.1/24": {}
}
这会让 SONiC 在硬件中创建一个 SVI(Switch Virtual Interface)——既是 VLAN 的网关,又是路由器接口。
VlanMgr:Linux 侧的配置者
VlanMgr 是 swss 容器里的一个 manager 进程,负责在 Linux 内核层面创建和管理 VLAN 相关的网络对象。
为什么需要 Linux 层面的 VLAN?
SONiC 的 CPU 流量(ping、SSH、BGP 报文等)走的是 Linux 内核协议栈。要让 CPU 能收发 VLAN 流量,必须在 Linux 里创建对应的网络设备:
Bridge— 一个 VLAN 对应一个 Linux bridge(或用 VLAN-aware bridge)Bridge port— 物理端口加入 bridgeVLAN sub-interface— 在端口上创建 .100、.200 等子接口
VlanMgr 的工作流程
CONFIG_DB (VLAN, VLAN_MEMBER)
↓ 订阅变化
VlanMgr 读取配置
↓
通过 netlink 在 Linux 内核中:
1. 创建 bridge 设备 "Bridge"(一次性)
2. 设置 bridge 为 VLAN-aware 模式
3. 将物理端口加入 bridge
4. 配置端口的 VLAN 成员关系和 tag 模式
↓
写入 APP_DB,通知 VlanOrch 做硬件配置
VlanMgr 的关键设计:它不直接配硬件。它只管 Linux 内核那一侧,然后把"期望状态"写入 APPL_DB,让 VlanOrch 去搞定硬件。这就是 SONiC 一贯的分层思路。
VLAN-aware Bridge 模式
SONiC 使用 Linux 的 VLAN-aware bridge 模式(而不是 legacy 模式)。区别:
| 模式 | 描述 | SONiC 的选择 |
|---|---|---|
| Legacy (per-VLAN bridge) | 每个 VLAN 创建一个独立的 bridge | ❌ 不用 |
| VLAN-aware bridge | 一个 bridge 管理所有 VLAN | ✅ 使用 |
VLAN-aware 模式的优势:
- 只需一个 bridge 设备,减少内核对象数量
- 端口只需加入 bridge 一次,用
bridge vlan命令管理 VLAN 成员 - 性能更好(内核查找路径更短)
VlanOrch:硬件侧的编程者
VlanOrch 在 orchagent 内部,负责把 VLAN 配置翻译成 SAI API 调用,编程到 ASIC 硬件。
创建 VLAN
当 VlanOrch 收到一个新 VLAN 的创建请求:
// 1. 创建 SAI VLAN 对象
sai_attribute_t attr;
attr.id = SAI_VLAN_ATTR_VLAN_ID;
attr.value.u16 = 100;
sai_vlan_api->create_vlan(&vlan_oid, switch_id, 1, &attr);
// 2. 记录 VLAN OID → VLAN ID 的映射
m_vlans[100] = vlan_oid;
添加 VLAN 成员
把端口加入 VLAN 需要创建一个 VLAN member 对象:
sai_attribute_t attrs[2];
// 关联到哪个 VLAN
attrs[0].id = SAI_VLAN_MEMBER_ATTR_VLAN_ID;
attrs[0].value.oid = vlan_oid;
// 关联到哪个 bridge port
attrs[1].id = SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID;
attrs[1].value.oid = bridge_port_oid;
sai_vlan_api->create_vlan_member(&member_oid, switch_id, 2, attrs);
配置 tag 模式
VLAN member 还需要设置 tagging 模式:
sai_attribute_t tag_attr;
tag_attr.id = SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE;
tag_attr.value.s32 = SAI_VLAN_TAGGING_MODE_UNTAGGED; // 或 TAGGED
Access 模式 vs Trunk 模式
这是交换机端口最基础的两种 VLAN 配置模式,理解它们的区别对网络设计至关重要。
Access 模式:面向终端设备
服务器 ←→ [Ethernet4: Access VLAN 100] ←→ 交换机内部
- 端口只属于一个 VLAN
- 进来的帧没有 VLAN tag(服务器不需要知道 VLAN 的存在)
- 交换机收到帧后,内部打上 VLAN 100 的 tag 进行转发
- 出去时把 tag 剥掉,服务器看到的是普通以太帧
Access 模式就像写字楼的门禁卡——你刷卡进门后自动被分配到对应楼层,不需要自己按电梯。
Trunk 模式:面向交换机互联
交换机A ←→ [Ethernet48: Trunk, 允许 VLAN 100,200,300] ←→ 交换机B
- 端口属于多个 VLAN
- 帧带着 VLAN tag 通过端口(4 字节 802.1Q header)
- 两端交换机通过 tag 区分不同 VLAN 的流量
- 通常还有一个 native VLAN:没有 tag 的帧属于这个 VLAN
Trunk 模式像高速公路的多车道——每辆车(帧)带着车道标识(VLAN tag),收费站(交换机)根据标识决定去向。
在硬件中的实现差异
| 行为 | Access 端口 | Trunk 端口 |
|---|---|---|
| 入口:无 tag 帧 | 打上本端口 PVID | 归入 native VLAN |
| 入口:带 tag 帧 | 通常丢弃 | 检查是否在允许列表 |
| 出口 | 剥掉 tag | 保留 tag(native VLAN 除外) |
| SAI 配置 | UNTAGGED member | TAGGED member |
在 SAI 层面,access 和 trunk 的区别最终体现在端口的 port VLAN ID (PVID) 和 VLAN member 的 tagging mode 上:
// 设置端口的 PVID(access 模式必须设置)
sai_attribute_t pvid_attr;
pvid_attr.id = SAI_PORT_ATTR_PORT_VLAN_ID;
pvid_attr.value.u16 = 100;
sai_port_api->set_port_attribute(port_oid, &pvid_attr);
VLAN 配置的完整数据流
一条 VLAN 配置从用户输入到硬件生效,经过的路径:

用户执行: config vlan add 100
↓
CLI 写入 CONFIG_DB: "VLAN|Vlan100"
↓ (订阅)
VlanMgr 收到通知
↓
VlanMgr 在 Linux 内核创建 bridge VLAN
VlanMgr 写入 APPL_DB: "VLAN_TABLE:Vlan100"
↓ (订阅)
VlanOrch 收到通知
↓
VlanOrch 调用 SAI: create_vlan(vlan_id=100)
↓
SAI 驱动把 VLAN 写入 ASIC 硬件表
↓
syncd 确认后写入 ASIC_DB
添加 VLAN 成员的路径类似,但涉及更多步骤(创建 bridge port、设置 tag 模式、设置 PVID 等)。
VLAN 与 STP 的交互
STP(Spanning Tree Protocol)防止二层环路。在有 VLAN 的网络中,STP 有两种运行方式:
传统 STP (CST)
所有 VLAN 共用一棵生成树。简单但不灵活——如果某条链路被 STP 阻塞,所有 VLAN 都不能用它。
Per-VLAN STP (PVST/PVST+)
每个 VLAN 独立计算生成树。VLAN 100 可能阻塞链路 A,VLAN 200 可能阻塞链路 B,实现流量负载分担。
SONiC 的 STP 支持
SONiC 社区版的 STP 支持相对有限:
- 早期版本不支持 STP(依赖数据中心无环拓扑设计,如 CLOS 架构)
- 社区贡献了 PVST 支持(通过 stpd 容器)
- stpd 与 VlanOrch 交互:当 STP 把某个端口置为 blocking 状态时,需要通知硬件停止在该端口转发该 VLAN 的流量
STP 端口状态在 SAI 中的体现:
// 设置端口在某 VLAN 的 STP 状态
sai_attribute_t stp_attr;
stp_attr.id = SAI_STP_PORT_ATTR_STATE;
stp_attr.value.s32 = SAI_STP_PORT_STATE_BLOCKING; // 或 FORWARDING, LEARNING
sai_stp_api->set_stp_port_attribute(stp_port_oid, &stp_attr);
在实际数据中心部署中,很多运营商选择不使用 STP,而是依赖 CLOS(Spine-Leaf)拓扑天然无环的特性,通过 ECMP 做负载分担。这种设计下,VLAN 通常限制在单个 Leaf 交换机对(MLAG pair)内部,不跨 Spine。
VLAN 相关的常见问题
Q1: VLAN 最多能创建多少个?
理论上 4094 个(1-4094),但实际受限于:
- ASIC 硬件资源(VLAN 表、VLAN member 表大小)
- 每个 VLAN 消耗的其他资源(STP 实例、广播域的 MAC 表占用)
- 实际部署中,数据中心单台交换机通常用几十到几百个 VLAN
Q2: 一个端口最多属于多少个 VLAN?
取决于 ASIC 的 VLAN member 表大小。理论上一个 trunk 端口可以允许所有 4094 个 VLAN,但实际很少这么做(安全和管理考虑)。
Q3: VLAN 和 VxLAN 的关系?
VLAN 是二层隔离,限制在本地交换机或 MLAG 范围内。VxLAN 是 VLAN 的"升级版"——用三层封装(UDP)把二层帧跨网络传输,支持最多 1600 万个网络标识(24-bit VNI)。在 SONiC 中,VxLAN tunnel 通常映射到本地 VLAN。
实战命令
# 创建 VLAN
config vlan add 100
# 添加成员(untagged)
config vlan member add 100 Ethernet4
# 添加成员(tagged)
config vlan member add 100 Ethernet8 --tagged
# 查看 VLAN 配置
show vlan brief
# 查看 VLAN 的 Linux 状态
bridge vlan show
# 查看硬件中的 VLAN(通过 Redis)
redis-cli -n 1 keys "*VLAN*"
小结
VLAN 管理看起来简单——不就是给端口分个组吗?但在 SONiC 里,它涉及:
- 双层实现:Linux bridge(CPU 流量)+ SAI 硬件(数据面流量)必须同步
- 多角色协作:VlanMgr 管内核、VlanOrch 管硬件、CLI 管配置
- 模式差异:Access/Trunk 在硬件编程上有本质区别
- 生态联动:与 STP、FDB、路由(SVI)、VxLAN 等功能深度交互
理解了 VLAN 的实现,你就理解了 SONiC “CONFIG_DB → Manager → APPL_DB → Orch → SAI” 这条标准配置流水线的经典模式。
参考资料
- SONiC VLAN HLD: https://github.com/sonic-net/SONiC/blob/d427063d68b45f16bd6dfcfcb98b664993fe8659/doc/vpp/vlan-bvi-hld.md
- IEEE 802.1Q Standard: https://standards.ieee.org/standard/802_1Q-2018.html
- Linux VLAN-aware Bridge: https://docs.kernel.org/networking/bridge.html
- SONiC STP HLD: https://github.com/sonic-net/SONiC/blob/master/doc/stp/SONiC_PVST_HLD.md
*上一篇:第10篇:FDB 与 MAC 地址学习
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)