1. 安装POX
POX基于Python2.7的环境运行,官方版本的POX可以运行在Windows、Mac OS、以及Linux操作系统中。POX源码已在github发布,可将POX的源码下载到本地机器进行安装使用。
在Linux系统下可以直接使用git 将pox源码下载下来,如:
$git clone http://github.com/noxrepo/pox
或在 https://github.com/pkpk8/pox 下载
2.配置POX
(1)修改监听端口
POX的监听端口默认是6633,修改监听端口的方式有以下两种:
1)临时修改方法
每次启动POX时指定监听端口,如指定的端口为6636,则在命令行后添加:
openflow.of_01 –port=6636
2)修改控制器的默认端口方法
修改/pox/openflow/of_01.py文件,如指定的端口为6636,则将文件中所有的port=6633改为port=6636。
(2)配置Web界面端口
1)获取POXDesk
cd pox/ext
git clone https://github.com/MurphyMc/poxdesk
2)获取qooxdoo
下载qooxdoo代码压缩包,然后把解压后文件夹名字改成qx
cd poxdesk
wget http://downloads.sourceforge.net/qooxdoo/qooxdoo-2.0.2-sdk.zip
unzip qooxdoo-2.0.2-sdk.zip
mv qooxdoo-2.0.2-sdk qx
3)初始化poxdesk
进入poxdesk目录,执行命令./generate.py
cd poxdesk
./generate.py
4)启动POX
cd ../../..
./pox.py samples.pretty_log web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk
Samples.pretty.log是一个组件,可以让pox开启的时候有字体有颜色,不添加也可以,但是界面比较难看。
这种启动pox-ui的方式只能启动监听并且开启ui视图,但是无法给switch下发消息(poxdesk的web中的terminal是打算用其他虚拟of-switch的工具来控制下发规则,但是我们是真实的of-switch)
完整的使用方式如下:
./pox.py samples.pretty_log web messenger messenger.log_service
messenger.ajax_transport openflow.of_service poxdesk openflow.discovery poxdesk.tinytopo py
poxdesk.tinytopo可以自动识别topo。上面命令的结尾添加py就可以出现熟悉的pox>命令模式,这时可以在web上看到下联的of-switch.
5)访问Web
用浏览器访问localhost:8000/poxdesk,默认端口8000
点击网页左下角的图标pox,可以打开许多小框。
3.POX加mininet测试
把环境都安装好了之后,分别在terminal下输入命令启动pox和poxdesk(启动命令以上的github的guide中都有),然后启动mininet(sudo mn),最后在浏览器中打开http://127.0.0.1:8000/poxdesk/source/ ,在浏览器左下角的POX按钮处选择topo viewer,然后在mininet动态配置拓扑,即可以在topo viewer中看到可视化的拓扑。
(1)简单测试:
启动POX时,需要运行pox.py 或debug-pox.py。前者是在一般的情况下运行POX,后者主要用于调试POX控制器,因此如果要在POX中做开发,通常会选用debug-pox.py来启动POX。POS启动命令中的可选参数主要包括verbose、no-cli、no-openflow,具体描述信息及其他参数可以借助命令./pox.py –help查看。
启动pox:
cd pox
./pox.py openflow.of_01 forwarding.l2_learning
或
./pox.py samples.pretty_log web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk poxdesk.terminal poxdesk.tinytopo openflow.discovery forwarding.l2_learning py
pox.py是程序的入口,需要openflow.of_01库解释后面的参数,forwarding.l2_learning为POX提供的组件。POX默认开启6633端口监听。
poxdesk.tinytopo可以自动识别topo,poxdesk.terminal可以使用linux terminal(在web上操作terminal)。上面命令的结尾添加py就可以出现熟悉的pox>命令模式,这时可以在web上看到下联的of-switch.
若出现端口占用问题:
netstat -anp|grep 6633
kill 3204(进程号)
开启mininet执行:
mn --controller=remote,ip=192.168.0.105 --topo=tree,2,2
mininet> dpctl dump-flows
mininet>pingall
mininet> dpctl dump-flows //触发flow entry下发flow entry
(2)流表测试
1,启动pox:
python pox.py openflow.of_01 --address=192.168.0.105 --port=6633 py
2,启动mininet:
virtualbox启动,ifconfig得到其ip为192.168.0.106
开启新终端登入mininet,密码mininet:
ssh -X [email protected]192.168.0.106
sudo mn --controller=remote,ip=192.168.0.105 //设置控制器
mininet> dpctl dump-flows
mininet>pingall //无匹配流表,无法ping通
mininet> dump
<Host h1: h1-eth0:10.0.0.1 pid=1980>
<Host h2: h2-eth0:10.0.0.2 pid=1984>
<OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=1989>
<RemoteController{‘ip‘: ‘192.168.0.105‘} c0: 192.168.0.105:6633 pid=1974>
3,添加流表:
POX> from pox.lib.addresses import IPAddr
POX> from pox.lib.addresses import EthAddr
POX> import pox.openflow.libopenflow_01 as of //导出核心模块,并命名为of
POX> core.openflow.connections.keys() //获取连接控制端的openflow switch的key
[1]
POX>msg=of.ofp_flow_mod() //编辑消息
POX>msg.priority=3
POX>msg.match.in_port=1
POX>msg.actions.append(of.ofp_action_output(port=2))
POX>core.openflow.connections[1].send(msg)
POX> msg.match.in_port=2
POX> msg.actions.append(of.ofp_action_output(port=1))
POX> core.openflow.connections[1].send(msg)
4,mininet端:
mininet> dpctl dump-flows //显示已添加流表
mininet> pingall //可以ping通
4.POX控制器下发openflow流表指南
启用pox控制器并同openflow交换机连接后,就可以使用pox控制器下发流表项了,这里先介绍一下下发流表项中各个匹配项和动作的命令。
匹配字段
- 编辑消息,消息类型为flowmod
命令:POX> msg=of.ofp_flow_mod(command=0)
参数:command:0为ADD(添加流),1为MODIFY,2为MODIFY_STRICT(严格匹配掩码和优先级修改流规则),3为DELETE(删除所有流规则),4为DELETE_STRICT(严格匹配掩码和优先级删除流规则)
缺省情况下,即不标明参数command,如:msg=of.ofp_flow_mod(),command=0,添加流表项。
- 设置规则的优先级
命令:POX> msg.priority=x
X为优先级数值,范围为1-65535
- 匹配入端口
命令:POX> msg.match.in_port=y
指定规则匹配的入端口值,y为交换机上端口对应的index值。
- 匹配源mac
命令:POX> msg.match.dl_src=EthAddr(“”)
- 匹配目的mac
命令:POX> msg.match.dl_dst=EthAddr(“ ”)
- 匹配以太类型
命令:POX> msg.match.dl_type=x
指定规则匹配ip类型报文
- 匹配vlan id
命令:POX> msg.match.dl_vlan=x
说明:dl_vlan必须为openflow交换机上存在的vlan
- 匹配vlan优先级
命令:POX> msg.match.dl_vlan_pcp=x
说明:dl_vlan_pcp必须在0-7之内。
- 匹配源ip地址
命令:POX> msg.match.nw_src=“A.B.C.D/X”
说明:下发匹配源ip地址时,必须指定匹配的以太类型,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_src=“192.168.2.133/24”
- 匹配目的ip地址
命令:POX> msg.match.nw_dst=“A.B.C.D/X”
说明:下发匹配目的ip地址时,必须指定匹配的以太类型,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_dst=“192.168.2.133/24”
- 匹配协议类型
命令:POX> msg.match.nw_proto=x
说明:必须指定匹配的以太网类型,再匹配ip协议类型,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_proto=6
- 匹配tos
命令:POX> msg.match.nw_tos=x
说明:必须指定匹配的以太网类型,再匹配tos值,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_tos=64
- 匹配tcp源端口
命令:POX> msg.match.tp_src=X
说明:必须指定匹配的以太网类型,再匹配ip协议类型,最后匹配tcp port,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_proto=6
POX> msg.match.tp_src=179
- 匹配tcp目的端口
命令:POX> msg.match.tp_dst=X
说明:必须指定匹配的以太网类型,再匹配ip协议类型,最后匹配tcp port,如:
POX> msg.match.dl_type=0x800
POX> msg.match.nw_proto=6
POX> msg.match.tp_dst=179
- 在idle时间内,如果没有报文触发此动作,该条规则将删除
命令:POX> msg.idle_timeout=X
说明:X为时间值,单位为秒。缺省时为0,表示不老化删除。
- 在到达hard时间时,无论如何,该条规则将删除
命令:POX> msg.hard_timeout=X
说明:X为时间值,单位为秒。缺省时为0,表示不老化删除。
修改动作
若规则无动作则默认为丢弃;规则中没有显示的设置出端口的需要在相应动作之后添加出端口。
- 指定出端口动作
命令:POX> msg.actions.append(of.ofp_action_output(port=X))
说明:port号是openflow vlan内的端口。
其中,port值可以为特殊参数值,IN_PORT = 0xfff8:从入端口将报文发出。FLOOD= 0xfffb:除了入端口和stp不允许的端口的所有端口。ALL = 0xfffc:除了入端口的其余端口。CONTROLLER = 0xfffd:发送给控制器。NONE = 0xffff:和物理端口无关
- 转发指定的端口和队列
命令:POX> msg.actions.append(of.ofp_action_enqueue(port=x,queue_id=y))
- 改变目的mac为指定mac
命令:POX> msg.actions.append(of.ofp_action_dl_addr.set_dst(“”))
说明:mac地址形式为ff:ff:ff:ff:ff:ff
- 改变源mac为指定mac
命令:POX> msg.actions.append(of.ofp_action_dl_addr.set_src(“”))
- 设定tos值
命令:POX> msg.actions.append(of.ofp_action_nw_tos(nw_tos=x))
- 设定vlan值
命令:POX> msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=x))
- 设定vlan cos值
命令:POX> msg.actions.append(of.ofp_action_vlan_pcp(vlan_pcp=x))
说明:设置cos值时必须先设置vlan id,如:
POX> msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=3))
POX> msg.actions.append(of.ofp_action_vlan_pcp(vlan_pcp=4))
POX使用实例
1. 下发匹配入端口,动作为出端口的流表项
命令:
POX>msg=of.ofp_flow_mod()
POX>msg.priority=3
POX>msg.match.in_port=193
POX>msg.actions.append(of.ofp_action_output(port=194))
POX>core.openflow.connections[13136560386L].send(msg)
说明:[13136560386L]为在POX和openflow交换机连接上时,使用命令POX>core.openflow.connections.keys()获取的交换机的key,每次下发流表项或者删除,修改流表项,这个key都是相同的。
2. 下发匹配目的MAC地址,动作为出端口的流表项
命令:
POX>msg=of.ofp_flow_mod()
POX>msg.priority=3
POX>msg.match.dl_src=EthAddr("ff:ff:ff:ff:ff:ff")
POX>msg.actions.append(of.ofp_action_output(port=194))
POX>core.openflow.connections[13136560386L].send(msg)
3. 下发匹配以太网类型,动作为出端口和队列的流表项
命令:
POX>msg=of.ofp_flow_mod()
POX>msg.priority=5
POX>msg.match.dl_type=0x800
POX>msg.actions.append(of.ofp_action_enqueue(queue_id=5,port=194))
POX>core.openflow.connections[13136560386L].send(msg)
4. 下发匹配源mac地址,动作为设置vlan 并指定出端口的流表项
命令:
POX>msg=of.ofp_flow_mod()
POX>msg.priority=5
POX>msg.match.dl_src=EthAddr(“00:03:0f:01:12:43”)
POX>msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=3))
POX>msg.actions.append(of.ofp_action_output(port=194))
POX>core.openflow.connections[13136560386L].send(msg)
5. 下发匹配入端口,动作为设置vlan、cos,并指定出端口的流表项
命令:
POX>msg=of.ofp_flow_mod()
POX>msg.priority=5
POX>msg.match.in_port=193
POX>msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=4))
POX>msg.actions.append(of.ofp_action_vlan_pcp(vlan_pcp=5))
POX>msg.actions.append(of.ofp_action_output(port=194))
POX>core.openflow.connections[13136560386L].send(msg)
6. 删除流表项
命令:
POX>msg=of.ofp_flow_mod(command=3)
POX>core.openflow.connections[13136560386L].send(msg)
说明:此命令是删除所有的流表项
7. 删除特定的流表项
命令:
POX>msg=of.ofp_flow_mod(command=4)
POX>msg.wildcards= 4194302
POX>msg.priority=5
POX>core.openflow.connections[13136560386L].send(msg)
说明:删除特定的流表项就是将command值为4,并且精确匹配需要删除的流表项的匹配字段和动作。
8. 修改流表项
命令:
POX>msg=of.ofp_flow_mod(command=2)
POX>msg.priority=5
POX>msg.match.in_port=193
POX>msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=4))
POX>msg.actions.append(of.ofp_action_vlan_pcp(vlan_pcp=5))
POX>msg.actions.append(of.ofp_action_output(port=194))
POX>core.openflow.connections[13136560386L].send(msg)
说明:修改流表项,即修改这条流表的动作。
5.POX组件介绍
按照组件的功能进行分类:
L2层地址学习、洪泛
forwarding.hub
forwarding.l2_learning
forwarding.l2_pairs
forwarding.l2_multi
forwarding.l2_nx
L3层地址学习
forwarding.l3_learning
构建拓扑
openflow.discovery
openflow.spanning_tree
forwarding.topo_proactive
openflow 连接相关
openflow.of_01
misc.full_payload
openflow.keepalive
pox内部服务
py
web.webcore
messenger
openflow.debug
pox网络服务应用
proto.arp_responder
proto.pong
proto.dns_spy
proto.dhcp_client
proto.dhcpd
misc.nat
misc.ip_loadbalancer
pox功能扩展
info.packet_dump
misc.of_tutorial
misc.mac_blocker
misc.gephi_topo
openflow.webservice
组件说明:
py
POX的交互式Python解释执行组件,用于DEBUG和交互式实验。默认执行,除非添加命令 –no-cli。其他组件可以向该解释器添加函数和值。
forwarding.hub
该组件每个交换机添加洪泛通配符规则,将所有交换机等效于ethernet集线器
forwarding.l2_learning
该组件使opennflow交换机实现 L2链路层上的地址学习(类似网桥)。但当该组件学习地址学习时,向流表下发的规则会尽可能的准确,而不仅仅是L2层的地址。例如不同的TCP连接将产生不同的表项。
forwarding.l2_pairs
类似于 forwarding.l2_learning,l2_pairs让交换机进行地址学习,但该组件是尽可能的简化规则学习,所有安装的表项时只使用L2层信息(如Mac地址)。
forwarding.l3_learning
该组件并不是一个完整的Router,该组件是可POX的packet library(代码)的一个实现样例,可以构造ARP请求和回复。l3_learning关心IP从哪来,但并不关心IP的填充域,如子网等。
forwarding.l2_multi
L2层地址学习,但该层的学习不是单个交换机的独立学习,而是通过 openflow.discovery交换机之间交换拓扑信息,学习整个网络的拓扑结构。只要网络中有一个交换机学习到一个新的Mac地址及其位置,所有的交换机就都能学会。
forwarding.l2_nx
Open vSwitch的quick-and-dirty组件,需要使用Openvswitch的Nicira扩展安装。
forwarding.topo_proactive
基于重要拓扑的IP地址安装规则。通过DHCP进行地址分配。所有的主机都必须用指定的IP地址,绝大部分规则都是主动安装(?)。该组件被添加至聚合规则复用分支中,路由编码基于l2_multi组件。该组件依赖openflow.discovery以及openflow.spanning_tree组件(有待确认)。
openflow.spanning_tree
该组件使用discovery组件来创建网络拓扑的视图,构造一棵生成树,然后使不在生成树中的交换机端口的洪泛功能失效,使得网络中不存在洪泛回路。需要注意的是该组件同生成树协议没有很大关系,只是有相似的目的。两个选项:
–no-flood,只要交换机连接上了就使该交换机的所有端口洪泛失效,对于某些端口,稍后将使能。
–hold-down,防止洪泛控制在一个完整的发现回路完成前被改变
因此该组件最安全的的使用方法是
openflow.spanning_tree –no-flood –hold-down .
openflow.webservice
Openflow的一个简单 JSON-RPC-ish web service交互式接口,由of_service信息服务派生而来,依赖于webcore组件。可以使用HTTP POST方式发送JSON进行访问。
目前支持的方法有:
method
get_flow_stats,获取流表的表项
get_switch_desc,获取指定交换机详细信息
get_switches,获取交换机列表和基本信息
set_table , 设置指定交换机的流表
web.webcore
在Pox进程中启动一个web服务,其他组件可以通过它提供静态或动态内容。
messenger
该组件通过双向JSON消息为POX在进程间提供了一个交互接口。该组件本质上是API,通过TCP Socket和HTTP进行通信。具体的功能通过Services实现。messenger.log_service允许远程操作log(读log信息,配置log等)。openflow.of_service 允许一下Openflow的操作(如显示交换机列表,设置流表表项等)。./tools/pox-log.py是一个独立的Python应用,可以通过TCP同log服务进行交互。
openflow.of_01
该组件同openflow 1.0协议版本的交换机 进行通讯,默认启动。
openflow.discovery
该组件在交换机之间使用特制的LLDP报文来发现整个网络的拓扑结构。当链路生效或者失效时,该组件都会产生一个事件(Raise Events)。
openflow.debug
加载该组件将导致POX创建pcap追踪(进行抓包),包括openflow报文,可导入wireshark进行分析。该工具并不能完全代替wireshark或tcpdump,不过有一个比较好的特性是每一个openflow报文都一个完整的帧中。
openflow.keepalive
该组件令POX向已经连接的交换机周期性的发送echo请求。但这会解决两个问题:
第一,有些交换机(包括推荐交换机)会认为空闲连接意味着同控制器连接丢失,将会在一段silence时间后断开连接。
第二,如果网络与交换机断开,控制器将不会立即获得一个FIN或RST,所以将会很难确定一个交换机失效。通过周期行发送echo请求,并分析交换机的响应,即可解决该问题。
proto.pong
该组件是一个简单的检测ICMP echo请求和应答的样例组件
proto.arp_responder
该组件为一个ARP应用,可以学习和代理ARP请求,也可以通过查询静态的表项来回复ARP请求。该组件提供了一个控制台交互界面来查询和修改arp表。
info.packet_dump
该组件将packet_in信息保存至log中,有点类似于在交换机中运行tcpdump
proto.dns_spy
检测DNS应答并存储应答结果,其他组件可以通过DNSSpy检测这些信息。
proto.dhcp_client
DHCP客户端,在同其他组件进行联合时有用
proto.dhcpd
简单的DHCP服务器端,服务器本身的默认地址为192.168.0.254,下发的地址域为192.168.0.1~192.168.0.253,同时宣称自身为网关和DNS服务器。
misc.of_tutorial
配合openflow tutorial使用的组件,类似于简单的hub,但可以修改成L2 learning的交换机
misc.full_payload
默认情况下,当一个数据包在交换机流表中没有命中时,交换机只向控制器发送数据包的前128bytes,使用该组件可以将每一个交换机配置成发送整个数据包
misc.mac_blocker
具有Tkinter-based界面,可以阻塞Mac地址
misc.nat
实现网络地址转换的组件(木有详细介绍)
misc.ip_loadbalancer
由carp branch(不理解是啥)启用的TCP负载均衡器
misc.gephi_topo
检测拓扑结构,并将其导入到gephi中进行分析