P4论文翻译浅读

P4原论文研读

P4: Programming Protocol-Independent Packet Processors

这里原文翻译就是:可编程的协议无关的数据包处理器

摘要

P4是一种用于编程协议无关的包处理器的高级语言。在支持P4语言的地方都能够应用,主要还是交换机(路由器)上的应用。

P4工作在SDN的控制平面,就像openflow,openflow有一些缺点,需要针对特定的协议头尽心操作,操作集合字段几年就从12个增加到41个,复杂性增长了并且针对新的头部协议处理不够灵活。

P4作为openflow的替代者,有几个设计目标:

  1. 可重配置(Reconfigurability ):程序员应该能够改变交换机处理数据包的方式。运行方式
  2. 协议无关(Protocol independence):交换机不应该被绑定到特定的网络协议。处理目标
  3. 目标无关(Target independence):程序员应该能够独立于底层硬件的细节来描述包处理功能。运行目标

在这里插入图片描述

介绍

SDN赋予运营商对其网络的程序控制权,SDN使得控制平面与转发平面在物理上分离。虽然转发设备可以通过多种方式编程,但拥有一个公共的、开放的、与供应商无关的接口使控制平台能够控制来自不同硬件和软件供应商的转发设备。

Openflow针对不同的协议的头部字段定义了许多Header Fields

在这里插入图片描述

Openflow 接口开始时很简单,抽象出一个规则表,可以匹配十几个头字段(例如,mac 地址、 ip 地址、协议、 tcp/udp 端口号等)上的数据包。在过去的五年中,规范变得越来越复杂(参见表1) ,具有更多的头字段和多阶段的规则表,以允许交换机开放更多控制能力。并且新的头部字段的增长没有停止的迹象。

例如,数据中心网络运营商越来越多地希望应用新形式的数据包封装(例如,nvgre、 vxlan 和 stt) ,为此他们采用部署软件交换机,这些软件交换机更容易扩展新的网络功能。

与其反复扩展 openflow 规范,我们认为未来的交换机应该支持解析包和匹配头字段的灵活机制,允许控制器应用程序通过一个公共的开放接口(即一个新的“ openflow 2.0” api)利用这些功能。这样一种通用的、可扩展的方法将比现在的 openflow 1.x 标准更简单、更优雅,并且更具未来性。

P4—used to configure a switch, telling it how packets are to be processed

existing APIs (such as OpenFlow) that are designed to populate the forwarding tables in fixed function switches.

P4提高了网络编程的抽象级别,可以作为控制器和交换机之间的通用接口,三个目标:

  1. Reconfigurability. The controller should be able to redefine the packet parsing and processing in the field.
  2. Protocol independence. The switch should not be tied to specific packet formats. Instead, the controller should be able to specify (i) a packet parser for extracting header fields with particular names and types and (ii) a collection of typed match+action tables that process these headers
  3. Target independence. Just as a C programmer does not need to know the specifics of the underlying CPU, the controller programmer should not need to know the details of the underlying switch. Instead, a compiler should take the switch’s capabilities into account when turning a target-independent description (written in P4) into a target-dependent program (used to configure the switch).

抽象转发模型

在抽象模型中,通过一个可编程解析器(parser)转发数据包,随后是多个阶段的 match action ,以串联、并行或两者的组合排列的方式。

从openflow中概括出三个经验:首先,openflow 假定一个固定的解析器,而我们的模型支持一个可编程的解析器,允许定义新的头。其次,openflow 假设 match action 阶段是串联的,而在我们的模型中,它们可以并行或串联。第三,我们的模型假设操作由交换机支持的与协议无关的基元组成。

我们的抽象模型概括了不同转发设备处理数据包的方式(如以太网交换机、路由器、负载均衡器)和不同技术(如 fixed function 交换机 asics、 npus、可重构交换机、软件交换机、 fpga)。这允许我们设计一种公共语言(p4)来表示数据包在公共抽象模型中的处理方式。因此,程序员可以创建运行目标无关的程序,编译器可以映射到各种不同的转发设备。

在这里插入图片描述

转发模型由两种操作来进行控制:Configure(配置) and Populate (填充):

Configure操作对解析器进行编程,设置各个 stage 的match-action的顺序,并指定每个 stage 处理的头字段。配置决定了支持哪些协议以及交换机如何处理数据包

Populate 操作将条目添加(和删除)到配置期间指定的 match action 表中。Populate 决定应用到数据包的策略。

为了本文的目的,我们假设配置和填充是两个不同的阶段。特别是,交换机不需要在配置期间处理数据包。但是,我们期望实现将允许在部分或全部重新配置期间进行数据包处理,从而使升级不需要停机。我们的模型特意允许,并鼓励,重新配置,不会中断转发。

显然,配置阶段在固定功能的 asic 开关中没有什么意义,对于这种类型的交换机需要检查是否支持P4语言。

到达的数据包首先由解析器处理。假设packet body被单独缓冲存储,并且不可用于匹配。解析器识别并从头中提取字段,从而定义交换机支持的协议。模型没有对协议头的含义进行任何假设,只是解析表示定义了一组字段,在这些字段上进行匹配和操作。

然后将提取的头字段传递给 match action 表。match action 表被分为ingress 和 egress。虽然两者都可能修改包头,但是 ingress match+action 操作确定 egress port(s)并确定包放入的队列。基于入口处理,数据包可以被转发、复制(用于多播、 span 或控制平面)、删除或触发流控制。egress match+action 动作对数据包报头执行每个实例( per-instance )的修改——例如,多播复制。action表(计数器、策略等)可以与流相关联,以跟踪帧到帧的状态。

数据包可以在不同的阶段(称为元数据)之间传输额外的信息,元数据与数据包头字段的处理方式相同。元数据的一些例子包括入口端口、传输目的地和队列、可用于分组调度的时间戳,以及不涉及改变分组的解析表示形式(如虚拟网络标识符)的从一个表到另一个表的传递数据。

队列规则的处理方式与当前的 openflow 相同: 一个操作将包映射到队列,队列被配置为接收特定的服务规则。服务规则(例如,最小速率、 drr)被选为交换机配置的一部分。

虽然超出了本文的范围,但是可以添加操作原语来允许程序员实现新的或现有的拥塞控制协议。例如,这个开关可能被编程为根据新的条件设置 ecn 位,或者它可能使用 match action 表实现一个专有的拥塞控制机制。

编程语言

我们使用抽象转发模型来定义一种语言来表达如何配置交换机和如何处理数据包。本文的主要目的是提出 p4编程语言。然而,我们认识到许多语言都是可能的,它们很可能具有我们在这里描述的共同特征。例如,语言需要一种方法来表示解析器是如何编程的,以便解析器知道所期望的包格式; 因此程序员需要一种方法来声明什么头类型是可能的。例如,程序员可以指定 ipv4报头的格式,以及哪些报头可以合法地跟随 ip 报头。这激励了我们通过声明合法的头类型在 p4中进行解析。类似地,程序员需要表达如何处理包头。例如,ttl 字段必须进行递减和测试,可能需要添加新的隧道头,并且可能需要计算校验和。这促使 p4使用命令式控制流程序来描述使用声明的头类型和一组基本操作的头字段处理。

包处理语言必须允许程序员(隐式或显式地)表达头字段之间的任何串行依赖关系。依赖关系决定了哪些表可以并行执行。例如,由于 ip 路由表和 arp 表之间的数据依赖关系,它们需要顺序执行。依赖关系可以通过分析Table Dependency Graphs(tdgs)来识别; 这些图描述了表之间的字段输入、操作和控制流。图3显示了 l2/l3交换机的示例表依赖关系图。Tdg 节点直接映射到match+action表,依赖性分析确定每个表在管道中的位置。不幸的是,tdgs 对于大多数程序员来说并不容易访问; 程序员倾向于使用命令式结构而不是图来思考数据包处理算法。

在这里插入图片描述

所以我们提出了一个两步编译的方法。在最高级别上,程序员使用表示控制流(p4)的命令式语言来表示数据包处理程序; 在此之下,编译器将 p4表示转换为 tdgs,以便于进行依赖性分析, 然后映射TDG到特定目标的交换机。P4的设计目的是将 p4程序转换成 tdg。

P4语言示例

我们通过深入研究一个简单的例子来探讨 p4。许多网络设备部署区分边缘和核心; 终端主机直接连接到边缘设备,这些设备又通过高带宽核心相互连接。整个协议的设计都是为了支持这种体系结构(例如 mpls [11]和 portland [12]) ,主要目的是在核心中简化转发。

考虑一个示例L2网络部署,在边缘使用两层核心连接 topof-rack (tor)交换机。

在这里插入图片描述

P4 Concepts

P4程序包含下列关键组成部分的定义:

  • **Headers:**A header definition describes the sequence and structure of a series of fields. It includes specification of field widths and constraints on field values.
  • **Parsers:**A parser definition specifies how to identify headers and valid header sequences within packets.
  • **Tables:**Match+action tables are the mechanism for performing packet processing. The P4 program defines the fields on which a table may match and the actions it may execute.
  • Actions: P4 supports construction of complex actions from simpler protocol-independent primitives. These complex actions are available within match+action tables.
  • Control Programs: The control program determines the order of match+action tables that are applied to a packet. A simple imperative program describe the flow of control between match+action tables
Header Formats

一般来说,每个标头都是通过声明字段名的有序列表以及它们的宽度来指定的。 standard Ethernet and VLAN headers are specified as follows:

在这里插入图片描述
在这里插入图片描述

The Packet Parser

P4假设底层交换机可以实现一个状态机,该状态机可以从头到尾遍历数据包头,并随时提取字段值。提取的字段值被发送到 match action 表进行处理。

P4将这个状态机直接描述为从一个头到下一个头的转换集。每个转换都可能由当前报头中的值触发。例如,我们将 mtag 状态机描述如下。

parser start{
	ethernet;
}

parser ethernet {
	switch(ethertype) {
		case 0x8100: vlan;
		case 0x9100: vlan;
		case 0x800: ipv4;
		// Other cases
	}
}

parser vlan {
	switch(ethertype) {
		case 0xaaaa: mTag;
		case 0x800: ipv4;
		// Other cases
	}
}

parser mTag {
	switch(ethertype) {
		case 0x800: ipv4;
		// Other cases
	}
}

解析开始于start状态,知道处理到stop状态或者到未处理状态,在达到新头的状态时,状态机使用其规范提取头并继续标识其下一个转换。提取的头被转发到 switch pipline 的后半部分的 match action 处理。

Mtag 的解析器非常简单: 它只有四个状态。实际网络中的解析器需要更多的状态; 有可能达到上百个状态。

Table Specification

程序员描述如何在 match action 阶段中匹配已定义的头字段(例如,它们是精确匹配、范围还是通配符?)以及匹配发生时应该执行什么操作。

在我们简单的 mtag 示例中,边缘交换机匹配 L2目的地址和 vlan id,并选择一个 mtag 添加到头部。程序员定义一个表 table来匹配这些字段,并应用一个操作action来添加 mtag 头(见下文)。reads 属性声明要匹配的字段,并使用匹配类型(exact, ternary, etc)进行限定。**actions **属性列出了表可能应用于包的可能操作。actions 将在以下部分进行解释。max_size 属性指定表应该支持多少条目。

表规范允许编译器决定它需要多少内存,以及实现表所需的内存类型(例如 tcam 或 sram)。

table mTag_table {
	reads {
		ethernet.dst_addr : exact;
		vlan.vid : exact;
	}
	actions {
		// At runtime, entries are programmed with params
		// for the mTag action. See below.
		add_mTag;
	}
	max_size : 20000;
}

为了完整性和以后的讨论,我们提供了控制程序引用的其他表的简短定义

table source_check {
	// Verify mtag only on ports to the core
	reads {
		mtag : valid; // Was mtag parsed?
		metadata.ingress_port : exact;
	}
	actions { // Each table entry specifies *one* action
		// If inappropriate mTag, send to CPU
		fault_to_cpu;
		// If mtag found, strip and record in metadata
		strip_mtag;
		// Otherwise, allow the packet to continue
		pass;
	}
	max_size : 64; // One rule per port
}

table local_switching {
	// Reads destination and checks if local
	// If miss occurs, goto mtag table.
	}
	
table egress_check {
	// Verify egress is resolved
	// Do not retag packets received with tag
	// Reads egress and whether packet was mTagged
}
Action Specifications

P4定义了一组基本操作,从中构建更复杂的操作。每个 p4程序声明一组由操作原语组成的操作函数; 这些操作函数简化了表规范和填充。P4假定在 action 函数中并行执行原语。(不能并行执行的交换机可以模拟语义。)

The add mTag action referred to above is implemented as follows:

action add_mTag(up1, up2, down1, down2, egr_spec) {
	add_header(mTag);
	// Copy VLAN ethertype to mTag
	copy_field(mTag.ethertype, vlan.ethertype);
	// Set VLAN’s ethertype to signal mTag
	set_field(vlan.ethertype, 0xaaaa);
	set_field(mTag.up1, up1);
	set_field(mTag.up2, up2);
	set_field(mTag.down1, down1);
	set_field(mTag.down2, down2);
	// Set the destination egress port as well
	set_field(metadata.egress_spec, egr_spec);
}

如果一个动作需要参数(例如,mtag 的 up1值) ,它在运行时从匹配表中提供。

If an action needs parameters (e.g., the up1 value for the mTag), it is supplied from the match table at runtime.

在本例中,交换机在 vlan 标记后插入 mtag,将 vlan 标记的 ethertype 复制到 mtag 以指示下面的内容,并将 vlan 标记的 ethertype 设置为0xaaaa 以指示 mtag。未显示的是反向操作规范,该规范从数据包和表中剥离出一个 mtag,以便在边缘交换机中应用该操作。

P4’s primitive actions include:

set_field: Set a specific field in a header to a value. Masked sets are supported.
copy_field: Copy one field to another.
add_header: Set a specific header instance (and all its fields) as valid.
remove_header: Delete (“pop”) a header (and all its fields) from a packet.
increment: Increment or decrement the value in a field.
checksum: Calculate a checksum over some set of header fields (e.g., an IPv4 checksum)

The Control Program

一旦定义了表和操作,剩下的唯一任务就是指定从一个表到下一个表的控制流。通过函数、条件和表引用的集合将控制流指定为程序。

在这里插入图片描述

图4显示了边缘交换机上 mtag 实现所需控制流的图形表示。解析之后,源检查表验证接收到的包和入口端口之间的一致性。例如,只能在连接到核心交换机的端口上看到 mtags。源检查还从数据包中带出 mtag,记录数据包中是否有 mtag 在元数据中。管道中稍后的表可能与此元数据匹配,以避免重新标记数据包。

然后执行本地交换表(local switching table )。如果这个表“未命中” ,表示该数据包不是发往本地连接的主机。在这种情况下,将 mtag 表(上面定义的)应用于数据包。本地和核心转发控制都可以通过出口( egress check)检查表处理,该检查表通过向 sdn 控制栈发送通知来处理未知目的地的情况。

数据包处理管道的命令表示如下:

control main() {
	// Verify mTag state and port are consistent
	table(source_check);
	
	// If no error from source_check, continue
	if (!defined(metadata.ingress_error)) {
		// Attempt to switch to end hosts
		table(local_switching);
		if (!defined(metadata.egress_spec)) {
			// Not a known local host; try mtagging
			table(mTag_table);
		}
		
	// Check for unknown egress state or
	// bad retagging with mTag.
	table(egress_check);
	}
}

编译一个P4程序

对于一个网络来实现我们的 p4程序,我们需要一个编译器将目标无关的描述映射到目标交换机的特定硬件或软件平台上。这样做包括分配目标的资源和为设备生成适当的配置。

Compiling Packet Parsers

对于具有可编程解析器的设备,编译器将解析器描述转换为解析状态机,而对于固定解析器,编译器仅验证解析器描述是否与目标解析器一致。生成状态机和状态表条目的详细信息可以在[16]中找到

表2显示了解析器的 vlan 和 mtag 部分的状态表条目(4.3)。每个条目指定当前状态、要匹配的字段值和下一个状态。为了简短起见,省略了其他列。

在这里插入图片描述

Compiling Control Programs

命令式控制流表示法是指定交换机逻辑转发行为的一种方便的方法,但是没有明确指出表之间的依赖关系或并发的机会。

因此,我们使用一个编译器来分析控制程序,以识别依赖关系,并寻找机会并行处理头字段。最后,编译器生成交换机的目标配置。

如第3章所述,编译器遵循两个阶段的编译过程。它首先将 p4控制程序转换为中间表依赖关系图表示形式,通过分析中间表依赖关系来确定表之间的依赖关系。特定于目标的后端然后将这个图表映射到交换机的特定资源上。

我们简要地研究了 mtag 示例如何在不同类型的交换机中实现:

Software switches: 软件交换机提供了完全的灵活性: 表计数、表配置和解析都在软件控制之下。编译器直接将 mtag 表图映射到切换表。编译器使用表类型信息约束每个表的表宽度、高度和匹配条件(例如,exact、 prefix 或 wildcard)。编译器还可以优化三元或前缀与软件数据结构的匹配。

Hardware switches with RAM and TCAM: 编译器可以配置哈希,使用内存对边缘交换机中的 mtag 表执行高效的精确匹配。相比之下,匹配标记位子集的核心 mtag 转发表将被映射到 tcam。

Switches supporting parallel tables: 编译器可以检测数据依赖关系,并以并行或串行方式排列表。在 mtag 示例中,表本地切换和 mtag 表可以并行执行,直到执行设置 mtag 的操作。

Switches that apply actions at the end of the pipeline : 对于只在管道末端进行操作处理的交换机,编译器可以告诉中间阶段生成用于执行最终写操作的元数据。在 mtag 示例中,是否添加或删除 mtag 可以用元数据表示。

Switches with a few tables: 编译器可以将大量 p4表映射到较少数量的物理表。在 mtag 示例中,本地交换可以与 mtag 表结合使用。当控制器在运行时安装新规则时,编译器的规则转换器可以“组合”两个 p4表中的规则,以生成单个物理表的规则。

结论

SDN 希望是单一的控制平面可以控制整个交换机网络。

Openflow 通过提供单一的、与供应商无关的 api 来支持这一目标。然而,现在的 openflow 针对的是固定功能交换机,它们可以识别预先确定的头字段集,并使用少量预定义的操作处理数据包。控制平面无法表达如何处理数据包以最好地满足控制应用的需要。

我们提出了一种更加灵活的交换机,其功能在该领域得到了指定,并且可能会发生变化。程序员决定转发平面如何处理数据包,而不用担心实现细节。编译器将命令式程序转换为表依赖关系图,可以映射到许多特定的目标交换机,包括优化的硬件实现。

我们强调,这只是第一步,作为 openflow 2.0的稻草人提案,为辩论做出贡献。在这个方案中,交换机的几个方面仍然没有定义(例如,拥塞控制原语、排队规则、流量监控)。不过,我们认为,拥有一种配置语言(以及为特定目标生成低级配置的编译器)的方法,将会带来更大灵活性的未来交换机,并释放软件定义网络的潜力。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值