你好,P4

29 Nov 2016

好久没有写技术相关的日志了,其实也好久没有写日志了,上一篇都快一年前了。

花了一天时间,阅读了P4最初的论文,感觉有蛮多比较有趣也值得以后继续学习的地方。

论文是2014年的,P4的出现可能要更早,据Wikipedia上的介绍,是2013年。

至于目前的发展怎样就不太清楚了,没有太去关注社区的情况。扫了一下邮件列表的记录,讨论并不是很热烈,社区的成员列表倒是挺长的。

说到SDN,实在是比较难定义的一个话题,当然无论如何不是应该纠结在所采用的tunnel技术或者隔离方式的。通行的定义嘛,基本认为有三个要素,控制转发分离,集中化的控制平台以及控制平台的可编程性。OpenFlow事实上提供了一种将控制与转发进行分离的手段,因而常被拿去直接等价于SDN,虽然显然不是。P4则更进一步,也是在将控制与转发进行分离这个话题上做文章。而有别于OpenFlow是对控制平面与转发平面之间的通信/关系进行了定义,P4并不着重讲这两者之间的关系,它的重点是更加明确转发平面上的行为,从而能够将决策行为更完全地交给控制平面去定义并完成。其次,是简单讨论了怎么将P4中的概念映射到具体的物理设备上面去。

P4并不是作为OpenFlow的挑战者而存在的,相反,它是对OpenFlow未来发展趋势的一种探讨,明确要解决的是OpenFlow中,要匹配的项目越来越多的问题。至于其他部分的功能,可以说是由于这个问题得到解决之后发展开去的自然结果。

网络设备对网络包的处理,很大程度上依赖于对packet header的解析。最简单的例子是一个二层交换机,当它从某个端口接收到包时,一般是记录下源MAC地址与端口的映射关系,然后在这样的一个映射关系表中根据包的目标MAC地址查找对应的端口,找到就直接转发,找不到就广播等接收到响应时再来建立这个目标MAC与端口的映射。而除了这个例子中所说的交换机,网络中还有很多其他类型的设备,但其实所有的设备离不开对包的匹配和处理这两个主要课题。

既然所有设备干的事情都差不多,为什么我们需要那么多的设备?传统上,网络设备上的控制逻辑通常和转发平面是没有明确界限的,都高度集成在设备当中。当然这在最初计算能力有限的情况下无疑是对效率作出的妥协。计算能力有限的情况下,控制逻辑也简单,于是整个网络上随着时间的发展,就充斥着各种头脑简单的设备。至于这些设备的四肢是否发达,对不起,没人关注,因为在当时,控制逻辑就只要求转发平面实现有限的功能,达到它所要求的效率即可。

于是SDN这样的课题应运而生。我们的计算能力得到了很大的发展,想做(和能做)的事情越来越多,控制逻辑越来越复杂,网络设备的部署规模也越来越大,传统上设备各自的独立性,很大程度上成为了瓶颈,不管是管理上还是技术上。于是人们不再满足于只堆砌网络设备然后成为它们的奴隶,开始觉得需要把控制逻辑和转发平面分离开来,从而能够在一个更高的层次上对网络设备进行统一的管理,人类才是那个控制一切的角色。

然后OpenFlow脱颖而出,它定义了一个协议来将控制逻辑和转发平面分开。虽然很直观的感受是,OpenFlow的目标设备只是交换机,但实际上,通过一定的抽象,它的目标对象可以变身成为其他的网络设备。或者说,它能够模糊各种网络设备之间的区别,只讨论他们之间的共同点,即上面所说的,对网络包/流的匹配和处理。

OpenFlow开始发展,从最初的1.0有12个匹配项目,发展到1.4,已经有41个可以匹配的项目。从最开始的直接进行匹配,到后来在协议中发展出来OXM来进行匹配。而且显而易见的是,这种匹配项目的扩展没有要停下来的迹象。每增加对一个新协议的支持,就可能增加好几个可以匹配的项目。这很复杂,不simple,不elegant。

于是今天的主角P4出场了,对比OpenFlow,它最大的特点是,你什么都不能匹配到,却又什么都可以进行匹配。P4原生没有预定义任何协议,对任何协议的支持,都是由写程序的人自己去定义的。后面会介绍到,当将P4中的Parser集合固定下来,它看起来就像OpenFlow一样。所以最大的区别在于这个Parser的概念,在P4中是动态的,可编程的。由这个区别所引申出来的,P4中的action,即对于包的处理,也不可能是固定的,它也是对协议独立的,动态并且可编程。额外的一个区别是,P4中讨论了对匹配和处理的并行化,在OpenFlow中都认为匹配和处理是串行的,P4考虑了底层设备的不同(单核vs多核),于是讨论了并行处理这个概念。以上三点,就是P4和OpenFlow间的不同。

上面说了,P4是对OpenFlow未来发展的一种思路,它本身并不太关注说控制逻辑和转发平面之间的通信应该如何。虽然照着它的定义去实现通信协议并不困难。它的重点在于,将原本协议是固化的这件事情,变成协议独立,可以动态化定义。于是思路再也不被局限在Ethernet,IP,MPLS,TCP这些协议的概念之上了,可以很自由的,真正的去实现自己的协议。

一个P4程序有以下几个组成部分:

从上面几个组成部分可以看出来,P4程序,类似于OpenFlow中所定义的那些匹配和动作的超集。假设一下我们将P4中的Parser简单的定义为Ethernet,然后是802.1Q(VLAN)/ARP/IP和IP之下的TCP/UDP,将tables定义为匹配前面那些网络包头部中解析出来的值,actions限制为OpenFlow 1.0中所支持的修改动作,tables的顺序定义为简单的逐个表格执行,那么我们最后得到的逻辑,就类似于一个OpenFlow 1.0中所定义的东西。可以看出来,解放了Parsers的定义,真正是解放了思想。

最后,P4作为一门编程语言,还有编译相关的东西,不过这些并不是我所擅长的东西。简单说一下,分成两级,首先将源文件编译成类似中间文件之类的东西,这个步骤是平台无关的,在支持动态Parser的目标上,会构造出来一个状态机,不过对于固定Parser(支持OpenFlow的那些),就只是简单检查下Parser的定义目标能否满足而已了。另外一个在这个步骤完成的事情是,多个tables的依赖关系和并行处理的可能性的确定。第二级编译是平台相关的,就是将上面生成的中间文件映射到具体设备的资源之上了。

接下来,我应该会进一步学习P4相关的东西,主要是SPEC本身以及示例的程序,过程中也应该开开脑洞思考一下P4还能做些什么,等有时间再写日志分享了。