P4教程Flowlet Switching源码分析

作者简介:陈翔,福州大学数计学院2015级计算机科学与技术(实验班)本科生 ,对软件定义网络SDN,特别是对P4语言感兴趣。

前言

为深入研究P4语言相关规范及运行操作使用,本系列文章根据P4.org网站给出的《The P4 Language Specification v1.0.2》[1]内容,并通过我们的运行使用的具体实例和分析汇总,希望能为大家研究P4提供一点参考。作为大二和大三的本科生,水平和经验有限,感谢SDNLAB提供平台,希望能和大家相互学习交流。

本系列文章分为三个部分,系列一翻译和阐述 P4.org网站给出的《The P4 Language Specification v1.0.2》的第二部分首部及字段,见链接:https://www.sdnlab.com/17955.html;系列二是翻译和阐述《The P4 Language Specification v1.0.2》的第三部分解析器,见链接:https://www.sdnlab.com/18021.html;系列三是基于Github开源项目中的P4项目源码分析。

本篇文章是系列文章的收尾篇,除了对于Tutorial中的名为Flowlet Switching项目的源码分析之外,也贴出了我们安装P4相关软件时的步骤与顺序,希望能够帮助到大家在安装相关项目的时候少遇到一些问题。

一、: P4-Related Tools Installation

本章节是安装P4相关工具的步骤和说明。
需要注意的是,本说明只适用于 Ubuntu 14.04 系统。

1.1 推荐安装的其他工具

  • mininet:SDN网络仿真工具
  • vim:编辑器
  • scapy:Python的一个功能十分强大的库,可以用于生成数据报
  • pip:Python包管理工具

1.2 P4Factory

官方README:P4 Model Repository,如果你对P4已经很熟悉并且能够独立搭建环境,这个repo已经不大适合现在的P4开发了(使用bmv1软件交换机),建议是使用bmv2搭建环境并进行相关开发。

1.安装外部引用的库:

2.安装Ubuntu14.04系统下所需的所有依赖:

3.在启动模拟器之前,需要创建虚拟的端口:

4.使用autoconf工具生成Makefile,并对工作环境进行配置:

5.验证安装是否成功,并测试一个简单的P4程序:

同时新打开一个终端进行测试:

1.3 BMv2

官方README:BEHAVIORAL MODEL REPOSITORY

1.Ubuntu 14.04下要求安装的依赖:

2.使用脚本安装外部依赖库,如thrift。

注意:如果已经安装了P4Factory,请忽略此步,否则会有一系列的版本不匹配问题。

3.按照以下步骤安装bmv2:

4.更新Linux库缓存:

5.检验:

1.4 P4c-bm

官方README:p4c-bm

1.要求安装好pip;

2.安装步骤:

二、 P4 Tutorial Flowlet Switching 源码分析

Exercise 2: Implementing TCP flowlet switching

最近P4社区更新了Tutorial这个Demo的代码,今天偶然发现了它并且觉得很有学习的价值,于是写了一个对源码的简易解读,希望能够帮助大家学习P4。

2.1 源码

simple_router.p4:Github Source Code

可以从 solution.tar.gz 解压获得。

元数据intrinsic.p4:

2.2 intrinsic.p4

这个文件是对固有元数据intrinsic_metadata的声明,在P414标准中有对该元数据进行相关解释:

Metadata is state associated with each packet…some metadata has special significance to the operation of the switch. This is called Intrinsic Metadata as it has semantics intrinsic to the operation of the machine.

也就是说,Intrinsic Metadata是用来存数据报中某些特殊状态的元数据,本实例使用的是该元数据中的第一个字段ingress_global_timestamp来表示和记录ingress阶段的时间戳。

2.3 主P4程序做了什么?

在对P4程序进行解读之前,先对整个P4干嘛的做个介绍。

这些P4程序是用来做Flowlet Switching的,什么是Flowlet Switching呢?

Flowlet switching leverages the burstiness of TCP flows to achieve better load balancing of TCP traffic. In this exercise, you will start from a program that load-balances based on layer 4 flows: this is generally considered “classic” ECMP. To do this, we compute a hash over the 5-tuple and use this value to choose from a set of possible next hops. This means that all packets belonging to the same flow (i.e. with the same 5-tuple) will be routed to the same nexthop.

简单的来说,Flowlet Switching是用来对TCP突发流量做一个负载均衡的工具,通过ECMP做一个四层的LB。做法是通过算法计算数据报五元组的hash值,然后用这个hash值选择下一跳。意味着同一个流的所有数据报都会被转发到同样的下一跳路由。

那么这个Demo是怎么实现的呢?

1.用modify_field_with_hash_based_offset()元动作和crc16算法计算五元组的hash值。这个hash值用来区别不同的流量。注意这里不考虑hash碰撞。

2.对于每条流,需要存两个状态:a)记录这条流上一个数据报的时间戳 b)flowlet_id,来区别不同的TCP流量;对于数据流中的每一个数据报都更新它的时间戳,如果上一个数据报的时间戳与当前数据报的时间戳超过了一定阈值(50ms,但是对于数据中心中的高突发性的快速流量而言,这个阈值需要设置的非常小),那么就给flowlet_id+1,以区别不同的TCP流量;同样的一条流中的数据报拥有相同的id,不同的流量之间的id是不一样的。不过这样就意味着我们需要在数据报的处理过程中维持必要的状态信息,可以通过P4程序中的寄存器来实现。时间戳则由P4软件交换机进行计算,并存储在字段intrinsic_metadata.ingress_global_timestamp中,该字段宽度为32bit,以亚微秒为单位,且只读。

3.有这个flowlet_id之后,即可进行ecmp的hash计算了,用来选择下一跳,在P4的Tutorial中有关于ECMP的实现,参考repo:Action Profile

对于ECMP的介绍:ECMP Wikipedia

“等价多路径路由(英文:Equal-cost multi-path routing,缩写 ECMP),是一个在next-hop封包传送到一个单一目的所产生在多个最佳路径并列时的首要路由权重计算路由策略。多路径路由能被应用于首要路由协定同时发生的状况,因为它是一个受限于单一路由的per-hop决策,它有可能借由在多路径负载平衡流量下提供大幅增加的带宽,然而,它可能在实际部署时发生重大问题。在RFC2991中讨论了一般的多路径路由。”

2.4 simple_router.p4

2.4.1 一些声明和宏定义

声明的内容包括:

  • 一个名为ingress_metadata的元数据,存储状态信息。
  • 一个hash字段列表和hash计算器flowlet_map_hash,用来计算flowlet map index,这个偏移位用于确定寄存器实例,查找相应的数据报状态。
  • 两个寄存器,flowlet_lasttime用来记录timestamp,flowlet_id记录id。

名为ingress_metadata的元数据保存有以下信息:

  • flow_ipg: In computer networking, a minimal pause may be required between network packets or network frames. Wikipedia IPG
  • flowlet_map_index: flowlet map index, 映射至寄存器的偏移量。
  • flowlet_id: 区别不同流量的flowlet id。
  • flowlet_lasttime: 上一次使用flowlet的时间,用于记录时间戳。
  • ecmp_offset: ecmp的偏移量。
  • nhop_ipv4: 下一跳的ipv4地址。

2.4.2 流控程序

这里着重对相对来说比较重要的flowlet流表、new_flow流表进行介绍。

2.4.3 Flowlet

这个P4程序中最主要的部分是Flowlet流表:

只有一个动作,跑demo的时候需要通过运行时命令将其设置为默认动作。lookup_flowlet_map动作是该流表的主体:

步骤一:首先通过l3 hash(flowlet_map_hash)计算出当前数据报flowlet的偏移量flowlet_map_index并记录至元数据中,以确定两个寄存器实例flowlet_lasttime[flowlet_map_index](存放当前数据报的时间戳)和flowlet_id[flowlet_map_index](存放当前数据报的flowlet id)以存储数据报状态信息:

步骤二:通过步骤一所述偏移量访问寄存器flowlet_id实例,获取当前数据报的flowlet id,并存放至元数据中:

步骤三:将bmv2交换机计算得到的ingress处理时间记录至数据报对应的寄存器flowlet_lasttime实例中:

步骤四:通过步骤一所述偏移量访问寄存器flowlet_lasttime实例,获取当前数据报的时间戳(通过步骤三得到),并记录至元数据中:

步骤五:更新 flowlet IPG,用于后续流程判断是否超过阈值:

在Flowlet流表处理完数据报之后,主控程序对数据报进行一个逻辑判断:

对数据报的时间戳进行判断,如果元数据(存放数据报状态信息,包括在执行存放的lookup_flowlet_map动作时获取的状态信息)中的记录的flowlet IPG值(存放在ingress_metadata.flow_ipg)大于我们设定的阈值(本实验是50ms),就通过new_flowlet流表更新该数据报的flowlet id:

可以看到,new_flowlet流表只有一个动作update_flowlet_id,该动作更新了这个数据报的flowlet_id,以表明这个数据报是属于一条新的流量。

2.4.4 ECMP

在接下来的处理流程中,我们就可以通过flowlet id来区别不同的流量,做ECMP等价路由。P4程序片段如下:

步骤和思路很清晰:

步骤1.对数据报的ipv4目的地址进行lpm匹配(最长前缀匹配),若匹配,则进行步骤2;

步骤2.根据匹配的表项执行丢包动作,或执行set_ecmp_select动作(转至步骤3);

步骤3.执行set_ecmp_select动作:根据flowlet id和相关数据报信息(源目IP等)计算得到ECMP hash值,存至元数据中;

步骤4.流表ecmp_nhop根据元数据中存储的ecmp hash值(ingress_metadata.ecmp_offset)进行下一跳路由的选择。

三、结语

本系列的文章至此就结束了,不过我们会持续关注P4社区的动态,跟进最新的P4讯息。此外,SDNLAB有一个非常棒的SDN技能图谱,链接:https://github.com/PONOUBA/opensdn_engineer_skill_map,我们也在Github整合了一个P4资源的仓库,链接:https://github.com/Wasdns/The-Road-to-P4,希望能够和大家多多交流和沟通,为数据平面可编程和P4的发展做出努力!


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/19040.html
分享到:
相关文章
条评论

登录后才可以评论

Chendns 发表于17-04-14
5