Version1.3.0(June25,2012)1介绍
本文档描述了对OpenFlow交换机的要求。此规范内容包括交换机的组件和基本功能,和一个远程控制器管理一个OpenFlow交换机的协议:OpenFlow。2交换机部件
OpenFlow的交换机包括一个或多个流表和一个组表,执行分组查找和转发,和到一个外部控制器OpenFlow的信道(图1)。该交换机与控制器进行通信,控制器通过OpenFlow协议来管理交换机。控制器使用OpenFlow协议,可以添加、更新和删除流流表中的表项,主动或者被动响应数据包。在交换机中的每个流表中包含的一组流表项;每个流表项包含匹配字段,计数器和一组指令,用来匹配数据包(见5.2)。匹配从第一个流表开始,并可能会继续匹配其它流表(见5.1)。流表项匹配数据包是按照优先级的顺序,从每个表的第一个匹配项开始(见5.3)。如果找到一个匹配项,那么与流表项相关的指令就会去执行。如果在流表中未找到匹配项,结果取决于漏表的流表项配置:(例如,数据包可能通过OpenFlow信道被转发到控制器、丢弃、或者可以继续到下一个的流表,见5.4)。与流表项相关联的指令包含行动或修改流水线处理(见5.9)。行动指令描述了数据包转发,数据包的修改和组表处理。流水线处理指令允许数据包被发送到后面的表进行进一步的处理,并允许信息以元数据的形式在表之间进行通信。当与一个匹配的流表项相关联的指令集没有指向下一个表的时候,表流水线停止处理,这时该数据包通常会被修改和转发(见5.10)。流表项可能把数据包转发到某个端口。这通常是一个物理端口,但它也可能是由交换机定义的一个逻辑端口或通过本规范中定义的一个保留的端口(见4.1)。保留端口可以指定通用的转发行为,如发送到控制器、泛洪、或使用非OpenFlow的方法转发,如“普通”交换机转发处理(见4.5);而交换机定义的逻辑端口,可以是指定的链路汇聚组、隧道或环回接口(见4.4)。与流表项相关的行动,也可直接把数据包发送到组,进行额外的处理(见5.6)。组表示一组泛洪的指令集,以及更复杂的转发(如多路径,快速重路由,链路聚合)。作为间接的通用层,组也使多个流表项转发到同一个标识者(例如IP转发到一个共同的下一跳)。这种抽象的行为使相同的输出行动非常有效。组表包含若干组表项,每个组表项包含一系列依赖于组类型的特定含义行动存储段(见5.6.1)。一个或多个行动存储段里的行动会作用到发送到该组的数据包。只要正确的匹配和指令含义保持不变,交换机设计者可以任意的实现内部结构。例如,当一个流表项使用一个所有组来转发至多个端口,交换机设计人员可以在硬件转发表中用一个单一的位掩码去实现。另一个例子是匹配;如果OpenFlow交换机是通过不同数量的硬件表进行物理实现的,那么流水线就会被暴露。3名词解释
本节介绍了关键的OpenFlow规范术语:.字节:一个8位位组。.数据包:以太网帧,包括报头和有效载荷。.端口:数据包进入和退出OpenFlow的流水线地方(见4.1)。可以是一个物理端口,由交换机定义的一个逻辑端口,或由OpenFlow的协议定义的一个保留端口。.流水线:在一个openflow交换机中提供匹配、转发和数据包修改功能的相连流表的集合。.流表:流水线的一个阶段,包含若干流表项。.流表项:在流表中用于匹配和处理数据包的一个元素。它包含用于匹配数据包的匹配字段、匹配次序的优先级,跟踪数据包的计数器,以及应用的指令集。.匹配字段:用来匹配数据包的字段,包括包头,进入端口,元数据值。一个匹配字段可能会进行通配符匹配(匹配任何值)或者在某些情况下通过位掩码进行匹配。.元数据:一个可屏蔽寄存器的值,用于携带信息从一个表到下一个表。.指令:指令存在于流表项中,当数据包匹配流表项时,指令用来描述OpenFlow的处理方式。指令要么改变流水线处理,如指导包匹配另一个流表,要么包含一组添加到行动集的行动,或包含一组立即应用到数据包的行动。.行动:是一种操作,可将数据包转发到一个端口或修改数据包,如TTL字段减1。行动可以是与流表项相关联的指令集的一部分,或者是与组表项相关联的行动存储段的一部分。我们可以将行动积累在数据包的行动集里,也可以立即将行动应用到该数据包。行动集:与数据包相关的行动集合,在数据包被每个表处理的时候这些行动可以累加,在指令集指导数据包退出处理流水线的时候这些行动会被执行。.组:一系列的行动存储段和选择一个或者多个存储段应用到每个数据包的手段。.行动存储段:行动和相关参数的集合,为组而定义的。.标记:一个头部,可以通过压入行动插入到数据包或者通过弹出行动进行移除。.最外层的标记:一个数据包最开始出现的标记。.控制器:与OpenFlow交换机使用OpenFlow协议交互的实体。.计量:一个交换机元件,可以测量和控制数据包的速度。当通过计量的数据包速率或字节速率超过预定义的阈值时,计量触发计量带。如果计量带丢弃该数据包,它则被称为一个限速器。4OpenFlow端口
本节介绍了OpenFlow的端口的概念和OpenFlow支持的各类端口。4.1OpenFlow端口OpenFlow的端口是OpenFlow处理机和网络其余部分之间传递数据包的网络接口。OpenFlow交换机之间通过OpenFlow端口在逻辑上相互连接。OpenFlow交换机提供一定数量的OpenFlow端口,开放给OpenFlow的处理机。OpenFlow的端口组可能与交换机硬件中提供的网络端口组不完全相同,因为有些硬件网络接口可能被OpenFlow禁用,OpenFlow交换机可能定义额外的端口。OpenFlow的数据包从入端口接收,经过OpenFlow的流水线处理(见5.1),可将它们转发到一个输出端口。入端口是数据包的属性,它贯穿整个OpenFlow流水线,并代表数据包是从哪个OpenFlow交换机的端口上接收的。匹配数据包的时候会用到入端口(见5.3)。OpenFlow流水线可以决定数据包通过输出行动发送到输出端口(见5.12),还定义了数据包怎样传回到网络中。一个OpenFlow交换机必须支持三种类型的OpenFlow的端口:物理端口,逻辑端口和保留端口。4.2标准端口OpenFlow的标准端口为物理端口,逻辑端口,本地保留端口(其他保留的端口除外)。标准端口可以被用作入口和出端口,它们可在组里使用(见5.6),都有端口计数器(见5.8)。4.3物理端口OpenFlow的物理端口为交换机定义的端口,对应于一个交换机的硬件接口。例如,以太网交换机上的物理端口与以太网接口一一对应。在有些应用中,OpenFlow交换机可以实现交换机的硬件虚拟化。在这些情况下,一个OpenFlow物理端口可以代表一个与交换机硬件接口对应的虚拟切片。4.4逻辑端口OpenFlow的逻辑端口为交换机定义的端口,并不直接对应一个交换机的硬件接口。逻辑端口是更高层次的抽象概念,可以是交换机中非OpenFlow方式的端口(如链路汇聚组,隧道,环回接口)。逻辑端口可能包括数据包封装,可以映射到不同的物理端口。这些逻辑端口的处理动作相对于openflow处理机来说必须是透明的,而且这些端口必须像硬件端口一样与openflow处理机互通。物理端口和逻辑端口之间的唯一区别是:一个逻辑端口的数据包可能有一个叫做隧道ID的额外的元数据字段与它相关联(见7.2.3.7);而当一个逻辑端口上接收到的分组被发送到控制器时,其逻辑端口和底层的物理端口都要报告给控制器(见7.4.1)。4.5保留端口OpenFlow的保留端口由本规范定义。它们指定通用的转发动作,如发送到控制器,泛洪,或使用非OpenFlow的方法转发,如“正常”交换机处理。一个交换机不需支持所有的保留端口,只支持那些标记为“Required”的保留端口。.Required:ALL:表示交换机可转发指定数据包到所有端口,它仅可用作输出端口。在这种情况下,数据包被复制后发送到所有的标准端口,不包括数据包的入端口和端口被配置为OFPPC_NO_FWD。.Required:CONTROLLER:表示OpenFlow控制器的控制通道,它可以用作一个入端口或作为一个出端口。当用作一个出端口,数据包封装进输入包消息,并使用OpenFlow协议发送(见7.4.1)。当用作一个入口端口,确认数据包来自控制器。.Required:TABLE:表示openflow流水线的开始(见5.1)。这个端口仅在输出包消息的行动列表里的输出行为时候有效(见7.3.7),此时交换机提交报文给第一流表使数据包可以通过OpenFlow流水线处理。.Required:INPORT:代表数据包的进入端口。当数据包通过它的入端口发送出去的话,只能用作输出端口。.Required:ANY:特别值,用在未指定端口的OpenFlow命令(端口通配符)。既不能作为入口端口,也不能作为一个输出端口。.Optional:LOCAL:表示交换机的本地网络堆栈和管理堆栈。可以用作一个入口端口或作为一个输出端口。远程实体通过本地端口与交换机和网络服务互通,而不是通过一个的控制网络。利用一组合适的默认流表项,本地端口被用来实现一个带内控制器连接。.Optional:NORMAL:代表传统的非OpenFlow流水线(见5.1)。仅可用于为一个输出端口,使用普通的流水线处理数据包。如果交换机不能转发数据包从OpenFlow流水线到普通流水线,它必须表明它不支持这一行动。.Optional:FLOOD:表示使用普通流水线处理进行泛洪(见5.1)。只作为一个输出端口,一般可以将数据包发往所有标准端口,但不能发往入端口或OFPPS_BLOCKED状态的端口。交换机也可以通过数据包的VLANID选择哪些端口泛洪。OpenFlow-only交换机不支持NORMAL端口和FLOOD端口,而OpenFlow-hybrid交换机均支持上述端口(见5.1)。转发数据包到FLOOD端口依赖交换机的实现和配置,若使用一组all类型进行转发,则可以使控制器能更灵活地实现泛洪(见5.6.1)。5OpenFlow表
本节描述流表和组表的组件,以及匹配和行动处理的机制。5.1流水线处理OpenFlow兼容的交换机有两种类型:OpenFlow-only和OpenFlow-hybrid。OpenFlow-only交换机只支持OpenFlow操作,在这些交换机中的所有数据包都由OpenFlow流水线处理,否则不能被处理。OpenFlow-hybrid交换机支持OpenFlow的操作和普通的以太网交换操作,即传统的L2以太网交换、VLAN隔离、L3路由(IPv4的路由,IPv6路由)、ACL和QoS处理。这种交换机必须提供一个OpenFlow外的分类机制,使流量路由到OpenFlow流水线或普通流水线。例如,某个交换机可以使用VLAN标记或数据包的输入端口,来决定是否使用一个流水线或其它流水线,或者它可引导所有数据包都到OpenFlow流水线进行处理。这种分类机制超出了本规范的范围。一个OpenFlow-hybrid交换机也允许数据包通过NORMAL和FLOOD保留端口从OpenFlow流水线转移到普通流水线处理(见4.5)。每个OpenFlow交换机的流水线包含多个流表,每个流表包含多个流表项。OpenFlow的流水线处理定义了数据包如何与那些流表进行交互(参见图2)。OpenFlow交换机至少需要一个流表,可选更多的流表。只有单一流表的OpenFlow交换机是有效的,而且在这种情况下流水线处理进程可以大大简化。Figure2:通过流水线处理的数据包流OpenFlow交换机的流表按顺序编号的,从0开始。流水线处理总是从第一流表开始:数据包首先与流表0的流表项匹配。其他流表根据第一个表的匹配结果来调用。被一个流表处理时,数据包与流表中的流表项进行匹配,从而选择一个流表项(见5.3)。如果匹配了流表项,则执行在该流表项里的指令;这些指令可能明确指导数据包传递到另一个流表(使用Goto指令,见5.9),在那里同样的处理被重复执行。一个流表项只能指导数据包到大于自己表号的流表,换句话说流水线处理,只能前进而不能后退。显然,流水线的最后一个表项可以不包括GOTO指令。如果匹配的流表项并没有指导数据包到另一个流表,流水线处理将停止在该表中。当流水线处理停止,数据包被与之相关的行动集处理,通常是被转发(见5.10)。如果数据包在流表中没有匹配到流表项,这是一个漏表行为。漏表行为取决于表的配置(见5.4)。一个流表中的漏表项可以指定如何处理无法匹配的数据包:可以选择丢弃,传递到另一个表,或利用输入包消息通过控制信道发送到控制器去(见6.1.2)。Openflow流水线和各种Openflow操作用同样的方法处理特定类型的数据包和规范定义的相同类型的包,除非目前的规范或Openflow配置规定了不同的方法。例如,Openflow定义的以太头部必须与IEEE规范一致,Openflow使用的TCP/IP头部定义必须与RFC规范一致。另外,Openflow交换机的包重排序必须与IEEE规范的要求一致,保证数据包能被流表项、组表和计量带同样的处理。5.2流表
一个流表中包含多个流表项。每个流表项包含:.匹配字段:对数据包匹配。包括入端口和数据包头,以及由前一个表指定的可选的元数据。.优先级:流表项的匹配次序。.计数器:数据包匹配时更新计数。.指令:修改行动集或流水线处理。.超时:最大时间计数值或流在交换机中失效之前的剩余时间。.cookie:由控制器选择的不透明数据值。控制器用来过滤流统计数据、流修改和流删除。但处理数据包时不能使用。流表项通过匹配字段和优先级决定:在一个流表中匹配字段和优先级共同确定唯一的流表项。所有字段通配(所有字段省略)和优先级等于0的流表项被称为table-miss流表项(见5.4)。5.3匹配Figure3:流程图详细描述了数据包流通过一个OpenFlow交换机。当OpenFlow交换机接收一个数据包,就执行图3所示的功能。交换机开始对第一个流表进行查找,并基于流水线处理,也可能在其它流表中(见5.1)执行表查找。数据包匹配字段是从数据包中提取的。用于表查找的数据包匹配字段依赖于数据包类型,也就是包括各种数据包头部字段,如以太网源地址或IPv4目的地址(见7.2.3)。除了通过数据包报头中进行匹配,也可以通过入端口和元数据字段进行匹配。元数据可以用来在一个交换机的不同表里面传递信息。数据包匹配字段表示数据包的当前状态,如果在前一个表中使用Apply-Actions改变了数据包的报头,那么这些变化也会在数据包匹配字段中反映。如果数据包中用于查找的匹配字段值匹配了流表项定义的字段,就表示这个数据包匹配了此流表项。如果流表项字段的值是ANY(字段省略),它就可以匹配包头部的所有可能的值。如果交换机支持对指定的匹配字段进行任意的的位掩码,这些掩码可以更精确地进行匹配。数据包与表进行匹配,而且只有匹配数据包的最高优先级的表项必须被选择,此时与所选流表项相关的计数器也会被更新,所选流表项的指令集也会被执行。如果多个匹配的流表项具有相同的最高优先级,所选流表项则被确定为未定义表项。只有控制器记录器在流信息中没有设置OFPFF_CHECK_OVERLAP位并且增加了重复的表项的时候,这种情况才能出现。如果交换机配置中包含OFPC_FRAG_REASM标志(见7.3.2),则在流水线处理前IP碎片必须被重新组装。当交换机接收到一个格式不正确或损坏的数据包,此版本的规范没有定义预期的行为。5.4Table-miss
每一个流表必须支持table-miss的流表项来处理漏表。table-miss表项指定如何处理在流表中与其他流表项未匹配的数据包(见5.1),比如把数据包发送给控制器、丢弃数据包或直接将包扔到后续的表。table-miss流表项也有它的匹配字段和优先级(见5.2),它通配所有匹配字段(所有字段省略),并具有最低的优先级(0)。table-miss流表项的匹配可能不属于正常范围内流表支持的匹配,例如精确匹配表可能不支持在其他流表项中使用通配符,但必须支持table-miss流表项通配所有字段。table-miss流表项可能不具备正常流表项(见7.3.5.5)相同的能力。table-miss流表项必须至少支持利用CONTROLLER保留端口将数据包发送到控制器(见4.5),和使用Clear-Actions指令(见5.9)丢弃数据包。为了和早期版本规范一致,如果可能,在实现中鼓励支持引导包给后续的表。table-miss表项的行为在许多方面像任何其他流表项:默认情况下,在流表中不存在table-miss表项。控制器可以在任何时候添加或删除它(见6.4),而且它可能会超时失效(见5.5)。table-miss流表项像期望的那样,利用它的匹配字段和优先级匹配表中的数据包。table-miss流表项可以匹配流表中其他表项中不能匹配的数据。当数据包与table-miss表项匹配时,table-miss表项指令就会执行(见5.9)。如果该table-miss表项直接将数据包通过CONTROLLER保留端口发送到控制器(见4.5),那么数据包输入的原因必须标识出table-miss表项(见7.4.1)。如果该table-miss表项不存在,默认情况下,流表项无法匹配的数据包将被放弃(丢弃)。交换机配置时,例如使用OpenFlow配置协议,可以覆盖此默认值,指定其他行为。5.5流表项删除
流表项可以通过两种方式在流表中删除,一个是通过控制器的请求,一个是利用交换机的流超时机制。交换机的流超时机制于控制器,由交换机根据流表项的状态和配置来运行。每个流的表项具有一个和它相关的idle_timeout和hard_timeout值。如果hard_timeout值不为零,交换机必须注意的流表项的老化时间,因为交换机可能删除该项。一个非零hard_timeout字段可能在规定数秒后引起流表项被删除,无论有多少数据包与之匹配。如果给定非零idle_timeout的值,交换机必须注意与流的最后一个数据包到达的时间,可能后面需要删除这个流表项。当在规定数秒内没有匹配数据包时,一个非零idle_timeout字段将引起流表项删除。交换机必须实现流表项超时就会从流表中删除的功能。控制器可以主动发送DELETE流表修改消息(OFPFC_DELETE,或OFPFC_DELETE_STRICT-见6.4),从流表中删除流表项。流表项被删除时,不管是控制器或流表项超时引起的,交换机必须检查流表项的OFPFF_SEND_FLOW_REM标志。如果该标志被设置,该交换机必须将流删除消息发送到控制器。每个流删除消息中包含一个完整的流表项描述、清除的原因(超时或删除),在清除时的流表项的持续时间,在清除时的流的统计数据。5.6组表
一个组表包括若干组表项。一个流表项指向一个组的能力使得openflow可以实现额外的转发方法(例如选择部分和所有)。每个组表项(见表2)由组编号确定,具体内容包含:.组编号:一个32位的无符号整数,唯一标识该组.组类型:确定组语义(参见5.6.1节).计数器:当数据包被组处理时更新.行动存储段:有序的行动存储段,其中的每个行动存储段包含了一组要执行的行动和相关参数。5.6.1组类型交换机只支持那些标记为“Required”的组类型,控制器可以查询交换机支持哪些“Optional”组类型。.Required:all:执行组中的所有存储段。这个组用于多播或广播的转发。数据包为每个存储段都有效地复制一份,然后被每个存储段处理。如果某个存储段中明确地指导数据包发往入端口,那么这个复制的包被丢弃。如果控制器记录器希望数据包从入端口转发出去,那么这个组必须包含一个额外的存储段,这个存储段包含到OFPP_IN_PORT保留端口的输出行动。.Optional:select:执行组中的一个存储段。基于交换机计算选择算法(如利用用户配置的元组/数组的哈希算法或简单的循环算法),数据包被组中的一个存储段处理。选择算法的所有配置和状态都在OpenFlow外部运行。选择算法实现可以使用等负荷分配,也可以选择根据存储段权重进行。当组中存储段所指定的端口出现故障时,交换机可对剩余部分(具有转发到有效端口行为的)选择存储段,而不是丢弃数据包。此行为可能会减少数据包在链路或交换机的中断。.Required:indirect:执行此组中定义的一个存储段。这个组只支持单一的存储段。允许多个流表项或者组指向一个共同的组编号,这样可以使转发更快,更高效的汇聚(例如:下一跳IP转发)。对于只有一个存储段的所有组,组类型应该是相同的。.Optional:fastfailover:执行第一个有效的存储段。每一个行动存储段与控制其有效性的一个指定端口/或组相关。组定义的存储段是有序的,首选选择与有效的端口或者组相关的第一个存储段。这个组类型可以使交换机改变转发,而无需通知控制器。如果没有有效的存储段,数据包将被丢弃。组类型必须实行有效机制(见6.5)。5.7计量表
一个计量表包含若干计量表项,确定每个流的计数。每个流的计数可以使OpenFlow实现各种简单的QoS操作,如限速,并且可以结合每个端口队列(见5.12)来实现复杂的QoS构架,如DiffServ。计量器可以测试数据包分配的速率,并可以控制数据包的速率。计量器直接连接到流表项(而不是被连接到端口的队列)。任意的流表项可以在它的指令集中定义一个计量器(见5.9),计量器测量和控制和它有关的所有流表项的总速率。在同一个表中可以使用多个计量器,但必须使用专用的方式(流表项分离设置)。在连续的流表中,对于同样的数据包集合,可以使用多个计量器。每个计量表项(见表3)由其计量标识符来区分,其包含:.计量器的标识符:一个32位的无符号整数唯一识别.计量带:计量带的无序列表,其中每个计量带指定带速和处理数据包的方式.计数器:计量器处理数据包时进行更新计数。5.7.1计量带每个计量器可能有一个或多个计量带。每个带指定所用的速率和数据包处理的方式。单个计量带以当前测量的计量速率处理数据包。当测量速率超过最高配置速率的时候,计量器就启用计量带。若当前的速率比任何指定的计量带速率率低,就没有计量带需要工作。每个计量带(见表4)用速率来识别,包括:.带类型:定义了数据包如何处理.速率:用于计量器选择计量带,也就是计量带可以启用的最低速率.计数器:当计量带处理数据包时更新计数.类型的特定参数:带类型的可选参数在本规范里带类型没有“Required”。控制器可以查询交换机支持的计量带类型“Optional”.Optional:drop:丢弃数据包。可以用来定义速率带。.Optional:dscpremark:增加数据包的IP头部DSCP字段丢弃的优先级。可用于定义一个简单的DiffServ策略。5.8计数器
每一个流表,流表项,端口,队列,组,组存储段,计量器和计量带都会修改计数器。OpenFlow-compliant计数器可以在软件中实现,也可以通过查询硬件计数器获取计数进行有限范围的修改。表5中包含了openflow规范中定义的计数器集。交换机不要求支持所有的计数器,只有那些标记为“Required”是必须支持的。持续时间指的是流表项,端口,组,队列或计量器在交换机中已安装的时间数值,而且必须精确到秒。ReceivedErrors字段是表5里定义的所有收到的和冲突的错误总和,也包括表里未列出的其它错误。计数器都是无符号值,可以环回且没有溢出指示。如果交换机里没有指定值的计数器,则其值必须设置成字段的最大值(无符号数就是-1)。5.9指令
每个流表项中包含一组指令集,当一个数据包匹配表项时指令就会被执行。这些指令可导致数据包,行动组和/或流水线处理发生改变。交换机不需要支持所有类型的指令,只需支持下面那些标记为“RequiredInstruction”。控制器可查询交换机支持的“OptionalInstruction”。.OptionalInstruction:Metermeter_id:将包转给指定的计量器。计量的结果可能会丢弃这个数据包(依赖于计量器的配置和状态)。.OptionalInstruction:Apply-Actionsaction(s):立即执行指定的行动,而不改变行动集。在两个表之间传递或者执行同类型的多个行动的时候,这个指令可用来修改数据包。这些行动被指定为一个行动列表(见5.11)。.OptionalInstruction:Clear-Actions:立即清除行动集中的所有行动。.RequiredInstruction:Write-Actionsaction(s):将指定的行动添加到当前的行动集中。如果行动存在于当前集合中,则进行覆盖,否则进行追加。.OptionalInstruction:Write-Metadatametadata/mask:在元数据字段写入掩码的元数据数值。掩码指的是元数据寄存器应进行修改的比特。(new_metadata=old_metadata&~mask|value&mask)。.RequiredInstruction:Goto-Tablenext-table-id:指示流水线处理的下一张表。表ID必须大于当前表ID。流水线最后一张表的流表项不能含有这个指令(见5.1)。Openflow交换机若只有一个流表则不需要实现这个指令。流表项所属的指令集中每个类型的单个指令都有个最大值。指令就是按照上述列表中指定的顺序来执行。实际上,有限定的是:Meter指令在Apply_Actions指令前执行,Clear_Actions指令在Write_Actions指令前执行,Goto_Table最后执行。如果流表项不能执行相关指令,交换机必须拒绝这个流表项。这种情况,交换机必须返回一个不支持的流错误信息(见6.4)。流表不一定支持每个匹配,每个指令或每个行动。5.10行动集
行动集是与每个数据包相关的,默认情况下是空的。一个流表项可以使用Write-Action指令或者与特殊匹配有关的Clear-Action指令来修改行动集。行动集在表间被传递。当一个流表项的指令集没有包含Goto-Table指令时,流水线处理就停止了,然后数据包的行动集执行其行动。行动集中每个类型的行动有一个最大值。set_field行动用字段类型来标识,因此行动集对每个字段类型的set_field行动(即,多个字段可被设置)有个最大值。当同一个类型需要多个行动时,例如,压入多个MPLS标签或弹出多个MPLS标签,应使用Apply_Actions指令(见5.11)。行动集中所有的行动,不管它们以什么顺序添加到行动集中,行动的顺序均按照下列顺序执行。如果行动集包含组行动,那么组行动存储段中的行动也按照下列顺序执行。当然,交换机也可以支持通过Apply-Actions指令任意修改行动执行顺序。1.copyTTLinwards:向数据包内复制TTL的行动2.pop:从数据包弹出所有标记的行动3.push-MPLS:向数据包压入MPLS标记的行动4.push-PBB:向数据包压入PBB标记的行动5.push-VLAN:向数据包压入VLAN标记的行动6.copyTTLoutwards:向数据包外复制TTL的行动7.decrementTTL:将数据包的TTL字段减18.set:数据包使用所有的set_field行动9.qos:使用所有的QOS行动,如对数据包排队10.group:如果指定了组行动,那么按顺序执行组行动存储段里的行动。11.output:如果没有指定组行动,数据包就会按照output行动中指定的端口转发。行动集中的Output行动是最后执行的。如果在一个行动集里组行动和输出行动都存在,则组行动优先。如果两者均不存在,数据包将被丢弃。如果交换机支持的话,组的执行将返回;组存储段可指定另外一个组,在这种情况下,行动将在组配置中指定的所有组中执行。5.11行动列表Apply-Actions指令和Packet-out消息包含一个行动列表。行动列表的含义与Openflow1.0规范的相同。行动列表中的行动按照列表中的次序执行,并立即作用到数据包。列表中的行动从第一个行动开始执行,行动都是按序执行的。行动的结果是累积的,比如行动列表中有两个pushVLAN行动,数据包就会被加上两个VLAN头部。如果行动列表有一个输出行动,一个当前状态下的包复制后就转发给所需端口。如果列表包含组行动,相关组存储段就会处理当前状态下的复制包。一个Apply_Actions指令执行完一个行动列表后,流水线继续处理已修改的数据包(见5.1)。数据包的行动集本身在行动列表执行的时候没有改变。5.12行动
交换机不要求支持所有类型的行动,只需支持标记为“RequiredAction”。控制器也可查询交换机所支持的“OptionalAction”。RequiredAction:Output.数据包输出到指定Openflow端口(见4.1)。Openflow交换机必须支持转发到物理端口,交换机定义的逻辑端口和所需的保留端口(见4.5)。OptionalAction:Set-Queue.设置数据包的队列ID。当数据包使用输出行动转发到一个端口,队列ID决定数据包安排到端口所属的哪个队列并转发。转发行为受队列配置控制,并用来提供Qos支持(见7.2.2)。RequiredAction:Drop.没有明确的行动来表现丢弃。相反,那些行动集中没有输出行动的数据包应该被丢弃。当流水线处理时或执行Clear_Actions指令后,空指令集或空指令行动存储段会导致丢弃这个结果。RequiredAction:Group.通过指定的组处理数据包,准确的解释依靠组类型。OptionalAction:Push-Tag/Pop-Tag.交换机可具有压入/弹出表6所示标记的能力。为了和已有网络更好结合,建议支持压入/弹出VLAN标记的能力。最新的压入标记应插入到最外侧有效位置作为最外侧的标记。当压入一个新VLAN标记,应作为最外侧标记来插入,位于以太头部后面,其它标记前面。同样的,当压入一个新MPLS标记,也应作为最外侧标记来插入,位于以太头部后面,其它标记前面。当多个压入行动添加到数据包行动集,按照行动集定义的规则依次作用到数据包,开始时MPLS,接着是PBB,后面是VLAN(见5.10)。当一个行动列表中有多个压入行动,按照列表次序(见5.11)作用到数据包。注意:5.12节所涉及的信息都是默认字段值。OptionalAction:Set-Field.不同Set-Field行动由它们的字段类型来标识,并对数据包中头部字段分别修改数值。当要求不很严格时,若支持使用Set-Field行动进行重写头部各字段将非常有益于Openflow的实现。为了和已有网络更好结合,建议支持VLAN修改行动。Set-Field行动应一直作用到头部可能的最外侧(例如,“setVLANID”行动一直设置VLAN标记的最外侧ID),除非该字段类型指定其它值。OptionalAction:Change-TTL.不同Change-TTL行动修改数据包中的IPV4TTL、IPV6HopLimit或MPLSTTL。当要求不很严格时,表7所示的行动非常有益于Openflow中路由功能的实现。Openflow交换机检查出携带无效IPTTL或MPLSTTL的数据包并拒绝接收。不是每个数据包都需要检查TTL是否有效,但是每次数据包完成TTL减1行动后应在最短时间内检查。交换机可能会改变其异步配置(见6.1.1)),利用输入包消息通过控制信道发送携带无效TTL的数据包给控制器(见6.1.2)。5.12.1字段压入的默认值当执行压入行动时,表8中所有字段指定的值应从已有外部头复制给新建外部头。表8中所列的新字段与已有字段不一致的应设置为0。Openflowset_field行动不能修改的字段用初始化成合适的协议数值。在压入操作之后,可通过指定的“set”行动对新建头部的某些字段进行设置。6、openflow通道
Openflow通道是每个交换机连接控制器的接口,通过这个接口,控制器配置和管理交换机,接收来自交换机的事件,将包从交换机转发出去。尽管所有openflow通道消息必须遵守openflow协议格式,但在数据通路和openflow通道之间,接口是具体实施者。openflow通道通常使用TLS加密,但也可能直接在TCP上运行。6.1openflow协议概述
Openflow协议支持三种消息:控制器到交换机消息、异步消息和对称消息,每个都有多个子消息类型。controller-to-switch消息由控制器发起,用来直接管理检查交换机的状态;异步消息由交换机发起,用于控制器更新网络事件和交换机状态变化;对称消息由交换机或者控制器发起,而且无需请求。下面介绍Openflow使用的消息类型。6.1.1Controller-to-SwitchController-to-Switch是由控制器发起,不强求交换机作出回应。Features:控制器通过发送feature请求查询交换机的身份以及基本功能,交换机必须响应,回答其身份和基本能力。通常在openflow通道建立后运行。Configuration:控制器用来设置、查询交换机的配置参数。交换机仅需要回应来自控制器的查询消息。Modify-State:mmodify-sate消息由控制器发出,用来管理交换机的状态。它们的首要目标是增加、删除、修改openflow表中的流表项/组表项,以及设置交换机的端口属性。Read-state:控制器用Read-state消息收集交换机的各种消息,例如当前配置、统计数据和性能等。Packet-out:控制器用这个Packet-out发送数据包到交换机特定的端口。并且转发通过Packet-in消息收到的数据包。Packet-out消息必须包括一个完整的数据包或者一个指明交换机中存储数据包缓冲区的ID。这个消息必须包含一个动作列表,并按指定顺序应用这些动作。若动作列表为空则丢弃该包。Barrier:控制器使用Barrier请求/回复消息确保消息依赖已经遇到或者收到操作完成的通知。Role-Request:控制器使用Role-Request消息,用来设置openflow通道角色,或者查询这个角色。当交换机连接多个控制器时这个消息则非常有用(见6.3.4)。Asynchronous-Configuration:控制器使用Asynchronous-Configuration消息来设置一个附加过滤器,滤出想在openflow通道中接受的异步消息,或者用来查询这些过滤器。这个消息在交换机连接多个控制器时非常有用(见6.3.4),通常在openflow通道建立后运行。6.1.2Asynchronous交换机发送Asynchronous消息时无需控制器的请求,通知控制器数据包到达、交换机状态改变或错误。四个主要的异步消息描述如下。Packet-in:将对包的控制转移给控制器。由于全部数据包使用流表项或者漏表项转发到“CONTROLLER”保留端口,一个packet-in事件就会发给控制器(见5.12)。其他处理,例如TTL检查,也可能产生packet-in事件将数据包发给控制器。缓冲数据包可以配置packet-in事件。由流表项或者组存储段中的输出行动产生的packet-in,可以在输出行动中各自分别指定(见7.2.5),其他的packet-in可在交换机中配置(见7.3.2)。如果这个packet-in事件配置给缓冲数据包,并且交换机中有足够的缓存,在交换机准备转发这个数据包时,这个packet-in事件仅仅包含数据包头部的一部分和控制器使用的缓冲ID。不支持内部缓冲的交换机,packet-in事件配置为不缓冲数据包,或内部缓冲耗尽时,将整个包作为事件的一部分发送给控制器。缓冲的数据包通常是利用控制器发来的packet-out消息进行处理,或者一段时间后自动过期。如果数据包已缓冲,包含在packet-in中的原始包字节数就可以配置,默认的是128字节。由流表项或者组存储段中的输出行动产生的packet-in,可以在输出行动中各自分别指定(见7.2.5),其他的可在交换机中配置(见7.3.2)。(注:交换机缓存足够,包被临时放在缓存中,包的部分内容(默认128字节)和在交换机缓存中的序号也一同发给控制器;如果交换机缓存不足以存储包,则将整个包作为消息的附带内容发给控制器)Flow-Removed:通知控制器一个流表项从流表中移除。流表项只有设置了OFPFF_SEND_FLOW_REM标志,Flow-Removed消息才会发送。此消息是由于控制器的流删除请求产生,或者交换机流处理超时产生,即某个流有效时间超出范围了。Port-status:通知控制器某个端口发生变化。交换机需要在端口配置或状态改变时发送port-status消息给控制器。包括端口配置的改变等事件,例如,端口被用户关闭,端口状态被用户改变,连接断开等。Error:交换机用Error消息通知控制器出现问题。6.1.3Symmetric(对称)Symmetric(对称)消息向每个方向发送时无需询问。包括Hello,Echo,Experimenter三种消息。Hello:Hello消息在连接一旦建立,就在交换机和控制器之间传递。Echo:从交换机或者控制器发出的Echo应答/请求消息,必须得到一个返回的Echo响应消息。他们主要用来验证controller-switch连接是否活跃,也可能来测量延迟率和带宽。Experimenter:Experimenter消息为交换机在其消息类型中提供附加功能提供了一个标准的方法。这是将来openflow修订时的一个功能中转区。6.2MessageHanding(消息处理)
Openflow协议提供可靠的消息传递和处理,但是不自动提供确认和保证消息的有序化处理。这一节所说的openflow消息处理行为是由可靠传输的主辅链接上完成的。MessageDelivery:消息可靠传输,除非Openflow通道完全失败,控制器不了解交换机的任何状态(如交换机可能已经进入了“失败模式”)。MessageProcessing:交换机必须完全处理从控制器接收的每个消息,并可能生成一个回复。如果交换机不能完全处理来自控制器的消息,那么它必须返回一个error消息。对于pack-out消息,消息被完全处理之后也不能保证包实际上退出了交换机。由于交换机的堵塞、QoS策略、或者数据包发送到一个阻塞或无效的端口,交换机处理之后数据包可能被丢弃。此外,交换机须发送所有OpenFlow状态改变时产生的异步消息,例如流删除,端口状态或者packet-in消息,这样控制器就可以与交换机的实际情况同步。基于异步配置(见6.1.1),这些消息可能被过滤,而且,在引起这些变化之前,触发Openflow状态改变的环境可能会被过滤掉。例如,数据端口接收的用来发送到控制器的数据包,由于交换机的阻塞或QoS策略和packet-in消息的缺失,可能被丢弃。这些丢失在数据包对控制器有明显的输出行动时会发生,也可能在数据包在表项里匹配失败产生,尽管表的默认行动是发给控制器。(这个错误会被发送到交换机)。发给控制器的数据包建议采用QoS行动和速率进行监管,以防止控制器链接的拒绝服务,此内容超出本规范范围。控制器可以自由忽略他们接收的消息,但是必须响应应答消息来防止交换机中断连接。MessageOrdering:排序可以通过使用barrier消息来保证。在缺少屏障消息时,交换机可以任意重新排序消息,来达到最佳性能。因此,交换机不应该依赖一个特定的处理顺序。特别的是,流表项插入到流表时,其顺序不同于交换机接收到的流模式。消息跨越一个屏障消息就不需要重新排序,只有前面所有的消息都处理后屏障消息才被处理。具体的说:1.屏障消息前面的消息必须先被处理,包括发送任何产生的错误和回复。2.屏障必须被处理,而后发送一个响应。3.屏障消息后面的消息可继续处理。如果从控制器接收到的2个消息是相互依赖的,那他们必须通过屏蔽消息来分离。6.3Openflow通道连接Openflow通道用来在控制器和交换机之间交换Openflow消息。控制器管理多个Openflow通道,每个通道连接到一个不同的交换机。一个交换机可能有一个通道连到控制器,或者,有多个通道连接到不同的控制器(见6.3.4)。控制器可以通过一个或者多个网络来远程管理交换机。这种方法是不在当前规范之内的,所使用的可能是一个的专用网络,或者由交换机管理的网络(带内控制器连接)。唯一的要求就是应提供TCP/IP连接。Openflow通道实际上作为一个交换机和控制器之间的单一的网络连接,使用TLS或TCP协议(见6.3.3)。另外,为了具有并行性,通道可以由多个网络连接组成。交换机通过初始化到控制器的连接来创建一个到控制器的通道(见6.3.1)。一些交换机实现时可能允许一个控制器连接到交换机,这种情况下,交换机通常应保证安全的连接,以防止没有授权的连接。6.3.1连接建立交换机必须能够与一个用户可配置IP地址(否则是固定的)的控制器建立连接,连接使用用户指定的一个端口或是默认端口。如果交换机与控制器的IP地址进行配置连接,那么交换机启动了一个标准的TLS或TCP连接。Openflow通道的流量不通过Openflow流水线。因此,交换机必须在流表检查之前就必须区分输入流量。当Openflow连接初次建立之时,连接的每一方必须立即发送携带版本字段的OFPT_HELLO消息,版本代表发送者支持的最高的OpenFlow协议版本。这个Hello消息可能含有一些可选内容来帮助建立连接(见7.5.1)。一旦接收到消息,接收方须立即计算出使用的协议版本。如果发送和接收的Hello消息都包含OFPHET_VERSIONBITMAP的hello元素,并且如果这些位图有一些共同的位设置,那双方协商的协议是最高版本的。否则,协商版本是接收到的版本字段中较小版本数字。如果接收方支持协商版本,那么连接可行。否则,接收方必须回应一个OFPT_ERROR消息,此消息带有OFPET_HELLO_FAILED的类型字段,OFPHFC_INCOMPATIBLE的字段以及一个解释数据状态的随机ASCII字符串,然后终止连接。在交换机和控制器交换过OFPT_HELLO消息并且有共同的版本数字之后,连接设置就完成了,标准的Openflow消息能够在连接之上交换。首先,控制器发送一个OFPT_FEATURES_REQUEST消息来取得交换机的数据路径ID(见7.3.1).6.3.2连接中断当交换机与所有的控制器丢失连接,会导致echo请求超时,TLS(安全传输协议)握手超时,或者其他的连接失败,交换机根据当前运行状态和配置,必须立即进入“失败安全模式”或者“失败模式”。在失败安全模式下,交换机行为唯一的改变就是丢弃发向控制器的包和消息。流表项应在“失败安全模式”下依据定时设置继续会发生超时现象。在“失败模式”下,交换机使用OFPP_NORMAL保留端口处理所有的包。换机话说,就是交换机作为传统以太网的交换机和路由器。“失败模式”一般只在Hybrid交换机上存在(见5.1)。当再一次连接控制器时,已有的流表项将保留。如果有必要的话,控制器可删除所有的流表项。交换机第一次启动时,它会运行在“失败安全模式”或者“失败模式”,直到它成功的连接到控制器。启动时流表项的默认设置内容不在本Openflow协议之内。6.3.3加密交换机和控制器可通过TLS连接(安全传输层协议)通信。交换机启动时初始化TLS连接来连接控制器,TLS连接默认TCP端口是6633。交换机和控制器通过交换由位置专一密钥签名的证书,来相互鉴权。每个交换机必须是用户可配置的,并携带控制器鉴权的证书(控制器证书)和另一个证书向控制器鉴权(交换机证书)。交换机和控制器可选择用普通TCP来互通,此TCP连接默认位于TCP端口6633,由交换机发起和初始化。当使用默认的普通TCP连接,推荐使用其他安全措施来防止窃听,伪装控制器以及其他Openflow通道上的攻击。6.3.4多控制器交换机可能与一个或多个控制器建立通信。多控制器模式可靠性更好,如果一个控制器连接失败,交换机还是能够继续运行在Openflow模式中的。控制器的hand-over(切换)机制由控制器自己管理,这能够使其从失败中快速恢复或者使其负载平衡。控制器通过现有规范之外的模式来调节对交换机的管理。多控制器的目的是帮助同步控制器的传输。多控制器的功能基于控制器容错和负载平衡,而不是基于Openflow协议之外的虚拟化。当Openflow操作启动,交换机必须连接到所有与其配置相关的控制器,并且尽力保持与他们的连接。许多控制器发送controller-to-swith命令到交换机,有关此命令的回复消息或错误消息必须被返回通过相关的控制器连接。异步消息可能发送给多个控制器,为每一个Openflow通道复制一个消息,当控制器允许时就发出去。控制器默认的身份是OFPCR_ROLE_EQUAL。以这种身份,控制器能够完全访问交换机,这对其他控制器是一样的。默认地,控制器接收交换机所有的异步消息(比如包输入消息,流删除)。控制器发送controller-to-swith命令来改变交换机的状态。交换机与众控制器之间互不干涉,也不进行资源共享。控制器可要求更换身份到OFPCR_ROLE_SLAVE。这样,控制器以只读方式接入到交换机。控制器默认不接收交换机的异步消息,除了端口状态消息。控制器拒绝执行发送数据或改变交换机状态的controller-to-swith命令,例如,OFPT_PACKET_OUT,OFPT_FLOW_MOD,OFPT_GROUP_MOD,OFPT_PORT_MOD,OFPT_TABLE_MOD请求,以及OFPMP_TABLE_FEATURES非空体复合请求必须拒绝。如果控制器发送以上命令中的一个,那么交换机必须返回一个携带OFPET_BAD_REQUEST类型字段和OFPBRC_IS_SLAVE代码段的OFPT_ERROR消息。其他controller-to-swith消息,例如OFPT_ROLE_REQUEST,OFPT_SET_ASYNCandOFPT_MULTIPART_REQUEST这些查询数据的消息,应该正常进行处理。控制器也可更换身份为OFPCR_ROLE_MASTER。这个角色与OFPCR_ROLE_EQUAL相似的,可完全访问交换机,不同的是,控制器要确保它的角色是唯一的。当控制器换到此身份时,交换机让OFPCR_ROLE_MASTER控制器改变为OFPCR_ROLE_SLAVE,但是不会影响到OFPCR_ROLE_EQUAL控制器。当交换执行身份切换操作时,没有消息生成发送发到正进行身份切换的控制器(大多数情况下控制器不再可到达)。每个控制器会发送OFPT_ROLE_REQUEST消息给交换机让其知道自己的身份,交换机必须记住每个连接控制器的身份。控制器可能随时改变身份,只要在当前消息中提供generation_id。身份请求消息提供了一种轻量级机制来帮助控制器管理选举进程,控制器互相协调来配置自己身份。交换机不能直接的改变控制器的状态,这是由另一个控制器发出的消息作用的结果。任何的从控制器或者对等控制器(equalcontroller)可选择自己的主控制器。交换机可能同时连接到多个对等控制器,或多个从控制器,但最多连接一个主控制器。主控制器和对等控制器能完全改变交换机的状态,控制器没有分割交换机的机制。如果主控制器需要作为唯一能改变交换机的控制器,其它控制器应该全是从控制器,而不能有对等控制器。控制器可控制在Openflow通道中传输的异步消息的类型,并改变上述的默认值。通过异步配置消息(6.1.1)列出需要使能或过滤的消息类型的所有原因。通过这个特性,不同的控制器可以接收不同的通知,主控制器可以选择性的禁用其不关心的通知,从控制器可以启动它想监控的通知。为了检测主从控制器切换时产生的无序消息,OFPT_ROLE_REQUEST消息包含了一个位序列字段,generation_id,来标识主控身份。作为主控选举机制的一部分,控制器(或者第三方)协调generation_id的分配。generation_id是单调递增的计数器:每次主控关系改变时,会分配一个新的(更大的)generation_id,例如,每当指定一个新的主控制器,generation_id会增加。当接收到身份是OFPCR_ROLE_MASTER和OFPCR_ROLE_SLAVE控制器发来的OFPT_ROLE_REQUEST消息,交换机必须将其包含的generation_id消息与之前最大的generation_id比较,若较小的话,则丢弃。交换机必须用错误消息回应,错误消息的类型是OFPET_ROLE_REQUEST_FAILED,代码是OFPRRFC_STALE。下面的伪代码描述了交换机处理generation_id的行为。交换机的启动:generation_is_defined=false;接收到身份是OFPCR_ROLE_MASTER和OFPCR_ROLE_SLAVE控制器发来的OFPT_ROLE_REQUEST消息,并携带一个给定的generation_id,代码GEN_ID_X:if(generation_is_definedANDdistance(GEN_ID_X,cached_generation_id)<0){ structofp_headerheader;uint16_ttype;/*一个OFPMP_*常数.*/uint16_tflags;/*OFPMPF_REPLY_*标记.*/uint8_tpad[4];uint8_tbody[0];/*回答的body,0或更多字节.*/};OFP_ASSERT(sizeof(structofp_multipart_reply)==16);enumofp_multipart_reply_flags{OFPMPF_REPLY_MORE=1<<0/*更多回复跟随*/};在请求和回复中为flags定义的值是唯一的,是否更多的请求/回复会跟随这个——这个值就是0x0001。为了方便实现,控制器允许发送请求和交换机允许发送回复时不携带额外的表项(即一个空的body)。然而,另一个消息必须使用更多的标志设置去跟随一个消息。跨越多个消息(有一个或多个消息设置了更多的标志)的请求或应答,消息队列中的所有消息必须使用相同的复合类型和事务id(xid)。如果多个未回答的复合请求或回复同时在传输中,复合请求或应答的消息可能与其他OpenFlow消息类型交替,包括其他复合请求或回复,但必须有不同的事务id。回复的事务id必须匹配激起他们的请求。在请求和响应中,type字段指所传递信息的种类,并决定如何解析body字段:enumofp_multipart_type{/*描述这个OpenFlow交换机。*请求body是空的。*回复主体是structofp_desc.*/OFPMP_DESC=0,/*单独流统计。*请求body是ofp_flow_stats_request结构。*回复body是一个structofp_flow_stats数组。.*/OFPMP_FLOW=1,/*总的流统计。*请求body是ofp_aggregate_stats_request结构。*回复body是ofp_aggregate_stats_reply结构.*/OFPMP_AGGREGATE=2,/*流表统计。*请求body是空的。*回复body是ofp_table_stats结构数组。*/OFPMP_TABLE=3,/*端口统计。*请求body是ofp_port_stats_request结构。*回复body是ofp_port_stats结构数组。*/OFPMP_PORT_STATS=4,/*一个端口的队列统计*请求的body是ofp_queue_stats_request结构体.*回复body是ofp_queue_stats结构体数组*/OFPMP_QUEUE=5,/*组计数器统计。*请求的body是ofp_group_stats_request结构体.*回复是ofp_group_stats结构体数组*/OFPMP_GROUP=6,/*组描述。*请求body是空的。/*回复body是ofp_group_desc结构体数组*/OFPMP_GROUP_DESC=7,/*组特征。*请求body为空。*回复body是ofp_group_features结构体。*/OFPMP_GROUP_FEATURES=8,/*计量器统计*请求body是ofp_meter_multipart_requests结构体。*回复body是ofp_meter_stats结构体数组*/OFPMP_METER=9,/*计量器配置*请求body是ofp_meter_multipart_requests结构体.*回复body是ofp_meter_config结构体数组。*/OFPMP_METER_CONFIG==10,/*计量器特征*请求body为空。*回复body是ofp_meter_features结构体。*/OFPMP_METER_FEATURES=11,/*表特征*请求body是空的或包含ofp_table_features结构体数组,包含控制器所需的交换机视图。如果交换机不能设置特定的视图,就会返回一个error.*回复body是一组ofp_table_features结构体.*/OFPMP_TABLE_FEATURES=12,/*端口说明*请求body是空的。*回复body是ofp_port结构体数组*/OFPMP_PORT_DESC=13,/*实验者扩展项*请求body和回复body都以ofp_experimenter_multipart_header结构体开始。*而请求body和回复body是由实验者定义的。*/OFPMP_EXPERIMENTER=0xffff};如果一个复合请求跨越多个消息并且扩展到交换机不能缓冲的大小,那么交换机必须回复一个OFPET_BAD_REQUEST类型的错误消息并且编码为OFPBRC_MULTIPART_BUFFER_OVERFLOW。如果一个复合请求包含一个不支持的类型,交换机必须回复一个OFPET_BAD_REQUEST类型的错误消息并且编码为OFPBRC_BAD_MUTIPART.在所有包含统计数字复合应答中,如果在交换机中没有指定的数字计数器,其值必须被设置为字段最大值(无符号数=-1)。计数器是无符号的并且循环时无溢出指示。7.3.5.1说明关于交换机厂商、硬件修订、软件修订、序列号和描述字段的信息,可以从OFPMP_DESCmultipart请求类型中获得:/*OFPMP_DESC请求的回复部分。每个表项都是NULL结束的ASCII码字符串*/structofp_desc{charmfr_desc[DESC_STR_LEN];/*厂商说明.*/charhw_desc[DESC_STR_LEN];/*硬件说明.*/charsw_desc[DESC_STR_LEN];/*软件说明.*/charserial_num[SERIAL_NUM_LEN];/*序列号.*/chardp_desc[DESC_STR_LEN];/*可读的数据通道描述.*/};OFP_ASSERT(sizeof(structofp_desc)==1056);每个表项都是ASCII码格式并且用空字节(\\0)从右边填充。DESC_STR_LEN是256,SERIAL_NUM_LEN是32。dp_desc是一个自由形式的字符串,调试时用来描述数据通道,例如:“switch3inroom3120”。因此,它不能被保证是唯一的并且不应用作数据通道的主要标识—-使用交换机的datapath_id字段来代替。7.3.5.2单个的流统计关于单个流表项的信息使用OFPMP_FLOW复合请求类型进行请求:/*OFPMP_FLOW的ofp_multipart_request部分*/structofp_flow_stats_request{uint8_ttable_id;/*要读的table_ID(fromofp_table_stats),OFPTT_ALL表示所有表.*/uint8_tpad[3];uint32_tout_port;uint32_tout_group;uint8_tpad2[4];uint_tcookie;uint_tcookie_mask;Structofp_matchmatch;};OFP_ASSERT(sizeof(structofp_flow_stats_request)==40);/*对齐到32bits.*//*作为一个输出端口要求包含这个匹配项.一个OFPP_ANY值表示没有。*//*作为一个输出组要求包含这个匹配项,一个OFPG_ANY值表示没有*//*对齐到bits.*//*要求匹配项要包含这个cookie值。*//*掩码用来那些必须匹配的cookiebits.0表示没有*//*用来匹配的字段,可变大小*/匹配字段包含需匹配的流表项说明,还可含有通配符和掩码字段。这些字段的匹配行为在6.4中介绍。Table_id表示一个将读取的一个流表的索引值,OFPTT_ALL表示所有流表。Out_port和out_group字段可又输出端口和组选择过滤。如果out_port或out_group包含一个分别不同于OFPP_ANY和OFPG_ANY的值,它会在匹配的时候引进一个约束。这个约束就是流表项必须包含一个指定端口或组的输出行动。其它约束例如ofp_match结构仍然在使用;这是纯粹一个额外的约束。注意为了禁止输出过滤,out_port和out_group都必须分别设置为OFPP_ANY和OFPG_ANY。Cookie和cookie_mask字段的用法见6.4部分。回复一个OFPMP_FLOW复合请求的部分由下列队列组成:/*回复一个OFPMP_FLOW请求的部分。*/structofp_flow_stats{uint16_tlength;/*这个项的长度*/uint8_ttable_id;/*流的来源表ID*/uint8_tpad;uint32_tduration_sec;/*流已生成的时间,以秒记*/uint32_tduration_nsec;/*流存在的时间超过duration_sec的时间,以ns记*/uint16_tpriority;/*流表项的优先权*/uint16_tidle_timeout;/*在到期之前闲置的秒数*/uint16_thard_timeout;/*到期之前的秒数*/uint16_tflags;/*OFPFF_*flags位图.*/uint8_tpad2[4];/*对齐到-bits.*/uint_tcookie;/*控制器发出的不透明标识符*/uint_tpacket_count;/*流里的包的数目。*/uint_tbyte_count;/*流的字节数.*/structofp_matchmatch;/*字段说明.可变大小*//*可变大小和填充的匹配总是跟随着指令.*///structofp_instructioninstructions[0];/*指令集--0或者更多.*/};OFP_ASSERT(sizeof(structofp_flow_stats)==56);由创建流表项的flow_mod提供的字段(见7.3.4.1),加上插入到流表项中的table_id,packet_count和byte_count对所有被流表项处理的数据包进行计数。duration_nsec和duration_sec字段显示流表项安装在交换机中已过去的时间。总共持续的时间可用duration_sec*10^9+duration_nsec计算出。实现的话要求提供第二精度;在能够获得的情况下鼓励用更高的精度。7.3.5.3总计的流统计关于多个的流表项的总计信息用OFPMP_AGGREGATE复合请求类型来请求:/*OFPMP_AGGREGATE类型的ofp_aggregate_atats_request部分*/structofp_aggregate_stats_request{uint8_ttable_id;/*要读取的表ID(来自ofp_table_stats),OFPTT_ALL为所有的表*/uint8_tpad[3];/*排列到32bits.*/uint32_tout_port;/*包含此项匹配的流表项要求作为一个输出端口.OFPP_ANY值表示没有*/uint32_tout_group;/*包含此项匹配的流表项要求作为一个输出组,OFPG_ANY值表示没有*/uint8_tpad2[4];/*排列到bits.*/uint_tcookie;/*要求正在匹配的流表项去包含这些cookie值*/uint_tcookie_mask;/*掩码(mask)用来那些必须匹配的cookie比特,0表示没有.*/structofp_matchmatch;/*将匹配的字段.可变大小.*/};OFP_ASSERT(sizeof(structofp_aggregate_stats_request)==40);在这个消息的中的字段与在单独的流统计请求(OFPMP_FLOW)里有相同的含义。回复部分的组成如下:/*OFPMP_AGGREGATE请求的回复部分.*/structofp_aggregate_stats_reply{uint_tpacket_count;/*流中的数据包数.*/uint_tbyte_count;/*流中的字节数.*/uint32_tflow_count;/*流的数目.*/uint8_tpad[4];/*排列到bits.*/};OFP_ASSERT(sizeof(structofp_aggregate_stats_reply)==24);7.3.5.4表统计请求关于表的信息使用OFPMP_TABLE复合请求类型。在请求内不包含任何数据。回复部分由如下一个数组组成:/*回复给OFPMP_TABLE请求的部分.*/structofp_table_stats{uint8_ttable_id;/*表标识符.低数值的表第一个访问*/uint8_tpad[3];/*排列到32-bits.*/uint32_tactive_count;/*活跃的流表项数量.*/uint_tlookup_count;/*表中处理过的数据包数量.*/uint_tmatched_count;/*表中匹配的数据包数量。*/};OFP_ASSERT(sizeof(structofp_table_stats)==24);在交换机支持的每一个表中,数组都有一个结构。流表项是以数据包通过表的顺序返回的。7.3.5.5表特征OFPMP_TABLE_FEATURES复合类型允许一个控制器去查询现存的表的能力和选择要求交换机去重新配置表去匹配一个已有的配置。一般来讲,表的能力体现了一个表的所有可能的特征,然而一些能力互不兼容,目前的能力结构不允许我们去解决兼容问题。7.3.5..5.1表特征请求和回复如果OFPMP_TABLE_FEATURES请求是空的,交换机将返回一组包含当前配置流表能力的ofp_table_features结构体。如果请求部分包含一个或更多ofp_table_features结构体的队列,交换机将尝试去改变它的流表去匹配被请求的流表配置。这个操作配置整个流水线,流水线里的流表设置必须和请求的设置匹配,否则必须返回一个error。尤其是,如果这个配置成功进行了设置,则给一个或更多交换机支持的流表的请求结构若不包含一个ofp_table_features结构体,这些流表将从流水线中被移除。配置改变成功会修改请求里面的所有流表的特性,也就是说,要么在请求里被指定的所有流表都修改,要么一个都不改,并且新的流表的功能必须是超集或者和被请求的功能相同。如果流表配置成功了,已删除的流表或在新旧配置里能力改变的流表,其流表项都将从流表中删除。如果交换机不能设置所请求的配置,将返回一个OFPET_TABLE_FEATURES_FAILED类型错误并带有适当错误代码。含有ofp_table_features的请求和回复至少要满足以下要求:●每个ofp_table_features结构的table_id字段的值在消息所有的ofp_table_features结构里应该是唯一的。●每个ofp_table_features结构的属性字段必须包含一个ofp_table_feature_prop_type属性,以及另外两个。第一,the_MISS后缀可能被忽略,如果它和常规流表项相应的属性相同;第二,OFPTFPT_EXPERIMENTER和OFPTFPT_EXPRIMENTER_MISS类型的属性可能会被多次忽略或使用。排序未规定,但鼓励使用在规范上列出的次序。(见7.3.5.5.2)一个交换机接收到一个请求,若不满足所需请求,应该返回一个OFPET_TABLE_FEATURES_FALLED类型的错误并带有适当的代码。下面的结构说明表特性请求和回复的部分:/*OFPMP_TABLE_FEATURES类的ofp_multipart_request部分.//*回复OFPMP_TABLE_FEATURES请求的部分.*/structofp_table_features{uint16_tlength;/*长度被填至bits.*/uint8_ttable_id;/*表的标识符.低编号先询问.*/uint8_tpad[5];/*排到-bits.*/charname[OFP_MAX_TABLE_NAME_LEN];uint_tmetadata_match;/*表能匹配元数据的位数.*/uint_tmetadata_write;/*表能写的元数据位数.*/uint32_tconfig;/*OFPTC_*值的位图*/uint32_tmax_entries;/*流表项被支持的最大数.*//*表特征属性列举*/structofp_table_feature_prop_headerproperties[0];/*属性举例*/};OFP_ASSERT(sizeof(structofp_table_features)==);数组有一个结构给每个被交换机支持的流表。流表项总是按照数据表通过流表的顺序返回。OFP_MAX_TABLLE_NAME_LEN是32。该metadata_match字段表示流表利用ofp_match结构体元数据字段时可匹配的元数据字段的位数,。值0xFFFFFFFFFFFFFFFF表明表可以匹配整个元数据字段。该metadata_write字段显示表可以使用ofpit_write_metadata指令写元数据字段的位数。值0xFFFFFFFFFFFFFFFF表明表可以写整个元数据字段。配置字段是表的配置,通过表的配置信息对表进行设置(见7.3.3)Max_entries字段表示能插入表的流表项最大数量。由于现代的硬件的,该max_entries值应考虑建议值和接近表最大努力的性能。不考虑表的高层抽象,在实践中通过一个单一的流表项所消耗的资源是不固定的。例如,一个流表项可能消耗多个流表项的资源,取决于它的匹配参数(e.g.IPv4vs.IPv6)。而且,在同个OPENFLOW层不同的表可能实际上共享相同的底层物理资源。进一步说,基于OpenFlow混合交换机,这些表可能与非OpenFlow功能部分共享。结果是交换机实现者应该报告所支持的总的流表项值,并且控制器的作者不应该把这个值设为固定的,物理常数。properties字段是表特征属性的一个列表,描叙表的不同性能。7.3.5.5.2表特征属性目前定义的表特征属性类型的清单是:/*表特征属性类型.*最低位被清除表示一个常规流表项的一个属性.*最低位被设置表示Table-MissFlowEntry的一个属性.*/enumofp_table_feature_prop_type{OFPTFPT_INSTRUCTIONS=0,/*指令属性.*/OFPTFPT_INSTRUCTIONS_MISS=1,/*table-miss的指令.*/OFPTFPT_NEXT_TABLES=2,/*NextTable属性.*/OFPTFPT_NEXT_TABLES_MISS=3,/*NextTablefortable-miss.*/OFPTFPT_WRITE_ACTIONS=4,/*WriteActions属性.*/OFPTFPT_WRITE_ACTIONS_MISS=5,/*WriteActionsfortable-miss.*/OFPTFPT_APPLY_ACTIONS=6,/*ApplyActions属性.*/OFPTFPT_APPLY_ACTIONS_MISS=7,/*ApplyActionsfortable-miss.*/OFPTFPT_MATCH=8,/*匹配属性.*/OFPTFPT_WILDCARDS=10,/*Wildcards属性.*/OFPTFPT_WRITE_SETFIELD=12,/*WriteSet-Field属性.*/OFPTFPT_WRITE_SETFIELD_MISS=13,/*WriteSet-Fieldfortable-miss.*/OFPTFPT_APPLY_SETFIELD=14,/*ApplySet-Field属性.*/OFPTFPT_APPLY_SETFIELD_MISS=15,/*ApplySet-Fieldfortable-miss.*/OFPTFPT_EXPERIMENTER=0xFFFE,/*Experimenter属性.*/OFPTFPT_EXPERIMENTER_MISS=0xFFFF,/*Experimenterfortable-miss.*/};_MISS后缀的属性描述漏表流表项的功能(见5.4),而其他属性描述常规流表项的功能。如果一个指定属性没有任何功能(例如不支持Set_Field),一个空列表属性也必须被包含在属性列表里。当漏表流表项的一个属性和常规流表项相应的属性相同,(i.e.两个属性都有相同的功能清单),这个漏表属性可以从属性列表里清除。一个属性定义包含属性类型、长度和关联的数据:/*所有表特征属性常用的标头*/structofp_table_feature_prop_header{uint16_ttype;/*OFPTFPT_*中之一.*/uint16_tlength;/*这个属性占字节长度.*/};OFP_ASSERT(sizeof(structofp_table_feature_prop_header)==4);OFPTFPT_INSTRUCTIONS和OFPTFPT_INSTRUCTIONS_MISS属性使用如下结构和字段:/*指令属性*/structofp_table_feature_prop_instructions{uint16_ttype;/*OFPTFPT_INSTRUCTIONS和OFPTFPT_INSTRUCTIONS_MISS之一.*/uint16_tlength;/*这个属性的字节长度.*//*接下来是:*-准确地讲(length-4)个字节包含指令的id,其次*-精确地(length+7)/8*8-(length)(between0and7)*全零字节的字节数*/structofp_instructioninstruction_ids[0];/*指令列表*/};OFP_ASSERT(sizeof(structofp_table_feature_prop_instructions)==4);Instruction_ids是被这个表支持的指令列表(见5.9)。列表里的元素是可变大小的,用于实验者表述指令的,非实验者指令是4字节。OFPTFPT_NEXT_TABLES和OFPTFPT_NEXT_TABLES_MISS属性使用如下结构和字段:/*NextTables属性*/structofp_table_feature_prop_next_tables{uint16_ttype;/*OFPTFPT_NEXT_TABLES和OFPTFPT_NEXT_TABLES_MISS之一.*/uint16_tlength;/*这个属性占的字节长度.*//*Followedby:*-Exactly(length-4)bytescontainingthetable_ids,then*-Exactly(length+7)/8*8-(length)(between0and7)*bytesofall-zerobytes*/uint8_tnext_table_ids[0];/*表地址列表.*/};OFP_ASSERT(sizeof(structofp_table_feature_prop_next_tables)==4);next_table_ids是表的数组,使用该OFPIT_GOTO_TABLE指令可以直接到达本表。(见5.1)。OFPTFPT_WRITE_ACTIONS,OFPTFPT_WRITE_ACTIONS_MISS,OFPTFPT_APPLY_ACTIONS和OFPTFPT_APPLY_ACTIONS_MISS属性使用如下结构和字段:/*行动属性*/structofp_table_feature_prop_actions{uint16_ttype;/*OFPTFPT_WRITE_ACTIONS,OFPTFPT_WRITE_ACTIONS_MISS,OFPTFPT_APPLY_ACTIONS,FPTFPT_APPLY_ACTIONS_MISS.中之一*/uint16_tlength;/*该属性字节长度.*//*Followedby:*-Exactly(length-4)bytescontainingtheaction_ids,then*-Exactly(length+7)/8*8-(length)(between0and7)*bytesofall-zerobytes*/structofp_action_headeraction_ids[0];/*Listofactions*/};OFP_ASSERT(sizeof(structofp_table_feature_prop_actions)==4);Action_ids是特征的行动列表(见5.12)。列表里的元素是可变大小的,用于实验者表述指令,非实验者指令是4字节。OFPTFPT_WRITE_ACTIONS和OFPTFPT_WRITE_ACTIONS_MISS属性描述使用OFPIT_WRITE_ACTIONS指令的表所支持的行动,而OFPTFPT_APPLY_ACTIONS和OFPTFPT_APPLY_ACTIONS_MISS属性描述被正在使用OFPIT_APPLY_ACTIONS指令的表支持的行动。OFPTFPT_MATCH,OFPTFPT_WILDCARDS,OFPTFPT_WRITE_SETFIELD,OFPTFPT_WRITE_SETFIELD_MISS,OFPTFPT_APPLY_SETFIELD和OFPTFPT_APPLY_SETFIELD_MISS属性使用如下结构和字段:/*Match,Wildcard或Set-Field属性*/structofp_table_feature_prop_oxm{uint16_ttype;/*OFPTFPT_MATCH,OFPTFPT_WILDCARDS,OFPTFPT_WRITE_SETFIELD,OFPTFPT_WRITE_SETFIELD_MISS,OFPTFPT_APPLY_SETFIELD,OFPTFPT_APPLY_SETFIELD_MISS.中之一*/uint16_tlength;/*Lengthinbytesofthisproperty.*//*Followedby:*-Exactly(length-4)bytescontainingtheoxm_ids,then*-Exactly(length+7)/8*8-(length)(between0and7)*bytesofall-zerobytes*/uint32_toxm_ids[0];/*OXM头数组*/};OFP_ASSERT(sizeof(structofp_table_feature_prop_oxm)==4);oxm_ids是针对特征的OXM类型列表(见7.2.3.2)。列表里是32位OXM头或者实验者使用的位OXM头。OFPTFPT_MATCH属性表示特别的表所支持匹配的字段(见7.2.3.7)。例如:如果表能够匹配入端口,一个OXM_OF_IN_PORT类型的OXM头应该被包括在列表里。如果在OXM头中HASMASK位被设置,那么交换机必须支持为所给的掩码类型。OFPTFPT_WILDCARDS属性表示特别的表所支持通配(省略)的字段。例如,一个直接查找的哈希表将把列表变空,而一个TCAM表或者有序查询表将设置成和OFPTFPT_MATCH属性相同的值。OFPTFPT_WRITE_SETFIELD和OFPTFPT_WRITE_SETFIELD_MISS属性利用OFPIT_WRITE_ACTIONS指令,来描述表所支持的Set_Field行动类型。而OFPTFPT_APPLY_SETFIELD和OFPTFPT_APPLY_SETFIELD_MISS属性利用OFPIT_APPLY_ACTIONS指令,来描述表所支持的Set-Field行动类型。控制器max_entries字段异常,在ofp_table_features中的所有字段可能被要求改变。此字段是只读的,并且由交换机返回。OFPTFPT_APPLY_ACTIONS,OFPTFPT_APPLY_ACTIONS_MISS,OFPTFPT_APPLY_SETFIELD,和OFPTFPT_APPLY_SETFIELD_MISS属性包含表能运用的行动和字段。对于每一个列表,如果一个元素ispresent,意味着表至少能使该元素隔离一次。目前没有办法表示哪些元素能一起运用,按哪种顺序,一个元素能在一个单一的流表项里被运用多少次。OFPTFPT_EXPERIMENTER和OFPTFPT_EXPERIMENTER_MISS属性使用如下结构和字段:/*实验者的表的特征属性*/structofp_table_feature_prop_experimenter{uint16_ttype;/*OFPTFPT_EXPERIMENTER和OFPTFPT_EXPERIMENTER_MISS中之一.*/uint16_tlength;/*这个属性字节长度.*/uint32_texperimenter;/*ExperimenterID在ofp_experimenter_header结构中有相同形式.*/uint32_texp_type;/*实验者定义.*//*Followedby:*-Exactly(length-12)bytescontainingtheexperimenterdata,then*-Exactly(length+7)/8*8-(length)(between0and7)*bytesofall-zerobytes*/uint32_texperimenter_data[0];};OFP_ASSERT(sizeof(structofp_table_feature_prop_experimenter)==12);实验者字段是ExperimenterID,在ofp_experimenter结构体中有相同形式(见7.5.4).7.3.5.6端口统计关于端口统计的信息使用OFPMP_PORT_STATS复合请求类型进行请求:/*Bodyforofp_multipart_requestoftypeOFPMP_PORT.*/structofp_port_stats_request{uint32_tport_no;/*OFPMP_PORT消息必须请求统计,要么给一个单一的端口(在port_no中指定的)或者所有端口(port_no==OFPP_ANY).*/uint8_tpad[4];};OFP_ASSERT(sizeof(structofp_port_stats_request)==8);port_no字段有选择的过滤统计请求到给定的端口。若访问所有端口的统计,port_no必须设置成OFPP_ANY.回复部分由以下数组组成:/*OFPMP_PORT请求的回复部分.如果一个计数器不被支持,设置该字段给所有的(ones).*/structofp_port_stats{uint32_tport_no;uint8_tpad[4];/*排到-bits.*/uint_trx_packets;/*收到包的数量.*/uint_ttx_packets;/*已传送包的数量*/uint_trx_bytes;/*收到的字节数.*/uint_ttx_bytes;/*传送的字节数.*/uint_trx_dropped;/*被RX丢弃的包数.*/uint_ttx_dropped;/*被TX丢弃的包数.*/uint_trx_errors;/*接受到错误的数量.这是一个超集(super-set)更具体的接收错误,应该大于或等于所有rx_*_err值的总和。*/uint_ttx_errors;/*传送错误的数量.这是一个超集更具体的传输错误,应该大于或等于所有tx_*_err值的总和(没有当前定义的。)*/uint_trx_frame_err;/*帧调整的错误数量.*/uint_trx_over_err;/*在RX溢出的数据包数.*/uint_trx_crc_err;/*CRC错误数.*/uint_tcollisions;/*冲突数量.*/uint32_tduration_sec;/*端口已经生存了的秒数.*/uint32_tduration_nsec;/*端口已生存的时间超过duration_sec的纳秒数.*/};OFP_ASSERT(sizeof(structofp_port_stats)==112);duration_sec和duration_nsec字段表示端口已配置成OpenFlow通道已过去的时间。持续的总的纳秒数可以被算成duration_sec*10^9+duration_nsec.实现时要求提供第二精度,在能获得的条件下鼓励提供更高的精度。7.3.5.7端口描述 端口描述请求OFPMP_PORT_DESCRIPTION能使控制器获得支持OpenFlow系统里所有的端口描述。请求部分是空的。回复部分由如下数组构成:/*一个端口的描述*/structofp_port{uint32_tport_no;uint8_tpad[4];uint8_thw_addr[OFP_ETH_ALEN];uint8_tpad2[2];/*排到bits.*/charname[OFP_MAX_PORT_NAME_LEN];/*Null-terminated*/uint32_tconfig;/*OFPPC_*flags的位图.*/uint32_tstate;/*OFPPS_*flags的位图.*//*描述特性的OFPPF_*的位图.如果不支持或不可用的所有位清零*/uint32_tcurr;/*当前特征*/uint32_tadvertised;/*端口公布的特性.*/uint32_tsupported;/*端口支持的特性.*/uint32_tpeer;/*对端公布的特性.*/uint32_tcurr_speed;/*当前端口的比特率,kbps.*/uint32_tmax_speed;/*最大端口比特率kbps*/};OFP_ASSERT(sizeof(structofp_port)==);这个结构被描述在7.2.1.7.3.5.8队列统计OFPMP_QUEUE复合请求消息提供队列统计给一个或多个端口和一个或多个队列。请求部分包含一个port_no字段为请求的统计标识出OpenFlow端口,或者OFPP_ANY去查阅所有的端口。queue_id字段识别优先队列之一。或者OFPQ_ALL指向在指定端口配置的所有队列。OFPQ_ALL是0xffffffff。structofp_queue_stats_request{uint32_tport_no;/*如果是OFPP_ANY表示所有端口.*/uint32_tqueue_id;/*如果是OFPQ_ALL表示所有队列.*/};OFP_ASSERT(sizeof(structofp_queue_stats_request)==8);回复部分由下列结构组成:structofp_queue_stats{uint32_tport_no;uint32_tqueue_id;/*队列i.d*/uint_ttx_bytes;/*传送的字节数.*/uint_ttx_packets;/*传送的包数.*/uint_ttx_errors;/*由于溢出丢弃的数据包数量.*/uint32_tduration_sec;/*队列已经生成的秒数.*/uint32_tduration_nsec;/*队列已经生成超出duration_sec的纳秒数.*/};OFP_ASSERT(sizeof(structofp_queue_stats)==40);Duration_sec和duration_nsec字段表示队列已经安装在交换机里过去了的时间。持续的总时间可以用duration_sec*10^9+duration_nsec.实现时要求提供第二精度,在能获得的条件下鼓励提供更高的精度。7.3.5.9组统计OFPMP_GROUP复合请求消息为一个或多个组提供统计。请求部分由group_id字段组成。它也能被设置为OFPG_ALL表示交换机里所有的组。/*OFPMP_GROUP请求部分.*/structofp_group_stats_request{uint32_tgroup_id;/*如果是OFPG_ALL表示所有的表.*/uint8_tpad[4];/*拍到bits.*/};OFP_ASSERT(sizeof(structofp_group_stats_request)==8);回复部分由如下结构组成:/*回复给OFPMP_GROUP请求的部分.*/structofp_group_stats{uint16_tlength;/*这个流表项的长度.*/uint8_tpad[2];/*排到bits.*/uint32_tgroup_id;/*组标识符.*/uint32_tref_count;/*直接指向该组的流或组的数量*/uint8_tpad2[4];/*排到bits.*/uint_tpacket_count;/*组处理过的包的数量.*/uint_tbyte_count;/*组处理过的字节数量.*/uint32_tduration_sec;/*组已经生存的秒数.*/uint32_tduration_nsec;/*组已经生存的超过duration_sec的纳秒数.*/structofp_bucket_counterbucket_stats[0];/*每个存储段设置一个计数器.*/};OFP_ASSERT(sizeof(structofp_group_stats)==40);字段包括创建组的group_mod提供的,加上ref_count表示计算与组相关的流的数量,packet_count,和byte_count计算所有组处理的数据包。Duration_sec和duration_nsec字段表示组安装在交换机里已经过去的时间。总的持续的纳秒数可以用duration_sec*10^9+duration_nsec.实现时要求提供第二精度,在能获得的条件下鼓励提供更高的精度。Bucket_stats字段由一组ofp_bucket_counter结构体组成:/*用来做组统计回复.*/structofp_bucket_counter{uint_tpacket_count;/*存储段处理的包数.*/uint_tbyte_count;/*存储段处理的字节数.*/};OFP_ASSERT(sizeof(structofp_bucket_counter)==16);7.3.5.10组描述OFPMP_GROUP_DESC复合请求消息提供一个方式将交换机上的组设置列出来,以及它们相应的存储段行动。请求部分是空的,而回复部分是如下结构的数组:/*回复给OFPMP_GROUP_DESC请求的部分.*/structofp_group_desc{uint16_tlength;/*流表项的长度.*/uint8_ttype;/*OFPGT_*中之一.*/uint8_tpad;/*填充至bits.*/uint32_tgroup_id;/*组标识符.*/structofp_bucketbuckets[0];/*存储段列表--0或更多.*/};OFP_ASSERT(sizeof(structofp_group_desc)==8);描述组的字段和那些ofp_group_mod结构体使用的一样(见7.3.4.2)。7.3.5.11组特征OFPMP_GROUP_FEATURES复合请求消息提供一个方式列出交换机上组的功能。请求部分是空的,而回复部分是如下结构:/*回复给OFPMP_GROUP_FEATURES请求的部分.组特征.*/structofp_group_features{uint32_ttypes;/*OFPGT_*值支持的位图.*/uint32_tcapabilities;/*OFPGFC_*功能支持的位图.*/uint32_tmax_groups[4];/*每个类型的组的最大数量.*/uint32_tactions[4];/*支持的OFPAT_*的位图.*/};OFP_ASSERT(sizeof(structofp_group_features)==40);max_groups字段是每个类型的组的最大数量。行动是每个组类型支持的行动。功能使用如下标志的一个组合:/*组配置标志*/enumofp_group_capabilities{OFPGFC_SELECT_WEIGHT=1<<0,/*选择组支持的重量*/OFPGFC_SELECT_LIVENESS=1<<1,/*选择组支持的活跃度*/OFPGFC_CHAINING=1<<2,/*支持链接组*/OFPGFC_CHAINING_CHECKS=1<<3,/*为循环检查和删除链接*/7.3.5.12计量器统计OFPMT_METER统计请求消息给一个或多个计量器提供统计。请求部分由一个meter_id字段组成,它能设置成OFPM_ALL表示交换机上所有计量器。/*OFPMP_METER和OFPMP_METER_CONFIG请求部分*/structofp_meter_multipart_request{uint32_tmeter_id;/*计量器实例,或者是OFPM_ALL.*/uint8_tpad[4];/*排列到bits.*/};OFP_ASSERT(sizeof(structofp_meter_multipart_request)==8);回复部分是如下结构:/*OFPMP_METER请求的回复部分.计量器统计.*/structofp_meter_stats{uint32_tmeter_id;/*计量器例子*/uint16_tlen;/*统计的字节长度.*/uint8_tpad[6];uint32_tflow_count;/*跳至计量器的流数量.*/uint_tpacket_in_count;/*输入数据包的数量.*/uint_tbyte_in_count;/*输入的字节数.*/uint32_tduration_sec;/*计量器已经生成了的秒数.*/uint32_tduration_nsec;/*计量器已经生存超出duration_sec的纳秒数.*/structofp_meter_band_statsband_stats[0];/*band_stats长度是字段长度里推出来的*/};OFP_ASSERT(sizeof(structofp_meter_stats)==40);packet_in_count和byte_in_count对计量器处理过的所有数据包进行计数。duration_sec和duration_nsec字段表示计量器安装在交换机上过去了的时间。总的持续时间可以用duration_sec*10^9+duration_nsec。实现时要求提供第二精度,在能获得的条件下鼓励提供更高的精度。band_stats字段由ofp_meter_band_stats结构组成:/*给每个计量带宽的统计*/structofp_meter_band_stats{uint_tpacket_band_count;/*带内的数据包数量.*/uint_tbyte_band_count;/*带内的字节数量.*/};OFP_ASSERT(sizeof(structofp_meter_band_stats)==16);packet_band_count和byte_band_count对带宽处理的数据包进行计数。带宽统计的顺序必须和OFPMT_METER_CONFIG统计回复里的一样。7.3.5.13计量器配置统计OFPMT_METER_CONFIG统计请求消息给一个或多个计量器提供配置。请求部分由一个meter_id字段组成,它可以被设置成OFPM_ALL表示交换机上所有的计量器。/*OFPMP_METER和OFPMP_METER_CONFIG请求部分.*/structofp_meter_multipart_request{uint32_tmeter_id;/*计量器实例,或者OFPM_ALL.*/uint8_tpad[4];/*对齐到bits.*/};OFP_ASSERT(sizeof(structofp_meter_multipart_request)==8);回复部分由一个如下结构组成:/*OFPMP_METER_CONFIG请求的回复部分.计量器配置*/structofp_meter_config{uint16_tlength;/*流表项的长度.*/uint16_tflags;/*AllOFPMC_*表示申请.*/uint32_tmeter_id;/*计量器实例.*/structofp_meter_band_headerbands[0];/*带宽的长度从字段长度里推导出*/};OFP_ASSERT(sizeof(structofp_meter_config)==8);该字段和用来配置计量器的字段相同(见7.3.4.4)7.3.5.14仪表功能统计OFPMT_METER_FEATRUES统计请求消息提供了计量子系统功能集合。请求部分是空的,和回复部分由以下结构组成:/*回复ofpmp_meter_features请求。计量功能*/structofp_meter_features{uint32_tmax_meter;/*计量器的最大数值.*/uint32_tband_types;/*支持位图ofpmbt_*的值*/uint32_tcapabilities;/*ofp_meter_flags的位图*/uint8_tmax_bands;/*每个计量的的最大频带*/uint8_tmax_color;/*最大的彩色值*/uint8_tpad[2];};OFP_ASSERT(sizeof(structofp_meter_features)==16);7.3.5.15实验者复合实验者特定复合消息通过OFPMP_EXPERIMENTER复合类型进行请求,请求的第一个字节和回复部分结构如下:/*ofp_multipart_request部分/回复OFPMP_EXPERIMENTER.*/structofp_experimenter_multipart_header{uint32_texperimenter;/*实验者标识符,与ofp_experimenter_header中格式相同*/uint32_texp_type;/*实验者定义*//*实验者自定义附加数据*/};OFP_ASSERT(sizeof(structofp_experimenter_multipart_header)==8);剩余的请求和回复部分是由实验者定义experimenter字段是实验者的ID,与OFPMP_EXPERIMENTER中的格式相同。7.3.6队列配置消息队列配置超出了OpenFlow协议范围,可通过一个命令行工具,或通过一个外部的专用配置协议。控制器使用下列结构来查询交换机端口上已配置队列:/*查询端口队列配置*/structofp_queue_get_config_request{structofp_headerheader;uint32_tport;/*查询的端口;应该指向一个有效的物理端口(或OFPP_ANY要求所有配置队列)*/uint8_tpad[4];};OFP_ASSERT(sizeof(structofp_queue_get_config_request)==16);交换机使用OFP_QUEUE_GET_CONFIG_REPLY命令回复,其中包含配置队列的列表。/*给定端口的队列配置*/structofp_queue_get_config_reply{structofp_headerheader;uint32_tport;uint8_tpad[4];structofp_packet_queuequeues[0];/*已配置的队列列表*/};OFP_ASSERT(sizeof(structofp_queue_get_config_reply)==16);7.3.7分组报文当控制器通过数据通路发送一个数据包,就使用OFPT_PACKET_OUT消息:/*发送数据包(控制器->通路)*/structofp_packet_out{structofp_headerheader;uint32_tbuffer_id;/*指定的标识符通过数据通路(OFP_NO_BUFFER如果没有)*/uint32_tin_port;/*分组的输入端口或OFPP_CONTROLLER*/uint16_tactions_len;/*以字节数组的大小的作用*/uint8_tpad[6];structofp_action_headeractions[0];/*行动列表-0或更多*//*可变大小的行动清单可在后面跟着分组数据。*如果buffer_id=-1目前的数据是有意义的。/*uint8_t数据[0];*//*分组数据长度是从长度字段的头部计算的*/};OFP_ASSERT(sizeof(structofp_packet_out)==24buffer_id与ofp_packet_in消息中给出的是相同的。如果buffer_id是OFP_NO_BUFFER,则数据包位于数据阵列中,和封装在消息里的数据包由行动的消息进行处理。OFP_NO_BUFFER等于0xffffffff。如果buffer_id是有效的,相关的端口被行动消息从缓冲区删除。in_port字段表示入端口,端口必须与OpenFlow处理数据包相关。它必须设置为一个有效的标准交换机端口(见4.2)或OFPP_CONTROLLER.例如,当使用OFPP_TABLE,OFPP_IN_PORT,OFPP_ALL和组处理数据包时就使用这个字段。Action是一个行动列表定义交换机如何处理数据包的字段。可包括包修改,组处理和一个输出端口。一个OFPT_PACKET_OUT行动清单消息也可以指定OFPP_TABLE保留端口作为输出行动来处理OpenFlow流水线中的数据包,从第一个流表开始(见4.5)。如果OFPP_TABLE被指定,in_port作为查找时流表的入端口。在某些情况下,发送到OFPP_TABLE的数据包,经过流表项行动或漏表后,可能转发给控制器。对这样控制器到交换机回路的检测和执行行动不在本规范范围内。一般来说,OpenFlow的消息不保证是顺序处理。因此,如果一个使用OFPP_TABLE的OFPP_TABLE消息依赖于最近发送到交换机(与OFPT_FLOW_MOD消息)的流,一个OFPT_BARRIER_REQUEST消息需要在OFPT_PACKET_OUT消息之前,确保在执行OFPP_TABLE之前把流表项交给流表。7.3.8屏障消息当控制器要想确保消息已送到或想接收到通知来完成操作,它可以使用一个OFPT_BARRIER_REQUEST消息。此消息没有内容。收到后,在执行基于BarrierRequest任何消息之前,交换机必须处理完所有先前收到的信息,包括发送相应的回复或错误信息。当处理完成,交换机必须发送一个消息OFPT_BARRIER_REPLY携带XID最初的请求。7.3.9任务请求消息当控制器要转变角色,它使用OFPT_ROLE_REQUEST消息,结构如下:/*请求和回复消息的角色*/structofp_role_request{structofp_headerheader;/*ofpt_role_request/ofpt_role_reply型*/uint32_trole;/*ofpcr_role_*之一*/uint8_tpad[4];/*对齐到位*/uint_tgeneration_id;/*主设备选择产生的标识符*/};OFP_ASSERT(sizeof(structofp_role_request)==24);role字段就是控制器要担任的新角色,并且可以有以下值:/*控制器的角色*/enumofp_controller_role{OFPCR_ROLE_NOCHANGE=0,/*不改变目前的角色*/OFPCR_ROLE_EQUAL=1,/*默认角色,完全访问。*/OFPCR_ROLE_MASTER=2,/*完全访问,最多一个主设备。*/OFPCR_ROLE_SLAVE=3,/*只读访问*/};如果消息中的角色值是OFPCR_ROLE_MASTER或OFPCR_ROLE_SLAVE,交换机必须验证generation_id检查过期消息(见6.3.4)。如果验证失败,交换机必须抛弃角色要求和返回OFPET_ROLE_REQUEST_FAILED类型和OFPRRFC_STALE代码的错误消息。如果角色值是OFPCR_ROLE_MASTER,所有其他角色是OFPCR_ROLE_MASTER的控制器都要改变为OFPCR_ROLE_SLAVE(见6.3.4)。如果角色值是OFPCR_ROLE_NOCHANGE,控制器当前的角色就不改变;这使控制器查询其目前的角色而无需改变它。收到一个OFPT_ROLE_REQUEST的消息后,如果没有错误,交换机必须返回一个OFPT_ROLE_REPLY消息。这则消息的结构与OFPT_ROLE_REQUEST消息是完全一样的,role字段就是当前控制的角色。generation_id设置为当前generation_id(上一次成功角色请求的generation_id,角色是OFPCR_ROLE_MASTER或OFPCR_ROLE_SLAVE),如果目前的generation_id控制器没有设置,回复中的generation_id必须设置为最大字段(无符号值相当于-1)。7.3.10设置异步配置信息在一个给定的OpenFlow通道上,分别使用OFPT_SET_ASYNC和OFPT_GET_ASYNC_REQUEST消息,控制器能设置和查询它想要接收的异步消息(除错误消息)。交换机使用OFPT_GET_ASYNC_REPLY消息响应一个OFPT_GET_ASYNC_REQUEST消息;它不回复一个设置配置的请求。基于OpenFlow头部的OFPT_GET_ASYNC_REQUEST消息没有body。OFPT_SET_ASYNC和OFPT_GET_ASYNC_REPLY消息的格式如下:/*异步消息的配置。*/structofp_async_config{structofp_headerheader;/*OFPT_GET_ASYNC_REPLYorOFPT_SET_ASYNC.*/uint32_tpacket_in_mask[2];/*ofpr_*值的位掩码*/uint32_tport_status_mask[2];/*ofppr_*值的位掩码。*/uint32_tflow_removed_mask[2];/*ofprr_*值的位掩码。.*/};OFP_ASSERT(sizeof(structofp_async_config)==32);结构structofp_async_config包含三个二维数组。每个数组控制是否接收控制器一个特定的枚举ofp_type异步消息。当控制器是OFPCR_ROLE_EQUAL或OFPCR_ROLE_MASTER角色时,每个数组中的元素0表示感兴趣的消息。当控制器是OFPCR_ROLE_SLAVE角色时,元素为1。每个数组元素的位掩码中的0禁止接收与比特位置有关的reason代码消息。而1则可以接收。例如,在port_status_mask[1]中比特值为2 2=4,当控制器的角色是OFPCR_ROLE_SLAVE时,决定控制器是否接收理由是OFPPR_MODIFY(值为2)的OFPT_PORT_STATUS消息。OFPT_SET_ASYNC设置控制器是否应该接受一个交换机产生的异步消息。其他的OpenFlow功能控制是否产生一个给定的消息;例如,在OFPFF_SEND_FLOW_REM标志控制交换机在流表项删除时是否产生OFPT_FLOW_REMOVED消息。。一个交换机的配置,例如使用OpenFlow配置协议,一旦OpenFlow建立连接,就可以设置异步消息的初始配置。交换机没有配置的话,初始配置应:在“master”或“equal”的角色,使能所有的OFPT_PACKET_IN消息,除了那些带有OFPR_INVALID_TTL原因的,使能所有的OFPT_PORT_STATUS和OFPT_FLOW_REMOVED消息。在“slave”角色,使能所有OFPT_PORT_STATUS消息,并禁用所有OFPT_PACKET_IN和OFPT_FLOW_REMOVED的消息。利用OFPT_SET_ASYNC的配置设置是针对一个特定的OpenFlow的通道,它不会影响任何其他OpenFlow通道,无论是目前建立的或是以后建立的。配置设置OFPT_SET_ASYNC不过滤器或影响的错误消息。7.4异步消息7.4.1包输入消息当数据包通过数据通路进行接收和发送给控制器,都使用OFPT_PACKET_IN消息:/*端口接收到的数据包(数据通路->控制器)*/structofp_packet_in{structofp_headerheader;uint32_tbuffer_id;/*分配的数据通路ID。*/uint16_ttotal_len;/*帧全长*/uint8_treason;/*包被发送的原因(一个ofpr_*)*/uint8_ttable_id;/*被查询的流表标识符*/uint_tcookie;/*查询的流表项cookie*/structofp_matchmatch;/*分组元数据。可变尺寸。*//*可变大小和填充匹配总是跟着:*2个全零填充字节,然后是以太网帧,其长度是根据header.length推断。*以太网帧前填充的字节,确保以太网报头后的IP头部(如果有的话)是32位*///uint8_tpad[2];/*对齐位+16位*///uint8_tdata[0];/*以太网帧*/};OFP_ASSERT(sizeof(structofp_packet_in)==32);buffer_id是个不透明的值,数据通路使用它识别一个缓冲数据包。当一个数据包进行缓存,消息的某些字节将包含在消息的数据部分。如果数据包是因为“发送给控制器”的行动而发送,那么流建立请求的ofp_action_output会发送max_len字节。如果数据包其他原因发送,如无效的TTL,然后OFPT_SET_CONFIG消息至少发送miss_send_len字节。默认miss_send_len是128字节。如果数据包没有缓冲-要么是因为没有可用的缓冲区,或因明确表示通过OFPCML_NO_BUFFER请求-整个数据包都包含在数据部分,而且buffer_id就是OFP_NO_BUFFER。 实现缓冲的交换机希望通过文档公开,可用的缓冲数量和缓冲区可重复使用前的时间长度。交换机必须妥善处理这样的事件,当一个packet_in消息缓冲,而控制器没有反应的情况。交换机应防止缓冲区被重复使用,直到它已由控制器处理,或经过一段时间(文档中说明)。data字段包含的数据包本身,或缓冲包的一小部分。包头部反映了前面处理对数据包的任何变化。reason字段可以是这些值的某个:/*为什么这个包被发送到控制器?*/enumofp_packet_in_reason{OFPR_NO_MATCH=0,/*没有匹配的流(漏表流表项)*/OFPR_ACTION=1,/*输出给控制器的行动。*/OFPR_INVALID_TTL=2,/*包有无效的TTL*/};OFPR_INVALID_TTL表明携带无效的IPTTL或MPLSTTL被OpenFlow流水线拒绝并传给控制器。不需要对每一个数据包都进行无效的TTL检查,但它至少在每次OFPAT_DEC_MPLS_TTL或OFPAT_DEC_NW_TTL行动应用到一个包时进行检查。cookie字段包含导致包被发送到控制器的流表项cookie。如果一个cookie不能与一个特定的流有关的,这字段必须设置为-1(0xffffffffffffffff)。例如,如果包输入是在组存储段里或从行动集产生的。当有事件触发包输入消息发生,同时包含一组OXMTLVs,match字段就反映分组的头部和上下午。这个上下文包括与数据包以前处理发生的任何改变,包括已经执行的行动,行动集的任何变化,除了无任何变化的。这OXMTLVs必须包括上下文字段,也就是,其值不能从数据包确定的字段。标准的上下文字段是OFPXMT_OFB_IN_PORT,OFPXMT_OFB_IN_PHY_PORT,OFPXMT_OFB_METADATA和OFPXMT_OFB_TUNNEL_ID.所有位都是零的字段应忽略。OXMTLVs可包括先前从分组中提取的数据包头部字段,也包括那些在处理过程中的任何修改。当在物理端口直接收到一个包时,而且未被逻辑端口处理,OFPXMT_OFB_IN_PORT和OFPXMT_OFB_IN_PHY_PORT有相同的值,OpenFlow物理端口的portno。OFPXMT_OFB_IN_PHY_PORT如果与OFPXMT_OFB_IN_PORT有相同的值则应忽略。当一个包是通过一个物理端口的逻辑端口上接收的,OFPXMT_OFB_IN_PORT是逻辑端口的端口的portno,OFPXMT_OFB_IN_PHY_PORT是物理端口的portno。例如,考虑一个包在隧道接口上接收,接口是由两个物理端口的链路汇聚组(LAG)进行定义的。如果隧道接口是绑定到OpenFlow的逻辑端口,那么OFPXMT_OFB_IN_PORT是隧道portno,OFPXMT_OFB_IN_PHY_PORT是已配置隧道的LAG物理端口portno成员。OFPXMT_OFB_IN_PORTTLV引用的端口必须是用来匹配流表项的端口(见5.3),也必须对OpenFlow处理有用(即OpenFlow可以转发数据包到该端口,依靠端口标志)。OFPXMT_OFB_IN_PHY_PORT不需要有效匹配或进行OpenFlow处理。7.4.2流删除消息如果控制器请求通知流表项超时或从表中删除(见5.5),数据通路使用OFPT_FLOW_REMOVED消息:/*流删除(数据通路->控制器)*/structofp_flow_removed{structofp_headerheader;uint_tcookie;/*不透明的控制器发出标识符。*/uint16_tpriority;/*流表项优先级。*/uint8_treason;/*一个ofprr_*uint8_ttable_id;/*流表的标识符*/uint32_tduration_sec;/*Timeflowwasaliveinseconds.*/uint32_tduration_nsec;/*Timeflowwasaliveinnanosecondsbeyondduration_sec.*/uint16_tidle_timeout;/*从原来的flowmod空闲超时*/uint16_thard_timeout;/*从原来的flowmod硬超时。*/uint_tpacket_count;uint_tbyte_count;structofp_matchmatch;/*字段描述。可变尺寸。*/};OFP_ASSERT(sizeof(structofp_flow_removed)==56);Match,cookie,和priority字段与那些在flowmod请求里使用的相同。Reason字段是下列之一:/*为什么流中删除?*/enumofp_flow_removed_reason{OFPRR_IDLE_TIMEOUT=0,/*流idle_timeout空闲时间超过*/OFPRR_HARD_TIMEOUT=1,/*时间超过hard_timeout。*/OFPRR_DELETE=2,/*由DELETEflowmod消除。*/OFPRR_GROUP_DELETE=3,/*删除的组。*/};duration_sec和duration_nsec字段在第7.3.5.2描述。idle_timeout和hard_timeout字段是直接从创建流表项的flowmod复制。利用上述三个字段,你可以找到流表项活跃的时间,以及流表项接收信息的时间。packet_count和byte_count分别表示与流表项相关联的包和字节的数值。这些计数器应像其他统计计数器(见7.3.5);如果没有设置,它们都是无符号的,并应设置为字段最大值。7.4.3端口的状态信息当端口被添加,修改,从数据通路中删除,利用OFPT_PORT_STATUS消息告知控制器:/*数据通路的一个物理端口改变*/structofp_port_status{structofp_headerheader;uint8_treason;/*一个ofppr_*/uint8_tpad[7];/*对齐到位。*/structofp_portdesc;};OFP_ASSERT(sizeof(structofp_port_status)==80);reason可以是下列值之一:/*是什么改变了关于物理端口*/enumofp_port_reason{OFPPR_ADD=0,/*端口添加。*/OFPPR_DELETE=1,/*端口被删除*/OFPPR_MODIFY=2,/*某些端口的属性已经改变了。*/};7.4.4错误消息交换机需要把问题通知给控制器。这是通过OFPT_ERROR_MSG消息完成:/*ofpt_error:错误消息(数据通路->控制器)。*/structofp_error_msg{structofp_headerheader;uint16_ttype;uint16_tcode;uint8_tdata[0];/*可变长度的数据。用类型和代码区分。无填充*/};OFP_ASSERT(sizeof(structofp_error_msg)==12);Type的值表示错误的高层次的类型。代码值是在类型基础上解析。数据是可变长度的并且基于类型和代码解析。除非另有规定data字段包含至少字节的失败请求,导致错误消息产生,如果失败请求小于字节,它应该是完整的请求而无填充。如果错误消息是来自控制器的响应,例如,OFPET_BAD_REQUEST, OFPET_BAD_ACTION,OFPET_BAD_INSTRUCTION,OFPET_BAD_MATCH,或OFPET_FLOW_MOD_FAILED,那么头部的xid字段必须匹配那个引起错误的消息。以_EPERM结束的错误代码表示一个允许产生的错误,例如,控制器和交换机之间插入一个OpenFlow管理程序。目前定义的错误类型是:/*ofp_error_message里的“type”值。这些值是不变的:他们不会在未来版本的协议改变(虽然新值可以添加)。*/enumofp_error_type{OFPET_HELLO_FAILED=0,/*hello协议失败*/OFPET_BAD_REQUEST=1,/*请求不被理解*/OFPET_BAD_ACTION=2,/*在行动中描述的错误。*/OFPET_BAD_INSTRUCTION=3,/*指令表中错误。*/OFPET_BAD_MATCH=4,/*错误匹配。*/OFPET_FLOW_MOD_FAILED=5,/*修改流表项问题。*/OFPET_GROUP_MOD_FAILED=6,/*修改组表项问题。*/OFPET_PORT_MOD_FAILED=7,/*端口属性请求失败。*/OFPET_TABLE_MOD_FAILED=8,/*流表请求失败*/OFPET_QUEUE_OP_FAILED=9,/*队列操作失败*/OFPET_SWITCH_CONFIG_FAILED=10,/*交换机配置请求失败*/OFPET_ROLE_REQUEST_FAILED=11,/*控制器任务请求失败*/OFPET_METER_MOD_FAILED=12,/*计量器错误*/OFPET_TABLE_FEATURES_FAILED=13,/*设置流表功能失败*/OFPET_EXPERIMENTER=0xffff/*实验者的错误消息*/};为OFPET_HELLO_FAILED错误type,下面是目前定义的codes:/*为OFPET_HELLO_FAILEDofp_error_msg“code”的值。Data包含ASCII文本字符串,可以提供详细的故障。*/enumofp_hello_failed_code{OFPHFC_INCOMPATIBLE=0,/*不兼容的版本*/OFPHFC_EPERM=1,/*允许失败*/};Data字段包含ASCII文本字符串,加上为什么发生错误的细节。为OFPET_BAD_REQUEST错误type,下面是目前定义的code:/*为OFPET_BAD_REQUESTofp_error_msg“code”的值。Data至少包含请求失败的第一个字节。*/enumofp_bad_request_code{OFPBRC_BAD_VERSION=0,/*ofp_header.版本不支持。*/OFPBRC_BAD_TYPE=1,/*ofp_header.type不支持的类型*/OFPBRC_BAD_MULTIPART=2,/*ofp_multipart_request.type类型不支持*/OFPBRC_BAD_EXPERIMENTER=3,/*不支持的实验者身份ID(在ofp_experimenter_header或ofp_multipart_request或ofp_multipart_reply)。*/OFPBRC_BAD_EXP_TYPE=4,/*实验者类型不支持。*/OFPBRC_EPERM=5,/*允许误差*/OFPBRC_BAD_LEN=6,/*类型错误的请求长度。*/OFPBRC_BUFFER_EMPTY=7,/*已被使用的指定缓冲区。*/OFPBRC_BUFFER_UNKNOWN=8,/*指定的缓冲区不存在。*/OFPBRC_BAD_TABLE_ID=9,/*指定的表标识符无效或不存在。*/OFPBRC_IS_SLAVE=10,/*拒绝因为控制器是从设备*/OFPBRC_BAD_PORT=11,/*无效的端口*/OFPBRC_BAD_PACKET=12,/*包输出里无效的数据包*/OFPBRC_MULTIPART_BUFFER_OVERFLOW=13,/*ofp_multipart_request分配的缓冲区溢出*/下面是目前定义OFPET_BAD_ACTION错误type的code:/*OFPET_BAD_INSTRUCTIONofp_error_msg'code'的值。数据至少包含请求失败的第一个字节*/enumofp_bad_action_code{OFPBAC_BAD_TYPE=0,/*未知的行动类型。*/OFPBAC_BAD_LEN=1,/*行动的长度问题。*/OFPBAC_BAD_EXPERIMENTER=2,/*未知的实验者指定标识符*/OFPBAC_BAD_EXP_TYPE=3,/*实验者的标识符。未知的行动*/OFPBAC_BAD_OUT_PORT=4,/*问题有效输出端口。*/OFPBAC_BAD_ARGUMENT=5,/*不良行为的论证*/OFPBAC_EPERM=6,/*允许的错误*/OFPBAC_TOO_MANY=7,/*不能处理这么多的行动。*/OFPBAC_BAD_QUEUE=8,/*问题验证输出队列。*/OFPBAC_BAD_OUT_GROUP=9,/*在转发的动作无效组标识符*/OFPBAC_MATCH_INCONSISTENT=10,/*行动不能申请匹配,或设置字段丢失的前提。*/OFPBAC_UNSUPPORTED_ORDER=11,/*应用行动指令的行动列表不支持行动排序*/OFPBAC_BAD_TAG=12,/*行动使用不支持的标签/封装。*/OFPBAC_BAD_SET_TYPE=13,/*在set_field行动不支持的类型。*/OFPBAC_BAD_SET_LEN=14,/*在set_field行动长度问题。*/OFPBAC_BAD_SET_ARGUMENT=15,/*在set_field行动不好的论据*/};下面是目前定义为OFPET_BAD_INSTRUCTION错误type的code:/*为OFPET_BAD_INSTRUCTIONofp_error_msg“code”的值。数据至少包含请求失败的第一个字节。*/enumofp_bad_instruction_code{OFPBIC_UNKNOWN_INST=0,/*未知的指令*/OFPBIC_UNSUP_INST=1,/*交换机或表不支持的指令。*/OFPBIC_BAD_TABLE_ID=2,/*指定流表标识符无效。*/OFPBIC_UNSUP_METADATA=3,/*元数据值不支持的数据通路。*/OFPBIC_UNSUP_METADATA_MASK=4,/*元数据的掩码值不支持的数据通路。*/OFPBIC_BAD_EXPERIMENTER=5,/*未知的实验者指定标识符。*/OFPBIC_BAD_EXP_TYPE=6,/*实验者未知指令标识符。*/OFPBIC_BAD_LEN=7,/*在指令长度的问题。*/OFPBIC_EPERM=8,/*允许的错误。*/};为OFPET_BAD_MATCH错误type,下面是目前定义的code:/*为OFPET_BAD_MATCHofp_error_msg“code”的值。数据至少包含请求失败的第一个字节。*/enumofp_bad_match_code{OFPBMC_BAD_TYPE=0,/*不支持匹配指定的匹配类型*/OFPBMC_BAD_LEN=1,/*匹配长度问题*/OFPBMC_BAD_TAG=2,/*匹配采用不支持的标签/封装。*/OFPBMC_BAD_DL_ADDR_MASK=3,/*不支持的数据地址掩码–交换机不支持任意链路地址掩码。*/OFPBMC_BAD_NW_ADDR_MASK=4,/*不支持的网络地址掩码–交换机不支持任意网络地址掩码。*/OFPBMC_BAD_WILDCARDS=5,/*不支持的域掩蔽或在匹配中省略的组合*/OFPBMC_BAD_FIELD=6,/*在匹配中不支持的字段类型。*/OFPBMC_BAD_VALUE=7,/*在匹配域不受支持的值。*/OFPBMC_BAD_MASK=8,/*不支持匹配中指定的掩码,字段不是dl_address或nw_address。*/OFPBMC_BAD_PREREQ=9,/*一个先决条件不满足。*/OFPBMC_DUP_FIELD=10,/*一种字段类型是重复的。*/OFPBMC_EPERM=11,/*允许的错误。*/};FortheOFPET_FLOW_MOD_FAILEDerrortype,thefollowingcodesarecurrentlyde_ned:对于OFPET_TABLE_MOD_FAILED错误type,下面是目前定义的代码:/*对于OFPET_TABLE_MOD_FAILED的ofp_error_msg“code”的值。”data至少包含请求失败第一个字节的。*/enumofp_flow_mod_failed_code{OFPFMFC_UNKNOWN=0,/*未指定的错误*/OFPFMFC_TABLE_FULL=1,/*因为表已满,流不能添加。*/OFPFMFC_BAD_TABLE_ID=2,/*流表不存在*/OFPFMFC_OVERLAP=3,/*使用check_overlap标志尝试添加重叠的流*/OFPFMFC_EPERM=4,/*允许的错误。*/OFPFMFC_BAD_TIMEOUT=5,/*因为不支持空闲/硬超时,流表不被添加。*/OFPFMFC_BAD_COMMAND=6,/*不支持的或未知的命令。*/OFPFMFC_BAD_FLAGS=7,/*不支持的或未知的标志。*/};对于OFPET_SWITCH_CONFIG_FAILED错误type,下面是目前定义的code:/*为OFPET_SWITCH_CONFIG_FAILED的ofp_error_msg“code”的值。”data至少包含请求失败第一个字节的*/enumofp_group_mod_failed_code{OFPGMFC_GROUP_EXISTS=0,/*组不添加因为组添加试图取代一个已经存在的组*/OFPGMFC_INVALID_GROUP=1,/*组不能添加因为组指定的组是无效的*/OFPGMFC_WEIGHT_UNSUPPORTED=2,/*交换机在所选组中不支持不均等的负荷分担*/OFPGMFC_OUT_OF_GROUPS=3,/*组表已满。*/OFPGMFC_OUT_OF_BUCKETS=4,/*组的行动存储段已超过最大值。*/OFPGMFC_CHAINING_UNSUPPORTED=5,/*交换机不支持需要转发去的组*/OFPGMFC_WATCH_UNSUPPORTED=6,/*这个组不能监视w指定的atch_port或watch_group。*/OFPGMFC_LOOP=7,/*组表项会引起循环*/OFPGMFC_UNKNOWN_GROUP=8,/*组不能修改,因为修改组试图修改一个不存在的组*/OFPGMFC_CHAINED_GROUP=9,/*组不能删除因为另一组是向其转发。*/OFPGMFC_BAD_TYPE=10,/*不支持的或未知的组类型*/OFPGMFC_BAD_COMMAND=11,/*不支持的或未知的命令。*/OFPGMFC_BAD_BUCKET=12,/*存储段里的错误*/OFPGMFC_BAD_WATCH=13,/*在观察端口/组的错误。*/OFPGMFC_EPERM=14,/*允许的错误。*/};下面是目前定义为OFPET_PORT_MOD_FAILED错误type的代码:/*OFPET_METER_MOD_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_port_mod_failed_code{OFPPMFC_BAD_PORT=0,/*指定的端口号不存在*/OFPPMFC_BAD_HW_ADDR=1,/*指定的硬件地址不匹配端口号*/OFPPMFC_BAD_CONFIG=2,/*指定的配置无效*/OFPPMFC_BAD_ADVERTISE=3,/*指定的标识符是无效的。*/OFPPMFC_EPERM=4,/*允许的错误.*/};下面是目前定义为OFPET_METER_MOD_FAILED错误type的code:/*OFPET_METER_MOD_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_table_mod_failed_code{OFPTMFC_BAD_TABLE=0,/*指定的流表不存在*/OFPTMFC_BAD_CONFIG=1,/*指定的配置无效*/OFPTMFC_EPERM=2,/*允许的错误*/};下面是目前定义为OFPET_TABLE_MOD_FAILED错误type的code:/*OFPET_TABLE_MOD_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_queue_op_failed_code{OFPQOFC_BAD_PORT=0,/*无效的端口(或端口不存在)*/OFPQOFC_BAD_QUEUE=1,/*队列不存在*/OFPQOFC_EPERM=2,/*允许的错误*/};下面是目前定义为OFPET_SWITCH_CONFIG_FAILED错误type的code:/*OFPET_SWITCH_CONFIG_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_switch_config_failed_code{OFPSCFC_BAD_FLAGS=0,/*指定的标志无效*/OFPSCFC_BAD_LEN=1,/*指定的长度无效*/OFPSCFC_EPERM=2,/*允许的错误*/};下面是目前定义为OFPET_ROLE_REQUEST_FAILED错误type的code:/*对于OFPET_ROLE_REQUEST_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_role_request_failed_code{OFPRRFC_STALE=0,/*过时消息:旧的generation_id.*/OFPRRFC_UNSUP=1,/*控制器不支持角色的变化*/OFPRRFC_BAD_ROLE=2,/*无效的角色*/};下面是目前定义为OFPET_METER_MOD_FAILED错误type的code:/*对于OFPET_METER_MOD_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_meter_mod_failed_code{OFPMMFC_UNKNOWN=0,/*未指定的错误.*/OFPMMFC_METER_EXISTS=1,/*计量器不加因为试图取代现有的计量器*/OFPMMFC_INVALID_METER=2,/*计量器不加因为指定的计量器是无效的*/OFPMMFC_UNKNOWN_METER=3,/*计量器不修改因为试图修改一个不存在的计量器*/OFPMMFC_BAD_COMMAND=4,/*不支持的或未知的命令*/OFPMMFC_BAD_FLAGS=5,/*配置的标志不支持*/OFPMMFC_BAD_RATE=6,/*速率不支持*/OFPMMFC_BAD_BURST=7,/*不支持的突发大小.*/OFPMMFC_BAD_BAND=8,/*频带不支持*/OFPMMFC_BAD_BAND_VALUE=9,/*频带值不被支持*/OFPMMFC_OUT_OF_METERS=10,/*没有更多的计量器有效*/OFPMMFC_OUT_OF_BANDS=11,/*对于计量器的属性数量已超过最大值.*/};下面是目前定义为OFPET_TABLE_FEATURES_FAILED错误type的codes:/*对于OFPET_TABLE_FEATURES_FAILED的ofp_error_msg“code”的值。Data至少包含请求失败的第一个字节*/enumofp_table_features_failed_code{OFPTFFC_BAD_TABLE=0,/*指定的流表不存在*/OFPTFFC_BAD_METADATA=1,/*无效的元数据的掩码*/OFPTFFC_BAD_TYPE=2,/*未知的属性类型.*/OFPTFFC_BAD_LEN=3,/*属性长度问题*/OFPTFFC_BAD_ARGUMENT=4,/*不支持的属性值*/OFPTFFC_EPERM=5,/*允许的错误*/};对于为OFPET_EXPERIMENTER错误type,错误信息由以下结构体和字段定义,后面跟着实验者定义的数据:/*OFPET_EXPERIMENTER:错误消息(数据通路->控制器)*/structofp_error_experimenter_msg{structofp_headerheader;uint16_ttype;/*ofpet_experimenter*/uint16_texp_type;/*实验者定义*/uint32_texperimenter;/实验者ID与ofp_experimenter_header中相同*/uint8_tdata[0];/*可变长度的数据。基于类型和代码解析。无填充*/};OFP_ASSERT(sizeof(structofp_error_experimenter_msg)==16);实验者字段是实验者ID,与ofp_experimenter结构体中的相同(见7.5.4)。7.5对称信息7.5.1HelloOFPT_HELLO消息由一OpenFlow头加一组可变尺寸hello元素。/*OFPT_HELLO.此消息包含零个或多个可变尺寸的元素。未知的元素类型必须忽略/跳过,允许未来的扩展*/structofp_hello{structofp_headerheader;/*hello元素列表*/structofp_hello_elem_headerelements[0];/*元素列表,0或更多*/};OFP_ASSERT(sizeof(structofp_hello)==8);Header字段中的version字段(见7.1)必须设置为发送者(见6.3.1)支持的最高OpenFlow协议版本。Elemnets字段是一组hello元素,包含连接进行初次握手时传递的可选数据。实现时必须忽略(跳过)Hello消息中不支持的所有元素。列表中的元素类型定义如下:/*Hello元素类型*/enumofp_hello_elem_type{OFPHET_VERSIONBITMAP=1,/*支持的版本位图*/};元素定义包含元素的类型,长度,和任何相关的数据:/*所有hello元素共同的头*/structofp_hello_elem_header{uint16_ttype;/*OFPHET_*之一*/uint16_tlength;/*在本单元的字节长度*/};OFP_ASSERT(sizeof(structofp_hello_elem_header)==4);OFPHET_VERSIONBITMAP元素使用下列结构和字段: /*hello元素的版本位图*/structofp_hello_elem_versionbitmap{uint16_ttype;/*OFPHET_VERSIONBITMAP.*/uint16_tlength;/*在本元素的字节长度*//*其次是:包含位图的(长度-4)字节,然后(长度+7)/8×8-(长度)(0~7)的全零字节*/uint32_tbitmaps[0];/*位图列表-支持的版本*/};OFP_ASSERT(sizeof(structofp_hello_elem_versionbitmap)==4);Bitmaps字段表示设备支持的OpenFlow交换协议版本,可在版本协商后使用(见6.3.1)。对位图的比特通过协议的ofp_version数索引;如果左位移数值表示的比特等于设置的ofp_version,就支持这个OpenFlow版本。字段中包含的位图数值取决于支持的最高版本号:ofp_version0-31在第一个位图中编码,ofp_version32-63在第二个位图中编码,以此类推。例如,如果一个交换机只支持1.0版(ofp_version=0x01)和1.3版(ofp_version=0x04),第一个位图将被设置为0x00000012。7.5.2回送请求回送请求消息包括一个OpenFlow头加一个任意长度的数据字段。数据字段可能是一个消息的时间戳来检查延迟,不同长度来测量带宽,或零大小来验证交换机和控制器之间是否活跃。7.5.3回送答复回送应答消息包括一个OpenFlow头加上回声请求消息中未修改的数据字段。一个OpenFlow协议在实现时划分成多个层,回声请求/应答的逻辑应该在“最深”的开发层实现。例如,在OpenFlow的实现里,用户空间进程靠近内核模块,回声请求/应答是则在内核模块实现。接收一个格式正确的回应则表示端到端功能比在用户空间的进程中实现的回声请求/应答更可靠,同时也提供了更精确的端到端延迟时间。7.5.4实验者实验者消息的定义如下:/*实验者的扩展*/structofp_experimenter_header{structofp_headerheader;/*ofpt_experimenter*/uint32_texperimenter;/*实验者标识符*MSB0:低位字节由IEEEOUI定义。*MSB!=0:ONF定义的*/uint32_texp_type;/*实验者定义*//*实验者定义任意附加数据*/};OFP_ASSERT(sizeof(structofp_experimenter_header)==16);Experimenter的字段是一个32位的值,唯一标识实验者。如果最高位字节是零,接下来的三个字节是实验者的IEEEOUI。如果最高位字节不为零,这是一个ONF分配的值。如果实验者没有(或希望使用)他们的OUI,他们应该与ONF联系获得一个唯一的实验者标识符。标准的OpenFlow处理对其余部分不进行解析,可由实验者任意定义。如果一个交换机不理解实验者的扩充,它必须发送一个带有OFPBRC_BAD_EXPERIMENTER错误代码和OFPET_BAD_REQUEST错误类型的OFPT_ERROR消息。 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务