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,并挂到隧道对象上。如果映射缺失,入方向报文会被丢弃,出方向则无法封装。

SONiC VXLAN 数据面与 SAI 映射关系 本地 VLAN 域 Vlan100 10.10.100.0/24 Vlan200 10.10.200.0/24 Vlan300 10.10.300.0/24 FDB / ARP MAC → 端口 IP → MAC VXLAN_TUNNEL_MAP Vlan100 ↔ VNI 10100 双向映射 Vlan200 ↔ VNI 10200 双向映射 Vlan300 ↔ VNI 10300 双向映射 SAI Tunnel Map VLAN_ID_TO_VNI VNI_TO_VLAN_ID VXLAN 隧道与远端 VTEP Vxlan1 隧道接口 src_ip: 10.0.0.1 (Loopback0) 远端 VTEP dst_ip: 10.0.0.2 VNI 10100 / 10200 / 10300 UDP 4789 封装 SAI Tunnel / Term Table create_tunnel / create_tunnel_term 入方向:VNI → VLAN(解封装) | 出方向:VLAN → VNI(封装) | FDB/ARP 表项由控制面学习并下发至 SAI

四、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_mapVLAN 与 VNI 的映射关系orchagent
sai_tunnel_map_entry具体的映射条目,如 Vlan100 → VNI 10100orchagent
sai_fdb_entry携带隧道信息的 FDB 表项fdbsyncd / orchagent
sai_neighbor_entry携带隧道信息的邻居表项neighsyncd / orchagent

SAI 的抽象使得同一套 SONiC 代码可以运行在不同厂商的 ASIC 上,只要厂商实现了对应的 SAI 接口。实际排障时,可以通过 sai 相关的 debug 命令(如 saiplayer 或 syncd 日志)查看隧道对象是否创建成功、映射表项是否完整。

实践提示:在 SONiC 中验证 VXLAN 是否正常工作,可以按以下顺序检查:
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 报文是否正常收发。
常见故障:如果 VXLAN 隧道已建立但业务不通,优先检查 VLAN 与 VNI 映射是否双向完整。SONiC 中只配置了 VLAN_ID_TO_VNI 而缺少 VNI_TO_VLAN_ID 时,入方向报文会被丢弃,表现为“能发不能收”。此外,源地址若未在 underlay 中发布,远端 VTEP 无法回程,也会导致单向不通。

总结来看,SONiC 的 VXLAN 实现是一条从 CONFIG_DB 到 APPL_DB、再到 SAI 和 ASIC 的完整下发链路。隧道接口和 VTEP 解决“在哪里封装”,VLAN-VNI 映射解决“封装成什么”,FDB/ARP 解决“发给谁”,SAI 则解决“怎么落到硬件”。理解这四层关系,就能在配置和排障时快速定位问题所在。