第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 ID
  • admin_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 — 物理端口加入 bridge
  • VLAN 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 memberTAGGED 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” 这条标准配置流水线的经典模式。


参考资料


*上一篇:第10篇:FDB 与 MAC 地址学习

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐