C COMPIN BLOG

COMPIN TECHNICAL NOTE

新手教材(11/13)|第十一编:从读懂到会验证

提供源码地图、功能覆盖核对、六组只读实验、常见误区、综合练习与答案。

本文是《从 IP 到 SRv6 计算编排》新手教材第 11/13 编。 总目录 · 上一篇:第十编:业务、故障、前端和证据 · 下一篇:第十二编:英中术语表

91. 推荐学习顺序

第一次阅读不要直接跳到HEFT代码。建议按以下顺序:

  1. 能解释byte、十六进制、网络字节序和封装;
  2. 能手算IPv4/IPv6前缀,并解释最长前缀匹配;
  3. 能区分普通路由下一跳与SRv6 segment list;
  4. 能从卫星位置推导LOS、链路时隙、HELLO邻接和本地FIB;
  5. 能拿一个SRH逐步写出active segment和IPv6 DA;
  6. 能解释控制面事实为何不等于内核已应用状态;
  7. 能区分task_id、Color、SID和Run ID;
  8. 能从逻辑Anycast SID推导本节点的primary、backup和provider漂移;
  9. 能按SPP头定位task/object/tile/epoch,并解释部分成功;
  10. 能逐步证明RGB→Gray→Edge经过真实本地算子;
  11. 能手算一次HEFT,再比较Exact与Resilient;
  12. 最后连接BNN、Alarm、10%损毁、handover、前端和证据;
  13. 掌握原理后再按照后端操作手册启动系统。

每完成一项,先用自己的话讲给别人听。能复述术语不等于理解;能根据一个新报文或新拓扑 推导结果,才算掌握。

91.1 当前开发功能覆盖总表

本教材覆盖当前完整系统的原理主线与业务功能,但不会把每个命令行flag和历史Issue都 塞进教学正文;实际命令归后端操作手册,历史演进归Issue。可按下表核对是否漏项:

已开发能力教材位置学完后应能说明
IPv4、IPv6、Ethernet、邻居和路由第1–6章一个普通包怎样逐跳交付
Linux原生SRv6、SRH、End/End.X/DX4/DX6/DT6、uSID、SR Policy第7–12章一串标准SID怎样执行而不依赖私有协议栈
200卫星、50飞机、50船与两机架构第13、16章每个前端对象为何对应真实节点及怎样运动
圆轨道、ECI/ECEF、LOS、跨轨匹配、端侧仰角第16章物理链路通断怎样由规则自然产生
60秒物理代次、SQLite事务、AF_XDP原子重载第16章300节点怎样只看到完整的新链路矩阵
veth、namespace、宿主XDP与AF_XDP第14–15章frame、UMEM、四个ring和有向链路队列的所有权
限速、burst、传播时延、拥塞与三类drop第15章token bucket和各类丢包为何不能混算
HELLO/ACK、四控制器、双向拓扑、端点与资源事实第16–22章物理变化怎样经真实观察形成协议图
节点本地普通FIB、LFA、accepted/applied第20–22章控制器为何不替节点安装FIB
统一DAG、ETS3 REQUEST/READY/REJECTED第23–24章普通传输、单算子和多算子为何共用生命周期
task_id、入口本地Color、eBPF classifier、策略表第25章task怎样在Linux入口选择自己的SR Policy
Exact与Resilient模式边界第26、45、74、78–79章两种模式分别由谁选择实例
七类真实算子与独立namespace第27–38章Gray、Edge、两种Mask、Mean、Blur、BNN怎样实现
BNN KEEP/DROP、模型摘要与96%稀疏结果语义第38章正常DROP为何不等于网络或算子错误
火情检测到地面Alarm闭环第38.1、86章新Alarm task怎样自然REQUEST、READY、发送和接收
逻辑Anycast SID、节点本地primary/backup FIB第40–47章provider怎样选择、撤销、切换和形成漂移
SPP 64-byte头、Tile、Morton、对象窗口和部分成功第48–54章100个Tile完成90个为何是90%成功
SPP与有状态Anycast的理论张力第54章无网络丢包时窗口为何仍可能拆散
RGB、Gray、Edge三级自主降档第55章链路比例怎样触发本地真实算子detour而非伪造格式
HEFT rank、EST/EFT、候选过滤和完整手算第57–67章Exact怎样联合选择具体实例
HEFT primary/backup、动态重算、无解与耗时分层第68–76章何时替换策略、怎样如实记录无解和CPU竞争
10%固定卫星损毁与A→B可靠性第16.13、80章故障集合为何独立于业务,分母为何不能筛选
飞机/船舶handover第16.10、81章几何接入怎样经HELLO和端点事实自然变化
控制面EAGAIN与latest-only背压第19、82章旧完整快照为何可被新代替代而不堆积
ClickHouse、MinIO、Gitea、Run ID与只读前端第83–86章观察失败为何不能反向停止后端
八类前端事实:SRv6、HEFT、重算、Anycast、SPP、BNN、Alarm、降档第86章每种画面应由哪类真实事件驱动
24/300统一模型及install/images/start/status/logs/stop/clean项目后端操作手册怎样在同一入口安全运行和清理系统

因此,Anycast和三级降档现在不仅“出现过”,而是分别拥有完整的第六编和第八编。若今后 新增正式业务能力,应先在这张表增加学习位置和源码入口,防止功能只存在于Issue或前端卡片 而没有进入教材。

92. 源码地图

源码会演进,文件名以当前checkout为准。阅读入口如下:

想理解的内容首先阅读
不可违反的系统边界docs/simulation-compass.md
当前研发原理摘要docs/technical-principles.md
裸机操作docs/backend-operations.md
SPP二进制头include/spp.h
SPP实现与Tile坐标src/spp.c及相关测试
图像算子算法src/gyr_tile_ops.c、src/bnn_fire_model.c及相关头文件
算子worker/AF_XDP循环src/gray_af_xdp_operator.c、src/gyr_tile_pipeline.c及SPP runtime
BNN检测与Alarm业务src/gray_af_xdp_operator.c、scripts/fire_alarm.py、scripts/endpoint_business.py
节点本地Anycast FIBscripts/anycast_fib.py、scripts/sdn_node_agent.py
三级降档与SRH detoursrc/spp_degradation.c、src/spp_srh_detour.c、src/host_link_fabric.c
HEFT算法scripts/heft_dag.py
任务classifierbpf/heft_task_classifier.bpf.c
Color map操作src/heft_task_map.c及节点启动脚本
节点FIB与任务状态机scripts/sdn_node_agent.py、scripts/local_heft_policy.py和节点脚本
控制协议scripts/sdn_wire.py、四个sdn_*_service.py和节点agent
宿主XDP入口bpf/xdp_link_fabric.bpf.c、include/link_fabric.h
宿主AF_XDP fabricsrc/host_link_fabric.c、scripts/setup_issue_76_physical_fabric.sh
场景生成configs/issue255-physical-scene-300.json、scripts/physical_scene_provider.py、scripts/polar_topology_provider.py
拓扑事务与时隙scripts/topology_slot_store.py、scripts/topology_scene_runtime.py、scripts/topology_slot_fabric.py
拓扑到fabric激活scripts/topology_snapshot_to_fabric.py、scripts/continuous_polar_fabric.py
HELLO邻居发现scripts/neighbor_hello_wire.py、scripts/neighbor_hello.py
协议拓扑与本地FIBscripts/sdn_topology_module.py、scripts/sdn_node_agent.py
前端真实事实投影src/frontend/src/App.tsx、src/frontend/src/business.ts及前端测试
统一部署入口scripts/envsim_host.sh
事件分析scripts/analyze_*.py、scripts/analyze_*.sh

阅读代码时先找wire contract(线上契约)和state owner(状态所有者),再看循环和优化。不要 从一个日志字符串反推整套架构。

93. 如何安全做只读学习

学习者在.5源码机上可以执行静态命令,不会启动仿真:

git status --short --branch
git log -3 --oneline
sed -n '1,240p' include/spp.h
python3 scripts/heft_dag.py --help
bash scripts/envsim_host.sh --help
bash scripts/envsim_host.sh doctor

doctor只检查能力;install默认也只输出计划,只有install --apply才改变依赖。不要在 .5启动300节点仿真。

在.2查看运行状态也应先使用操作手册中的status和logs。不要随意执行全局 docker prune、删除network namespace、清空bpffs或修改宿主sysctl,因为这些动作可能影响 本项目以外的工作。

94. 实验一:手算IPv6前缀

给出:

地址 A = fd42:3:14::100
地址 B = fd42:3:14::200
地址 C = fd42:3:15::100
前缀 P = fd42:3:14::/64

问题:A、B、C谁属于P?

方法:IPv6每个hextet是16 bit,/64比较前四个hextet:

A前四组 = fd42:0003:0014:0000
B前四组 = fd42:0003:0014:0000
C前四组 = fd42:0003:0015:0000

答案是A、B属于,C不属于。这就是本项目用fd42:3:<node>::/64覆盖某节点全部具体算子SID 的原因。

95. 实验二:手推SRH

假设概念执行顺序为:

S1 → S2 → S3

入口封装后:

  • IPv6 DA是S1;
  • SRH保存足够信息以继续到S2、S3;
  • S1执行End后,DA变为S2;
  • S2执行End后,DA变为S3;
  • S3执行最终endpoint behavior。

练习:画出每一步的Segments Left。它表示还有多少segment需要推进,而不是“数组里共有 多少项”。抓包工具显示segment list的顺序可能与概念执行顺序相反,必须同时看DA和 Segments Left。

96. 实验三:解码一个SPP头

在受控测试文件中取64 byte头,按偏移读取:

0..3    magic
7       payload format
10..11  payload length
12..19  task id
20..27  object id
28..35  tile id
52..55  object epoch

每读取多字节字段都先确认网络字节序。然后验证:

actual_frame_payload >= 64 + declared_payload_length
task_id != 0
object_id != 0
format与payload length相容
tile坐标在grid边界内

学习目标不是背偏移,而是形成“先验证边界,再解释字段”的解析习惯。

97. 实验四:手算Color路由

假设:

task_id = 70001
Color   = 4466
dst     = fd42:10:12c::2

推导:

  1. classifier识别70001并查map;
  2. skb->mark=4466;
  3. ip rule选择table 10000+4466=14466;
  4. table 14466的目的/128路由执行SRv6封装;
  5. 后续节点不需要知道Color。

若map没有task key,先查为什么安装未完成;不要为了“让包走起来”把所有未知task都塞到某 条默认正确策略。

98. 实验五:手算HEFT

先完全遮住第67章答案,使用表格独立计算:

  1. 两个stage的平均计算时间;
  2. 四个候选组合的平均通信时间;
  3. upward rank;
  4. Gray两个候选的EST/EFT;
  5. Edge两个候选含sink的完成时间;
  6. 最终placement和makespan。

然后改变一个条件:把G5计算时间从500 us改成100 us。重新计算,观察入口传输代价是否仍 使G2获胜。这个练习能建立“局部快不等于端到端快”的直觉。

99. 实验六:区分真实失败与观察失败

构造下面四组证据并判断:

源端发送算子处理目的端接收前端显示结论
有有有无观察面失败,业务成功
有DROP无正确显示DROPBNN正常业务裁决
有无无无需继续定位数据面边界
无无无无先查业务是否自然产生,不应先改网络

这张表训练“缺少显示不等于缺少事实”。

100. 常见误区与纠正

100.1 “SRv6就是IPv6源路由”

不完整。SRv6不仅列路径,还把SID解释为网络程序行为,例如End.X、End.DX6和算子实例。

100.2 “控制器知道全网,所以应该直接写所有节点FIB”

本项目明确禁止。控制器分发事实,节点根据自己已经应用的事实形成FIB和SR Policy。

100.3 “Color是画面颜色或业务优先级”

不是。Color是入口本地把task导向专用策略表的短标识。

100.4 “Anycast会把同一个包复制给多个容器”

普通Anycast选择一个provider,不复制包。出现五个实例记录通常意味着不同包或不同时刻的 FIB选择发生了漂移。

100.5 “有一个Tile缺失,整条task失败”

不符合当前SPP部分成功语义。应按完成Tile/预期Tile统计。

100.6 “HEFT没有解就是Bug”

不是。资源、算子或路径约束可能使问题真实不可行,应记录无解原因。

100.7 “HEFT超过100 ms必须强行短路”

不是。先区分算法CPU时间、调度等待、快照传播和内核安装;观察阈值不是修改协议语义的命令。

100.8 “把超时加长就能提高可靠性”

加长可能只推迟错误并增加旧状态堆积。先证明第一个未闭环的组件边界。

100.9 “前端页面是系统真相”

前端是事实投影。真实来源是节点、内核、fabric、控制器和对象证据。

100.10 “24节点是简化假模型”

24与300使用相同镜像、PID 1、协议和启动逻辑,只改变规模和参数。

100.11 “10%损毁后只统计仍有路的任务更合理”

这会改变实验分母。可以另报可行任务完成率,但不能替代损毁后的总业务成功率B。

100.12 “SPP和Anycast不能同时使用”

过于绝对。无状态算子自然兼容;有状态算子会承受provider漂移带来的窗口损失,当前将其按 Tile可靠性量化,更高层状态安置是后续理论问题。

101. 综合练习

101.1 基础题

  1. IPv6地址128 bit共有多少byte?
  2. /64表示哪部分是前缀?
  3. FIB与RIB分别解决什么问题?
  4. SRH中的active segment与IPv6 DA有什么关系?
  5. End.X与End.DX6的作用有什么不同?

101.2 系统题

  1. 为什么宿主XDP只按MAC redirect,而不自己计算IPv6路由?
  2. 为什么控制器的accepted generation不能直接当作节点applied generation?
  3. 为什么resource report必须有instance、sequence和lifetime?
  4. task_id、Color、Run ID的作用域各是什么?
  5. Exact策略中为什么使用具体算子SID?
  6. Resilient策略中为什么使用逻辑Anycast SID?

101.3 SPP题

  1. 两个包object_id相同、epoch不同,能否进入同一缓存窗口?
  2. Tile Mean为什么不能按“任意四个包”聚合?
  3. 100个预期Tile到95个,Tile成功率是多少?
  4. BNN DROP与算子ERROR有什么区别?

101.4 HEFT题

  1. upward rank使用平均成本,最终placement也使用平均成本吗?
  2. EST为何可能晚于所有前驱完成时间?
  3. 一个stage在node-5的EFT更小,但它到sink很远;出口选择应比较什么?
  4. primary排除首边与具体实例后backup无解,正确记录是什么?
  5. Resilient provider变化为什么不触发HEFT?

101.5 诊断题

  1. 前端没有图但目的端有接收事件,应先修数据面还是观察面?
  2. 控制socket出现EAGAIN时,为什么不应无限累积旧拓扑快照?
  3. HEFT墙钟耗时变大,至少还要观察哪三类数据?
  4. 一轮运行有业务ENETUNREACH,为什么不能立即断言宿主网络安装失败?
  5. 观察器失败后,分析脚本应该怎样继续?

102. 综合练习答案

  1. 128÷8=16 byte。
  2. 前64 bit是网络前缀,其余64 bit是接口标识部分;具体地址规划仍由项目定义。
  3. RIB保存控制面候选路由知识,FIB保存内核实际用于快速转发的结果。
  4. active segment作为当前IPv6 DA;端点行为推进后,DA变为下一个active segment。
  5. End.X推进SRH并交指定下一跳;End.DX6解封装并交付内层IPv6。
  6. 保持Linux拥有路由语义,XDP只做最小可证的L2分流,避免宿主暗中形成第二套路由器。
  7. accepted仅表示消息被接收,节点还要通过单一worker验证并安装,成功后才是applied。
  8. 用来区分进程重启、消息新旧和事实过期,防止旧实例“复活”。
  9. task_id是端到端业务任务;Color是某入口本地策略选择;Run ID是一整轮实验和证据。
  10. Exact已由HEFT选择具体实例,策略必须把选择落实成可执行地址。
  11. Resilient把实例选择留给每个逻辑服务的当前FIB。
  12. 不能,epoch不同表示对象版本不同。
  13. 必须是同对象、同epoch、同2×2空间group的四块。
  14. 95/100=95%。
  15. DROP是模型作出的正常负类裁决;ERROR表示格式、模型或运行异常。
  16. 不使用;最终placement使用候选间具体计算和通信代价。
  17. 目标processor可能仍在执行此前放置的stage,所以还要等待resource available time。
  18. 比较EFT加该候选到sink的具体通信时间。
  19. 记录primary成功、backup no solution及约束原因,不伪造backup。
  20. Resilient不运行HEFT;它只更新逻辑服务FIB,task SRH稳定。
  21. 先查观察面查询、Run ID、权限和投影。
  22. 旧拓扑已被新代完整取代;积累历史会使节点永远追赶过期状态。
  23. 线程CPU时间、调度/run queue、输入候选规模;还应分开快照传播与内核安装。
  24. 业务路径在动态拓扑/损毁下可以自然不可达,需先区分宿主能力、控制面、FIB和任务结果。
  25. 捕获该观察器状态并继续其他领域分析,最后统一汇总,不能让set -e提前退出。

总目录 · 上一篇:第十编:业务、故障、前端和证据 · 下一篇:第十二编:英中术语表