3. SONiC 中的 VXLAN 实现机制
在 SONiC 中,VXLAN 并不是一个独立运行的协议进程,而是由 SONiC 控制面(orchagent + 各 orch 模块) 通过 SAI(Switch Abstraction Interface) 把隧道、映射表、转发表项下发到 ASIC 的。理解 SONiC 的 VXLAN 实现,关键要抓住五条主线:隧道接口的创建、VTEP 的配置、VLAN 与 VNI 的映射、FDB/ARP 表项的管理,以及 SAI 在其中扮演的抽象角色。下面按数据面的实际落地顺序展开。
一、VXLAN 隧道接口的创建
SONiC 中的 VXLAN 隧道接口是一个逻辑三层接口,通常命名为 Vxlan1 或 vtep1。它由 intfmgrd 与 vxlanmgrd 协同创建,配置来源是 CONFIG_DB 中的 VXLAN_TUNNEL 表。一个典型的配置如下:
{
"VXLAN_TUNNEL": {
"vtep1": {
"src_ip": "10.0.0.1"
}
},
"VXLAN_TUNNEL_MAP": {
"vtep1|map_100_Vlan100": {
"vni": "100",
"vlan": "Vlan100"
}
}
}
其中 src_ip 是本端 VTEP 的源地址,必须是一个已存在于内核、且被路由可达的本地地址(通常绑定在 Loopback0 上)。vxlanmgrd 读取该表后,通过 SAI 的 create_tunnel 创建隧道对象,再通过 create_tunnel_term_table_entry 创建隧道终结表项,把远端 VTEP 地址与本端 VTEP 地址关联起来。隧道接口创建完成后,内核中会出现一个 vxlan 类型的 netdev,SONiC 会把它加入对应的 VRF 或默认路由域。
二、VTEP 配置与源地址选择
VTEP 的配置核心是 源 IP 地址。在 SONiC 中,源地址通常来自 Loopback0,因为 Loopback 接口始终 up,且可通过 underlay 路由(如 BGP、OSPF)被远端 VTEP 访问。配置时需要注意三点:
- 源地址必须是本设备上真实存在的地址,否则 SAI 创建隧道会失败;
- 源地址所在网段必须通过 underlay 网络可达远端 VTEP;
- 如果使用 IPv6 作为 VTEP 地址,需要在 CONFIG_DB 中显式指定地址族。
远端 VTEP 地址不需要在本地逐条配置,而是由控制面(如 EVPN 的 Type-3 路由)动态学习,或者通过静态方式在 VXLAN_TUNNEL 的 src_ip 之外补充 dst_ip 字段。SONiC 默认支持动态学习,这也是 EVPN 场景下最常用的方式。
三、VLAN 与 VNI 的映射表
VLAN 与 VNI 的映射是 VXLAN 实现中最容易出错的一环。SONiC 使用 VXLAN_TUNNEL_MAP 表来维护映射关系,每一条映射把一个 VLAN 和一个 VNI 绑定。映射的方向是双向的:
- 入方向:收到 VXLAN 报文后,根据 VNI 查找映射表,剥离 VXLAN 头,把内层帧送入对应 VLAN;
- 出方向:从某个 VLAN 收到帧后,根据映射表查找 VNI,封装 VXLAN 头,目的地址为远端 VTEP。
映射表在 SAI 中对应 sai_tunnel_map 对象,分为 SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI 和 SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID 两个方向。SONiC 会为每个映射创建一对 map entry,并挂到隧道对象上。如果映射缺失,入方向报文会被丢弃,出方向则无法封装。
四、FDB 与 ARP 表项管理
VXLAN 场景下的 FDB 和 ARP 表项与普通二层转发有本质区别:普通 FDB 表项是 MAC → 端口,而 VXLAN 的 FDB 表项是 MAC → 远端 VTEP + VNI。SONiC 通过 fdbsyncd 和 neighsyncd 把内核中的 FDB/ARP 表项同步到 APPL_DB,再由 orchagent 转换为 SAI 的 sai_fdb_entry 和 sai_neighbor_entry。
在 EVPN 场景下,远端 MAC 和 IP 由 BGP EVPN 的 Type-2 路由学习,bgp 容器把结果写入 APPL_DB,orchagent 再下发到 ASIC。此时 FDB 表项的目的地不再是物理端口,而是隧道接口 Vxlan1,并携带 VNI 信息。本地 MAC 则仍然指向物理端口,形成“本地桥接 + 远端隧道”的混合转发模型。
需要特别注意的是 ARP 表项。VXLAN 场景下,ARP 请求通常由控制面代答(ARP Suppression),避免广播泛洪到所有 VTEP。SONiC 支持在 VLAN 接口上开启 arp_suppress,由 neighsyncd 维护的邻居表直接响应 ARP 请求,只有未知单播才走隧道泛洪。
五、SAI 对 VXLAN 的支持
SAI 是 SONiC 与 ASIC 之间的抽象层,VXLAN 相关的 SAI 对象主要包括:
| SAI 对象 | 作用 | 对应 SONiC 模块 |
|---|---|---|
sai_tunnel | 表示一个 VXLAN 隧道,包含源地址、目的地址、封装类型 | vxlanmgrd / orchagent |
sai_tunnel_term_table_entry | 隧道终结表项,匹配远端 VTEP 地址 | orchagent |
sai_tunnel_map | VLAN 与 VNI 的映射关系 | orchagent |
sai_tunnel_map_entry | 具体的映射条目,如 Vlan100 → VNI 10100 | orchagent |
sai_fdb_entry | 携带隧道信息的 FDB 表项 | fdbsyncd / orchagent |
sai_neighbor_entry | 携带隧道信息的邻居表项 | neighsyncd / orchagent |
SAI 的抽象使得同一套 SONiC 代码可以运行在不同厂商的 ASIC 上,只要厂商实现了对应的 SAI 接口。实际排障时,可以通过 sai 相关的 debug 命令(如 saiplayer 或 syncd 日志)查看隧道对象是否创建成功、映射表项是否完整。
1.
show vxlan tunnel 确认隧道接口和源地址;2.
show vxlan vlanvnimap 确认 VLAN 与 VNI 映射;3.
show mac 和 show arp 确认 FDB/ARP 表项是否指向隧道;4.
show ip route 确认远端 VTEP 地址可达;5. 抓包确认 UDP 4789 端口的 VXLAN 报文是否正常收发。
VLAN_ID_TO_VNI 而缺少 VNI_TO_VLAN_ID 时,入方向报文会被丢弃,表现为“能发不能收”。此外,源地址若未在 underlay 中发布,远端 VTEP 无法回程,也会导致单向不通。
总结来看,SONiC 的 VXLAN 实现是一条从 CONFIG_DB 到 APPL_DB、再到 SAI 和 ASIC 的完整下发链路。隧道接口和 VTEP 解决“在哪里封装”,VLAN-VNI 映射解决“封装成什么”,FDB/ARP 解决“发给谁”,SAI 则解决“怎么落到硬件”。理解这四层关系,就能在配置和排障时快速定位问题所在。