在上期《云计算与虚拟化硬核技术内幕 (16) —— 抄作业的熊孩子》中,我们发现,虽然用DPDK可以极大提升Intel x86 Linux系统对网络数据包的处理效率,但如果硬件网卡(NIC)不能将数据包按流均分到各个DPDK运行的CPU HT上,会造成部分数据包乱序。
因此,所有支持DPDK的网卡,需要支持硬件辅助的流分类(flow classification)。
如何进行流分类呢?这需要在纷繁的网络通信流量中,把一条“流”识别出来。
我们知道,在所有通信系统中,一条“流”都是在源地址和目的地址之间流动的。
2009年,一句话火遍全网:
“贾君鹏你妈妈喊你回家吃饭”
在通信工程师看来,这句话是一个标准的通信控制信令数据包。
包的目的地址是“贾君鹏”,源地址是“你妈妈”,控制信令的内容是“回家吃饭”。
在网络世界中,一条流是这样的:
如图,用户210.71.9.114打开端口53311,并通过TCP访问服务器166.111.8.238上的23端口(懂得这是在干什么的,都已经老了)。只要是属于本次通信行为的数据包,一定都具备这五个特点:
源地址:210.71.9.114
源端口:53311
目的地址:166.111.8.238
目的端口:23
通信协议:6(TCP)
当然,通信是双向的,因此,返程流量的数据包,其源地址/目的地址,源端口/目的端口需要调换:
源地址:166.111.8.238
源端口:23
目的地址:210.71.9.114
目的端口:53311
通信协议:6(TCP)
那么,只要数据包中,这五个字段符合以上特征的,就可以被识别为同一条流。我们可以将这五个字段进行一定的运算(也就是所谓的hash运算),得到数据包的一个特征值(也就是所谓的hash key),根据这个特征值将其分发到指定的HT上。
网卡所谓的流分类功能,指的就是自动计算hash key并根据hash key分发数据包的功能。
问题来了,世界上并非所有的数据包都是TCP和UDP,还存在一些其他的数据包,如RAW IP,比如这个数据包:
它是一个IP数据包,但四层协议号既不是6(TCP),也不是17(UDP),而是0x2F。可以看出,这是一个NVGRE(Network Virtualization using Generic Routing Encapsulation)数据包,区分GRE隧道的字段为GRE Hearder的Virtual Subnet ID字段,与TCP/UDP的端口字段在完全不同的偏移量位置。
那么,如果网卡硬件简单粗暴地按照UDP和TCP的流分类方式对数据包进行字段提取和hash key计算,是不可能得到正确的结果的,这条NVGRE流会被送到多个HT,而无法保证送到同一个HT,进而造成数据包的乱序。
因而,网卡需要可编程功能,智能识别不同的数据包,才能避免数据包的乱序!
这就推开了智能网卡(SmartNIC)领域的大门……
本期再讲一个数据包乱序的故事:
秦少游写了一首诗,通过基于UDP的QQ,发送给苏小妹,想表现自己是一个顿悟哲理的好青年:
终日昏昏醉梦间,忽闻春尽强登山。
因过竹院逢僧话,偷得浮生半日闲。
由于出现了数据包乱序,苏小妹收到的是:
偷得浮生半日闲,忽闻春尽强登山。
因过竹院逢僧话,终日昏昏醉梦间。
苏小妹心里想:你原来是“终日昏昏醉梦间”的普信男啊!
顺手删除了秦少游的QQ。
而基于https的wx,不像QQ使用UDP,就没有这样的问题了。
(以上为段子,不要当真)