栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

pox装置介绍(pox理论)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

pox装置介绍(pox理论)

POX 入门 1. POX

POX 是一个用 Python 编写的网络软件平台。

POX 最初是作为 OpenFlow 控制器的,但现在也可以用作 OpenFlow 交换机,并且通常可用于编写网络软件。 它目前支持 OpenFlow 1.0 并包括对 Open vSwitch/Nicira 扩展的特殊支持。从 POX “gar” 开始,POX 正式要求 Python 3。支持 Python 2 的最后一个版本是 POX “fangtooth”。

POX 组件基本上是带有一些 POX 特定约定的 Python 模块。它们会在 Python 通常查找的所有地方以及 pox 和 ext 目录中查找。因此,可以执行以下操作:

./pox.py forwarding.l2_learning

可以通过在组件名称后指定选项来将选项传递给组件。这些被传递给相应模块的 launch() 函数。例如,如果想将 POX 作为 OpenFlow 控制器运行并控制它使用的地址或端口,可以将这些作为选项传递给 openflow._01 组件:

./pox.py openflow.of_01 --address=10.1.1.1 --port=6634

--address 表示控制器运行的地址,这里只能设置为本地地址(127.0.0.1),否则会出错。--port:控制器运行的端口,默认是 6633,这里可以任意指定。

POX 完整参考文档

2. POX 安装与使用 2.1. 安装运行

下载源码:

git clone https://github.com/noxrepo/pox.git
# 保证 pox 分支是 betta,否则 POXDesk 无法正常使用
cd pox
git checkout betta

启动 POX 时,需要运行 pox.py 或 debug-pox.py。前者是在一般的情况下运行 POX,后者主要用于调试 POX 控制器,因此如果要在 POX 中做开发,通常会选用 debug-pox.py 来启动 POX。POS 启动命令中的可选参数主要如下,具体描述信息及其他参数可以借助命令 ./pox.py –help 查看。

--verbose 打印更多调试信息(对启动问题特别有用)。--no-openflow 不要自动启动 openflow 模块。--log-config=F 加载 Python 日志配置文件(如果包含该选项而不指定 F,则默认为 logging.cfg)。 2.2. 配置 Web 界面

    获取 POXDesk
cd ext
git clone git://github.com/MurphyMc/poxdesk
    获取 qooxdoo
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
# 上述方式作废
cd poxdesk
wget https://codeload.github.com/qooxdoo/qooxdoo/zip/refs/tags/release_2_0_2
unzip release_2_0_2
mv qooxdoo-release_2_0_2 qx
    初始化 poxdesk:进入poxdesk目录,执行命令 ./generate.py。
cd poxdesk
./generate.py
    启动 pox
cd ../../..
./pox.py openflow.of_01 samples.pretty_log web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk openflow.discovery poxdesk.tinytopo poxdesk.terminal forwarding.l2_learning py

./pox.py 程序的入口,会自动检测系统中的 Python 版本,也可以使用 Python3 pox.py。它在命令行上获取组件名称列表,定位组件,调用它们的 launch() 函数(如果存在),然后转换到 up 状态。openflow.of_01 使用这个库解释后面的参数。查看 POX 的官方文档,说的好像就是只支持到 OpenFlow 1.0。Samples.pretty.log 可以让 pox 开启的时候有字体有颜色,不添加也可以,但是界面比较难看。poxdesk.tinytopo 可以自动识别 topo。poxdesk.terminal 可以在 Web 上使用 Linux 终端。py:表示启动控制器后,进入一个类似 Python 的交互式命令行界面 pox>。

如果出现端口占用问题:

netstat -anp|grep 6633
kill 15005 # 进程号

在另一个终端下启动 Mininet:

sudo mn --topo=tree,3,2 --controller=remote,ip=127.0.0.1,port=6633
    访问 Web:

用浏览器访问 localhost:8000/poxdesk/source,默认端口 8000。点击网页左下角的图标 pox,可以打开许多小框。选择打开 topoViewer 可以看到拓扑如下:

2.3. 结合 Mininet 简单使用 2.3.1. 流表测试
    启动 POX:
cd pox
./pox.py openflow.of_01 --address=127.0.0.1 --port=6633 py
    启动 Mininet:
sudo mn --controller=remote,ip=127.0.0.1,port=6633 # 设置控制器
mininet-wifi> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
mininet-wifi> pingall # 无匹配流表,无法 ping 通
*** Ping: testing ping reachability
h1 -> X 
h2 -> X 
*** Results: 100% dropped (0/2 received)
mininet-wifi> dump
 
 
 
 
mininet-wifi> 
    添加流表:
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() # 获取连接控制端的 ovs 的 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)
POX>
    在 Mininet 端查看结果:
mininet-wifi> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
 cookie=0x0, duration=72.985s, table=0, n_packets=0, n_bytes=0, priority=3,in_port="s1-eth1" actions=output:"s1-eth2"
 cookie=0x0, duration=12.922s, table=0, n_packets=1, n_bytes=70, priority=3,in_port="s1-eth2" actions=output:"s1-eth2",output:"s1-eth1"
mininet-wifi> pingall
*** Ping: testing ping reachability
h1 -> h2 
h2 -> h1 
*** Results: 0% dropped (2/2 received)
mininet-wifi> 
2.3.2. 启用 l2_pairs(开启二层自学习功能)

首先运行 Mininet:

jason@MininetWiFi:~$ sudo mn --controller=remote,ip=127.0.0.1,port=6633
*** Creating network
*** Adding controller
Unable to contact the remote controller at 127.0.0.1:6666
*** Adding hosts:
h1 h2
*** Adding switches:
s1
*** Adding links:
(h1, s1) (h2, s1)
*** Configuring hosts
h1 h2
*** Starting controller
c0
*** Starting 1 switches
s1 ...
*** Starting CLI:
mininet-wifi> dump




然后在另一个终端运行 POX。运行 l2_pairs 组件,该组件可以抽取 packet-in 中的 dst_mac 和 src_mac,根据源和目的端口下发 flow entry 到交换机,即工作在交换机模式。参数 forwarding.l2_learning 可以开启二层自学习功能。命令如下:

cd pox
./pox.py openflow.of_01 -address=127.0.0.1 -port=6666 forwarding.l2_pairs py
POX 0.7.0 (gar) / Copyright 2011-2020 James McCauley, et al.
INFO:forwarding.l2_pairs:Pair-Learning switch running.
WARNING:version:Support for Python 3 is experimental.
INFO:core:POX 0.7.0 (gar) is up.
INFO:openflow.of_01:[00-00-00-00-00-01 1] connected
Ready.
POX>

输出提示 INFO:openflow.of_01:[00-00-00-00-00-01 1] connected,有交换机连接上,key 值为 1。

在 Mininet CLI 中运行 dpctl dump-flows 可以看到此时交换机 s1 的流表为空。

mininet-wifi> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
mininet-wifi>

然后在 Mininet CLI 中运行 h1 ping h2,触发 flow entry 的下发,生成两条 flow entry,使得 h1 可以 ping 通 h2。

mininet-wifi> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
mininet-wifi> h1 ping h2 -c3
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=1.44 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.045 ms

--- 10.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2007ms
rtt min/avg/max/mdev = 0.041/0.510/1.446/0.661 ms
mininet-wifi>

此时再查看交换机 s1 中的流表如下,可以看到交换机 s1 中确实已经有两条流表。

mininet-wifi> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
 cookie=0x0, duration=59.885s, table=0, n_packets=4, n_bytes=336, dl_src=8e:f8:66:c1:b0:22,dl_dst=86:4e:50:ca:17:b7 actions=output:"s1-eth2"
 cookie=0x0, duration=59.886s, table=0, n_packets=5, n_bytes=378, dl_src=86:4e:50:ca:17:b7,dl_dst=8e:f8:66:c1:b0:22 actions=output:"s1-eth1"
mininet-wifi>
2.4. 自定义拓扑

如果自己定义拓扑结构,光凭借以上的命令生成的树并不稳定,节点之间的连接时常会断开。这是因为没有加载好 pox 组件,这里以 Fat Tree 网络来说明。

拓扑文件命名为 tree.py,存放路径为 /home/jason/mininet-wifi/custom。自定义拓扑网络文件代码如下:

#!/usr/bin/env python

from mininet.net import Mininet
from mininet.node import Controller, RemoteController
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import link, Intf, TClink
from mininet.topo import Topo
from mininet.util import dumpNodeConnections
import logging
import os

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger( __name__ )

class HugeTopo(Topo):
    logger.debug("Class HugeTopo")
    CoreSwitchList = []
    AggSwitchList = []
    EdgeSwitchList = []
    HostList = []
    iNUMBER = 0
    def __init__(self):
        logger.debug("Class HugeTopo init")
        iNUMBER = 4

        self.iNUMBER = iNUMBER
        self.iCoreLayerSwitch = iNUMBER
        self.iAggLayerSwitch = iNUMBER * 2
        self.iEdgeLayerSwitch = iNUMBER * 2
        self.iHost = self.iEdgeLayerSwitch * 2

        # 通过父类初始化拓扑
        Topo.__init__(self)

        logger.debug("Start create Core Layer Swich")
        self.createCoreLayerSwitch(self.iCoreLayerSwitch)
        logger.debug("Start create Agg Layer Swich ")
        self.createAggLayerSwitch(self.iAggLayerSwitch)
        logger.debug("Start create Edge Layer Swich ")
        self.createEdgeLayerSwitch(self.iEdgeLayerSwitch)
        logger.debug("Start create Host")
        self.createHost(self.iHost)

        self.createlink()
    """
    创建交换机和主机
    """

    # 创建核心层
    def createCoreLayerSwitch(self, NUMBER):
        logger.debug("Create Core Layer")
        for x in range(1, NUMBER+1):
            PREFIX = "100"
            if x >= int(10):
                PREFIX = "10"
            self.CoreSwitchList.append(self.addSwitch(PREFIX + str(x)))

    # 创建聚合层
    def createAggLayerSwitch(self, NUMBER):
        logger.debug( "Create Agg Layer")
        for x in range(1, NUMBER+1):
            PREFIX = "200"
            if x >= int(10):
                PREFIX = "20"
            self.AggSwitchList.append(self.addSwitch(PREFIX + str(x)))

    # 创建边缘层
    def createEdgeLayerSwitch(self, NUMBER):
        logger.debug("Create Edge Layer")
        for x in range(1, NUMBER+1):
            PREFIX = "300"
            if x >= int(10):
                PREFIX = "30"
            self.EdgeSwitchList.append(self.addSwitch(PREFIX + str(x)))

    def createHost(self, NUMBER):
        logger.debug("Create Host")
        for x in range(1, NUMBER+1):
            PREFIX = "400"
            if x >= int(10):
                PREFIX = "40"
            self.HostList.append(self.addHost(PREFIX + str(x)))

    """
    创建链接
    """
    def createlink(self):
        logger.debug("Create Core to Agg")
        for x in range(0, self.iAggLayerSwitch, 2):
            self.addlink(self.CoreSwitchList[0], self.AggSwitchList[x])
            self.addlink(self.CoreSwitchList[1], self.AggSwitchList[x])
        for x in range(1, self.iAggLayerSwitch, 2):
            self.addlink(self.CoreSwitchList[2], self.AggSwitchList[x])
            self.addlink(self.CoreSwitchList[3], self.AggSwitchList[x])

        logger.debug("Create Agg to Edge")
        for x in range(0, self.iAggLayerSwitch, 2):
            self.addlink(self.AggSwitchList[x], self.EdgeSwitchList[x])
            self.addlink(self.AggSwitchList[x], self.EdgeSwitchList[x+1])
            self.addlink(self.AggSwitchList[x+1], self.EdgeSwitchList[x])
            self.addlink(self.AggSwitchList[x+1], self.EdgeSwitchList[x+1])

        logger.debug("Create Edge to Host")
        for x in range(0, self.iEdgeLayerSwitch):
            ## limit = 2 * x + 1
            self.addlink(self.EdgeSwitchList[x], self.HostList[2 * x])
            self.addlink(self.EdgeSwitchList[x], self.HostList[2 * x + 1])


topos = { 'mytopo': ( lambda: HugeTopo() ) }

启动 POX:

cd pox
./pox.py forwarding.l2_learning openflow.spanning_tree --no-flood --hold-down log.level --DEBUG samples.pretty_log openflow.discovery web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk poxdesk.terminal poxdesk.tinytopo host_tracker openflow.of_01 --address=127.0.0.1 --port=6633

Mininet 启动拓扑:

cd /home/jason/mininet-wifi/custom
sudo mn --custom tree.py --topo mytopo --mac --switch=ovsk --controller=remote,ip=127.0.0.1,port=6633

然后可以得到如下所示的拓扑图:

可以看到主要是加入了 openflow.spanning_tree --no-flood --hold-down 这样的组件参数,最终使得 Fat Tree 网络稳定连接。

3. POX 组件介绍

按照组件的功能进行分类:

3.1. L2层地址学习、洪泛

forwarding.hub:该组件每个交换机添加洪泛通配符规则,将所有交换机等效于 ethernet 集线器。

forwarding.l2_learning:该组件使 OVS 实现 L2 链路层上的地址学习(类似网桥)。但当该组件学习地址学习时,向流表下发的规则会尽可能的准确,而不仅仅是 L2 层的地址。例如不同的TCP连接将产生不同的表项。

forwarding.l2_pairs:类似于 forwarding.l2_learning。l2_pairs 让交换机进行地址学习,但该组件是尽可能的简化规则学习,所有安装的表项时只使用 L2 层信息(如 Mac 地址)。

forwarding.l2_multi:L2 层地址学习,但该层的学习不是单个交换机的独立学习,而是通过 openflow.discovery 交换机之间交换拓扑信息,学习整个网络的拓扑结构。只要网络中有一个交换机学习到一个新的 Mac 地址及其位置,所有的交换机就都能学会。

forwarding.l2_nx:OVS 的 quick-and-dirty 组件,需要使用 OVS 的 Nicira 扩展安装。

3.2. L3层地址学习

forwarding.l3_learning:该组件并不是一个完整的 Router,该组件是 POX 的 packet library(代码)的一个实现样例,可以构造 ARP 请求和回复。l3_learning 关心 IP 从哪来,但并不关心 IP 的填充域,如子网等。 3.3. 构建拓扑

openflow.discovery:该组件在交换机之间使用特制的 LLDP 报文来发现整个网络的拓扑结构。当链路生效或者失效时,该组件都会产生一个事件(Raise Events)。

openflow.spanning_tree:该组件使用discovery组件来创建网络拓扑的视图,构造一棵生成树,然后使不在生成树中的交换机端口的洪泛功能失效,使得网络中不存在洪泛回路。需要注意的是该组件同生成树协议没有很大关系,只是有相似的目的。两个选项:

--no-flood,只要交换机连接上了就使该交换机的所有端口洪泛失效,对于某些端口,稍后将使能。--hold-down,防止洪泛控制在一个完整的发现回路完成前被改变。

因此该组件最安全的的使用方法是 openflow.spanning_tree --no-flood --hold-down,在上述自定义网络拓扑的例子中就是这样用的。

forwarding.topo_proactive:基于重要拓扑的 IP 地址安装规则。通过 DHCP 进行地址分配。所有的主机都必须用指定的 IP 地址,绝大部分规则都是主动安装。该组件被添加至聚合规则复用分支中,路由编码基于 l2_multi 组件。该组件依赖 openflow.discovery 以及 openflow.spanning_tree 组件(有待确认)。

3.4. OpenFlow 连接相关

openflow.of_01:该组件同 openflow 1.0 协议版本的交换机进行通讯,默认启动。

misc.full_payload:默认情况下,当一个数据包在交换机流表中没有命中时,交换机只向控制器发送数据包的前 128bytes,使用该组件可以将每一个交换机配置成发送整个数据包。

openflow.keepalive:该组件令POX向已经连接的交换机周期性的发送 echo 请求。但这会产生两个问题:

    有些交换机(包括推荐交换机)会认为空闲连接意味着同控制器连接丢失,将会在一段 scilence 时间后断开连接。

    如果网络与交换机断开,控制器将不会立即获得一个 FIN 或 RST,所以将会很难确定一个交换机失效。通过周期行发送 echo 请求,并分析交换机的响应,即可解决该问题。

3.5. pox 内部服务

py:POX 的交互式 Python 解释执行组件,用于 DEBUG 和交互式实验。默认执行,除非添加命令 -no-cli。其他组件可以向该解释器添加函数和值。

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.debug:加载该组件将导致 POX 创建 pcap 追踪(进行抓包),包括 openflow 报文,可导入 wireshark 进行分析。该工具并不能完全代替 wireshark 或tcpdump,不过有一个比较好的特性是每一个 openflow 报文都一个完整的帧中。

3.6. pox 网络服务应用

proto.arp_responder:该组件为一个 ARP 应用,可以学习和代理 ARP 请求,也可以通过查询静态的表项来回复 ARP 请求。该组件提供了一个控制台交互界面来查询和修改 arp 表。

proto.pong:该组件是一个简单的检测 ICMP echo 请求和应答的样例组件。

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.nat:实现网络地址转换的组件。

misc.ip_loadbalancer:由 carp branch 启用的 TCP 负载均衡器。

3.7. pox功能扩展

info.packet_dump:该组件将 packet_in 信息保存至 log 中,有点类似于在交换机中运行 tcpdump。

misc.of_tutorial:配合 openflow tutorial 使用的组件,类似于简单的 hub,但可以修改成 L2 learning 的交换机。

misc.full_payload:默认情况下,当一个数据包在交换机流表中没有命中时,交换机只向控制器发送数据包的前128bytes,使用该组件可以将每一个交换机配置成发送整个数据包。

misc.mac_blocker:具有 Tkinter-based 界面,可以阻塞 Mac 地址。

misc.gephi_topo:检测拓扑结构,并将其导入到 gephi 中进行分析。

openflow.webservice:Openflow 的一个简单 JSON-RPC-ish web service 交互式接口,由 of_service 信息服务派生而来,依赖于 webcore 组件。可以使用 HTTP POST 方式发送 JSON 进行访问。

目前支持的方法有:

get_flow_stats,获取流表的表项。get_switch_desc,获取指定交换机详细信息。get_switches,获取交换机列表和基本信息。set_table , 设置指定交换机的流表。 4. POX实验

基于Mininet使用POX动态改变转发规则实验

基于POX和Mininet实现的静态路由

5. 参考
    Pox + Mininet2.0的安装和初级使用Ubuntu18.04 mininet+pox+poxdesk配置POXDesk Getting StartedSDN控制器之POX篇POX 控制器POX 官方文档
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/773017.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号