0x00 目录

0x01 流表项操作与Flow_Mod消息

在OpenFlow中,对流表项的操作,例如增加、修改、删除流表项,都是通过控制器下发Flow_Mod消息完成的。Flow_Mod消息的格式如图所示,其中command字段定义了对流表项的操作(增加、修改、删除),而对于修改和删除操作又分为NON_STRICT和STRICT两个版本。

Flow_Mod消息格式

Flow_Mod消息command字段

0x02 流表项删除DELETE与DELETE_STRICT区别

要想删除流表项,只需要构造command = DELETE或command = DELETE_STRICT的Flow_Mod消息即可,两者的区别如下:

  • DELETE:根据匹配域,删除所有匹配的流表项,意味着可能有多条流表项被删除
  • DELETE_STRICT:根据匹配域以及优先级,删除特定的流表项,只有一条流表项被删除

例子:假设使用openflow1.0,且openflow交换机流表中只有以下两条流表项

flow entry1:
{
   prioirity : 42
   match :
   {
      dl_type : 0x0800
      ip_src : 10.0.0.1
      ip_dst : 10.0.0.2
   }
   actions : output : 'sw1-eth2'
}

flow entry2:
{
   prioirity : 42
   match :
   {
      dl_type : 0x0800
      ip_src : 10.0.0.1
      ip_dst : 10.0.0.2
      ip_protocol : 6
      tp_dst : 80
   }
   actions : output : 'sw1-eth2'
}
  • 若控制器下发command = DELETE的Flow_Mod消息

    flow_mod msg:
    {
     command : DELETE
     prioirity : 42
     match :
     {
        dl_type : 0x0800
        ip_src : 10.0.0.1
        ip_dst : 10.0.0.2
     }
     actions : output : 'sw1-eth2'
    }

    那么openflow交换机将会根据Flow_Mod消息中的匹配域(match)去流表中查找所有匹配的流表项(若流表项中的匹配域描述比Flow_Mod消息中的匹配域更详细,也算查找成功),这里flow entry1和flow entry2都满足,因为它们都含有

    match :
    {
     dl_type : 0x0800
     ip_src : 10.0.0.1
     ip_dst : 10.0.0.2
    }

    因此,两条流表项都会被删除

  • 若控制器下发command = DELETE_STRICT的Flow_Mod消息

flow_mod msg:
{
   command : DELETE_STRICT
   prioirity : 42
   match :
   {
      dl_type : 0x0800
      ip_src : 10.0.0.1
      ip_dst : 10.0.0.2
   }
   actions : output : 'sw1-eth2'
}

openflow交换机会根据Flow_Mod消息中的匹配域(match)和优先级(prioirity)去流表中查找特定的流表项,这里只有flow entry1满足条件,因为flow entry2的匹配域多了两个字段

ip_protocol : 6
tp_dst : 80

因此只有flow entry1被删除

0x03 POX + Mininet实验验证

按照0x02中提到的例子,使用POX和Mininet进行验证

实验环境

- OpenFlow 1.0 : SDN控制器与openflow交换机之间通信的协议
- POX-eel : python实现的SDN控制器,用于构造Flow_Mod消息,并下发至openflow交换机
- Mininet 2.3.0d1 : 创建" h1 -- sw1 -- h2 "拓扑
- POX与Mininet均部署在同一台运行ubuntu 18.04 LTS的机器上

实验步骤

1.启动POX

打开终端,输入

home/ctz/pox-eel/pox.py openflow.of_01 --address=127.0.0.1 --port=6653 py

- home/ctz/pox-eel/pox.py : POX程序的入口
- openflow.of_01 : POX的组件,使用openflow1.0进行通信
- address : openflow.of_01的参数,定义POX控制器的IP地址,这里定义为本地回环
- port : openflow.of_01的参数,定义POX控制器的监听端口,用于监听openflow交换机发来的消息
- py:使用POX交互模式,可在终端与POX控制器进行交互,例如构造Flow_Mod消息并发送给交换机

启动POX

2.运行Mininet

另开一终端,输入

sudo mn --controller=remote,ip=127.0.0.1,port=6653 --mac

- controller=remote : mininet连接远程控制器
- ip : controller的参数,定义要连接的远程控制器IP地址
- port : controller的参数,定义要连接的远程控制器端口
- --mac : 从00:00:00:00:00:01开始,按递增序为主机设置MAC地址

运行Mininet

3.添加两条流表项

在运行POX的终端上,构造两条Flow_Mod消息,用于添加两条流表项到交换机

# 以下三条命令在POX控制器同openflow交换机连接上后只需要输入一次
import pox.openflow.libopenflow_01 as of
from pox.lib.addresses import IPAddr
core.openflow.connections.keys()    # 获取连接的交换机dpid,会在终端上显示dpid

# 下发一条流表项(h1 -> h2 基于源目IP)
msg = of.ofp_flow_mod()
msg.priority = 42
msg.command = of.OFPFC_ADD
msg.match.dl_type = 0x800
msg.match.nw_src = IPAddr("10.0.0.1")
msg.match.nw_dst = IPAddr("10.0.0.2")
msg.actions.append(of.ofp_action_output(port = 2))
core.openflow.connections[1].send(msg)    # 1为交换机的dpid

# 下发一条流表项(h1 -> h2 基于源目IP和TCP目的端口号)
msg = of.ofp_flow_mod()
msg.priority = 42
msg.command = of.OFPFC_ADD
msg.match.dl_type = 0x800
msg.match.nw_src = IPAddr("10.0.0.1")
msg.match.nw_dst = IPAddr("10.0.0.2")
msg.match.nw_proto = 6
msg.match.tp_dst = 80
msg.actions.append(of.ofp_action_output(port = 2))
core.openflow.connections[1].send(msg)    # 1为交换机的dpid

在运行Mininet的终端中输入

dpctl dump-flows

显示交换机中流表信息

添加两条流表项

4.DELETE删除流表项

在运行POX的终端上,构造一条command = DELETE的Flow_Mod消息,删除所有匹配的流表项

# 删除所有匹配流表项(h1 -> h2 基于源目IP)
msg = of.ofp_flow_mod()
msg.priority = 42
msg.command = of.OFPFC_DELETE
msg.match.dl_type = 0x800
msg.match.nw_src = IPAddr("10.0.0.1")
msg.match.nw_dst = IPAddr("10.0.0.2")
msg.actions.append(of.ofp_action_output(port = 2))
core.openflow.connections[1].send(msg)    # 1为交换机的dpid

如下图所示,交换机根据Flow_Mod消息的match字段查找流表项,所有流表项均被删除

DELETE删除流表项

5.添加两条流表项

按照步骤3,重新添加两条流表项

6.DELETE_STRICT删除流表项

在运行POX的终端上,构造一条command = DELETE_STRICT的Flow_Mod消息,删除指定流表项

# 删除所有匹配流表项(h1 -> h2 基于源目IP)
msg = of.ofp_flow_mod()
msg.priority = 42
msg.command = of.OFPFC_DELETE_STRICT
msg.match.dl_type = 0x800
msg.match.nw_src = IPAddr("10.0.0.1")
msg.match.nw_dst = IPAddr("10.0.0.2")
msg.actions.append(of.ofp_action_output(port = 2))
core.openflow.connections[1].send(msg)    # 1为交换机的dpid

如下图所示,交换机根据Flow_Mod消息的match字段和priority字段查找流表项,匹配域中含有端口号的流表项被保留,匹配域中不含端口号的流表项被删除

DELETE_STRICT删除流表项

0x04 总结

使用Flow_Mod删除流表项时,command =

  • DELETE:删除所有匹配的流表项,只要流表项中Match字段描述 >= Flow_Mod消息中的Match字段(如流表项中Match:{in_port:1,ip_src:10.0.0.1},Flow_Mod消息中Match:{in_port:1}),则相关流表项均会被删除,因此被删除的流表项可能有多个

  • DELETE_STRICT:删除特定的流表项,只有同时满足Flow_Mod消息中匹配域以及优先级的流表项会被删除,被删除的流表项只有一个

0x05 参考



SDN     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!