# P4 PSA v1.1.0 中文精读笔记

**Source:** P4_16 Portable Switch Architecture (PSA)
**URL:** https://p4lang.github.io/p4-spec/docs/PSA-v1.1.0.html
**Version:** 1.1
**Date:** 2018-11-22
**Notes date:** 2026-04-28

本文是面向 OpenUSim / UBody 建模讨论的中文精读笔记，不是 PSA 规范的逐字全译。重点保留公开规范事实、体系结构边界、multi-pipeline 证据，以及对 `UBody` 建模有参考价值的部分。

---

## 1. 文档定位

PSA 是 P4.org Architecture Working Group 定义的 Portable Switch Architecture。它描述一类多端口 packet switch 的通用目标架构，让 P4_16 程序可以在符合 PSA 的设备之间更可移植。

PSA 的定位可以概括为：

- P4_16 是数据面编程语言。
- PSA 是一套 switch target architecture。
- PSA 定义了常用类型、externs、metadata、packet paths 和 programmable blocks。
- PSA 不规定某个具体 ASIC 的内部实现细节。
- PSA 中有一些 target-dependent block，例如 packet buffer / replication / queuing。

对 `UBody` 调研最有价值的部分是：

- Target Architecture Model。
- Packet paths。
- Ingress / egress processing split。
- Packet buffer、PRE 和 BQE 的边界。
- Appendix D 中关于 egress、output port 和 metadata 的设计理由。
- Appendix E 中关于 multi-pipeline PSA devices 的说明。

---

## 2. PSA 目标架构模型

PSA 模型包含六个 P4 可编程 block 和两个固定功能 block。

六个 P4 可编程 block：

- `IngressParser`
- `Ingress`
- `IngressDeparser`
- `EgressParser`
- `Egress`
- `EgressDeparser`

两个固定功能 / target-dependent block：

- `Packet buffer and Replication Engine (PRE)`
- `Buffer Queuing Engine (BQE)`

PSA 的基本 packet flow 是：

```text
IngressParser
  -> Ingress match-action pipeline
  -> IngressDeparser
  -> PRE / packet buffer / BQE
  -> EgressParser
  -> Egress match-action pipeline
  -> EgressDeparser
  -> output port
```

规范强调：

- Ingress pipeline 决定 packet 去哪里。
- Ingress deparser 决定哪些 packet contents 和 metadata 会被送入 packet buffer。
- Packet 可在 ingress 之后被复制到多个 egress port。
- 每个进入 egress 的 packet copy 都会经过 egress parser、egress match-action pipeline 和 egress deparser。
- PRE 和 BQE 是 target-dependent 的，PSA 只定义它们与 P4 programmable blocks 的接口和行为边界。

对 OpenUSim 的启发：

- `UBody` 不需要一开始建成完整商业微架构，但可以保留 ingress decision、metadata / descriptor、buffer / queue、egress processing 这几个公开结构点。
- `UbNetworkOnChip` 和未来 body fabric 可以视为 PSA 中 target-dependent block 类似的建模区域：公开接口稳定，内部实现可逐步细化。

---

## 3. Packet paths

PSA 定义多种 packet path，用于描述 packet 在 programmable blocks 之间如何流动。

主要路径包括：

- `NFP`：normal packet from port，普通端口入包。
- `NFCPU`：packet from CPU port，CPU 注入包。
- `NU`：normal unicast packet，从 ingress 到 egress 的普通单播包。
- `NM`：normal multicast-replicated packet，从 ingress 经过 PRE 复制后到 egress。
- `NTP`：normal packet to port，从 egress 出端口。
- `NTCPU`：normal packet to CPU port，从 egress 到 CPU。
- `RESUB`：resubmitted packet，从 ingress deparser 回到 ingress parser。
- `RECIRC`：recirculated packet，从 egress deparser 回到 ingress parser。
- `CI2E`：clone from ingress to egress。
- `CE2E`：clone from egress to egress。

关键设计点：

- PSA 关注 P4 programmable blocks 之间的可见 packet path。
- 在这些 source / destination 之间，实际实现可以有硬件、软件或其他 PSA architecture components。
- 一个入包可以产生 0、1 或多个出包。
- PSA 不强制实现用什么具体队列、buffer 或 fabric 实现这些路径。

对 `UBody` 的启发：

- `LocalSink / ForwardToBody / ForwardToExternalPort` 可以视为 OpenUSim 自己的 disposition path，而不是复刻 PSA packet path。
- `ForwardToBody` 的内部具体实现可以保持 target-dependent：先 fixed delay，后续加 queue / arbitration / credit。
- 如果未来支持 multicast-like 或 clone-like 行为，可以借鉴 PSA 的“路径”和“copy”视角，而不是把所有行为硬编码成单一路径。

---

## 4. Ingress 和 egress 的职责分工

PSA 的一个核心设计是把 ingress processing 和 egress processing 分开。

Ingress 侧负责：

- parse packet。
- 做 match-action decision。
- 选择 drop、resubmit、multicast group 或 egress port。
- 设置 class of service。
- 决定送入 packet buffer 的 packet contents 和 metadata。

Egress 侧负责：

- 对即将出端口的 packet 做最终处理。
- 根据 egress port / instance / timestamp 等 metadata 做 per-copy 处理。
- 可 drop packet。
- 可做 clone / recirculate 等行为。
- 完成最终 deparse 并送出。

一个重要限制是：egress processing 不能改已经选好的 output port。PSA 的理由是 packet buffer 和 output-port scheduler 必须在 packet 入队前知道目标 output port，否则可能造成端口过载、端口饥饿或调度错误。

对 OpenUSim 的启发：

- `ForwardToExternalPort` 的目标端口最好在 body-local ingress / routing decision 阶段确定，后续 egress 阶段只做排队、调度、rewrite、drop 或发送。
- 如果后续引入 body-local egress unit，应避免让 egress unit 随意改变已调度的目标 port。
- body fabric / queueing 模型需要在入队前知道 destination body / port，这与 Cisco Q200 的 VOQ by destination port 也一致。

---

## 5. Packet buffer、PRE 和 BQE

PSA 把 packet buffer / replication / queuing 作为 P4 pipeline 之外的 target-dependent 区域。

Ingress 完成后，packet 可能发生：

- clone to egress。
- drop。
- resubmit。
- multicast replication。
- enqueue one packet for output port。

如果 packet buffer 空间不足，或者实现里的拥塞控制机制选择丢包，PSA 允许实现 drop packet。PSA 还建议实现维护不同原因的 drop counters。

PSA 对 class of service 做了接口层定义：

- Ingress 可以设置 `class_of_service`。
- PSA 不强制 packet buffer 内部使用什么 queue scheduling policy。
- 如果实现为不同 class of service 维护独立 queue，规范建议至少有类似 weighted fair queuing 的能力，也可加 strict high priority queue。

对 OpenUSim 的启发：

- `UBody` 的 `IngressQueue / ContextBuffer / WriteBuffer` 应该被看作 OpenUSim 的 target-dependent queue/buffer 抽象，不必绑定某个标准实现。
- 后续如果加 body-to-body queue，可先定义接口：destination、class、packet metadata、admission/drop reason。
- 调度策略可以作为可配置策略，不必写死为某一种。

---

## 6. Multicast、clone、resubmit、recirculate

PSA 支持多种 packet 复制或回流方式。

Multicast：

- Ingress 可以设置 multicast group。
- PRE 根据 control plane 配置，为 multicast group 创建 0 个或多个 copy。
- 每个 copy 带有自己的 `egress_port` 和 `instance`。
- 对同一个原始 packet 的多个 copy，egress 阶段可以独立处理。

Clone：

- Ingress 可以创建 ingress-to-egress clone。
- Egress 可以创建 egress-to-egress clone。
- Clone session 由 control plane 配置。
- Clone 可以指定 egress port、class of service、是否 truncate 等。

Resubmit：

- 从 ingress deparser 回到 ingress parser。
- Packet contents 可回到 ingress 前的版本。

Recirculate：

- 从 egress deparser 回到 ingress parser。
- Packet contents 来自 egress deparser 输出。

对 `UBody` 的启发：

- 后续如果支持一对多 `ForwardToBody`，可优先考虑 descriptor / metadata based copy，而不是在 ingress 处直接复制完整 payload。
- 对 URMA / LDST 这类事务，如果需要重入、重试或回流，也可以借鉴 PSA 的 path 分类思想：区分 original packet、copy、recirculated packet 的 metadata。
- 当前阶段不需要把这些都实现进 `UBody`，但文档可以保留这些公开术语作为后续扩展参考。

---

## 7. Metadata 和 packet contents 的显式边界

PSA 特别强调 ingress deparser 和 egress parser 的显式存在。原因是 packet 从 ingress 到 egress 时，哪些 packet contents 和 metadata 被携带，应该由程序明确决定，而不是隐式携带所有可能被 egress 使用的数据。

这个设计的工程理由包括：

- 提高不同 target 之间的可移植性。
- 避免 metadata 隐式膨胀。
- 限制送入 packet buffer 的数据量。
- 当 packet buffer I/O bandwidth 成为瓶颈时，减少携带数据量有现实意义。

对 OpenUSim 的启发：

- `UBody` 后续如果引入 packet descriptor，不应默认把所有内部状态随 packet 在 body 间移动。
- 应明确区分 packet payload、routing metadata、body-local accounting metadata、debug/trace metadata。
- Cross-body path 上携带的 metadata 应该是显式字段集，而不是隐式复制整个对象状态。

---

## 8. Externs 和状态对象

PSA 定义了一系列 extern，包括：

- `Counter`
- `DirectCounter`
- `Meter`
- `DirectMeter`
- `Register`
- `Random`
- `ActionProfile`
- `ActionSelector`
- `Digest`
- checksums
- timestamps

这些 extern 对 `UBody` 最重要的启发不在具体 P4 API，而在“状态位置”和“并发更新”问题。

PSA 对 table / extern 的 control plane 操作要求原子性：

- 单次 table add / delete / modify 操作必须相对于 packet forwarding 是原子的。
- packet 应该看到旧状态或新状态，不应看到部分更新状态。
- 对 `Register` 单个元素的 control plane read 或 write 也应表现为原子。
- 规范不要求一组多操作整体原子。

对 OpenUSim 的启发：

- 如果 `UBody` 后续有 body-local counters / resource limits / registers，control plane 更新和 packet processing 的可见性要明确。
- 对仿真而言，可以先用事件顺序保证原子性语义；如果后续多线程仿真，需要单独定义跨 body state update 的一致性。

---

## 9. Appendix E：multi-pipeline PSA devices

这是 PSA 对 `UBody` 最关键的部分。

PSA 解释了为什么高 packet rate switch ASIC 常用多 pipeline：

- 现代高 packet rate ASIC 的 clock rate 通常在 1 到 2 GHz 量级。
- ASIC 中常见设计是每个 clock cycle 启动处理一个新 packet，并每个 clock cycle 完成一个 packet。
- TCAM / SRAM 等资源通常受每周期访问次数限制。
- 多端口 SRAM 或更高访问率的 TCAM / SRAM 会增加面积和功耗。
- 如果想获得 N 倍于 clock rate 的 packet processing rate，直接方式是建立 N 条 pipeline，让每条 pipeline 以 clock-rate 处理 packet。

PSA 描述的 typical multi-pipeline device：

- 通常有 N 条 ingress pipelines。
- 通常有 N 条 egress pipelines。
- 多个物理端口会以 hard-wired 方式分配给每条 pipeline。
- 例如 32 个 100G 端口的设备，可把端口 0-15 物理绑定到 pipeline 0，端口 16-31 绑定到 pipeline 1。
- 来自某组端口的 packet 一定先进入对应 ingress pipeline。
- ingress 选择的 output port 决定 packet 进入哪个 egress pipeline。
- 通常希望同一个 P4 program 跑在所有 ingress pipelines 和所有 egress pipelines 上。

这段对 `UBody` 的映射非常直接：

| PSA multi-pipeline 概念 | OpenUSim / UBody 概念 |
| --- | --- |
| N ingress pipelines + N egress pipelines | multiple `UBody` datapath slices |
| ports hard-wired to pipeline | ports owned by one body |
| ingress pipeline chosen by input port | body-local ingress owner |
| egress pipeline chosen by output port | `ForwardToExternalPort` target body / port |
| packet buffer between ingress and egress | body fabric / queue / future descriptor buffer |
| same P4 program copied to pipelines | same `UBody` behavior instantiated per body |

判断：

PSA 是规范级公开依据。它直接支撑 `UBody` 的 “port ownership + local ingress processing + output-port-driven egress body + explicit cross-body path” 建模方向。

---

## 10. Pipeline-local state 和跨 pipeline 一致性

Appendix E 进一步讨论了多 pipeline 里的 state 问题。

PSA 说明：

- P4 table apply 本身高度并行，只要 table entries 安装在可能匹配它们的 pipeline 内，各 pipeline 可以独立运行。
- 一些 extern 不会修改影响其他 packet 的共享状态，因此也适合并行。
- Counter state 可以在每个 pipeline 内独立维护；如果多个 pipeline 的对应 counter entry 统计同一对象，control plane 可以把各 pipeline 的值相加。
- Meter state 如果在每条 pipeline 独立维护，那么想实现“所有 pipeline 合计不超过某个速率”就不是天然并行问题。
- 要实现全局共享 meter，可以用 pipeline 间状态协调，或把 packet 移动到共享 state 所在位置，但这会降低性能并增加复杂度。
- 网络交换机中常见做法是接受每条 pipeline 独立维护 meter state，不做自动协调。
- Register 比 meter 更通用，也面临同样的跨 pipeline state split 问题。
- 如果没有自动 coherency，常见策略是接受各 pipeline 独立 state，或把相关 packet 移动到 state 所在位置。
- 实现可以把多 pipeline 显式暴露给 control plane，例如给每条 pipeline 及其 tables / externs 单独命名。
- 实现也可以在每条 pipeline 上使用 PSA program 的拷贝，从而保持 pipelines fully isolated。

这段对 `UBody` 的含义很重要：

- body-local counters / buffers / meters 不默认是全局共享。
- 如果需要全局视图，应由 IoDie / control plane 聚合。
- 如果需要访问某个 body-local mutable state，应把 packet / event 路由到该 body，或者明确定义跨 body 协调机制。
- `UBody` 不需要假设 cross-body coherent memory。

与当前设计的对应：

| PSA state 问题 | UBody 当前 / 后续设计 |
| --- | --- |
| per-pipeline counter state | per-body resource usage / counters |
| per-pipeline meter state | per-body rate / admission limit |
| no automatic coherency | no implicit cross-body resource sharing |
| move packets to shared state | `ForwardToBody` / explicit body-local owner |
| expose pipelines to control plane | expose body id / body resource snapshots |
| fully isolated pipeline copies | same UBody object model per body |

---

## 11. Packet ordering

Appendix F 给出 packet ordering 建议，而不是硬性要求。关键点包括：

- 同一 input port 到达的 packet，建议按到达顺序开始 ingress processing。
- 同一 output port 的 packet，建议按开始 egress processing 的顺序发送。
- 同 ingress port、same egress port、same class of service 的 unicast packet，建议保持相对顺序。
- 不同 class of service 的 packet 可能因为不同 FIFO queue 而重排。
- multicast 和 unicast 之间不要求相对顺序。

对 OpenUSim 的启发：

- `ForwardToBody` 后续引入 queue / arbitration 后，需要明确 ordering 保证。
- 最小可公开规则可以是：同 ingress body、same destination body/port、same traffic class 尽量 FIFO。
- 不同 class、multicast-like path、cross-body path 可以允许重排，但需要文档说明。

---

## 12. 拥塞观测的开放问题

PSA 的 open issues 中明确提到，当前 PSA 没有机制直接观察某个 output port 或 queue 是否导致 packet buffer congestion，因此无法仅靠 PSA 标准机制实现 ECN 之类功能。规范也提到，希望未来定义一些 metadata，让 egress processing 可知道 packet 在 packet buffer 中经历了多少 congestion。

对 OpenUSim 的启发：

- 如果 `UBody` 后续要支持 queue occupancy / ECN / congestion trace，不能简单声称这是 PSA 已定义行为。
- 可以把这些作为 OpenUSim 自己的 observability extension。
- 对外文档中应区分 PSA portable interface 和 OpenUSim-specific trace / metric。

---

## 13. PSA 对 UBody 的强支撑点

PSA 对 `UBody` 的支撑主要有五条：

1. `pipeline` 是规范级公开术语。

PSA 明确讨论 multi-pipeline switch ASIC，并把多条 ingress / egress pipelines 作为高 packet rate 的常见实现方式。

2. 端口绑定到 pipeline 是公开常见结构。

PSA 明确举例说明多个 physical ports 可以 hard-wired 到某个 pipeline。这个点支撑 `UBody` 拥有本地 ports 的建模。

3. output port 决定 egress pipeline。

PSA 中 ingress 选择 output port，之后 packet buffer / egress path 根据 output port 进入对应 egress pipeline。这支撑 `ForwardToExternalPort` 和 cross-body egress 的目标需要明确。

4. pipeline-local state 不默认 coherent。

PSA 明确讨论 counter / meter / register 在多 pipeline 中可能各自独立维护，自动 coherency 会带来性能和复杂度问题。这个点支撑 body-local resource 和无隐式 cross-body sharing。

5. metadata / packet buffer 边界需要显式。

PSA 把 ingress deparser、packet buffer、egress parser 分清楚，说明跨阶段传递哪些 packet contents 和 metadata 应该显式定义。这支撑 `UBody` 后续 descriptor-based body fabric。

---

## 14. 不能从 PSA 推出的结论

PSA 不能支撑以下说法：

- `UBody` 等同于 PSA pipeline。
- `UBody` 是某个 P4 target 的真实硬件实现。
- PSA 规定了具体 buffer 深度、queue 数量、scheduler 算法或 crossbar 结构。
- PSA 规定了所有 pipeline 必须完全隔离。
- PSA 规定了 Cisco Q200 那类 multislice ASIC 的具体实现。
- PSA 支持把 `UBody / BD` 作为公开行业术语。

PSA 能支撑的是更抽象的公开论证：

```text
Multi-pipeline switch ASICs, port-to-pipeline binding, pipeline-local state,
and explicit packet-buffer / egress-pipeline transitions are public architecture
patterns standardized at the PSA architecture level.
```

---

## 15. 建议写入 OpenUSim 公开文档的中文表述

```text
UBody 是 OpenUSim 中的 body-local 数据路径 / 网络切片抽象。P4 PSA 规范公开
讨论了 multi-pipeline switch ASIC：多个物理端口可以硬绑定到某条 ingress
pipeline，ingress 选择 output port 后，packet 经过 packet buffer / queueing
进入相应 egress pipeline；counter、meter、register 等状态在多 pipeline 中常常
按 pipeline 独立维护，不默认提供跨 pipeline 一致性。OpenUSim 用 UBody 表达类似
的本地端口、本地资源和显式跨 body 转发边界。
```

更保守的英文表述：

```text
UBody is an OpenUSim simulation abstraction for a body-local datapath/network slice.
The abstraction is aligned with public multi-pipeline switch architecture patterns
described by PSA: ports may be statically associated with pipelines, packet-buffer
transitions select the egress pipeline by output port, and mutable state is often
maintained per pipeline without implicit cross-pipeline coherency.
```

---

## 16. 对 OpenUSim 后续建模的具体建议

短期保持：

- `UBody` 继续表示 body-local `NetworkUnit`。
- `body -> ports` 保持显式绑定。
- `ForwardToBody` 保持显式 body-to-body path。
- 不默认跨 body 共享 queue、counter、meter 或 register-like state。

中期可细化：

- 引入 `traffic class / class_of_service` 字段，作为 body-local queue selection 的维度。
- 把 packet payload 和 cross-body metadata 分离，形成 descriptor-like 内部结构。
- 定义 per-body counters，并提供 IoDie-level aggregation。
- 定义 body-local admission / drop reason counters。
- 定义 `same ingress body + same egress body/port + same class` 的 ordering 规则。

公开风险控制：

- 把 PSA 作为公开规范依据，不把 `UBody` 说成 PSA 实现。
- 不复用 PSA API 名称作为内部私有模型名称，除非确实要实现 P4 / PSA 兼容层。
- 不声称 PSA 规定了具体 crossbar / VOQ / buffer 微架构。
- `UBody / BD` 的名称来源仍需单独确认，公开解释建议主用 `body-local datapath/network slice`。

---

## 17. 一句话结论

P4 PSA v1.1.0 足以支撑 `UBody` 的一个核心公开论据：多 pipeline 交换 ASIC、端口到 pipeline 的硬绑定、pipeline-local state、以及由 output port 驱动的 egress pipeline 选择，都是公开规范中讨论过的架构模式；`UBody` 可被描述为 OpenUSim 对这类 body-local datapath/network slice 思想的仿真抽象。
