tpunetd 协议
本页中的所有地址、符号和线缆字符串都适用于
libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64wheel 中的libtpu.so(ELF 64-bit LSB, x86-64, ~745 MB, BuildID md589edbbe81c5b328a958fe628a9f2207d)。其他版本会不同。
摘要
tpunetd 是驻留在主机上的控制守护进程,拥有 Cloud TPU VM 或 superpod 主机上的物理 TPU 芯片。用户进程从不直接接触这些芯片;相反,libtpu.so 链接了完整的客户端桩 — superpod::tpunetd_client — 它通过本地 gRPC 通道连接到守护进程,并经由守护进程驱动芯片生命周期。本页记录的是 在 libtpu.so 内观察到的客户端桩:它链接的四个 gRPC 服务、请求/响应消息形状、Unix-socket / TCP 端点发现,以及客户端在作业启动时如何连接到(或拒绝连接到)守护进程。该 wheel 中不包含守护进程二进制文件;这里的每一条结论都只来自链接进来的客户端侧单元,其中携带了 gRPC 桩、四个 proto FileDescriptorProto blob、验证器,以及 TpunetdControl / SessionMaster 机制。
如果你用过 gRPC 生成的 C++ 桩,这个表面会很熟悉:每个服务一个 Stub 类,每个 RPC 一个由 BlockingUnaryCall 支撑的方法,外加一个 async 内部类 ClientUnaryReactor 变体;一个接受 shared_ptr<grpc::ChannelInterface> 的 NewStub 工厂;以及一个很薄的手写包装器(TpunetdControl),它把内部 SessionData 结构体封送进 proto 请求。需要先记住的两个意外点是:(1) 默认情况下,libtpu 不是与守护进程自己的 SessionControl 服务通信,而是与位于不同 package(libtpu.tpunetd)下、包含 8 个方法的 VBARControl shim 通信;(2) 四个服务中的两个 — TpuNetworkSessionWorker 和 TpuNetworkSessionBarrier — 是客户端进程之间的点对点服务,并且由 libtpu 自身提供服务, 不是由 tpunetd 提供。
使用这个桩的 bootstrap 会合(CreateTpuNetworkInterface → Init → MaybeInitSessionMaster 启动序列及其相对于 Megascale 的位置)由 bootstrap/tpunetd-relationship.md 负责;本页负责 RPC 表面、消息分类和端点发现,不重新推导启动序列。
对于重新实现,契约是:
- 四个 gRPC 服务及其线缆前缀 — 精确的服务路径、各自的方法集合,以及它们所在的 package。
- 请求/响应消息形状 — 从链接的
FileDescriptorProto字符串以及被改编的桩方法签名中恢复(每个 RPC 的Request/Response类型对)。 - 端点发现和通道构造 — Unix-socket 默认路径、
--vbar_control_service_url覆盖、明文 (InsecureChannelCredentials) gRPC,以及连接重试循环。 - 默认与绕过分支 — libtpu 何时选择
VBARControl而非SessionControl::Stub,以及何时改为安装 no-op 桩。
| 客户端命名空间 | superpod::tpunetd_client(774 个 mangled-symbol 命中,nm | rg -c '8superpod14tpunetd_client') |
| 守护进程命名空间 | superpod::tpunetd(720 个 mangled-symbol 命中,nm | rg -c '8superpod7tpunetd') |
| 源路径前缀 | platforms/deepsea/software/superpod/routing/ |
| 本地端点(默认) | /var/google/services/tpunetd/user.socket (UDS) |
| 传输 | 明文 gRPC (grpc::InsecureChannelCredentials) |
| 通道构造函数 | superpod::tpunetd_client::ConnectToGrpcEndpoint (0x1ffcef60) |
| 实现选择工厂 | superpod::routing::CreateTpuNetworkInterface (0x1fba1100) |
| 默认客户端桩 | libtpu::tpunetd::grpc::VBARControl::Stub |
| 绕过客户端桩 | superpod::tpunetd::grpc_gen::SessionControl::Stub (NewStub 0x1ffcdd20) |
| 服务 / 方法 | 4 个服务 / 21 个 RPC |
服务表面概览
四个 gRPC 服务被链接进 libtpu.so。它们可以按谁托管服务器、谁发起调用清晰划分。下面的每个线缆前缀都是从反编译的 .rodata 字符串表中逐字提取的;方法数量与 IDA 数据库中存在的逐方法桩函数匹配。
| 服务 | 线缆前缀 | 方法数 | 服务器 | 由 libtpu 发起 |
|---|---|---|---|---|
SessionControl | /superpod.tpunetd.SessionControl/ | 7 | tpunetd 守护进程 | 仅当 --bypass_vbar_control_service=true |
VBARControl | /libtpu.tpunetd.VBARControl/ | 8 | tpunetd 守护进程(shim) | 默认路径 |
TpuNetworkSessionWorker | /superpod.tpunetd_client.TpuNetworkSessionWorker/ | 4 | 对等 libtpu 进程 | session master → workers |
TpuNetworkSessionBarrier | /superpod.tpunetd_client.proto.TpuNetworkSessionBarrier/ | 2 | 对等 libtpu 进程 | barrier fan-out |
怪异点 —
SessionControl和VBARControl暴露几乎相同的方法名,但位于不同的 proto package(superpod.tpunetd与libtpu.tpunetd),因此拥有不同且不可互换的消息类型。superpod.tpunetd.StartSessionRequest和libtpu.tpunetd.StartSessionRequest是不同的描述符。把它们作为别名处理的重新实现会针对错误的FileDescriptorProto进行序列化。线缆路径中的 package 前缀就是判别器。注意 —
tpunetd守护进程的SessionControlproto 还声明了 ~20 个 ICI-fabric / routing-controller RPC(CreateNetwork,SetRoutingTable,SetGtcConfiguration,PerformReset, …)。这些存在于描述符中,但从不由libtpu发起 — 它们属于权限更高的 superpod-routing 控制器平面。为完整起见,它们被编入下面的“仅守护进程 RPC 表面”, 而不是作为客户端契约的一部分。
端点发现和通道构造
目的
在可以发起任何 RPC 之前,客户端必须解析一个端点 URL 并向其打开 gRPC 通道。端点要么是 Unix domain socket(本地守护进程链路),要么是 TCP 地址(对等 fanout);通道始终是明文的。
入口点
TpunetdClient::Init (decl, throws "Must run TpunetdClient::Init first")
└─ ConnectToTpunetd ── default-vs-bypass + NoOp branch
└─ ConnectToGrpcEndpoint (0x1ffcef60) ── CreateChannel + retry loop
├─ grpc::InsecureChannelCredentials
├─ grpc::CreateChannel(url, creds)
└─ Channel::GetState(true) until READY or deadline
```text
### 算法
```c
// superpod::tpunetd_client::ConnectToGrpcEndpoint (0x1ffcef60)
// args: (string_view url, absl::Duration deadline)
function ConnectToGrpcEndpoint(url, deadline):
creds = grpc::InsecureChannelCredentials() // line 67 — plaintext, no TLS
channel = grpc::CreateChannel(url, creds) // line 70
end = absl::Now() + deadline
loop:
state = channel.GetState(/*try_to_connect=*/true)
if state == 2: // line 104 — GRPC_CHANNEL_READY
return channel
if absl::Now() >= end:
return Error("Failed to connect to " + url) // rodata "Failed to connect to "
WaitForStateChange(state, short_deadline) // spin until next transition端点选择
通道打开所用的 URL 在 ConnectToTpunetd 中按以下顺序解析:
OptionsURL 字段,如果嵌入运行时提供了该字段。FLAGS_vbar_control_service_url— absl flag--vbar_control_service_url=<url>;TPU-driver env-var token 是kVbarControlServiceUrl.- 当该 flag 未设置时,回退到 Unix-socket 默认值
/var/google/services/tpunetd/user.socket。 这个精确字符串在.rodata中出现一次(已在反编译输出中确认)。
连接日志行是 "Connecting to vbar control service at "(后接解析后的 URL),已在二进制中逐字确认。
通道之上选择的桩
通道进入 READY 后,会准确包装两个守护进程桩之一:
// inside ConnectToTpunetd
if process_owns_chips == false:
install NoOpControl // rodata "process_owns_chips is false, using NoOpControl"
return OK // never opens a channel at all
else:
channel = ConnectToGrpcEndpoint(url, retry_timeout)
if FLAGS_bypass_vbar_control_service: // default = false
stub = superpod::tpunetd::grpc_gen::SessionControl::NewStub(channel) // 0x1ffcdd20
wrap into TpunetdControl
else:
stub = libtpu::tpunetd::grpc::VBARControl::NewStub(channel)
wrap into VbarControl proxy
```text
> **陷阱 —** 当 `Options.process_owns_chips == false` 时,永远不会打开通道。客户端会安装 `NoOpControl`,其每个方法都会记录
> `"NoOpControl::<Op> is called; skipping tpunetd call"` 并返回 OK。
> 总是拨打 socket 的重新实现会在合法不拥有芯片的 chip-less / sidecar 进程上挂住。
### 激活门(实现选择工厂)
是否使用 `tpunetd` 完全由上一层决定,即位于 `0x1fba1100` 的
`superpod::routing::CreateTpuNetworkInterface(const tpu::TpuTopology&,
bool)`。分支如下:
```c
// superpod::routing::CreateTpuNetworkInterface (0x1fba1100)
function CreateTpuNetworkInterface(topology, process_owns_chips):
if FLAGS_enable_tpunetd_client // default false
&& binary_search(kTpunetdSupportedTpuVersions, topology.tpu_type):
log("Running in Cloud, using TpunetdClient")
return TpunetdClient::Create(topology, tpu_type, Options) // kTpunetd impl
else:
log("tpunetd either not supported or disabled, falling back to Slice Builder")
return SliceBuilder-backed impl // accel_ssw::deepsea::slice_builder::*kTpunetdSupportedTpuVersions 是 .rodata 中位于 0xb8ec184 的已排序 tpu::TpuType 数组 — 它是 superpod::routing::CreateTpuNetworkFactory 的 static-local,但在这里被引用。它正好包含两个条目 {4, 5}(字节 04 00 00 00 05 00 00 00, 结束哨兵位于 0xb8ec18c);查找是在这些 4 字节 TpuType 值上进行的 lower_bound 风格二分搜索。因此 tpunetd 严格是 Cloud / production-superpod 路径;其他一切都会回退到进程内 SliceBuilder 家族及其自己的 /accel_ssw.deepsea.slice_builder.SliceBuilderWorkerService/* RPC。.rodata 中的 BorglessTpunetd token 是在没有 Borg 作业管理器的 Cloud TPU VM 上使用的本地主机变体。两个激活日志字符串都已逐字确认。完整启动序列见 bootstrap/tpunetd-relationship.md.
服务 1 — SessionControl(守护进程,7 个方法)
目的
完整守护进程上的面向用户的芯片 session 生命周期。仅当 --bypass_vbar_control_service=true 时才直接使用。“session”是对一组由 asic_sw::proto::ChipLocation 标识的芯片进行独占(或共享)控制的权利。
编码
Wire prefix : /superpod.tpunetd.SessionControl/
Package : superpod.tpunetd
Stub class : superpod::tpunetd::grpc_gen::SessionControl::Stub
NewStub : 0x1ffcdd20 (takes shared_ptr<grpc::ChannelInterface>, StubOptions)
Ctor : 0x1ffcdd60
```text
全部七个方法都遵循标准生成桩签名
`Stub::<Op>(grpc::ClientContext*, const <Op>Request&, <Op>Response*)`,
并带有一个包含 `ClientUnaryReactor` 的 `async` 内部类变体。请求和响应类型对从逐方法的 mangled 符号中恢复。
| RPC | 请求 | 响应 | 桩地址 |
|---|---|---|---|
| `StartSession` | `superpod.tpunetd.StartSessionRequest` | `…StartSessionResponse` | `0x1ffce0e0` |
| `StopSession` | `…StopSessionRequest` | `…StopSessionResponse` | `0x1ffce2c0` |
| `StatSession` | `…StatSessionRequest` | `…StatSessionResponse` | `0x1ffce4a0` |
| `CheckSessionHealth` | `…CheckSessionHealthRequest` | `…CheckSessionHealthResponse` | `0x1ffce6a0` |
| `GetChipCoordinates` | `…GetChipCoordinatesRequest` | `…GetChipCoordinatesResponse` | `0x1ffceaa0` |
| `GetCoreDump` | `…GetCoreDumpRequest` | `…GetCoreDumpResponse` | `0x1ffce8a0` |
| `GrantSessionPermission` | `…GrantSessionPermissionRequest` | `…GrantSessionPermissionResponse` | `0x1ffcdf00` |
### 客户端包装器
`superpod::tpunetd_client::TpunetdControl` 是手写类,它包装 `SessionControl` 桩,并把内部 `SessionData`
结构体转换为 proto 请求。已确认的入口点:
| 包装器方法 | 地址 |
|---|---|
| `TpunetdControl::StartSession(const SessionData&)` | `0x1ffcb660` |
| `TpunetdControl::StopSession(const SessionData&)` | `0x1ffcbc80` |
| `TpunetdControl::StatSession` | `0x1ffcc2a0` |
| `TpunetdControl::CheckSessionHealth` | `0x1ffcc9a0` |
| `TpunetdControl::GetCoreDump` | `0x1ffcd040` |
| `TpunetdControl::GetChipCoordinates` | `0x1ffcd7c0` |
每个包装器都从全局常量 `superpod::tpunetd_client::kSessionControlTimeout`(mangled
`_ZN8superpod14tpunetd_client22kSessionControlTimeoutE`,类型
`absl::Duration`)设置 `grpc::ClientContext` deadline。所有包装器中的 deadline 计算完全相同:
`now = absl::Now(); deadline = now + kSessionControlTimeout;`
然后是 `absl::ToChronoTime` → `grpc::Timepoint2Timespec` →
`context.set_deadline`。
---
## 服务 2 — VBARControl(libtpu↔守护进程 shim,8 个方法,默认)
### 目的
这是**默认**路径。当 `--bypass_vbar_control_service` 为 false(默认)时,libtpu 不直接调用 `SessionControl`;它通过一个 Virtual-BAR shim,由该 shim 经由
`tpunetd` 中介 BAR-register 操作,而不是让用户进程直接接触芯片。方法集合镜像了 `SessionControl` 的六个芯片 session 调用,并额外包含两个方法:
`GetHostMetrics` 和 `TPUBackendConnectionTest`。它**不**暴露 `GrantSessionPermission`(该授权是守护进程内部 /
控制器关注点)。
### 编码
```text
Wire prefix : /libtpu.tpunetd.VBARControl/
Package : libtpu.tpunetd (note: NOT superpod.tpunetd)
Stub class : libtpu::tpunetd::grpc::VBARControl::Stub
NewStub : 0x1ffd2360 (Stub ctor at 0x1ffd23a0)
Source proto: learning/45eac/tfrc/tpunetd/proto/vbar_control.proto (TFRC team)| RPC | 请求 | 响应 | 桩地址 |
|---|---|---|---|
StartSession | libtpu.tpunetd.StartSessionRequest | …StartSessionResponse | 0x1ffd2580 |
StopSession | …StopSessionRequest | …StopSessionResponse | 0x1ffd2760 |
StatSession | …StatSessionRequest | …StatSessionResponse | 0x1ffd2940 |
CheckSessionHealth | …CheckSessionHealthRequest | …CheckSessionHealthResponse | 0x1ffd2b20 |
GetChipCoordinates | …GetChipCoordinatesRequest | …GetChipCoordinatesResponse | 0x1ffd3120 |
GetCoreDump | …GetCoreDumpRequest | …GetCoreDumpResponse | 0x1ffd2d20 |
GetHostMetrics | …GetHostMetricsRequest | …GetHostMetricsResponse | 0x1ffd3320 |
TPUBackendConnectionTest | …TPUBackendConnectionTestRequest | …TPUBackendConnectionTestResponse | 0x1ffd2f20 |
全部八个桩函数及其 async / ClientUnaryReactor 变体都作为不同的反编译函数存在;请求和响应类型名直接从 mangled 签名读取(例如 …Stub::StartSession(grpc::ClientContext*, const StartSessionRequest&, StartSessionResponse*))。
libtpu.tpunetd package 中的额外消息
除了请求/响应对之外,VBAR proto 还声明了用于复用 BAR poke 的 envelope 机制:
| 消息 / 枚举 | 作用 |
|---|---|
libtpu.tpunetd.Status | 携带嵌套 Status.StatusCode 枚举的 status 包装器 |
libtpu.tpunetd.VBARRequestType | oneof-tag 枚举,用于选择 envelope 携带哪一种 VBAR poke |
libtpu.tpunetd.VBARRequestInput | 跨 poke 类型的请求 envelope union |
注意 —
TPUBackendConnectionTest受TPU_BACKEND_CONNECTION_TESTenv var 控制。VBARRequestType/VBARRequestInputoneof envelope 在线缆上的序列化无法仅从客户端单元恢复 — 复现它需要解码protodesc_cold字段 ID 或守护进程二进制。对于需要逐字节精确 VBAR poke framing 的重新实现者,标记为 LOW。
服务 3 — TpuNetworkSessionWorker(点对点,4 个方法)
目的
这是主机间 fanout 通道。一个 slice 中的一个节点运行 session-master 角色;其余节点运行 session-worker 角色。master 通过 TCP gRPC 联系每个 worker,以进行 heartbeat、session info 和 core-dump 收集。这是栈中唯一一个客户端主机彼此通信的部分;tpunetd 不知道它的存在 — 它把 worker 列表交给 master 后就退出这个流程。
编码
Wire prefix : /superpod.tpunetd_client.TpuNetworkSessionWorker/
Package : superpod.tpunetd_client
Transport : gRPC over TCP (peer hosts) / in-process loopback (local node)
```text
| RPC | 请求 | 响应 |
|---|---|---|
| `CheckHeartbeat` | `superpod.tpunetd_client.CheckHeartbeatRequest` | `…CheckHeartbeatResponse` |
| `GetSessionInfo` | `…GetSessionInfoRequest` | `…GetSessionInfoResponse` |
| `UpdateSessionInfo` | `…UpdateSessionInfoRequest` | `…UpdateSessionInfoResponse` |
| `CollectCoreDump` | `…CollectCoreDumpRequest` | `…CollectCoreDumpResponse` |
### 桩实现
两个桩类型实现相同表面:
- **`SessionWorkerStubRpc`**(`CheckHeartbeat` 位于 `0x1ffcb1a0`)— 通过内部 `TpuNetworkSessionWorker::StubInterface*` 进行的真实
gRPC。
- **`SessionWorkerStubLocal`**(`CheckHeartbeat` 位于 `0x1ff920e0`)— 相同表面,但通过 `FakeServerContext` 循环调用,使 master 能在没有实际 TCP 往返的情况下调用自己的 worker 进程。
peer 列表**不是由客户端自身发现的**。它由调用方以 `flat_hash_map<string worker_name,
SessionWorkerStubFactory>` 的形式提供给 `SessionMaster::Create`;每个条目的工厂闭包都会产出一个 `unique_ptr<SessionWorkerStub>`,可能是 RPC 变体或本地变体。peer 地址的权威来源是 Megascale coordinator(`MEGASCALE_COORDINATOR_ADDRESS`)。见
[`fleet-metadata/overview.md`](fleet-metadata/overview.md).
### UpdateSessionInfoRequest 字段模式
从二进制中逐字确认的验证器错误文本中恢复(`session_worker_validation.cc`):
| 字段 | 类型 | 规则 |
|---|---|---|
| `in_session` | bool | 必需(`"in_session must be specified"`) |
| `session_id` | string | 当且仅当 `in_session == true` 时必需(`"session_id must be present iff in_session is true"`) |
| `failure_type` | enum | 当且仅当 `in_session == true` 时必须不存在;值 `SLICE_FAILURE_UNKNOWN` 被拒绝 |
`failure_type` 枚举与 SliceBuilder 代码路径共享
(`accel_ssw::deepsea::slice_builder::SliceFailureType`)。
### Heartbeat 行为
`SessionMaster::CheckSessionHeartbeat()`(`0x1ffa6180`)驱动扫描:
```c
// SessionMaster::CheckSessionHeartbeat (0x1ffa6180)
function CheckSessionHeartbeat():
lock(heartbeat_mutex) // SessionMaster offset +104
ExecuteOnAllWorkers([](name, stub){ // fans CheckHeartbeat to all peers
return stub->CheckHeartbeat(req, resp, deadline)
})
for worker in results:
if any chip has chip_id == 0: // vector<asic_sw::proto::ChipLocation>
log("Session is failing due to the following chips having zero as chip id")
transition SessionState -> kFailing (=3) // HandleFailingSession on ThreadPool
return
reschedule self at now + heartbeat_interval // ThreadPool::ScheduleAt; interval at offset 0heartbeat_interval 位于 SessionMaster 偏移 0(由 Options.heartbeat_interval 设置);heartbeat 扫描的逐调用 deadline 是用户提供的绝对 absl::Time,而不是一元守护进程调用使用的 kSessionControlTimeout 时长。
服务 4 — TpuNetworkSessionBarrier(点对点,2 个方法)
目的
用于同步一个 slice 中各主机的点对点 rendezvous barrier。与 TpuNetworkSessionWorker 一样,服务器侧由每个 libtpu 进程自身托管 — 符号表中的 WithCallbackMethod_Notify / WithCallbackMethod_WaitForReady 模板实例化就是进程内服务器。tpunetd 不参与。
编码
Wire prefix : /superpod.tpunetd_client.proto.TpuNetworkSessionBarrier/
Package : superpod.tpunetd_client.proto (note the extra .proto sub-namespace)
Client class: BroadcastBarrier (tpunetd_client/lib/broadcast_barrier.cc)
```text
| RPC | 请求 | 响应 |
|---|---|---|
| `Notify` | `superpod.tpunetd_client.proto.NotifyRequest`(barrier_id string + chip_locations) | `…NotifyResponse`(仅 status) |
| `WaitForReady` | `…WaitForReadyRequest`(barrier_id string) | `…WaitForReadyResponse`(仅 status) |
### 算法
```c
// BroadcastBarrier (Init 0x1ff9bac0, BroadcastNotification 0x1ff9c320)
function Init(absl::Duration):
for each known peer worker: // peer count at this+104, peer array at this+96
build one std::function<absl::Status()> // 32 B closure each; vector sized 32 * num_workers
function BroadcastNotification(barrier_id, deadline):
materialize vector<grpc::ClientContext>(num_peers) // 400 B each; alloc = 400 * num_peers
counter = absl::BlockingCounter(num_peers)
for peer in peers: // parallel fan-out
log("Notifying " + peer + " with barrier id " + barrier_id)
async Notify(peer, {barrier_id, chip_locations}) -> counter.DecrementCount()
counter.Wait()
function BroadcastWaitForReady(barrier_id, deadline):
// symmetric parallel fan-out of WaitForReady
function SyncWithTimeout(barrier_id, timeout):
BroadcastNotification(barrier_id, now + timeout) // fire-and-forget per peer
BroadcastWaitForReady(barrier_id, now + timeout) // blocks until every peer notified AND waitingSyncWithTimeout 是面向用户的 collective rendezvous 点:Notify 对每个 peer 都是即发即忘;WaitForReady 会阻塞,直到每个 peer 都已经通知了相同的 barrier_id,并且自身也在等待它。当 process_owns_chips == false 时,NoopBarrier(lib/noop_barrier.h)会替代它。
SessionData — 每个守护进程请求携带的内容
superpod::tpunetd_client::SessionControlInterface::SessionData 是 TpunetdControl 封送进每个 Start/Stop/Stat/ CheckHealth/GetCoreDump/GetChipCoordinates 请求的内部结构体。布局从反编译调用点恢复(偏移以字节计):
| 偏移 | 类型 | 含义 |
|---|---|---|
+0 | vector<DriverInterface*>::begin | 逐芯片 driver 指针数组(起点) |
+8 | vector<DriverInterface*>::end | drivers vector 末尾 — 用作 for-loop 边界 |
+24 | superpod::routing::proto::Topology | 附加到 session 的 topology proto |
+104 | NetworkContextId | network identity,当且仅当 +144 == 1 处的 flag 为真时复制进请求 |
+144 | bool | has_network_context — 控制是否复制 +104 |
[+0, +8) 数组中的每个 driver 都在 vtable 偏移 +56 处暴露一个虚函数,返回 asic_sw::ChipLocation;libtpu 对每个 driver 调用它,并把结果追加到请求的 repeated ChipLocation chip_locations。
怪异点 —
tpunetd从不自行发现芯片。每个 session RPC 都携带用户进程的完整本地ChipLocation集合, 由客户端从其 driver vector 公布。期望守护进程枚举芯片的重新实现会得到空的chip_locations,以及一个不拥有任何东西的 session。
CoreDump 收集
Two distinct paths produce core dumps:
direct (daemon):
TpunetdControl::GetCoreDump(SessionData, CoreDumpType, Duration)
-> /superpod.tpunetd.SessionControl/GetCoreDump
CoreDumpType ∈ { CORE_DUMP_UNKNOWN, CORE_DUMP_CHIP_DUMP, CORE_DUMP_ICI_DUMP }
peer fanout (master collects from all workers):
SessionMaster::ExecuteOnAllWorkers([](name, stub){
return stub->CollectCoreDump(req, resp, deadline); })
-> /superpod.tpunetd_client.TpuNetworkSessionWorker/CollectCoreDump
writes through accel_ssw::deepsea::CoreDumpUploader (CoreDumpUploaderInterface)
which can also reach logmanagerd at
/var/google/services/logmanagerd/remote_coredump.socket
```text
---
## 仅守护进程 RPC 表面(已声明,从不由 libtpu 发起)
`superpod.tpunetd` proto 描述符声明了一个很大的 ICI-fabric /
routing-controller 表面,它被链接进来(作为描述符字节),但客户端从不调用。这些属于同样会与 `tpunetd` 通信的 superpod-routing 控制器平面。下面按轴列出而非穷尽列出,使重新实现者无需 30 行转储也能了解守护进程的完整方法空间:
| 轴 | RPC(在描述符中声明) |
|---|---|
| Network lifecycle | `CreateNetwork`, `DeleteNetwork`, `ListNetworks`, `UpdateTopology`, `GetLocalTopology` |
| ICI data links | `ConfigureIci`, `EnableIciDataLink`, `WaitForDataLinkUp`, `ResetIciNetwork`, `UpdateIciNetworkConfiguration` |
| Routing | `SetRoutingTable` (+ `RoutingTableMap`) |
| Coordinates / IDs | `SetChipCoordinates`, `SetGlobalChipId` |
| Global time counter (GTC) | `SetGtcConfiguration`, `ClearGlobalGtc`, `WaitForGtcReset` |
| Reset / driver | `PerformReset`, `RestartDriver` |
这些确认 `tpunetd` 拥有主机上的 ICI-link 配置、routing-table
安装和 global-time 同步 — 但它们都不是 libtpu 客户端契约的一部分。它们产生的 chip-coordinate 输出会被 libtpu 通过 `GetChipCoordinates` 读回,并流入
[fleet-metadata](fleet-metadata/overview.md) 和 Megascale topology
exchange。
---
## Proto 文件清单
四个 `FileDescriptorProto` blob 支撑四个服务;另外三个 routing proto 提供共享消息类型。文件名作为带长度前缀的字符串在 proto pool(`protodesc_cold` ELF section)中可见。
| Proto 路径 | Package | 服务 |
|---|---|---|
| `…/superpod/routing/tpunetd/proto/tpunetd.proto` | `superpod.tpunetd` | SessionControl |
| `…/superpod/routing/tpunetd/proto/common.proto` | `superpod.tpunetd` | (仅消息) |
| `…/superpod/routing/tpunetd_client/proto/session_worker.proto` | `superpod.tpunetd_client` | TpuNetworkSessionWorker |
| `…/superpod/routing/tpunetd_client/proto/session_barrier.proto` | `superpod.tpunetd_client.proto` | TpuNetworkSessionBarrier |
| `…/superpod/routing/tpunetd_client/proto/common.proto` | `superpod.tpunetd_client` | (仅消息) |
| `learning/45eac/tfrc/tpunetd/proto/vbar_control.proto` | `libtpu.tpunetd` | VBARControl |
共享 routing proto:`common/proto/topology.proto`
(`superpod.routing.proto`)、`common/proto/chip_coordinate.proto`、
`common/proto/tpu_type.proto`(`TpuType` 枚举,dense `0..10`,名称在运行时通过
`proto2::internal::NameOfDenseEnum<&TpuType_descriptor,0,10>` 获取),以及
`common/proto/ici_network_config.proto`.
> **陷阱 —** 每个描述符文件名字符串开头的数字是 protobuf 内部长度前缀字节,**不是**字段号。这里没有恢复每个请求/响应的数值型**字段 ID**;
> 它们需要解码压缩的 `protodesc_cold` 条目或守护进程二进制。任何逐字节精确的线缆重新实现都必须执行该解码 —
> 本页中的消息*形状*足以命名字段,但不足以分配它们的 tag number。(字段编号置信度 LOW;消息名称和 RPC 表面 CERTAIN。)
---
## 安全性和可观测性说明
- **本地链路没有传输安全性。** 通道使用
`grpc::InsecureChannelCredentials()` 构建(已在
`ConnectToGrpcEndpoint` 第 67 行确认)。认证如果存在,也是在守护进程侧 —
可能是 Unix socket 上的 `SO_PEERCRED` 或文件系统权限 — 并且**无法从客户端单元观察到**。连接到该 socket 的第三方客户端将面对守护进程强制执行的任何机制,而这个二进制没有揭示其细节(LOW)。
- **Telemetry。** `IciSessionMonitorImpl` 通过 `tsl::monitoring` 把 session-health、
state-transition latency、broadcast latency、notification latency,以及
missed-health-check 计数记录到 `/tpu/…`
树下的 TF streamz counters 中。`tpu_type` label 值通过
`NameOfDenseEnum<&TpuType_descriptor,0,10>`.
---
## 交叉引用
- [Megascale 概览](overview.md) — tpunetd 在 multi-host / DCN 栈中的位置
- [bootstrap/tpunetd 关系](bootstrap/tpunetd-relationship.md) — *使用*这个桩的启动序列;tpunetd → MegaScaleTransport 顺序
- [bootstrap/概览](bootstrap/overview.md) — 整体 job-bringup rendezvous
- [fleet-metadata/概览](fleet-metadata/overview.md) — 通过这个表面交换的 peer-address / chip-coordinate metadata
- [错误聚合器](error-aggregator.md) — session-failure 信号(kFailing、zero-chip-id)呈现给 runtime 的位置
- [ICI Topology Discovery](../ici/topology-discovery.md) — 守护进程的 superpod-controller 表面驱动的 ICI-fabric 配置