侧边栏壁纸
  • 累计撰写 53 篇文章
  • 累计收到 3 条评论

数据面转发逻辑分层详解 —— L2/L3/ACL 在 SAI 链路上的完整映射

PacketForge
2026-08-18 / 0 评论 / 1 阅读 /

数据面转发逻辑分层详解 —— L2/L3/ACL 在 SAI 链路上的完整映射

本文回答:一个报文的转发行为(L2 交换、L3 路由、ACL 过滤、上 CPU),在 SONiC 的每一层分别对应什么对象、什么芯片表?配置变更时数据到底流向哪里、会在哪些"墙"上撞住?

0. 总览:转发对象的依赖图

                        ┌────────────── SAI 对象依赖关系 ──────────────┐
                        │                                              │
   L2 线:  VLAN ──→ VLAN Member ──→ Bridge Port ──→ FDB Entry          │
                        │                                              │
   L3 线:  Virtual Router ──→ Router Interface ──→ Neighbor Entry      │
                                   │                                   │
                                   ├──────→ Next Hop ──→ Route Entry   │
                                   │              │                    │
                                   │        Next Hop Group ─┘ (ECMP)   │
                        │                                              │
   ACL 线: ACL Table ──→ ACL Entry ──→ ACL Counter                     │
              │                                                      │
              └→ Table Group ──→ Group Member ──→ 绑定到端口/VLAN/LAG   │
                        │                                              │
   上 CPU:  Hostif Trap ──→ Trap Group(限速) ──→ Hostif(内核网口)      │
                        │                                              │
                        └──────────────────────────────────────────────┘

依赖方向就是删除顺序的约束:守门员层(meta)的引用计数强制"先删引用者,再删被引用者"。看懂这张图,就看懂了 syncd 下发操作的顺序,也看懂了为什么"删不掉一个还在被用的下一跳"。


1. L2 交换路径

1.1 逐层映射

 配置层    VLAN / VLAN_MEMBER 配置
   │
 编排层    orchagent 直接消费配置(L2 不绕应用库)
   │        组装出 VLAN、VLAN Member、Bridge Port 三类 SAI 对象
   │
 1 号库    出现 VLAN / VLAN_MEMBER / BRIDGE_PORT / FDB_ENTRY 四类表项
   │
 厂商 SAI  VLAN、桥接、FDB 三个实现文件分别接手
   │
 BCM SDK  建 VLAN、加成员端口、写 MAC 地址项
   │
 芯片      VLAN 表 + L2 地址表(TD3/TH3 上是共享存储池里的地址项)

1.2 FDB 的特殊性:唯一的"硬件也会说话"的 L2 对象

 下行(静态 MAC)              上行(芯片学习/老化)
 配置 → orchagent              芯片学到新 MAC / 老化删除
   → 1 号库 FDB 表项            → SDK 线程捕获
   → 厂商 SAI                   → SAI 通知回调
   → 芯片 L2 表(标记静态)      → syncd 通知处理器
                                  ├→ 发通知给 orchagent
                                  └→ 直接回写 1 号库 FDB 表 ★

注意上行路径里那个"直接回写"——它是保证 1 号库和芯片状态一致的机制。排障"MAC 学了但库里没有"时,第一嫌疑是通知通道,而不是学习本身。

1.3 Bridge Port 的隐含角色

SONiC 的 L2 模型里,"端口加入 VLAN"实际是桥端口 + VLAN 成员两个对象的组合。端口相关转发异常时,先确认桥端口对象存在、类型正确——这是 L2 问题的常用第一手检查。


2. L3 路由路径(博通平台的主战场)

2.1 对象创建顺序与职责分工

  ① Virtual Router (VRF)
     └─ 一张独立的路由表命名空间
        │
  ② Router Interface (RIF)
     └─ "哪个口/哪个 VLAN 属于哪个 VRF" + 本端 MAC
        │
  ③ Neighbor Entry ────── 管解析:邻居 IP → 目的 MAC(ARP/ND 的结果)
        │
  ④ Next Hop ──────────── 管方向:下一跳 IP + 出接口(RIF)
        │
  ⑤ Route Entry ───────── 管命中:VRF + 前缀 → 指向 Next Hop 或 Group
        │
  ⑥ Next Hop Group + Member ── 等价多路径:一组 Next Hop 的集合

邻居和下一跳是解耦的:邻居管"IP 到 MAC 的解析",下一跳管"路由的出方向和下一跳 IP",两者在芯片的 L3 egress 对象处汇合。理解这个分工,才能理解为什么邻居失败和路由失败是两种不同的报错。

2.2 下沉到博通芯片的对照表

 ┌─────────────┬───────────────────────┬──────────────────────────────┐
 │ SAI 对象     │ SDK 侧动作             │ 芯片表(TD3/TH3)              │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ Route Entry │ 路由添加               │ ALPM:pivot TCAM + 数据桶       │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ Neighbor    │ 主机表项添加            │ L3 主机表;溢出时可转 ALPM      │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ Next Hop    │ 创建 egress 对象        │ L3 出方向下一跳表              │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ NH Group    │ 创建 ECMP 组           │ ECMP 组表                     │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ RIF         │ 创建 L3 接口           │ L3 入接口表 / 出接口表         │
 ├─────────────┼───────────────────────┼──────────────────────────────┤
 │ VRF         │ 创建/复用 VRF          │ VRF 表                        │
 └─────────────┴───────────────────────┴──────────────────────────────┘

2.3 容量链:转发问题先定位"哪一层先满"

邻居/路由下不去,本质是一条容量链上某一环先到顶。每一环满了,上层表现一模一样,但修法完全不同:

 第 1 环:厂商 SAI 软件数据库的上限
   └─ 纯软件计数,芯片可能还空着。满了报"表满",但硬件无辜

 第 2 环:L3 主机表(邻居的家)
   └─ TH3 上固定 16K,硬件锁死,配置改不动
      v6 邻居占双倍宽度 → 实际只装得下 8192 条 v6 ND

 第 3 环:host-as-route 溢出通道
   └─ 主机表满了以后,把邻居以主机路由形式压进 ALPM
      需要芯片开关和标志位同时满足才启用
      ★ v6 额外门槛:128 位路由模式开关必须开
        → ipv6-64 模式下此路不通,8192 就是 v6 ND 的天花板

 第 4 环:ALPM(路由的家)
   └─ pivot TCAM 规模有限,同前缀共享 pivot 的条目便宜、
      随机散列的主机路由是 pivot 消耗大户
      数据桶可用 bank 数由 FPEM 是否占用决定(4 或 8,无中间档)

 第 5 环:L3 出方向下一跳表
   └─ 每个唯一的 (MAC, 端口, VLAN) 组合占一个 egress 对象

定位方法:用芯片交互命令看硬件真实用量,逐环对比——哪一环先贴到顶,问题就在哪一环。

2.4 DEF.CHECK:ALPM 模式的隐藏规则

ALPM 组合模式有一条硬件级约束:非默认 VRF 里的第一条路由,必须是默认路由(0.0.0.0/0 或 ::/0)。违反时 SDK 直接报参数非法。

这是"路由莫名 Invalid parameter"的最高频根因,特征是:

  • 报错参数非法,但路由前缀本身完全合法;
  • 只在某些 VRF 上出现;
  • 和下发顺序强相关——第一条不是默认路由就触发。

取证靠调用录像文件(第三篇讲),确认该 VRF 第一条路由的下发顺序即可实锤。SDK 侧的详细报错只进芯片日志通道,不进系统日志——光 grep 系统日志会误判为"SDK 没报错"。

2.5 IP2ME:到本机的流量走特殊路径

目的地址是本机接口/环回地址的主机路由,SAI 层走"IP2ME"分支:理想路径是下一条芯片路由并把报文 punt 上 CPU。但在 TH3 的 ipv6-64 模式下,v6 的 128 位主机路由塞不进 64 位的 ALPM key,这条路必然失败——此时改由 hostif trap 兜底上 CPU。

现象特征:路由配置失败的报错,配对的是 v6 /128 + 本机接口。看到这对组合先想 IP2ME,不要当成普通路由故障。

2.6 上 CPU 路径:hostif trap

控制面报文(ARP/ND/BGP/LLDP……)的"转发"不经过前面任何一张表,走独立的 trap 通道:

 配置(COPP 策略/协议使能)
   → 编排层组装 trap 对象、限速组、内核网口对象
   → 厂商 SAI 配置芯片的"上 CPU 原因"和限速
   → 芯片命中 reason → DMA 上 CPU → 内核网络接口 → 协议栈

"三层表项全对但 ping 不通/邻居学不到"的案子,十有八九要查这条通道。


3. ACL 路径

3.1 对象模型与芯片映射

  SAI 侧                                  芯片侧
 ┌────────────────────────┐          ┌──────────────────────────┐
 │ ACL Table              │          │ 字段处理器 group          │
 │  · 阶段(入/出/前置)      │ ───────→ │  · 按阶段落 IFP/VFP/EFP   │
 │  · 绑定点类型            │          │  · 占用 TCAM slice       │
 │  · 使能哪些匹配字段       │          │                          │
 │      │                 │          │                          │
 │      ▼                 │          │                          │
 │ ACL Entry              │ ───────→ │ TCAM 表项                 │
 │  · 优先级               │          │  · 匹配域 + 动作           │
 │  · 匹配值 + 动作         │          │  · 可选硬件计数器          │
 │      │                 │          │                          │
 │      ▼                 │          │                          │
 │ Table Group + Member   │ ───────→ │ 表项真正 install 进芯片 ★  │
 │  (绑定到端口/VLAN/LAG)   │          │                          │
 └────────────────────────┘          └──────────────────────────┘

3.2 "创建成功 ≠ 下进芯片"

ACL 链条上最重要的认知:对象创建成功只代表软件结构建好,表项 install 进芯片是独立一步,可能单独失败——TCAM 满、slice 冲突都在这一步暴雷,且这类失败在系统日志里往往只有一句笼统的资源不足。ACL"配了不拦"的案子,标准动作是直接在芯片交互 shell 里 dump 字段处理器的 group 和表项。

3.3 与视图比对的交互

ACL 条目是最佳匹配器的重点关照对象(按优先级预匹配)。改规则时 syncd 倾向原地修改;一旦匹配失败走删除重建,会出现瞬时放行窗口——安全敏感场景必须意识到这个行为。


4. QoS / 缓存路径(速览)

 配置(缓冲池/水线/队列/调度/丢弃曲线/优先级映射)
   → SAI 对象:缓冲池、缓冲水线、队列、调度器、调度组、WRED、映射表
   → 厂商 SAI 的 MMU 子系统(按架构分叉)
   → 芯片 MMU:cell 分配、队列调度树、WRED 曲线

调度树(调度组的层级结构)是 QoS 问题的定位核心——芯片交互命令可以把芯片侧真实的树形结构打出来,和 SAI 对象树逐层对照。


5. 隧道与 VXLAN(速览)

 隧道配置
   → SAI 对象:隧道本体 + 映射表 + 映射条目 + 终结项
   → 厂商 SAI 隧道子系统(分架构变体)
   → 芯片 overlay 引擎

一个容易踩的坑:TD3 上 VXLAN 相关芯片参数是按"有没有开 VXLAN"动态增删的——开不开 VXLAN,芯片的表分配方案不一样。排障前先确认当前处于哪种形态。


6. 总结:现象 → 嫌疑层 → 验证手段

 ┌────────────────────┬────────────────────────┬─────────────────────────┐
 │ 现象                │ 先怀疑                  │ 第一手验证               │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ 邻居下不去           │ 容量链五环逐一对比       │ 芯片主机表用量 vs 软件上限 │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ 路由报参数非法        │ DEF.CHECK(首条非默认)  │ 调用录像看 VRF 内下发顺序  │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ 静态 MAC 不生效      │ FDB 通道                │ 1 号库表项 vs 芯片 L2 表  │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ ACL 配了不拦         │ install 失败/绑定点错    │ 芯片字段处理器 dump       │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ 协议报文不上 CPU     │ trap 通道               │ 芯片上 CPU 配置 + 网口存在性│
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ 改配置后转发闪断      │ 匹配失败走了删除重建     │ syncd 日志里的操作单      │
 ├────────────────────┼────────────────────────┼─────────────────────────┤
 │ v6/128 到本机失败    │ IP2ME 特殊路径          │ 看报错是否配对 RIF+全1掩码 │
 └────────────────────┴────────────────────────┴─────────────────────────┘

下一篇:用 1 号数据库把上面每一层变得"看得见"——库里存了什么、怎么读、调用录像怎么回放、五层日志怎么开、错误码怎么解码。

0

评论 (0)

取消