文章

卡皮巴拉代码结构和接口设计考量

有点干不下去,点开下一集甄嬛传,然后决定先记点日志再看。

卡皮巴拉的代码主要分布在三个源码文件中(略去共同路径前缀src/rust/inetstack/

  • tcp/peer.rs:顶层接口。因为是Demikernel原本就有的,所以和Demikernel运行时中其他部分进行对接,也就是对TCP协议栈修改的「入口」必须写在这里,比如在接收端处理数据包的条件分支中加入对迁移期间来包的缓存逻辑,在轮询的条件分支中加入在迁移完成时把缓存的数据包送进TCP控制块,等等。面向上层应用的接口也会写在这里并向下穿透。
  • tcpmig/peer.rs:迁移核心逻辑,即控制面
  • tcpmig/active.rs:迁移数据面,但是有状态

peer.rs当中是整个网络栈范围内的全局状态,并且对每个活跃迁移维护一个active.rs中定义的对象实例。而后者是给每个迁移中的连接专门维护的状态,基本上是一个协议状态机。


另外一边。TLSe的接口看起来提供了SSL兼容模式,可以快速出活(来给我的拖延找补)的概率大幅提升。

重点关心了一些它的上下文导入/导出接口。看起来导出流程是先调用一次接口来获得数据长度,再调用一次来写数据。这告诉了我们两点

  • 数据长度是动态可变的
  • 数据长度是可以获取的。另外从导出的内容来看长度可能还不会短,因此还是不要考虑假设一个最大长度的偷懒做法

总之先去掉了目前的设计。经典活干不完了回滚,还滚得非常彻底因为本来也还没干多少。

看起来我应该把用户连接的状态放在tcpmig/peer.rs中,实在有必要的话也可以放进tcpmig/active.rs

迁入一侧的接口好设计,因为这个接口是在上层应用逻辑中被调用的,所以简单的一手交描述符一手交迁移来的用户连接数据(如果有的话)就可以了。

迁出一侧就比较麻烦,因为需要在卡皮巴拉运行时中执行用户逻辑来告知迁出和获取用户连接数据。

一方面,这就需要用户提供点什么来给卡皮巴拉调用。目前的部署模式,即用垫片层无感知地替换系统调用,对于这个反向调用的需求很不友好。

另一方面,这涉及到相当规模的穿针引线。我们希望用户连接的序列化尽量和卡皮巴拉序列化TCP连接的逻辑放在一起,不然就要做些多余的数据复制。显然TLSe的导出功能已经包含一次多余的复制了我们就不要再增加了。然而当前的代码库又非常倾向于擦掉所有的类型参数——反正目前是一个类型参数都没有的。所以要把一个「无类型」的用户连接传来传去,有点让人不舒服。

最后也是最重要的,「迁移出」是一个副作用而「序列化」应当是没有副作用可重入的。嘛虽然接口随便设计设计也就可以了但是还是想把两者表示清楚,感觉会有用的。

好了先想一会吧。

本文由作者按照 CC BY 4.0 进行授权