路由模式指的是Service Chain节点本身具备三层转发功能,其与交换设备之间互联通道需要配置IP地址,交换设备发送报文到这些节点是通过三层路由的方式到达,报文在这些节点返回交换设备时也是通过三层路由的方式到达。
以下图作为路由模式下的引流模型来进行阐述:
为案例覆盖方便,设定P1、P5属于SVI下的两个成员口,P4属于路由口。
P2、P3属于路由口分别与对应的FW或者WAF互联。
交换机其他任意口与控制器互联(三层可达即可),用于传递配置命令和OpenFlow流表。
FW/WAF完成IP和其对应网关配置后会向Switch请求对应ARP信息,这时的ARP请求由Switch进行应答,这个过程和传统流程一致。
由于控制器后续下发的Service Chain流表需要用到FW/WAF节点的MAC地址,因此控制器需要获取FW/WAF的ARP信息。但是如果如无特殊表项设置的话,FW/WAF的ARP应答会被Switch本身的ARP模块拦截,因此控制器需要预先设置一条OpenFlow流表,该流表包含如下内容(以上述的例子为例):
Match | Action | ||
FW | Flow1 | In_Port == P2 && Ether_Type == ARP_Reply | Output_Port = Controller |
Flow2 | In_Port == P3 && Ether_Type == ARP_Reply | Output_Port = Controller |
Switch端在收到这些流表之后,通过Switch端的OpenFlow PI模块将这些流表最终设置到交换芯片上(到芯片上的流表转义成送cpu的行为,由OpenFlow PI模块劫走这个ARP Reply报文,并转换成OpenFlow Packet_in报文上送控制器)。
Controller完成流表下发后,通过OpenFlow Packet_out消息将FW/WAF的ARP Request报文发送给Switch,Switch的OpenFlow PI模块将OpenFlow Packet_out报文中的ARP请求解析出来并通过Switch发送到FW/WAF上,当FW/WAF应答ARP Reply后,该报文会被之前设置的表项送到Switch端的CPU继而通过OpenFlow PI模块最终发送到控制器上,从而控制器完成FW/WAF的ARP学习。
ARP请求的流表如下:
{table="0", duration_sec="10929", priority="5100", flags ="0x0",idle_timeout="0", hard_timeout="0", cookie="0xe516189520000", packet_count="0", byte_count="0". match=oxm{in_port="2", eth_type="0x806"} instructions=[apply{acts=[output{port="controller", max_len="65535"}]}]} |
1) in_port=“2”:这里的端口指的是“引流口”和“回流口”,即与安全设备互联的接口
2) eth_type=“0x806“:0x806代表ARP报文,这里只需要匹配ARP报文即可。
3) output{port=“controller”:将arp送控制器一份,这样控制器下发引流的流表时,才可以修改流表中的源目MAC,然后交换机转发数据时,就根据流表中的源目MAC去修改报文。
4) 其他字段说明参见透明模式的流表解析
设定存在一条从P1输入的流需要三层转发到P4接口。(注意:Service Chain不会改变原有数据流在Switch上的出口,只是将该数据流流经Switch时的过程路径做了改变。)
在控制器上构建服务链使得最终P1àP4的数据流经过如下路径:
当构建出这条Service Chain后,控制器会下发如下4条流:
流量方向 | Match | Action | |
去流 | Flow1 | In_Port == P1 && 用户定义的特征流 | Output_Port = P2&& SET_SMAC = Switch_MAC && SET_DMAC = FW_MAC |
Flow2 | In_Port == P3 && 用户定义的特征流 | Output_Port=Normal | |
回流 | Flow3 | In_Port == P4 && 用户定义的特征流 | Output_Port = P3&& SET_SMAC = Switch_MAC && SET_DMAC = FW_MAC |
Flow4 | In_Port == P2 && 用户定义的特征流 | Output_Port=Normal |
同样通过Switch端的OpenFlow PI模块经由交换适配层将这两条流表最终设置到交换芯片上(对应的VLAN信息由交换适配层根据P2的vlan自行添加上,控制器不感知P2路由口的vlan信息)。
此时设备端的行为如下:
报文转发(流表生成4个流条目)
1) P1口收到报文(A->B),根据流表(引流,修改目标MAC),从P2口发出(B->C1);
2) P3口收到报文(C2->B),根据流表(传统转发),从P4口发出(B->D);
3) P4口收到报文(D->B),根据流表(引流,修改目标MAC),从P3口发出(B->C2);
4) P2口收到报文(C1->B),根据流表(传统转发),从P1口发出(B->A)。
从而就实现了指定数据流按如下方式转发的行为,这也就是服务链的一个基本过程:
引流流表如下(flow1):
{table="0", duration_sec="177", priority="1500", flags ="0x0",idle_timeout="0", hard_timeout="0", cookie="0xe51efb3520000", packet_count="0", byte_count="0". match=oxm{in_port="1", eth_type="0x800", ipv4_dst=“30.7.0.0", ipv4_dst_mask="255.255.255.0"} instructions=[apply{acts=[set_field{field:eth_src= “00:d0:f8:22:33:e5"},set_field{field:eth_dst=" 00:d0:f8:22:33:d9 "}, output{port="3"}]}]} |
主要字段说明:
1) in_port=“1”:这里指的是数据进SDN交换机的接口
2) set_field{field:eth_src=“00:d0:f8:22:33:e5 "}, set_field{field:eth_dst=" 00:d0:f8:22:33:d9 "}:如果匹配到了报文,则将报文源MAC修改为00:d0:f8:22:33:e5 ,目的MAC修改为00:d0:f8:22:33:d9
3) 其他字段说明参见透明模式的流表解析
如果特征流本身是二层转发行为,则目前的Service Chain方案不支持这种类型的流在路由模式下转发,具体参考下文分析。
在推导的过程可以先以能够支撑这种二层流进入Service Chain来描述,看在哪个环节会出现与现有转发逻辑相违背的地方,从而得出不支持的结论。前文设定P1和P5端口是同属于一个SVI口下的两个物理端口,因此这两个端口同属于一个VLAN,它们之间的转发行为归属于二层转发行为,为了与三层转发有个明显的对比,我们设定转发数据流如下:
同样从控制器上设定如下表项:
流量方向 | Match | Action | |
去流 | Flow1 | In_Port == P1 && 用户定义的特征流 | Output_Port = P2&& SET_SMAC = Switch_MAC && SET_DMAC = FW_MAC |
Flow2 | In_Port == P3 && 用户定义的特征流 | Output_Port=Normal | |
回流 | Flow3 | In_Port == P5 && 用户定义的特征流 | Output_Port = P3&& SET_SMAC = Switch_MAC && SET_DMAC = FW_MAC |
Flow4 | In_Port == P2 && 用户定义的特征流 | Output_Port=Normal |
同样通过Switch端的OpenFlow PI模块经由交换适配层将这两条流表最终设置到交换芯片上(对应的VLAN信息由交换适配层根据P3、P5的vlan自行添加上,控制器不感知P3、P5路由口的vlan信息)。
此时设备端的行为如下:
报文转发MAC A访问MAC E:
1) P1口收到报文(A->B),根据流表(引流,修改目标MAC),从P2口发出(B->C1);
2) P3口收到报文(C2->B),根据流表(传统转发),从P5口发出(B->D);——该过程无法实现,P3收到报文的目的MAC已经不是E,数据将丢失。
3) P4口收到报文(D->B),根据流表(引流,修改目标MAC),从P3口发出(B->C2);
4) P2口收到报文(C1->B),根据流表(传统转发),从P1口发出(B->A);——该过程无法实现,P2收到报文的目的MAC已经不是A,数据将丢失。
从上文可见,二层流一旦被Service Chain捕获,则会导致最终的断流,对于用户来说这是一个故障。因此在路由模式下发对应的Service Chain流表时,都必须在交换适配层为对应的流表加上MyMAC_hit/L3_Route_hit等类似的标志位,目的是仅让触发了三层转发行为的报文才能进入Service Chain流表,避免用户误配置后导致转发不通的问题。