本文主体内容译于[DPDK社区文档],但并没有逐字翻译,在原文的基础上进行了一些调整,增加了对TSS分类器的详细阐述。
1. 概览
本文描述了OVS+DPDK中的包分类器(datapath classifier -- aka dpcls)的设计与实现思路。本文的内容主要牵涉到分类器对封包流的分类及缓存技术,并且对于一些典型场景下的细节给予解释说明。
虚拟交换机与传统硬件交换机的差别较大。硬件交换机通常都使用TCAM以求高效率的包分类与转发。而虚拟交换机由于自身是纯软件实现,不能依靠特殊的硬件设计,为了达到较高的工作效率,在设计和实现上大量使用缓存技术。OVS是一个兼容OpenFlow协议的虚拟交换机软件,发展比较迅速,基本上算是当前的业界网络虚拟化中的标杆与事实标准,OVS为了获得较高的转发性能,采用的基本思想也比较朴素:缓存。
OVS的数据转发面(datapath -- aka dp)有多种实现,其中比较著名的有基于Linux内核协议栈的实现与DPDK的实现。当采用DPDK的实现时,封包的处理流程将完全绕过内核协议栈。OVS+DPDK在封包的查找匹配中,共有三级查找表/缓存的设计。最底一级是为完全精确匹配(Exact Match Cache -- aka EMC),如其名所示,这一级的查找匹配无法实现范围匹配、掩码前缀匹配等功能。中间一级就是本文的主角:dpcls,这一级的包分类器其实就是[这篇论文]描述的TSS分类器,使用论文中描述的TSS算法,这一级的分类器可以实现范围匹配、掩码前缀匹配等功能。如果单纯的作为一个虚拟交换机,仅有最底一级与中间级已经足够,而为了兼容OpenFlow协议,OVS还有最上一级的查找表:OpenFlow分类表(ofproto classifier table),其表项由OpenFlow控制器管理。下图基本展示了这三级查找表/缓存的设计逻辑。
当一个包到达时,优先查找最底一级的EMC表,命中则转发,不命中则继续查找中间一级的包分类器,再不命中的话锅就扔给OpenFlow的分类器了,再不命中就要扔给OpenFlow控制器了,逻辑很清晰。
当封包流很稳定,流的数量EMC表也能hold住的时候,转发的性能取决于EMC表的查找匹配效率。这算是理想状态,现实世界很残酷,EMC表的容量有限,在封包流的数量达到一定规模的时候,决定转发效率的瓶颈就变成了中间一级的dpcls。所以dpcls本身的处理效率对于OVS+DPDK来说是很重要的一个关隘,其设计与实现是比较精巧的。
2. TSS分类算法简述
2.1. rule的定义
这里简单的介绍一下TSS分类器所使用的分类算法,不牵涉任何优化手段,仅介绍原算法本身。
定义rule就是单条的包过滤规则+动作,它可能长这样:
1 Rule #1: ip_src=10.10.2.0/24 ip_dst=* protocol=UDP port_src=* port_dst=4789 actions=drop 2 Rule #2: ip_src=10.11.0.0/16 ip_dst=* protocol=TCP port_src=* port_dst=23 actions=output:3
为了描述清晰起见,rule中的过滤规则使用了稳定的五个字段,即经典的五元组,但实际上rule可以使用任意多的字段
rule中的过滤规则,或者叫匹配规则,是由多个单字段过滤规则组成的,这些过滤规则符合,或者能转化为以下的形式:
1 字段值/掩码前缀
比如,对于IP地址来说,经常就是如下的形式
1 ip_src=192.168.0.0/16 2 ip_dst=33.23.12.0/24
对于IP头中的协议字段来讲,由于协议字段仅占八位,多数情况下都是严格匹配,比如上面列出的两个rule,其协议字段都是严格匹配为UDP或TCP,故它们可以写成如下形式
1 protocol=6/8(TCP) 2 protoco=17/8(UDP)
对于四层头中的端口号,一般情况下在各种防火墙也好,OpenFlow流表也好,匹配规则一般都写成精确匹配或者取值范围的形式,精确匹配可以很简单的写成字段值/前缀掩码的形式,无非就是掩码是16位掩码,而取值范围要转化为字段值/前缀掩码的形式,就需要一定的转化。我们举个例子好了,取值范围[12345, 33123]可以转化为如下形式:
1 0011 0000 0011 1001 | 12345 2 0011 0000 0011 101* | 12346~12347 3 0011 0000 0011 11** | 12348~12351 4 0011 0000 01** **** | 12352~12415 5 0011 0000 1*** **** | 12416~12543 6 0011 0001 **** **** | 12544~12799 7 0011 00