Ryu控制器官方应用simple_switch_13.py解读

来源:互联网 发布:我的世界java源代码 编辑:程序博客网 时间:2024/04/23 18:36

简单分析

  Ryu控制器官方应用simple_switch_13.py实现的是简单的交换机功能。代码难度来说应该算是简单,但对于我这样的新手来说,想要了解下它为什么这么实现。参考ryu-book中的教程,网络拓扑如下:
这里写图片描述
  通过抓包观察,主机第一次相互ping时,会发生3次Packet-in事件;这3次Packet-in事件中又夹杂了两次Flow-Mod(flow_add)。
下面是主机h1第一次ping主机h2时的抓包截图
这里写图片描述

为何会产生3次Packet-in事件

  1. 第一次是因为:主机h1 第一次ping主机h2,最初时主机h1中ARP缓存表为空,所以会产生ARP Request数据包发往交换机s1,被S1初始流表中的“漏表项”匹配然后以Packet-in方式转发至Controller处理;Controller发现该request数据包目的地MAC地址在mac_to_port字典不存在,所以会将该request数据包洪泛至所有端口。Controller回应相应的Packet-out,动作(actions)是将该数据包输出(OFPAT_OUTPUT)至除源端口之外的所有物理端口(OFPP_FLOOD)。
      此时没有新增任何流表项,但是将request数据包来源MAC地址与端口保存至mac_to_port中。
  2. 第二次是因为:主机h2为回应ARP Request生成ARP Reply数据包,但是交换机S1中并没有流表可以处理该reply数据包,所以被S1初始流表中的“漏表项”匹配然后以Packet-in方式转发至Controller处理;Controller发现该reply数据包目的地已经被保存至mac_to_port字典中,所以新增一条表项。同时Controller回应相应的Packet-out,动作(actions)是将该数据包输出(OFPAT_OUTPUT)至端口1
      此时新增了一条流表项(1),同时将reply数据包来源MAC地址与端口保存至mac_to_port中。
    (1)表项内容是:
    cookie=0x0, duration=4.219s, table=0, n_packets=2, n_bytes=196, priority=1,
     in_port=2,dl_dst=00:00:00:00:00:01 actions=output:1
  3. 第三次是因为:交换机没有流表项来处理主机h1的ICMP Request数据包,所以以之前两次同样的Packet-in方式发送至Controller,Controller发现该request数据包目的地已经被保存至mac_to_port字典中,所以新增一条表项。同时Controller回应相应的Packet-out,动作(actions)是将该数据包输出(OFPAT_OUTPUT)至端口2
      此时新增了一条流表项(2),内容是
    cookie=0x0, duration=4.215s, table=0, n_packets=1, n_bytes=98, priority=1,
     in_port=1,dl_dst=00:00:00:00:00:02 actions=output:2

最终流表是:

cookie=0x0, duration=4.219s, table=0, n_packets=2, n_bytes=196, priority=1,
 in_port=2,dl_dst=00:00:00:00:00:01 actions=output:1
cookie=0x0, duration=4.215s, table=0, n_packets=1, n_bytes=98, priority=1,
 in_port=1,dl_dst=00:00:00:00:00:02 actions=output:2
cookie=0x0, duration=79.866s, table=0, n_packets=3, n_bytes=182, priority=0
 actions=CONTROLLER:65535

  最后一条是“漏表项”。OpenFlow1.3及以上版本增加了一个“漏表项”概念,附在每张流表最后,优先级最低,用来匹配处理所有失配的数据包;所以在控制器启动时与交换机连接后,就需要向交换机写入这张表项。

我的疑问

我主要有两个疑问
- 为什么要有3次Packet-in事件?可以的话应该1次就够了。
- 为什么simple_switch_13.py代码中下发的流表项有两个匹配项:in_porteth_dst?总觉得使用 eth_dst这一个匹配项就够了。

为什么1次Packet-in就够了

  这有且仅有1次的Packet-in事件是因为ARP广播,这一次肯定会发生,因为在h1主机 第一次ping主机h2之前交换机只有一条漏表项,并不能处理任何数据包,任何数据包都会被送往控制器处理。
  如果在ARP Request广播帧产生时,记录导致这个广播帧发生的数据包来源,即我可以记录导致广播帧产生的数据包来源端口与这个端口所连接的主机MAC与IP地址;这时候马上添加一条流表,目的是:

把之后发往这个主机MAC或者这个主机IP的数据包从该request来源端口发出去

  ARP Request广播帧会从除了来源端口之外得所有端口广播出去,然后就有一个主机发送ARP Reply数据包,然后reply数据包就会被上面添加的流表项匹配处理,发送request主机。
这时候由于ARP Reply数据包携带了reply主机的信息,就可以利用这些信息新建一条流表项,目的是:

把之后发往此主机MAC或者此主机IP的数据包从该reply来源端口发出去

这样,就只会产生一次Packet-in事件,但是Flow-Mod事件不会减少。

为什么只需要 eth_dst这一个匹配项

  官方的simple_switch_13.py代码中下发的流表项有两个匹配项:in_porteth_dst;即根据数据报的来源端口与目的MAC地址匹配得到数据报目的端口进行转发。
  普通交换机的MAC地址表匹配项只有一个:eth_dst;即根据数据报的目的MAC地址匹配得到数据报目的端口进行转发。
  所以我觉得simple_switch_13.py中的in_port匹配项纯属多余,还增加了流表项数目,所以尝试去掉in_port匹配项。

  这两个疑问是从第一次看完simple_switch_13.py就有的,后面一段时间有时想想,能感觉到其中肯定有没考虑到的地方,但是又说不清楚,因为是初学Ryu。所以决定做个试验,彻底解决这些疑问。

1 0