前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向云网络的高性能易扩展NFV技术平台

面向云网络的高性能易扩展NFV技术平台

作者头像
鹅厂网事
发布2020-04-30 17:40:28
2.4K1
发布2020-04-30 17:40:28
举报
文章被收录于专栏:鹅厂网事鹅厂网事

      为帮助客户快速构建灵活的网络能力,大部分云服务提供商都选择使用他们最擅长的软件的方式来进行支持。沿用通信行业的一种叫法,即是NFV(Network Function Virtualization)。

      公有云厂商的NFV主要用于解决以下几类问题。一是多个网络的互联互通问题,例如有物理网络到Overlay网络的互通、异构网络架构之间的互通、公网私网之间的NAT互通等等;二是多个网络之间的路由传递和快速感知,例如复杂冗余组网时局部网络发生故障或变更时的快速网络自愈、异构网络之间的路由传递等;三是网络安全相关问题,主要包括安全传输、防攻击、流量识别等;四是4-7层网络服务,例如LB、WOC、WAF等。

      目前我们的NFV产品大多是为解决其中的一类问题或多类问题而产生。在数量众多的NFV产品不断迭代过程中,我们发现越来越多的共性问题需要解决。例如基本的IPv4/IPv6转发能力的支持、GRE/VxLAN隧道能力的支持、BGP/BFD路由能力的支持、大规模路由表项的支持、底层虚拟化的支持等等。因此,我们希望构建一套NFV通用平台来系统性的解决这些共性问题。

设计思路

设计目标

      这套NFV通用平台需要具备哪些特点呢?首先,它必须具备高性能转发能力,NFV产品使用通用的x86 CPU来处理业务报文,和传统网络设备使用ASIC/NP的方式存在极大的区别。ASIC/NP处理逻辑固定、结构单一,可以达到很高的处理性能。NFV平台所有的功能都依赖CPU指令集实现,CPU指令集设计粒度非常细,因此可以灵活解决很多不同场景的业务问题。但同时带来一个副作用,由于设计过于灵活,在包处理场景如果不经过精心设计很可能导致业务处理延时过大、无法满足业务性能要求。因此NFV通用平台必须在框架层面保证极高性能的报文处理能力。

      其次,它需要具备灵活的功能可扩展能力,前面有提到,NFV在公有云场景需求多、功能差异大,不同产品要求的功能千差万别。功能可扩展能力包括两个方面。一方面在转发面功能上必须能够灵活扩展,例如转发面可能支持的特性包括L2/L3转发、流表转发、NAT转发、报文分析、加解密、QOS等等,NFV通用平台本身不一定要支持所有的功能,但需要具备基于基础功能进行快速迭代的能力,并且不同的功能之间可以做到互相不影响。

      另一方面控制面功能上也要做到支持灵活扩展,控制面功能也可能有很多,例如IKE、BGP、主备HA、集群能力、gRPC通道等等,NFV通用平台需要提供一种可以灵活组装这些控制面功能的能力,方便产品快速迭代。除此之外,这套NFV通用平台还需要具备灵活的资源抽象能力。在实际应用场景中,我们可以基于物理服务器,也可以基于虚拟机来构建我们的NFV产品。NFV通用平台需要同时支持两种应用模式,并在底层屏蔽两种应用模式的区别,做到底层硬件与功能特性解耦。同时,由于物理硬件和虚拟机的能使用的资源各不相同,例如它们可能有不同数量的CPU核心数、不同数量的内存量、不同数量的端口等等,通用NFV平台需要能支持所有这些差异,灵活为产品适配不同的硬件资源。综上所述,我们期望构建一个高性能易扩展的通用NFV平台。

架构设计

      为满足上述这些目标,我们应该如何构建这样一套通用的NFV平台呢?

      首先,我们来看下转发面。转发面的主要诉求是高性能和易扩展,从技术成熟度和支持硬件的范围来看,底层使用DPDK进行收发包基本没有太多争议。DPDK实现的PMD驱动可以帮助我们高效的将网卡上的报文送到我们的用户态应用程序,同时DPDK社区十分活跃,支持的硬件种类十分广泛。但光有DPDK还不够,它只能解决高性能收发包问题。高性能的报文处理和转发面灵活扩展的能力还需要进一步进行构建。社区中有一些开源项目在这方面做了许多工作,比较知名的有VPP、OVS、ODP等。从转发框架设计目标、实现框架、功能丰富性、社区热度等方面来看,VPP是最接近我们期望的转发框架。

      另外我们来看下控制面,控制面我们需要的功能很多,每个产品各不相同,例如路由转发产品需要路由协议栈、IPsec网关产品需要IKE支持、SSLVPN产品需要SSL控制层协议等等,这些功能都可能通过不同的应用程序来实现。但控制面的各种功能都有一个共性的需求,向上需要支持与控制器联动,向下需要支持与转发面互通。因此,控制面需要一个模块,实现控制面对上对下以及不同控制功能之间的粘合。这部分基本没有可参考的开源实现,必须自研解决。同时在底层,我们还需要一个资源抽象层,来适配物理环境和虚拟环境的各种资源抽象。基于此,我们构思整个NFV通用平台的原型框架如下图所示。

实现方案

关键模块

      在这个框架下,我们如何解决上面提到的那些问题呢?

      首先,转发面高性能和功能可扩展能力,我们期望基于VPP来构建。

      高性能方面,VPP通过报文的批量处理提高了i-cache和d-cache的命中率。如图所示,VPP一次性从网卡队列中读取N个报文,与常见的RTC(Run To Complete)模型处理每个报文直至结束不同,VPP是将一批的N个报文批量传递给func1处理,然后再交给func2处理,直至处理结束。这样就极大的提高了i-cache的命中率。因为处理报文1时,func1的指令可能不在i-cache中,产生了一次cache miss。而后面的N-1个报文,仍然是要执行func1的指令,而这时func1对应的指令已经被加载到i-cache中。这样就把一次cache miss的成本,摊平到了N个报文上,相对于RTC模型来说,其i-cache命中率无疑要高出很多。d-cache高命中,则是通过prefetch来实现的。在处理函数func中,因为明确知道要处理N个报文。那么可以在处理当前报文的时候,显式调用prefetch来指示CPU提前将后面的报文加载到d-cache中。这样在处理后面的报文时,可以直接在d-cache中命中。

      通过这种批量报文处理方式,VPP可以获得较好的性能数据。

在转发面功能扩展性方面,VPP实现了一种可plugin的方式。在VPP中,“每个”功能都是一个node,每个node中仅实现一个简单的功能,然后通过将各个node组成一个graph图,让数据报文在node之间“流动”,从而实现业务功能。node之间基本上没有“业务”上的逻辑依赖,只有“指向”的关联。这样的设计,无疑实现了程序员们一直追求的“高内聚”和“低耦合”。

node graph的“生成”由三个因素决定:

1) node代码静态定义下一级的node;

2) 由vpp代码在启动过程中生成node和更改node之间的关系;

3) 根据vpp的配置命令生成和更改node之间的关系;

     当新增功能时,只需要实现若干新的node,将其串联到当前VPP的node graph中,即可完成功能的支持,并且可以基于不同产品维护不同的node graph,支撑不同的应用场景。

      其次,我们需要构建一个通用的粘合层,用于粘合上层控制器/网络编排器的指令,对接数据平面,实现不同控制面功能的整合。我们构造了如下图所示的一套粘合层来实现这项功能。对外,我们提供统一的GRPC接口和CLI接口,供控制器或运维人员使用。内部实现一套命令注册/合法性校验/服务注册/服务框架/审计日志/配置核查的功能模块,支持各种命令行或GRPC接口的实现。对控制面功能,我们实现一批定制化模块,实现与各个控制面功能的互通,例如通过swanctl与strongswan互通相关配置信息和SA信息,通过frrclient实现与frr互通配置信息及路由信息。通过vppstub实现与转发面的互通,主要包括下发路由信息、SA信息等。并且,针对未来可能有的新增控制面功能,我们都可以在粘合层扩展对应的client功能实现与之对接,并复用转发面通道。通过这种方式,我们可以较好的实现控制面功能的扩展。

      另外,在底层资源抽象方面,我们采用的这套框架也可以较好的支持。首先控制面协议和粘合层都是通过Linux进程方式运行,对底层资源没有太多依赖。主要存在依赖的是转发面部分。所幸,转发面框架VPP,可以在启动时通过参数的方式指定使用的硬件资源。因此,我们可以简单的通过启动脚本读取当前系统资源配置,进行资源划分,将一部分资源划分给内核使用,一部分资源划分给控制面使用,一部分资源划分给转发面使用。不同的产品可以使用不同的分配策略。这种方式缺点很明显,即无法支持未知硬件资源的应用场景。但由于目前大部分应用场景中,我们是预先知道对应的硬件资源分配情况的,在当前的应用场景中基本可行。

主要问题

      通过上述设计,我们期望可以构造出一个高性能易扩展的NFV通用平台。但在实现过程中,我们碰到了很多具体的问题,主要集中在转发面的VPP上。仔细分析开源版本VPP实现,我们发现在许多实现细节上开源代码实现不够细致,存在较多缺陷。其中较突出的几个问题如下。

      首先,VPP线程间同步机制存在问题。VPP的线程模型是一个控制线程(也是其主线程)和多个工作线程。工作线程只负责报文转发,其它功能都由控制线程完成,如端口监听,配置更新,定时器,耗时任务(可能有阻塞调用)等,甚至还实现了协程,并由其负责调度执行。这是一个标准的一写多读的模型,ctrl thread负责做配置修改,worker thread根据配置做相应的处理。这时需要保证writer进行配置修改时,reader看到的是一个“完整”的数据,writer进行配置删除(如内存释放)时,reader可以安全的使用配置。最直接的方法就是读写锁。然而对于NFV设备来说,读写锁的代价太重。当ctrl thread持有写锁时,worker thread拿不到读锁导致block,是网络设备不可以承受的代价。

      所以,在这样的场景下,大家一般都是使用RCU来解决这个问题,做到ctrl thread修改配置时,worker thread不会阻塞,仍然可以正常工作。VPP没有采用以上两个方案,而是使用了它宣扬的barrier机制。其示意图如下:

      这里的barrier并不是我们常说的内存屏障,而是vpp用来保证安全修改配置的一个方法。ctrl thread要修改配置前,会设置于一个全局的barrier标志。worker线程在处理循环中,每次都要检查这个标志。如果有,则让自己的工作停止下来,等待ctrl thread修改完成。ctrl thread设置完标志后,会一直等待到所有worker thread全部停止了,再进行配置修改。配置更新完毕后,再reset barrier标志。这时候worker thread才能继续工作。从这个流程上看,其实这个barrier机制类似于读写锁,但在这个场景下比读写锁更适合。因为这里的barrier机制,是保证了写者优先,避免在这种大量reader的情况下(可能几十个),会一直持有读锁,导致writer“饿死”的情况。然而它还是无法避免一个问题,writer在做更新的时候,reader也就是worker thread只能处于“停滞”状态。这对于满负荷工作的网络设备来说,会产生丢包,几乎不能接受。

      其次,VPP的对外通信机制也存在问题。前面提到过,转发面有一个重要的工作,是接收控制面下发的相关规则,并基于对应规则进行转发。VPP提供了一套VAPI机制实现这项功能,可以通过share memory方式对外通信,也可以通过unix socket方式进行通信。VPP默认使用shared memory方式,shared memory方式的优点是通信效率非常高,将数据写到对应内存中,通知对端读取即可,缺点是共享内存竞争读写时十分复杂,需要使用锁机制来进行保护。我们最初采用的也采用了shared memory方式。但在验证的过程中,发现这种方式很容易触发死锁,甚至崩溃。我们尝试解决了一些问题,但还是稳定不下来。由于时间所限,就直接切换到了基于unix socket的方式,避免锁竞争。因为unix socket方式做到了进程之间的内存隔离,所以整体还是比较稳定的。但在测试大量消息通信的条件下,也暴露了一些问题,主要集中在消息的拆分和合并上。例如我们发现一个问题,当遇到大量消息通信时,还是会偶尔触发消息parser错误的情况,最终定位发现是底层创建unix socket时使用了SOCK_SEQPACKET,而socket收发包是按照stream方式处理,导致客户端在读取数据时在没有读完所有数据情况下将报文丢弃,引起应用层parser错误。

      另外,VPP在一些业务处理逻辑上也存在部分问题,例如分片报文IPID直接填写为0、隧道封装报文IPID没有做多线程支持、IP报文某些处理逻辑只考虑头部长度为20字节、某些变量没有初始化等等。类似这种细节实现问题比较多,这里不一一列举,反映出VPP开源代码距离产品化还存在一些差距。

      针对VPP原生的这些问题,我们的策略是对VPP代码进行裁减,只保留核心框架和必需的业务功能代码。同时,对必需的业务功能代码,重点进行消化吸收,对不合理逻辑进行优化,增加调试定位手段。经过将近1年时间的测试/分析/解决/验证,目前已经可以稳定下来。值得称赞的是VPP的基础node graph框架部分代码实现质量还是非常高的,基本没有出现过问题。总体来看,VPP设计思路非常好,框架本身质量可控,但相关转发功能、通信机制等实现细节还需要持续进行打磨

效果验证

      基于目前的NFV通用平台可以达到较好的处理性能,这里分享一组数据,供参考。测试场景说明如下:主要业务类型为IPsecVPN业务,流量类型为IPsecVPN和GRE实现Overlay转发,规格为2000条IPsec隧道及2000条GRE隧道,硬件配置为双路至强CPU,80个逻辑线程,MLX CX-4 40G网卡。性能数据如下:

      从实测数据来看,当前的NFV通用平台基本可以实现大规格IPsec隧道下大包40G线速转发,实现了预期目标。针对普通的L3转发数据,由于不做加解密,性能表现会更好,这里不重复提供,可以参考VPP官方提供的数据。

未来展望

      基于上述思路和方法,我们构建了一套支持高性能转发、支持转发面和控制面功能扩展、支持底层硬件资源解耦的通用的NFV平台。目前,我们基于这套通用NFV平台的一款产品已经正式发布,我们已经启动将其他的NFV产品逐步迁移到这套平台上。未来我们计划将这套平台开源出来,回馈社区,为所有开发者提供一个能够快速构建NFV能力的质量稳定可靠的产品级研发平台。目前我们的NFV平台还是不断优化迭代中,欢迎大家留言探讨通用的NFV平台技术!

欢迎关注公众帐号“鹅厂网事”,我们给你提供最新的行业动态信息、腾讯网络最接地气的干货分享。

注1:凡注明来自“鹅厂网事”的文字和图片等作品,版权均属于“深圳市腾讯计算机系统有限公司”所有,未经官方授权,不得使用,如有违反,一经查实,将保留追究权利;

注2:本文图片部分来自互联网,如涉及相关版权问题,请联系v_meizhuang@tencent.com

鹅厂网事

分享鹅厂网络的那些事

扫码关注!解锁更多~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鹅厂网事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档