精华内容
下载资源
问答
  • 这是一个翻译/更新文档的项目 基于原始文档的OpenFlow POX控制器
  • POX控制器的分析(一)

    千次阅读 2014-10-24 13:46:57
    要分析POX控制器,不得不从POX的

           最近刚刚对SDN产生了很大的兴趣,相对之前使用的POX控制器作出一个分析,了解控制器的机制,这样更好的理解SDN。

           本文从https://openflow.stanford.edu/display/ONL/POX+Wiki官方网站中进行学习的。

          首先从POX的自带的组件来分析:



    其中:

    forwarding作为转发应用,包括l2_learning、l2_pairs、l3_learning、l2_multi、l2_nx。

    OpenFlow是控制驱动,包括of_01、discovery、debug、keepalive。


    POX包括core部分和组件:

    其中core部分包括:of_01和openflow。

    POX处理的流程如下:

    1、of_01监听到交换机消息;

    2、握手消息自己处理,其他都触发事件;

    3、在监听该事件的组件,触发相应函数处理该事件。


            of_01 主要是运行一个线程,该线程不断与交换机进行TCP连接,当某交换机送来一个协议消息时,of_01会触发该消息所对应的事件。openflow则与所有的物理交换机相连,而控制器可以通过openflow控制所有的交换机。


    POX伴随着组件一起启动,有些组件提供主要功能,而有些仅仅是一些例子。下面具体解释:

    Py

    让POX启动一个交互式的python解释器,方便调试和开发,这个默认就是启动控制器POX。

     

    Forwarding.hub

    为每一个交换机建立通配的洪泛规则,让交换机拥有hub的功能。

     

    Forwarding.l2_learning

    让OpenFlow交换机成为2层自学习交换机。当组件学习到2层地址时,流表会建立精确匹配。例如,不同的TCP连接会导致不同的流表建立。

     

    Forwarding.l2_pairs

    让OpenFlow交换机扮演2层自学习交换机。与l2_learning不同的是,只为MAC地址建立流表规则。

     

    Forwarding.l3_learning

    这既不是一个router,也不完全是2层交换机,只是个3层学习交换组件。主要功能是使用POX的数据包库来检查和构建ARP请求和回复。

    一个使用场景是使用l3_learning来配置“fake gateways”即:

    ./pox.pyforwarding.l3_learning --fakeways=10.0.0.1,192.168.0.1

     

    Forwarding.l2_multi

    L2_multi使用openflow.discovery来学习整个网络中的拓扑结构。只要一个交换机学习到MAC地址,其他所有的交换机都会学习到。

     

    Forwarding.l2_nx

    使用Nicira扩展(即Open vSwitch)的L2 switch。

    RunLike this:

    ./pox.pyopenflow.nicira –convert-packet-in forwarding.l2_nx

    基于源MAC和目的MAC地址进行转发。因此交换机中有两张表:一张是源MAC,另一张是目的MAC。

     

    forwarding.topo_proactive

    为指定的IP地址建立转发规则。这些IP地址必须是DHCP分配的。

     

    openflow.spanning_tree

    组件使用发现组件建立网络拓扑,建立生成树,然后禁止交换机端口的洪泛,这个和生成树协议没什么关系。

    组件有两个选项:

    –no-flood 当交换机连接时,禁止所有端口flood;

    –hold-down 当一个完整的发现过程未结束时,阻止改变flood控制。

     

    web.webcore

    在POX进程中启动一个web server。

     

    Messenger

    通过基于JSON的双向消息提供一个POX和外部进程通信的接口。

     

    openflow.of_01

    该组件和所有OpenFlow交换机通信(默认是1.0)。通常是默认启动(除非你指定–no-openflow选项),通常借助它来选择侦听端口等选项。

     

    openflow.discovery

    使用LLDP消息来发现网络拓扑,链路开启或关闭时会触发事件。

     

    openflow.debug

    生成pcap追踪消息,便于使用wireshark进行抓包分析。

     

    openflow.keepalive

    这个组件使POX定期发送回显请求到连接到的交换机。

    支持以下命令行选项:

    –interval=X 每X秒发送一个回显请求(default 20)

    –timeout=X 期望X秒从交换机得到回复 (default 3)

     

    proto.pong

    主要用于ICMP回显和请求(ping)。

     

    proto.arp_responder

    一种arp工具可以学习到代理ARP,并且可以答复静态流表项。

    例子:指定IP地址和MAC地址

    proto.arp_responder--192.168.0.1=00:00:00:00:00:01--192.168.0.2=00:00:00:00:00:02

     

    info.packet_dump

    收集packet_in信息日志,类似于tcpdump。

     

    proto.dns_spy

    监测DNS回复并记录结果。其它组件能够检测它们通过访问core.DNSSpy.ip_to_name[<ip address>] 和core.DNSSpy.name_to_ip[<domainname>].

     

    proto.dpcp_client

    DHCP客户端,需要和其它组件一起使用。

     

    proto.dhcpd

    DHCP服务器。默认可以使用proto.arp_responder使192.168.0.254为代理ARP。如:

    proto.dhcpd--network=10.1.1.0/24 --ip=10.1.1.1 --first=10 --last=None --router=None--dns=4.2.2.1

    具体的可以参考wiki。

     

    misc.of_tutorial

    和 OpenFlowtutorial一起使用。

     

    misc.full_payload

    默认时,当一个数据包在交换机上丢失流表时,交换机可能只发送部分数据包到控制器(前128字节)。当发送一个全部的数据包时,这个组件需要在每个交换机上重新配置。

     

    misc.mac_blocker

    阻止MAC地址

     

    misc.nat

    NAT地址转换

     

    misc.ip_loadbalancer

    TCP负载均衡

    ./pox.pymisc.ip_loadbalancer –ip=<Service IP> –servers=<Server1IP>,<Server2 IP>,…

     

    misc.gephi_topo

    带有拓扑图的图形界面

    ./pox.pyopenflow.discovery misc.gephi_topo host_tracker forwarding.l2_learning

     

    log

    日志功能,POX使用python logging模块。下面有一些选项:

    禁止控制台日志,日志格式,日志输出,日志颜色,日志级别等。可参考python logging。

     

    samples.pretty_log

    使用log.color和用户自定义的日志格式来优化控制台输出

     

    tk

    基于Tk的GUI

     

    host_tracker

    跟踪网络主机,通常会分发一个HostEvent。host_tracker通常会检查packet_in消息以及MAC地址表。

     

    当然POX中也可以创建自己的组件,这点就要弄清楚POX组件是如何建立和加载的,这点需要分析POX中代码,在后面会给出相应的分析。

    POX中from pox.core import core也可以建立许多接口来进行许多应用。额外补充一句在python中,如果import某个库文件,则会执行该库文件中除了def之外的可执行语句。这点可以复用代码。




    展开全文
  • POX控制器的分析(二)

    千次阅读 2014-10-24 16:10:32
    最近刚刚对SDN产生了很大的兴趣,相对之前使用的POX控制器作出一个分析,了解控制器的机制,这样更好的理解SDN。 本文从https://openflow.stanford.edu/display/ONL/POX+Wiki官方网站中进行学习的。 首先从POX的...

           在上一篇具体讲述POX有哪些组件,以及各个组件的功能,这篇文章主要理解POX的启动以及组件是如何启动的,以及组件与事件的关系:


    由上图知,of_01 主要是运行一个线程,该线程不断与交换机进行TCP连接, 当某交换机送来一个协议消息时,of_01会触发该消息 所对应的事件。openflow则与所有的物理交换机相连,而控制器可以通过openflow控制所有的交换机,任意交换机传上来的消息都会触发openflow的事件,在设计自己的组件时,如果不需要监听特定的交换机,监听openflow肯定没错。

    事件组成:

    • source:给组件提供可被监听的事件,通过raise函数触发事件给监听它的组件;
    • sink:监听source的组件。

     启动pox.py:

    Pox.py 里面大部分都是注释,真正只有以下几行代码:


    调用pox.boot模块中的boot()函数。

    这时就想了解boot函数的作用,下面是进入boot.py里查看的代码:



    
    

    可以看出里面的内容包括:

    第442~444行代码将pox和ext的两个文件夹的路径加入到了系统的path里;

    还有启动了POX以及相关组件。

    关键代码是第459行的_do_launch()函数启动了相关组件,其中_post_startup()由下图390~392行启动openflow.of_01,core.goUp则启动了core里面的登记Debug信息和事件机制。

    在core.py的代码中,有core = POXCore()。代码中还有这个函数的定义class POXCore() (EventMixin)。可以看出,POXCore这个类是revent.py中class EventMixin的一个子类,是处理事件最高层的模块。另外,如果看后面的代码可以知道,POX的启动是由_do_Launch()函数完成的。

    组件启动:

     组件启动函数:pox.boot.do_launch

    这些代码完成了模块的加载+初始化工作,其中:

    第135~155行代码创建component_order的列表,用于存放组件的名称。然后再逐个启动,初始化;

    第157~164行代码通过创建组件的函数名,并定义了组件的加载顺序;

    第166~169行代码使用_do_import()函数将相关组件模块引入;

    第171行代码检查了类中是否存在相应的launch函数。其中sys.modules 是一个字典,它包含了从Python 开始运行起,被导入的所有模块。用sys.modules[name]可以获取name模块的引用。由于类的实例会有一个__dict__的特性字典,其中是该类的所有特性。

    如:

    第172行从特性中初始化函数实例;

    第189行代码就是执行初始化函数的语句。

    
    pox的过程如下:
    



    组件启动代码:

    以l3_learning组件来举例:


    我们观察到最后一行需要注册组件,这时就需要查看core.registerNew()这个函数:


    可执行语句很少,基本上注释已经完全涵盖了这个函数的作用。主要是在pox注册一个新的线程,如果已存在名字则重载,返回新的实例。同时我们看到在这个函数里面使用到了register()函数,函数定义如下:


    Register()实现了在初始化的时候,将相关组件加入到了pox.core.core之中。这时Core raise了一个ComponentRegistered事件,是以组件为参数注册事件。

    注册阶段结束了?还没有,有一个问题还没有解决:组件的event_handler是如何与events绑定在一起的呢?

    组件与事件的关系:(事件绑定)


    上面可以看出:组件通过监听内核core来注册事件。

    这时就需要listenTo()函数,经过查找在revent.py里面:


    这时接着调用autoBindEvents()函数:


    从注释中我们可以看出这个函数的作用:

    无非就是讲handler端的sink和event的source连接起来,方式就是先在sink端将所有event的名字放在一个字典中,然后在sink中寻找带有“__handle__event”的函数,最后,如果两边有对应的event和handler,就建立连接。


    其中又调用了addListener()函数,这个函数的功能最重要:



    建立一个与eventType对应的handlers,将带有handler和eid等信息的entry添加到handlers队列中,priority决定这个handlers在处理时的优先级,若无特殊优先级,则按正常顺序放在队尾

    下面还有一个问题:handler在哪?这个问题关系到事件如何被处理。其实,从autoBindEvent的函数定义可以看到,最后addListener函数的执行对象是source。也就是说,handler列表在发起事件的组件中可以看到。因而我们来看source类,即:


    第83行代码中使用raiseEvent()函数,其中参数为组件注册。来看raiseEvent函数:


    就这样事件就绑定完成了。

    POX的过程图如下:


    额外的一个小case:在POX中添加新模块,将新模块存入ext文件夹,可以通过参数,直接调用。如:

    copy一个模块(forwarding.l2_learning.py)到ext文件夹中,改名为ext/my_component.py,执行新模块为:./pox.py my_component.

    以上的学习是在网上看北邮赵伟明的blog,加上自己的理解总结的,看完后发现制定POX控制器团队的优秀,还有就是自己暂时分析到这里,当然还有好多代码也没有看,需要今后边学边看,自己还需要很长的道路需要走,需要更加努力,这样才能在SDN的学习有更多自己的成果。




    展开全文
  • (需翻墙)pox控制器自带的保持负载均衡的规则代码附在后面: 基于ryu的负载均衡:https://www.sdnlab.com/10211.html https://www.cnblogs.com/levylovepage/p/11251065.html 2.创建topo 启动h1 和 h2 的...

    1.教程链接:

    (需翻墙)pox控制器自带的保持负载均衡的规则代码附在后面:

    基于ryu的负载均衡:https://www.sdnlab.com/10211.html

    https://www.cnblogs.com/levylovepage/p/11251065.html

    2.创建topo

    启动h1 和 h2 的命令行面板:  然后使得h1 h2 作为web服务器:

    开启pox控制器,开启官方自带策略loadbalancer 并且指定ip和服务器的ip运行

    然后用h3 4 5 6主机的控制台去访问服务器

     

     

    3.pox控制器官方的策略代码:

    https://download.csdn.net/download/Taylor_Ocean/12235925

    展开全文
  • pox控制器学习笔记

    千次阅读 2020-04-06 23:03:01
    一、安装pox pox基于python2.7 $ git clone http://github.com/noxrepo/pox $ cd pox ~/pox$ git checkout dart 二、调用pox 如果想快速入门 ./pox.py samples.pretty_log Forwarding.l2_learning POX本身有几...

    一、安装pox

    pox基于python2.7

    $ git clone http://github.com/noxrepo/pox
    $ cd pox
    ~/pox$ git checkout dart
    

    二、调用pox

    1. 如果想快速入门
    ./pox.py samples.pretty_log Forwarding.l2_learning
    
    1. POX本身有几个可选的命令行参数,这些参数可以在命令行开始时使用:
    选项 含义
    –no-cli 不要启动交互式shell(从betta开始不再适用
    –no-openflow 不要自动开始侦听OpenFlow连接(从dart开始有用,它仅按需加载OpenFlow)
    –verbose 显示其他信息(对于调试启动问题特别有用)

     

    l2_learning具有“透明”模式,其中交换机甚至将转发通常丢弃的数据包(例如LLDP消息),并且Web服务器的端口号可以从默认值(8000)更改为任意端口

    eg:
    ./pox.py --no-cli Forwarding.l2_learning --transparent web.webcore --port = 8888
    

     

    三、POX中的组件

    3.1库存成分

    1. py
      该组件使POX启动一个交互式Python解释器,该解释器可用于调试和交互式实验。在betta版本之前,这是默认行为

    2. forwarding.hub
      仅在每个交换机上安装通配泛洪规则

    3. Forwarding.l2_learning
      使OpenFlow交换机充当L2学习交换机的一种。当此组件学习L2地址时,它安装的流在尽可能多的字段上都是完全匹配的。

    4. forward.l2_pairs
      像l2_learning一样,此组件也使OpenFlow交换机的行为类似于L2学习交换机的类型。但是,与l2_learning不同,l2_pairs仅基于MAC地址安装规则。

    5. Forwarding.l3_learning
      它最有用的方面是作为使用POX的数据包库检查和构造ARP请求和答复的一个很好的例子。l3_learning并不真正在乎诸如子网之类的传统IP东西,它只是了解IP地址在哪里。

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

    7. forwarding.l2_nx
      Open vSwitch的quick-and-dirty组件,需要使用Openvswitch的Nicira扩展安装。

    8. forwarding.topo_proactive
      基于重要拓扑的IP地址安装规则。通过DHCP进行地址分配。

    9. openflow.spanning_tree
      该组件使用discovery组件来创建网络拓扑的视图,构造一棵生成树,然后使不在生成树中的交换机端口的洪泛功能失效,使得网络中不存在洪泛回路。
      两个选项:
        --no-flood,只要交换机连接上了就使该交换机的所有端口洪泛失效,对于某些端口,稍后将使能。
        --hold-down,防止洪泛控制在一个完整的发现回路完成前被改变
      因此该组件最安全的的使用方法是
      openflow.spanning_tree --no-flood --hold-down .

    10. openflow.webservice
      Openflow的一个简单JSON-RPC-ish web service交互式接口,由of_service信息服务派生而来,依赖于webcore组件。可以使用HTTP POST方式发送JSON进行访问。
      目前支持的方法有:
      get_flow_stats,获取流表的表项
      get_switch_desc,获取指定交换机详细信息
      get_switches,获取交换机列表和基本信息
      set_table , 设置指定交换机的流表

    11. web.webcore
      在Pox进程中启动一个web服务,其他组件可以通过它提供静态或动态内容。

    12. 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服务进行交互。

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

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

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

    16. openflow.keepalive
      该组件令POX向已经连接的交换机周期性的发送echo请求。但这会解决两个问题:
      第一,有些交换机(包括推荐交换机)会认为空闲连接意味着同控制器连接丢失,将会在一段silence时间后断开
      连接。
      第二,如果网络与交换机断开,控制器将不会立即获得一个FIN或RST,所以将会很难确定一个交换机失效。通过周期行发送echo请求,并分析交换机的响应,即可解决该问题。

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

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

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

    20. proto.dns_spy
      检测DNS应答并存储应答结果,其他组件可以通过DNSSpy检测这些信息。

    21. proto.dhcp_client
      DHCP客户端,在同其他组件进行联合时有用(??)

    22. proto.dhcpd
      简单的DHCP服务器端,服务器本身的默认地址为192.168.0.254,下发的地址域为192.168.0.1~192.168.0.253,同时宣称自身为网关和DNS服务器。

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

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

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

    26. misc.nat
      实现网络地址转换的组件(木有详细介绍)

    27. misc.ip_loadbalancer
      由carp branch(不理解是啥)启用的TCP负载均衡器

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

    3.2 自定义组件

    1. ext目录
      “ ext”目录是构建您自己的组件的方便位置,因为POX会自动将其添加到Python搜索路径(即在其中查找其他模块),并且将其从POX git存储库中排除。
      开始构建自己的POX模块的一种常见方法是简单地将现有模块(例如forwarding/l2_learning.py)复制到ext目录(例如ext/my_component.py)中。

    四、POX API

    4.1 pox core对象

    pox是许多pox api的中心点,它提供的某些功能只是围绕其他功能的便捷包装,而有些则是唯一的。但是,核心对象的另一个主要目的是在组件之间提供一个集合点。

    1. 注册组件
      对于组件来说,将提供api的对象注册在核心对象上会更方便。在OpenFlow实施中可以找到一个示例POS OpenFlow组件默认将OpenFlowNexus的实例住粗为core.openflow,然后其它程序可以从哪里访问许多OpenFlow功能。
    2. 依赖和事件管理
      当pox中的组件依赖于其它组件,通常是因为他们想要监听该组件的事件。(例子看不懂)

    4.2 使用地址:pox.lib.addresses

    POX中的IPv4,IPv6和以太网地址由pox.lib.addresses的IPAddr,IPAddr6和EthAddr类表示。

    from pox.lib.addresses import IPAddr, IPAddr6, EthAddr
     
    ip = IPAddr("192.168.1.1")
    print str(ip) # Prints "192.168.1.1"
    print ip.toUnsignedN() # Convert to network-order unsigned integer -- 16885952
    print ip.raw # Returns a length-four bytes object (a four byte string, more or less)
     
    ip = IPAddr(16885952,networkOrder=True)
    print str(ip) # Also prints "192.168.1.1" !
    

    4.3 事件系统:pox.lib.revent

    POX中的事件都是revent.Event实例的子类。引发事件的类从revent.EventMixin继承,并声明它在eventMixin.events的类级变量中引发的事件。

    4.3.1 处理事件

    1. 事件处理程序
      它是一个函数或方法或可调用的其它东西,只有一个参数
    2. 聆听事件
    chef.addListener(SpamFinished, spam_ready)
    or
    chef.addListenerByName("SpamFinished", spam_ready)
    
    1. 自动设置监听器
      使用addListeners()侦听同一源对象的多个事件。
    class HungryPerson (object):
      """ Models a person that loves to eat spam """
     
      def __init__ (self):
        chef.addListeners(self)  //查看chef的事件,self名称为方法时,为侦听器
     
      def _handle_SpamStarted (self, event):
        print "I can't wait to eat!"
     
      def _handle_SpamFinished (self, event):
        print "Spam is ready!  Smells delicious!"
    
    要用一个类来监听来自多个事件源的事件,用前缀来区分不同的事件。
    
    class VeryHungryPerson (object):
      """ Models a person that is hungry enough to need two chefs """
     
      def __init__ (self):
        master_chef.addListeners(self, prefix="master")
        backup_chef.addListeners(self, prefix="secondary")
     
      def _handle_master_SpamFinished (self, event):
        print "Spam is ready!  Smells delicious!"
     
      def _handle_secondary_SpamFinished (self, event):
        print "Backup spam is ready.  Smells slightly less delicious."
    
    1. 创建自己的事件类型
      事件是子类revent.event,因此创建事件只需创建子类Event
    class SpamStarted (Event):
      def __init__ (self, brand = "Hormel"):
        Event.__init__(self)
        self.brand = brand
     
      @property
      def genuine (self):
        # If it's not Hormel, it's just canned spiced ham!
        return self.brand == "Hormel"
    
    1. 引发事件
    chef.raiseEvent(SpamStarted("Generic"))
    or
    chef.raiseEvent(SpamStarted, "Generic")
    

    4.4 使用数据包:pox.lib.packet

    POX中的许多应用程序都与数据包进行交互(例如,构造数据包并将其发送到交换机之外,或者会通过ofp_packet_inOpenFlow消息从交换机接收到它们)。为方便起见,POX具有用于解析和构造数据包的库。
    pox支持的某些数据包类型包括:

    • ethernet
    • ARP
    • IPv4
    • ICMP
    • TCP
    • UDP
    • DHCP
    • DNS
    • LLDP
    • VLAN

    引用pox数据包库为:import pox.lib.packet as pkt
    包对象的find()方法可用于通过所需的类型名称(例如"icmp")或其类(例如pkt.ICMP)来查找特定的封装包。如果数据包对象未封装所请求类型的数据包,则find()返回无。例如:

    def handle_IP_packet (packet):
      ip = packet.find('ipv4')
      if ip is None:
        # This packet isn't IP!
        return
      print "Source IP:", ip.srcip
    

    4.4.1 以太网(ethernet)

    属性:

    • dst(EthAddr)
    • src(EthAddr)
    • type(int)-以太网类型或以太网长度字段。对于带有VLAN标签的帧,该值为0x8100
      Effective_ethertype(int)-以太网类型或以太网长度字段。对于带有VLAN标签的帧,这将是VLAN标头中引用的类型。

    常数:
    IP_TYPE,ARP_TYPE,RARP_TYPE,VLAN_TYPE,LLDP_TYPE,JUMBO_TYPE,QINQ_TYPE-各种以太类型

    4.4.2 ipv4

    IP版本4(ipv4)
    属性:

    • srcip(IPAddr)
    • dstip(IPAddr)
    • tos(int)-8位服务类型/ DSCP + ECN
    • id(int)-标识字段
    • 标志(int)
    • frag(int)-片段偏移
    • ttl(int)
    • protocol(int)-有效负载的IP协议编号
    • csum(int)-校验和

    常数:
    ICMP_PROTOCOL,TCP_PROTOCOL,UDP_PROTOCOL-各种IP协议编号
    DF_FLAG-不分段标志位
    MF_FLAG-更多片段标志位

    4.4.3 tcp

    属性:

    • srcport(int)-源TCP端口号
    • dstport(int)-目标TCP端口号
    • seq(int)-序列号
    • ack(int)-ACK号
    • off(int)-偏移量
    • flags(int)-标记为位字段(更易于使用全大写标记属性)
    • csum(int)-校验和
    • options(tcp_opt对象的列表)
    • win(int)-窗口大小
    • urg(int)-紧急指针
    • FIN(bool)-设置FIN标志时为真
    • SYN(bool)-设置SYN标志时为True
    • RST(bool)-设置RST标志时为true
    • PSH(bool)-设置PSH标志时为true
    • ACK(bool)-设置ACK标志时为真
    • URG(bool)-设置URG标志时为真
    • ECN(bool)-设置ECN标志时为true
    • CWR(bool)-设置CWR标志时为true

    常数:
    FIN_flag,SYN_flag等 -与标志对应的位

     
    tcp_opt类

    属性:
    type(int)-TCP选项ID(可能在下面对应于常数)
    val(变量)-选项值
    常数:
    EOL,NOP,MSS,WSOPT,SACKPERM,SACK,TSOPT-选项类型ID

    4.4.4 arp messages

    def _handle_PacketIn (self, event):
        packet = event.parsed
        if packet.type == packet.ARP_TYPE:
            if packet.payload.opcode == arp.REQUEST:
                arp_reply = arp()
                arp_reply.hwsrc = <requested mac address>
                arp_reply.hwdst = packet.src
                arp_reply.opcode = arp.REPLY
                arp_reply.protosrc = <IP of requested mac-associated machine>
                arp_reply.protodst = packet.payload.protosrc
                ether = ethernet()
                ether.type = ethernet.ARP_TYPE
                ether.dst = packet.src
                ether.src = <requested mac address>
                ether.payload = arp_reply
                #send this packet to the switch
                #see section below on this topic
            elif packet.payload.opcode == arp.REPLY:
                print "It's a reply; do something cool"
            else:
                print "Some other ARP opcode, probably do something smart here"
    

    五、pox中的OpenFlow

     

    5.1DPID:

    OpenFlow中每个数据路径(交换机)具有唯一的数据路径ID或DPID,该ID或DPID是64位值,并且在握手期间通过ofp_switch_features消息从交换机传递到控制器。

    5.2 与数据路径通信

    1. 1)当从控制器到交换机进行通信时,这是由控制器代码执行的,该代码将OpenFlow消息发送到特定的交换机(稍后对此进行详细介绍)。2)当消息来自交换机时,它们作为事件显示在POX中您可以为其编写事件处理程序–通常,有一个事件类型对应于交换机可能发送的每种消息类型。
    2. 与POX中的数据路径进行通信的方式基本上有两种:通过Connection该特定数据路径的对象通过管理该数据路径的OpenFlow Nexus。Connection连接到POX的每个数据路径都有一个对象,并且通常有一个OpenFlow Nexus管理所有连接。
    3. 在正常配置中,只有一个OpenFlow关系,可以作为core.openflow。两者之间有很多重叠Connections和Nexus。
    4. 侦听所有事件时可以选择侦听nexus,只对一个交换机感兴趣时侦听connection。

    5.2.1 connection对象

    每次开关连接到POX时,都会有一个关联的Connection对象。

    connection对象属性 描述
    ofnexus 对与此连接关联的关系对象的引用
    dpid 交换机的数据路径标识符
    features 交换机在握手过程中具有交换机发送的回复
    ports 交换机上的端口。此属性是对特殊PortCollection对象的引用,有端口号,以太网地址,端口名称
    sock 连接到对等方的套接字。
    send(msg) 一种用于向交换机发送OpenFlow消息的方法。

    使用方法:self.connections = set()

    5.2.2 Nexus – core.openflow

    一个OpenFlow nuxus 本质上是一组OpenFlow的管理器Connections。

    属性 描述
    miss_send_len 当数据包与数据路径上的任何表条目都不匹配时,数据路径将在数据包进入消息中将数据包转发到控制器。
    clear_flows_of_connect 如果为True(默认值),则POX在连接时将删除交换机第一个表上的所有流。
    connections 一个特殊的集合,包含对该关系正在处理的所有连接的引用。
    getConnection(< dpid>) 通过其DPID或特定(如果不可用)获取特定数据路径的connection对象。
    sendToDPID(< dpid>,< msg>) 将OpenFlow消息发送到特定的数据路径,如果未连接数据路径,则丢弃该消息(并记录警告)。

    nexus本质上是一个字典,其中的键是DPID,值是Connection对象。

    5.3 openflow事件:对交换机的响应

    大多数与OpenFlow相关的事件都是直接响应从交换机收到的消息而引发的。
    与openflow相关的event具有以下三个属性:

    属性 类型 描述、
    connection connection 与相关交换机的连接(例如,发送此事件对应的消息的交换机)
    ofp ofp_header子类 导致此事件的OpenFlow消息对象。
    dpid long 相关交换机的数据路径ID

    5.3.1 ConnectionUp

    不会响应于从交换机接收到特定的OpenFlow消息而发出-只是响应于通过开关建立新的控制通道而触发。

    属性 类型 描述
    ofp ofp_switch_features 包含有关交换机的信息,例如受支持的操作类型和端口信息

    5.3.2 ConnectionDown

    此事件不会在响应实际的OpenFlow消息时触发,仅在终止与交换机的连接时触发该事件。

    5.3.3 PortStatus

    class PortStatus (Event):
      def __init__ (self, connection, ofp):
        Event.__init__(self)
        self.connection = connection
        self.dpid = connection.dpid
        self.ofp = ofp
        self.modified = ofp.reason == of.OFPPR_MODIFY
        self.added = ofp.reason == of.OFPPR_ADD
        self.deleted = ofp.reason == of.OFPPR_DELETE
        self.port = ofp.desc.port_no
    

    5.3.4 FlowRemoved

    当控制器ofp_flow_removed从交换机接收到OpenFlow流删除消息()时引发事件

    属性 类型 含义
    idleTimeout bool 如果由于闲置而删除了条目,则为真
    hardTimeout bool 如果条目由于超时而被删除,则为真
    timeout bool 如果条目由于任何超时而被删除,则为True
    deleted bool 如果条目被明确删除则为真

    5.3.5 Statistics Events

    事件 openflow统计类型
    SwitchDescReceived ofp_desc_stats
    FlowStatsReceived ofp_flow_stats
    AggregateFlowStatsReceived ofp_aggregate_stats_reply
    TableStatsReceived ofp_table_stats
    PortStatsReceived ofp_port_stats
    QueueStatsReceived ofp_queue_stats

    5.3.6 PacketIn

    当控制器收到openflow的packet-in消息时触发。该消息表示到达交换机端口的包未能匹配表中的所有条目,或者匹配条目包括的动作–指定发送该包的到控制器。
    除了通常的openflow事件属性外:

    • port(int)-数据包进入的端口号
    • data(bytes)-原始数据包数据
    • 解析(包子类)-pox.lib.packet的解析版本
    • ofp(ofp_packet_in)-导致此事件的OpenFlow消息

    5.3.7 ErrorIn

    当从交换机收到一个openflow错误时触发。
    除了通常的openflow事件属性外:

    属性 含义
    should_log 通常,OpenFlow错误会导致出现日志消息。如果处理ErrorIn事件,则可以将此属性设置为False,以使默认日志消息静音。
    asString() 将此错误格式化为字符串。

    5.3.8 BarrierIn屏障进入

    当控制器从交换机接收到OpenFlow屏障回复时触发,表明交换机已在相应的屏障请求之前完成了控制器发送的处理命令.
     

    5.4 openflow消息

    OpenFlow消息是OpenFlow交换机与控制器进行通信的方式。

    5.4.1 ofp_packet_out-从交换机发送数据包

    该消息的主要目的是指示交换机发送数据包(或使其入队)。但是,它也可用作指示交换机丢弃缓冲的数据包的方法。

    属性 类型 默认 描述
    in_port int OFPP_NONE 重新发送数据包时,数据包到达的交换端口。
    data 字节/以太网/ ofp_packet_in ‘’ 要发送的数据
    buffer_id int/none none 数据包存储在数据路径中的缓冲区的ID。如果您不是按ID重新发送缓冲区,请使用“无”。
    actions ofp_action_XXXX的清单 [ ] 如果只有一个项目,则也可以使用初始化程序的命名参数“ action”进行指定。

    ~~

    附:
    在这里插入图片描述

    
    """
    A stupid L3 switch
    
    For each switch:
    1) Keep a table that maps IP addresses to MAC addresses and switch ports.
       Stock this table using information from ARP and IP packets.
    2) When you see an ARP query, try to answer it using information in the table
       from step 1.  If the info in the table is old, just flood the query.
    3) Flood all other ARPs.
    4) When you see an IP packet, if you know the destination port (because it's
       in the table from step 1), install a flow for it.
    """
    
    from pox.core import core
    import pox
    log = core.getLogger()
    
    from pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST
    from pox.lib.packet.ipv4 import ipv4
    from pox.lib.packet.arp import arp
    from pox.lib.addresses import IPAddr, EthAddr
    from pox.lib.util import str_to_bool, dpid_to_str
    from pox.lib.recoco import Timer
    
    import pox.openflow.libopenflow_01 as of
    
    from pox.lib.revent import *
    
    import time
    
    # Timeout for flows
    FLOW_IDLE_TIMEOUT = 10
    
    # Timeout for ARP entries
    ARP_TIMEOUT = 60 * 2
    
    # Maximum number of packet to buffer on a switch for an unknown IP
    MAX_BUFFERED_PER_IP = 5
    
    # Maximum time to hang on to a buffer for an unknown IP in seconds
    MAX_BUFFER_TIME = 5
    
    
    class Entry (object):
      """
      Not strictly an ARP entry.
      We use the port to determine which port to forward traffic out of.
      We use the MAC to answer ARP replies.
      We use the timeout so that if an entry is older than ARP_TIMEOUT, we
       flood the ARP request rather than try to answer it ourselves.
      """
      def __init__ (self, port, mac):
        self.timeout = time.time() + ARP_TIMEOUT
        self.port = port
        self.mac = mac
    
      def __eq__ (self, other):
        if type(other) == tuple:
          return (self.port,self.mac)==other
        else:
          return (self.port,self.mac)==(other.port,other.mac)
    
      def __ne__ (self, other):
        return not self.__eq__(other)
    
      def isExpired (self):
        if self.port == of.OFPP_NONE: return False
        return time.time() > self.timeout
    
    
    def dpid_to_mac (dpid):
      return EthAddr("%012x" % (dpid & 0xffFFffFFffFF,))
    
    
    class l3_switch (EventMixin):
      def __init__ (self, fakeways = [], arp_for_unknowns = False, wide = False):
        # These are "fake gateways" -- we'll answer ARPs for them with MAC
        # of the switch they're connected to.
        self.fakeways = set(fakeways)
    
        # If True, we create "wide" matches.  Otherwise, we create "narrow"
        # (exact) matches.
        self.wide = wide
    
        # If this is true and we see a packet for an unknown
        # host, we'll ARP for it.
        self.arp_for_unknowns = arp_for_unknowns
    
        # (dpid,IP) -> expire_time
        # We use this to keep from spamming ARPs
        self.outstanding_arps = {}
    
        # (dpid,IP) -> [(expire_time,buffer_id,in_port), ...]
        # These are buffers we've gotten at this datapath for this IP which
        # we can't deliver because we don't know where they go.
        self.lost_buffers = {}
    
        # For each switch, we map IP addresses to Entries
        self.arpTable = {}
    
        # This timer handles expiring stuff
        self._expire_timer = Timer(5, self._handle_expiration, recurring=True)
    
        core.listen_to_dependencies(self)
    
      def _handle_expiration (self):
        # Called by a timer so that we can remove old items.
        empty = []
        for k,v in self.lost_buffers.iteritems():                 '''不知道self.lost_buffers的表项是如何'''
          dpid,ip = k
    
          for item in list(v):                                         '''v是一个表项,expires_at,buffer_id,in_port'''
            expires_at,buffer_id,in_port = item                     """,expires_at是到期时间,buffer_id为数据包存储再数据路径中的缓冲区id"""
            if expires_at < time.time():
              # This packet is old.  Tell this switch to drop it.
              v.remove(item)
              po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port)          '''交换机发出的消息'''
              core.openflow.sendToDPID(dpid, po)              '''将OpenFlow消息发送到特定的数据路径,如果未连接数据路径,则丢弃该消息'''
          if len(v) == 0: empty.append(k)                   '''条目如果是空的,则将该表项的dpid和ip加入empty'''
    
        # Remove empty buffer bins
        for k in empty:
          del self.lost_buffers[k]           '''删除empty中的表项'''
    
      def _send_lost_buffers (self, dpid, ipaddr, macaddr, port):
        """
        We may have "lost" buffers -- packets we got but didn't know
        where to send at the time.  We may know now.  Try and see.
        """
        if (dpid,ipaddr) in self.lost_buffers:                            '''如果有dpid和主机的ip在缓冲区内'''
          # Yup!
          bucket = self.lost_buffers[(dpid,ipaddr)]                        '''bucket为一个表项,expires_at, buffer_id, in_port'''
          del self.lost_buffers[(dpid,ipaddr)]                  '''丢掉该表项'''
          log.debug("Sending %i buffered packets to %s from %s"
                    % (len(bucket),ipaddr,dpid_to_str(dpid)))
          for _,buffer_id,in_port in bucket:                     '''对于上述提取的表项发送数据包,设置目的mac和出端口并发送到特定的数据路径,如果不存在,就丢失'''
            po = of.ofp_packet_out(buffer_id=buffer_id,in_port=in_port)            '''从交换机发出的消息,参数有buffer_id,in_port,actions,date'''
            po.actions.append(of.ofp_action_dl_addr.set_dst(macaddr))             '''添加设置目的mac地址的动作'''
            po.actions.append(of.ofp_action_output(port = port))                    '''设置出端口'''
            core.openflow.sendToDPID(dpid, po)                    '''将OpenFlow消息发送到特定的数据路径,如果未连接数据路径,则丢弃该消息'''
    
      def _handle_openflow_PacketIn (self, event):
        dpid = event.connection.dpid                            '''connection对象有ofnexus,dpid,features,ports,sock,send(msg)对象'''
        inport = event.port
        packet = event.parsed                                '''pox.lib.packet的解析版本'''
        if not packet.parsed:             '''如果不能解析,则丢弃该数据包'''
          log.warning("%i %i ignoring unparsed packet", dpid, inport)
          return
    
        if dpid not in self.arpTable:          '''如果交换机的dpid不在arp表中'''
          # New switch -- create an empty table
          self.arpTable[dpid] = {}                 '''创建一个该交换机的arp表项'''
          for fake in self.fakeways:              '''将该交换机匹配虚拟网关加入arptable中'''
            self.arpTable[dpid][IPAddr(fake)] = Entry(of.OFPP_NONE,
             dpid_to_mac(dpid))
    
        if packet.type == ethernet.LLDP_TYPE:                  '''如果包类型是lldp(链路层发现协议)则丢弃'''
          # Ignore LLDP packets
          return
    
        if isinstance(packet.next, ipv4):             '''如果报文是ipv4的话执行,next中包含  包类型,源地址和目的地址 '''
          log.debug("%i %i IP %s => %s", dpid,inport,
                    packet.next.srcip,packet.next.dstip)
    
          # Send any waiting packets...
          self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport)      '''尝试能不能从缓冲区发出去(next.srcip就是ipaddr)'''
    
          # Learn or update port/MAC info
          if packet.next.srcip in self.arpTable[dpid]:                   '''如果包源ip在arp表中'''
            if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src):    '''如果arp表项的入端口和包源地址不匹配'''
              log.info("%i %i RE-learned %s", dpid,inport,packet.next.srcip)
              if self.wide:
                # Make sure we don't have any entries with the old info...
                msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)           '''删除所有流表项'''
                msg.match.nw_dst = packet.next.srcip                         '''设置流表项目的地址为包的目的地址'''
                msg.match.dl_type = ethernet.IP_TYPE
                event.connection.send(msg)
          else:                                                 '''包源ip不在arp表中'''
            log.debug("%i %i learned %s", dpid,inport,packet.next.srcip)
          self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)             '''对应包dpid和包源地址的条例创建为此包的匹配项目'''
    
          # Try to forward
          dstaddr = packet.next.dstip                    '''取包的目的地址'''
          if dstaddr in self.arpTable[dpid]:             '''如果目的地址在arp表中'''
            # We have info about what port to send it out on...
    
            prt = self.arpTable[dpid][dstaddr].port          '''取表中目的交换机和目的地址对应的端口'''
            mac = self.arpTable[dpid][dstaddr].mac           '''取表中目的交换机和目的地址对应的地址'''
            if prt == inport:                                  '''如果出端口等于入端口,不发送'''
              log.warning("%i %i not sending packet for %s back out of the "
                          "input port" % (dpid, inport, dstaddr))
            else:                                              '''如果出端口不等于入端口,发送'''
              log.debug("%i %i installing flow for %s => %s out port %i"
                        % (dpid, inport, packet.next.srcip, dstaddr, prt))
              actions = []                               '''建立行为列表'''
              actions.append(of.ofp_action_dl_addr.set_dst(mac))                   '''添加动作,为设置目的mac地址'''
              actions.append(of.ofp_action_output(port = prt))                      '''添加动作,为交换机发消息的出端口为arp表中目的交换机的端口'''
              if self.wide:                                 '''如果为广泛匹配'''
                match = of.ofp_match(dl_type = packet.type, nw_dst = dstaddr)            
              else:
                match = of.ofp_match.from_packet(packet, inport)
    
              msg = of.ofp_flow_mod(command=of.OFPFC_ADD,            '''添加流表项'''
                                    idle_timeout=FLOW_IDLE_TIMEOUT,        '''在FLOW_IDLE_TIMEOUT时间内,如果没有报文触发,则该规则删除'''
                                    hard_timeout=of.OFP_FLOW_PERMANENT,       '''到达OFP_FLOW_PERMANENT时间时,无论如何都删除该规则'''
                                    buffer_id=event.ofp.buffer_id,          '''设计数据包存储在数据路径中的缓冲区的ID'''
                                    actions=actions,                         '''动作为动作列表'''
                                    match=match)
              event.connection.send(msg.pack())
          elif self.arp_for_unknowns:                         '''也就是说目的地址不在arp表中'''
            # We don't know this destination.
            # First, we track this buffer so that we can try to resend it later
            # if we learn the destination, second we ARP for the destination,
            # which should ultimately result in it responding and us learning
            # where it is
    
            # Add to tracked buffers
            if (dpid,dstaddr) not in self.lost_buffers:             '''如果交换机的dpid和目的地址不在缓冲区内'''
              self.lost_buffers[(dpid,dstaddr)] = []             '''创建该交换机的表项'''
            bucket = self.lost_buffers[(dpid,dstaddr)]               '''取缓冲区的表项'''
            entry = (time.time() + MAX_BUFFER_TIME,event.ofp.buffer_id,inport)        '''建立条例,当前的时间,条例最大存在时间,数据包存储在数据路径中的缓冲区的ID,入端口'''
            bucket.append(entry)
            while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0]          '''如果bucket项目的长度大于交换机上用于未知ip的最大数据包数'''
    
            # Expire things from our outstanding ARP list...
            self.outstanding_arps = {k:v for k,v in                       
             self.outstanding_arps.iteritems() if v > time.time()}
    
            # Check if we've already ARPed recently
            if (dpid,dstaddr) in self.outstanding_arps:
              # Oop, we've already done this one recently.
              return
    
            # And ARP...
            self.outstanding_arps[(dpid,dstaddr)] = time.time() + 4            '''目的地址表项过期时间为4秒,不再接收'''
    
            r = arp()                                 '''构建一个arp消息'''
            r.hwtype = r.HW_TYPE_ETHERNET                 '''arp消息的类型为以太网'''
            r.prototype = r.PROTO_TYPE_IP                    '''报文proto类型为ip'''
            r.hwlen = 6                         
            r.protolen = r.protolen                 '''协议长度'''
            r.opcode = r.REQUEST                    '''广播请求'''
            r.hwdst = ETHER_BROADCAST               '''广播'''
            r.protodst = dstaddr               '''协议目的为目标地址'''
            r.hwsrc = packet.src               '''源地址是请求包的地址'''
            r.protosrc = packet.next.srcip            '''协议源是请求包源ip'''
            e = ethernet(type=ethernet.ARP_TYPE, src=packet.src,
                         dst=ETHER_BROADCAST)
            e.set_payload(r)             '''将arp消息封装在链路层协议中'''
            log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport,
             r.protodst, r.protosrc))
            msg = of.ofp_packet_out()         '''指示交换机发送数据包'''
            msg.data = e.pack()                               '''将e封装在msg的数据域中'''
            msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
            msg.in_port = inport
            event.connection.send(msg)
    
    
    
        elif isinstance(packet.next, arp):
          a = packet.next                         '''a中有包类型,目的地址,源地址'''
          log.debug("%i %i ARP %s %s => %s", dpid, inport,
           {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
           'op:%i' % (a.opcode,)), a.protosrc, a.protodst)
    
          if a.prototype == arp.PROTO_TYPE_IP:           '''如果a的协议类型为arp协议'''
            if a.hwtype == arp.HW_TYPE_ETHERNET:           '''如果为链路层协议'''
              if a.protosrc != 0:                 '''并且包的协议源地址不为0.0.0.0'''
    
                # Learn or update port/MAC info
                if a.protosrc in self.arpTable[dpid]:                 '''如果协议源地址在arp表中'''
                  if self.arpTable[dpid][a.protosrc] != (inport, packet.src):       '''并且交换机号和源地址不等于入端口和包源地址的是哦胡'''
                    log.info("%i %i RE-learned %s", dpid,inport,a.protosrc)
                    if self.wide:
                      # Make sure we don't have any entries with the old info...
                      msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)   '''删除流表项'''
                      msg.match.dl_type = ethernet.IP_TYPE
                      msg.match.nw_dst = a.protosrc
                      event.connection.send(msg)
                else:
                  log.debug("%i %i learned %s", dpid,inport,a.protosrc)
                self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src)           '''不在的话建立表项'''
    
                # Send any waiting packets...
                self._send_lost_buffers(dpid, a.protosrc, packet.src, inport)       '''尝试把缓冲区发出去'''
    
                if a.opcode == arp.REQUEST:            '''如果操作码为请求'''
                  # Maybe we can answer
    
                  if a.protodst in self.arpTable[dpid]:
                    # We have an answer...
    
                    if not self.arpTable[dpid][a.protodst].isExpired():
                      # .. and it's relatively current, so we'll reply ourselves
    
                      r = arp()
                      r.hwtype = a.hwtype
                      r.prototype = a.prototype
                      r.hwlen = a.hwlen
                      r.protolen = a.protolen
                      r.opcode = arp.REPLY
                      r.hwdst = a.hwsrc
                      r.protodst = a.protosrc
                      r.protosrc = a.protodst
                      r.hwsrc = self.arpTable[dpid][a.protodst].mac
                      e = ethernet(type=packet.type, src=dpid_to_mac(dpid),
                                   dst=a.hwsrc)
                      e.set_payload(r)
                      log.debug("%i %i answering ARP for %s" % (dpid, inport,
                       r.protosrc))
                      msg = of.ofp_packet_out()
                      msg.data = e.pack()
                      msg.actions.append(of.ofp_action_output(port =
                                                              of.OFPP_IN_PORT))
                      msg.in_port = inport
                      event.connection.send(msg)
                      return
    
          # Didn't know how to answer or otherwise handle this ARP, so just flood it
          log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport,
           {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
           'op:%i' % (a.opcode,)), a.protosrc, a.protodst))
    
          msg = of.ofp_packet_out(in_port = inport, data = event.ofp,
              action = of.ofp_action_output(port = of.OFPP_FLOOD))
          event.connection.send(msg)
    
    
    def launch (fakeways="", arp_for_unknowns=None, wide=False):
      fakeways = fakeways.replace(","," ").split()
      fakeways = [IPAddr(x) for x in fakeways]
      if arp_for_unknowns is None:
        arp_for_unknowns = len(fakeways) > 0
      else:
        arp_for_unknowns = str_to_bool(arp_for_unknowns)
      core.registerNew(l3_switch, fakeways, arp_for_unknowns, wide)
    
    
    展开全文
  • 使用Openflow 1.0的pox控制器上的网络应用程序,它控制单平面以太网,并有望在以太网中启用多路径路由。 它是基于一篇名为“为以太网中的单播流量启用多路径路由”的论文构建的。 您可以在找到文档 更新:此SDN应用...
  • POX控制器源码阅读

    2018-03-23 16:51:45
    pox主要流程概览首先通过命令行参数启动相关组件,组件运行launch函数。在launch函数中,组件一般对组件内的类进行注册。之后组件通过监听core来获取事件1. 启动core和openflow2. 根据参数启动组件3. 组件初始化并...
  • POX的自带的组件来分析: https://blog.csdn.net/jk19920523/article/details/40426341?utm_source=blogxgwz3 开始构建自己的 POX 模块的常用方法是将现有模块(例如 forwarding/l2_learning.py)复制到 ext ...
  • pox控制器学习总结

    千次阅读 2015-11-13 16:30:54
    创建的组件需要注册到控制器上,launch函数中通常有两种方法注册:core.register()、core.registerNew()。这两个函数的区别是:Register()第二个参数传的是组件的实例对象,launch()多次被调用的时候会出现多次注册...
  • POX启动时使用命令:openflow.discovery openflow.spanning_tree --no-flood --hold-down来自:https://openflow.stanford.edu/display/ONL/POX+Wiki/ 原文: openflow.spanning_tree This component uses the ...
  • bellemanford的实现如下: ... Based on [url=https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l2_multi.py]l2_multi.py[/url] pox controller module, I write l2_bellmanford.py which us
  • POX控制器下Dijkstra算法的实现

    千次阅读 2015-12-05 17:41:40
    http://csie.nqu.edu.tw/smallko/sdn/bellmanford2.htm http://csie.nqu.edu.tw/smallko/sdn/pyretic_and_pox.htm from pox.core import core import pox.openflow.libopenflow_01 as of from pox.lib.r
  • 控制器应用程序(POX,Python)连接到交换机,以便修改流规则并平衡所有服务器之间的负载。 客户端不知道后端服务器,他们只知道透明代理(交换机)。 要运行SDN LB,请运行脚本start_lb.sh 。
  • POX SDN控制器包括将网络拓扑的数据发送到数据Gephi可视化平台,可显示节点和表示网络拓扑结构链接的曲线图。 具体操作步骤 启动POX 关于POX的安装可以参考作者的前一篇博客。 首先打开第一个Terminal,开始运行...
  • POX提供一系列API,使用户可以创建自己的组件,实现自己的功能 组件的注册 创建的组件需要注册到core中,使用core的一个主要目的就是为各个组件提供一个集结地。core是类POXcore的一个实例。 向core注册组件,有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,549
精华内容 619
关键字:

pox控制器