C COMPIN BLOG

COMPIN TECHNICAL NOTE

新手教材(4/13)|第四编:统一任务、Color 和策略安装

讲清 DAG、REQUEST/READY、task_id、Color、入口分类与 Linux SR Policy 安装之间的完整生命周期。

本文是《从 IP 到 SRv6 计算编排》新手教材第 4/13 编。 总目录 · 上一篇:第三编:300 节点系统的控制面和数据面 · 下一篇:第五编:算子让网络路径执行计算

23. DAG把普通传输和计算链统一起来

23.1 DAG

**DAG(Directed Acyclic Graph,有向无环图)**由vertex(顶点/任务节点)和有向edge (边/依赖)组成,且不存在沿有向边回到自身的cycle(环)。

在本项目中:

source → sink

是没有中间算子的普通传输DAG;

source → gray → mean2x2 → blur3x3 → edge → sink

是图像处理DAG。它们共享同一个REQUEST、Color、SR Policy、READY和数据发送生命周期。

23.2 Task Request合同

TaskRequest包含:

字段范围意义
task_id非零uint32幂等任务身份
origin_endpoint非零uint16业务发起端身份
destination_endpoint非零uint16业务目的端身份
dag_profile1或21=plain,2=带规范DAG
dag_json最大1400 bytesprofile 2的规范JSON
placement_modeexact/resilient明确选择放置模型

**uint32(unsigned 32-bit integer,无符号32位整数)**范围为0..2^32-1;uint16同理。 任务合同禁止源和目的相同,禁止未知profile,禁止超长或非canonical DAG JSON。

**Canonical JSON(规范JSON)**使用确定键顺序和紧凑编码,让同一DAG只有一种字节表示, 便于严格校验和摘要。

23.3 固定支持的DAG

当前主要模板:

dag_id链
spp-transport-v1source→sink
image-pipeline-v1source→gray→mean→blur→edge→sink
fire-tile-filter-v1source→bnn→sink

普通传输固定使用exact,因为它没有算子Anycast放置问题;图像DAG显式选择exact或 resilient,不在任务中途自动切换模式。

24. REQUEST、READY和REJECTED

24.1 ETS3线格式

当前端点任务信令magic为ETS3。**Magic(魔数)**是协议开头的固定字节,用来快速 判断payload类型和版本。

magic | kind | task_id | origin | destination | profile | placement | dag_length | DAG
 4B      1B      4B       2B          2B          1B        1B          2B

kind取值:

  • REQUEST=1:请求建立任务;
  • READY=2:入口已成功安装策略;
  • REJECTED=3:请求明确不合法或不能接受。

“事实暂缺、正在等待资源”通常是pending(待处理),不等于永久REJECTED。

24.2 来源验证

入口不能只相信REQUEST正文里的origin_endpoint,还要验证:

  • 外部端侧是否从真实data interface发来;
  • IPv6源地址是否对应声明的endpoint;
  • 集成端侧是否从本地business veth发来;
  • 声明origin是否等于当前入口身份或已本地接入身份。

这防止普通容器伪造另一个endpoint发起任务。

24.3 幂等与重试

**Idempotent(幂等)**表示相同请求重复一次不会创建第二份不同任务。端侧可以在暂时 没有READY时按协议重试;入口按task_id合并客户地址并返回已有READY。

重试不由外部脚本注入,且不能靠延长固定超时掩盖规划错误。

24.4 完整状态机

端侧常驻
  └─ 自然产生任务
       └─ REQUEST
            ├─ 来源/合同非法 ─► REJECTED
            ├─ 当前事实不足 ─► pending,等待事实或端侧重试
            └─ 规划和安装成功
                  └─ READY
                       └─ 端侧发送业务数据

没有FLOW_START,控制器不产生任务,观察窗口也不激活任务。

25. Color的完整实现

25.1 Color到底是什么

本项目的**Color(策略分类编号)**是入口本地非零16-bit整数,把task_id映射到Linux 策略路由表。它是转发资源,不是业务含义本身。

分配算法:

start = ((task_id - 1) mod 65535) + 1
从start循环寻找本入口尚未使用的Color

因此通常Color接近task ID的低16-bit,但冲突时会选择下一个空闲值。不同入口可以为 不同任务使用相同Color,因为它们的Linux路由表互相隔离。

25.2 分类器识别哪几种业务

入口eBPF分类器读取IPv6/UDP payload的magic:

magic协议task字段位置
SPP1SPP TileSPP头offset 12的uint64 task_id
CFV2普通业务流magic后offset 4的uint32 flow/task ID
FAL1火灾Alarmmagic后offset 4的uint32 alarm task ID

查map成功时:

skb->mark = Color

已识别任务格式但map没有条目时使用保留mark 65535,避免未知任务意外进入main route。 非组播、非link-local的普通UDP/TCP可以使用generic mark 10000;HELLO等本地控制流量 不被任务分类器改写。

25.3 安装顺序

新任务第一次安装包含:

  1. 删除可能存在的同Color旧rule,保证幂等;
  2. 增加fwmark Color lookup table priority Color;
  3. 在table 10000+Color安装目的endpoint /128路由;
  4. exact路由直接携带encap seg6 mode encap segs ...;
  5. resilient路由引用一个携带不变SRH的稳定nexthop object;
  6. 把task_id→Color写入pinned eBPF map;
  7. 全部成功后才发送READY。

**Pinned Map(固定挂载的eBPF映射)**通过bpffs路径让不同进程访问同一个内核map。 本项目路径为:

/sys/fs/bpf/tc/globals/heft_task_colors

25.4 示例

假设task_id=70001,入口分到Color=4466:

table = 10000 + 4466 = 14466

概念命令是:

ip -6 rule add fwmark 4466 lookup 14466 priority 4466
ip -6 route replace fd42:10:12c::2/128 table 14466 \
  encap seg6 mode encap segs <segments> via <gateway> dev eth0
heft-task-map ... 70001 4466

业务包本身仍携带task_id=70001,不携带4466。Color只存在入口内核。

25.5 策略替换和撤销

同一task重算时保持task、Color、目的和placement mode不变,只用route replace更新 segment或nexthop,避免delete/add产生人为流量空窗。

源端真实detach后,旧入口依次删除:

  • eBPF map中的task key;
  • task table的目的route;
  • Color对应的ip rule;
  • resilient任务的nexthop object。

随后释放Color供未来本地任务使用。

26. REQUEST为什么必须先声明Exact或Resilient

任务请求中的placement_mode先声明入口要采用哪一种实例选择模型。本章只建立最小区别; 算子实例尚未学完,所以暂时不展开算法和逻辑地址。

26.1 Exact只先理解为“入口明确选实例”

**Exact Placement(精确放置)**由入口根据一份事实快照,为每个计算阶段明确选择某个 物理实例,最终形成具体服务SID的完整策略。

抽象阶段A -> 明确实例A@某节点
抽象阶段B -> 明确实例B@某节点

第九编才讲入口为什么用HEFT、怎样计算primary/backup以及何时重算。本章不要求读者提前 接受一个尚未推导的算法答案。

26.2 Resilient只先理解为“路径到达时选择实例”

**Resilient Placement(弹性放置)**不在入口固定具体实例。task只引用逻辑服务身份, 数据到达该服务时由当前节点的普通IPv6 FIB选择provider。

逻辑阶段A -> 当时可达的某个A实例
逻辑阶段B -> 当时可达的某个B实例

第六编从普通路由开始完整讲Anycast地址、provider候选和FIB切换。

26.3 不能混用两套推理

Exact把实例选择当成一次全链编排;Resilient把实例选择当成每项服务的局部路由。二者都 遵守同一REQUEST/READY和Color安装生命周期,但不能混用对方的重算或备份语义。全部细节 等学完第六编Anycast和第九编HEFT以后再比较。

26.4 第三、四编自测

  1. 四个控制器模块分别拥有什么状态?
  2. generation与sequence有什么区别?
  3. accepted拓扑为什么不能立即用于task planning?
  4. task_id、Color和SRH分别是什么身份?
  5. Color是否由控制器下发?
  6. Exact与Resilient在哪里选择具体算子实例?

总目录 · 上一篇:第三编:300 节点系统的控制面和数据面 · 下一篇:第五编:算子让网络路径执行计算