当前位置: 首页 > POX > 正文

POX 控制器入门教程

这篇教程目标读者是那些使用POX平台进行SDN应用开发的初学者。熟悉Python的基础知识对学习本文是有帮助的,但并不是必须的。

快速入门

下载SDN Hub Tutorial VM并在 Virtualbox 或 VMware Player中运行VM。关于SDN Hub Tutorial VM请参考:http://sdnhub.cn/all-in-one-vm.html

运行在终端窗口中运行如下的Mininet命令, 实现1个交换机和3个主机的网络拓扑,交换机试图连接本机的运行在6633端口(localhost的6633)的控制器,但是此时,控制器还未启动,所以是无法连接成功的:

#mn --topo single,3 --mac –controller remote --switch ovsk

由于POX目前仅支持OpenFlow 1.0 ,而不支持OpenFlow 1.3,最好在命令行设置OVS所使用的OpenFlow的版本。命令如下:

#mn --topo single,3 --mac –controller remote --switch ovsk,protocols=OpenFlow10

如果上面的命令还是出现“WARNING:openflow.of_01:Bad OpenFlow version (0x00) on connection [None 120]”之类的错误,则使用如下的命令直接设置openvswitch使用的OpenFlow版本号:

#ovs-vsctl get bridge s1 protocols
[“OpenFlow10″, “OpenFlow13″]
#ovs-vsctl set bridge s1 protocols=OpenFlow10
#ovs-vsctl get bridge s1
[“OpenFlow10″]

接下来,启动POX控制器,假设POX的主目录被安装在/home/ubuntu/pox,下面的命令将启动POX控制器:

#cd /home/ubuntu/pox
#./pox.py log.level --DEBUG forwarding.tutorial_l2_hub

上面的命令以DEBUG模式运行POX控制器,可以额外打印POX控制器和交换机之间的报文交换信息。

POX 0.1.0 (betta) / Copyright 2011-2013 James McCauley, et al.
DEBUG:core:POX 0.1.0 (betta) going up…
DEBUG:core:Running on CPython (2.7.3/Sep 26 2013 16:35:25)
DEBUG:core:Platform is Linux-3.5.0-30-generic-x86_64-with-Ubuntu-12.10-quantal
INFO:core:POX 0.1.0 (betta) is up.
DEBUG:openflow.of_01:Listening on 0.0.0.0:6633
INFO:openflow.of_01:[00-00-00-00-00-01 1] connected

接下来,mininet测试创建的拓扑中主机间的连通性:

mininet> h1 ping h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=49.1 ms
64 bytes from 10.0.0.2: icmp_req=2 ttl=64 time=46.3 ms
64 bytes from 10.0.0.2: icmp_req=3 ttl=64 time=29.1 ms
64 bytes from 10.0.0.2: icmp_req=4 ttl=64 time=42.9 ms
64 bytes from 10.0.0.2: icmp_req=5 ttl=64 time=26.2 ms

理解代码

上面运行的hub应用的代码保存在/home/ubuntu/pox/pox/forwarding/tutorial_l2_hub.py中,完整代码如下:

# Copyright (C) 2014 SDN Hub
#
# Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
# You may not use this file except in compliance with this License.
# You may obtain a copy of the License at
#
#    http://www.gnu.org/licenses/gpl-3.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
from pox.core import core
import pox.openflow.libopenflow_01 as of

# Object spawned for each switch
class L2Hub (object):
def __init__ (self, connection):

# Keep track of the connection to the switch so that we can
# send it messages!
self.connection = connection

# This binds all our event listener
connection.addListeners(self)

# Handles packet in messages from the switch.
def _handle_PacketIn (self, event):
packet = event.parsed # This is the parsed packet data.
packet_in = event.ofp # The actual ofp_packet_in message.
msg = of.ofp_packet_out()
msg.buffer_id = event.ofp.buffer_id
msg.in_port = packet_in.in_port

# Add an action to send to the specified port
action = of.ofp_action_output(port = of.OFPP_FLOOD)
msg.actions.append(action)

# Send message to switch
self.connection.send(msg)

def launch ():
    def start_switch (event):
        L2Hub(event.connection)

core.openflow.addListenerByName("ConnectionUp", start_switch)

当在命令行启动程序时,launch()函数被POX自动调用执行, 在这个函数内部完成应用程序注册事件监听器和创建应用程序对应class的对象。如上所示的launch()函数中,当有新的交换机连接到控制器时,实例化一个新的L2Hub对象。

1.监听事件
有两种常用的方法为一个应用程序向控制器注册事件。
(1)针对特定的事件(事件可以是被OpenFlow handler模块或象拓扑发现之类的特定模块所抛出的),注册回调函数 。
可以在launch()函数中在一个类初始化时完成:

core.openflow.addListenerByName(“EVENTNAME”, CALLBACK_FUNC, PRIORITY)

(2)注册对象到OpenFlow handler模块或类似拓扑发现之类的特定模块。
典型在一个类初始化时,调用addListener(self)。一旦添加了这样的代码,控制器将查找一个名称为 _handle_EVENTNAME(self, event)的函数。这个方法被自动的注册为一个事件句柄(event hadler)。

2.数据包解析
POX提供了几个基本组件完成常见包的解析, 通过“packet_in”事件接收到的以太网包可以使用下面的代码:

packet = event.parsed
src_mac = packet.src
dst_mac = packet.dst
if packet.type == ethernet.IP_TYPE:
    ipv4_packet = event.parsed.find("ipv4")
    # Do more processing of the IPv4 packet
    src_ip = ipv4_packet.srcip
    src_ip = ipv4_packet.dstip

然后,使用from_packet函数创建流规则的匹配:

match = of.ofp_match.from_packet(packet)

3.向交换机发送报文
在POX中向交换机发送packet_out,flow_mod 和其它的OpenFlow协议报文是很简单的。具体步骤:
(1)构建相应的报文对象,在报文中填入字段值。
(2)使用connection对象向交换机发送报文:self.connect.send()。下面是一个例子:

msg = of.ofp_packet_out()              # Create packet out message
msg.buffer_id = event.ofp.buffer_id    # Use the incoming packet as the data for the packet out
msg.in_port = packet_in.in_port        # Set the in_port so that the switch knows
msg.match = of.ofp_match.from_packet(packet)

# Add an action to send to the specified port
action = of.ofp_action_output(port = of.OFPP_FLOOD)
msg.actions.append(action)

# Send message to switch
self.connection.send(msg)

4.管理多个应用程序
POX支持多个应用程序同时工作。被控制器接收的事件的回调函数具有优先级(在函数addListenerByName()中指定优先级)。

更多的内容

从交换机的报文(发送到控制器)中产生的中断:

FlowRemoved, FeaturesReceived, ConnectionUp, FeaturesReceived, RawStatsReply, PortStatus, PacketIn, BarrierIn, SwitchDescReceived, FlowStatsReceived, QueueStatsReceived, AggregateFlowStatsReceived, TableStatsReceived, PortStatsReceived

可被pox/lib解析的网络协议数据包:

arp, dhcp, dns, eapol, eap, ethernet, icmp, igmp, ipv4, llc, lldp, mpls, rip, tcp, udp, vlan

也可以使用命令‘grep class pox/pox/openflow/libopenflow_01.py’查看应用程序可以发送给交换机的报文列表。

更多示例应用

  • 二层MAC学习型交换机(L2 MAC Learning Switch): 将 pox/pox/misc/of_tutorial.py 转变为一个二层交换机
  • 无状态负载均衡器(Stateless load-balancer): pox/pox/forwarding/tutorial_stateless_lb.py 实现了一个负载均衡器(处理进入的HTTP请求),它以循环的方式将HTTP请求送给一组服务器。在代码中,服务器的IP地址是静态设置的。当流量到达负载均衡器的虚拟IP时,负载均衡器以轮询(或称为循环)的方式,在重写双向IP报头后将请求转发给不同的真正的HTTP服务器。 Mininet中网络拓扑的配置在这里http://sdnhub.cn/index.php/useful-mininet-setups/可以找到。

本文固定链接: http://sdnhub.cn/index.php/pox-beginner-tutorial/ | 软件定义网络SDN

该日志由 sdnhub 于2014年05月11日发表在 POX 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: POX 控制器入门教程 | 软件定义网络SDN
关键字:

POX 控制器入门教程:目前有2 条留言

  1. 板凳
    qgx:

    楼主写的很好,向您学习

    2014-11-19 10:19 [回复]
  2. 沙发
    sdn:

    很有用的

    2014-12-03 21:55 [回复]

发表评论

*

快捷键:Ctrl+Enter