美文网首页
131SDN 软件定义网络动手实验--Ryu 的 REST AP

131SDN 软件定义网络动手实验--Ryu 的 REST AP

作者: Jachin111 | 来源:发表于2021-09-05 14:45 被阅读0次

    推荐阅读

    本节实验推荐阅读下述内容:
    ryu 官方手册
    openflow 的流表项
    open vswitch 的常用命令

    Ryu 的 APP 使用

    在充分的了解底层的工作者,我们明白 SDN 中交换机只是一个执行者,只是通过其数据库中的各种表格来进行操作,而操控这些底层工作者的是控制器,由控制器来下发流表等操作来真正的控制数据流的走向。

    在之前我们我们说过我们将使用 Ryu 控制器来作为我们学习的工具,首先我们来回顾一下我们使用 Ryu 控制器的三种方式:
    在外部启动,通过指定 ip 地址、端口来连接
    直接指定 ryu 控制器
    通过 xterm 来制定控制器

    1.在外部启动 ryu,通过制定 ip 地址来连接
    首先我们启动 ryu-manager:

    ryu-manager
    
    image.png

    然后我们再打开一个终端,在该终端中使用 mininet 远程连接:

    sudo mn --controller=remote,ip=127.0.0.1
    

    此时我们在打开一个终端我们可以通过这样的命令来判断我们的 mininet 是否连接上了 ryu 控制器:

    sudo ovs-vsctl show
    

    在上章节中的结构图中我们了解到 ovs-vsctl 命令是控制 ovsdb 的工具,通过该工具我们可以修改查看 ovsdb 中的一些配置信息,如使用 show 参数我们便可查看当前的网络:


    image.png

    从显示的信息中我们可以看到 is_connected 值为 true,说明 mininet 中的 switch 已经成功的与我们的 ryu 控制器相连接,因为我们是首先启动的 ryu,会占用 6653 端口,并且 controller 指定为 remote,所以这并不是默认所指定的 pox 控制器。
    这便是第一种方式启动、连接 ryu 的方法

    2.直接指定 ryu 控制器
    在 2.2.2 版本中,mininet 修复了 ryu 控制器的支持,所以我们可以直接通过 controller 来指定 ryu:

    sudo mn --controller=ryu
    
    image.png

    由此我们便可直接使用 ryu 控制器,十分的便捷,我们用 dump 命令查看其中的详情,确定使用的是 ryu 控制器:


    image.png

    同样使用 ovs-vsctl show 来确定成功连接了控制器:


    image.png
    这便是直接指定 ryu 的方式

    3.在 xterm 中连接控制器
    还有一种方式是在 controller 的 xterm 中启动要使用的控制器.
    首先启动 mininet:

    sudo mn --controller=remote -x
    

    x 参数可以在启动的同时帮我们开启每个节点的 xterm:


    image.png

    然后我们找到 c0 的 xterm 窗口,也就是 controller 所对应的终端窗口,在这里面我们启动 ryu:

    ryu-manager
    
    image.png

    同样我们可以使用上述的方式来检测我们的 controller 是否连接成功。
    这是 ryu 的启动,我们使用 cd /home/shiyanlou/ryu/ryu/app 切换至 ryu 中我们可以看见其中有很多的事例,如不同版本的支持,有 API 的支持,有 stp 的功能支持,有路由、Qos、防火墙等等功能的支持。
    我们只需要在启动 ryu 的同时指定运行想要的功能的程序即可。例如 simple_switch_13.py 便是一个实现对 openflow 1.3 支持的普通交换机,如何来运行它呢?
    我们使用 xterm 的方式来实验一次如何使得我们的网络使用 openflow1.3 的协议。
    首先我们启动 mininet:

    sudo mn --controller=remote -x
    

    从上一章的实验中我们可以发现默认情况下使用的协议是 openflow1.0,所以首先我们需要在 switch 的 xterm 中为其指定使用 openflow 协议使用的版本,否在 hello 包协商时会出错。
    首先我们启动 simple_switch_13,让 controller 端使用 openflow1.3 版本,在此之前别忘记启动 wireshark 开启数据包的抓取:

    ryu-manager --verbose ryu.app.simple_switch_13
    
    image.png

    此时我们在终端,在 wireshark 都可以看到因协商失败而产生的报错与错误数据包的信息:


    image.png

    hello 数据包的阶段就是为了协商 controller 与 switch 之间相互通信的 openflow 协议的版本,毕竟低版本的 openflow 并不能支持高版本 openflow,所以此时协商失败便会导致连接不成功。
    在这个时候我们需要使用 ovs-vsctl 来设置此时 switch 使用的 openflow 的版本:

    ovs-vsctl set Bridge s1 protocols=OpenFlow13
    

    我们在上一章说过其实 datapath 的作用就是转发数据包,本质就像是一个网桥,而 mininet 的实现就是使用 openvswitch 创建网桥,如这样的命令 ovs-vsctl add-br s1,所以此处我们是修改 switch 支持协议的版本所以使用的参数是 set Bridge,紧接着我们通过 protocols 参数来指定支持的协议版本。由此便可使得 s1 设备支持 openflow1.3 的版本。


    image.png

    既然 switch 可以通过命令的方式来创建,是否 host 也能通过这样的方式来启动?
    host 我们探究过是使用不同的 namespace 来隔离实现虚拟化,所以若是使用命令来实现便是 ip netns add h1,而主机间的连接或者与 switch 之间的连接可以通过 ip link add 命令来连接,所以其实这是第四种自定义的方式,但是这样的方式有一定的门槛,需要对 openvswitch 与 linux 一些不是特别常用的命令很熟悉,这也是为什么我们在第一章中选择了 mininet 而没有选择 openvswitch 的方式来模拟网络,mininet 抽象出了一些简单易用的接口,隐藏了这些繁复的操作,减小了我们的学习成本,让我们更容易上手,同样让我们在模拟网络的时候也便捷了不少。
    此时我们可以看到 c0 窗口中的提示立即发生了变化:


    image.png
    与此同时我们也可以看到 controller 结束了暗无天日的 of_echo_reply 的数据包发送,进入了正常的流程中:
    image.png

    我们可以通过这样的方式来查看此时是否能够正常的通信:

    pingall
    
    image.png

    所有的数据包都通过,没有被丢的数据包,于此同时我们可以查看控制器中的信息:


    image.png

    因为刚刚启动的控制器与 switch,所以此时的流表示空的,当 datapath 接受 ping 所再来的数据包是并不知道该如何处理,所以只有向上汇报请示 controller,所以 controller 会接受到 pactet in 的处理,通过 h1 ifconfig 我们可以得知 e6:30:60:84:d0:f5 这个 Mac 地址是属于 h1 的,而 ff:ff:ff:ff:ff:ff 是一个广播泛洪的地址,这是因为 h1 向 h2 发送 ping 数据包,但是并不知道 h2 的 ip 地址与 Mac 地址,此时就会泛洪,而当事人回复该数据包时,switch 就会将这两个 Mac 地址记录下来,这样 h1 与 h2 之间就可以相互通信了。
    当然我们在此使用 pingall 命令,便会发现控制器中没有再接收到 packet in 的事件,这便是 controller 在 packet out 的同时下发流表,更新了 switch 中的流表,后续 datapath 接受到数据包与流表项匹配,匹配成功便执行其对应的操作,所以这样便不会有 packet in 的事件了。
    我们可以通过这样的命令来查看此时的流表项:

    ovs-ofctl dump-flows -O openflow13 s1
    
    image.png

    可以看到此时多了三个流表项,分别是:
    发送给 h1 的处理方式
    发送给 h2 的处理方式
    以及没有匹配到则发送给控制器

    此时添加了 -O 参数是我们使用了 openflow13 来通信,若是不添加该参数指明使用的协议版本默认使用的 openflow1.0,如此会有这样的报错:


    image.png

    这就是使用自定义应用的方式,我们只需要在启动的时候在参数中指定即可,而这样的应用可以让我们实现各种各样的功能,这就是 SDN 的灵魂所在,数据层与控制层的分离,功能的自由添加,实现。

    Ryu 的 API 使用

    不仅如此,我们还可以使用 REST API 来控制 controller 的一些行为,如下发流表、删除流表项等等,这样使得我们在一些临时的变动时更易修改,若是传统的机制我们还需到物理设备前,亦或者是远程登录至设备,一台台配置,在此凸显了 SDN 的灵活。
    在 ryu 中提供了 wsgi 的 web server 端,所以只需要我们实现相关的访问接口来相结合便可实现。
    在 ryu 的源码中同样有前辈为我们贡献出了实现简单 REST API 的相关事例以供我们参考。

    less /home/shiyanlou/ryu/ryu/app/simple_switch_rest_13.py
    

    查看代码,首先注意到的便是引入的外部文件,与之前我们所看到 simple_switch_13 最大的不同便是引入了 wsgi 的相关工具,随之我们看到这份简单的代码结构很简单:


    image.png

    代码的简洁是我们非常容易读懂,主要是理清楚其处理的流程。
    在理清楚其如何实现之后我们便来尝试一下我们该如何使用相关的 API。

    1.启动模拟网络
    第一步当然是启动网络拓扑结构,设置交换机使用的协议。

    sudo mn --controller=remote -x --mac
    

    通过上述命令启动需要模拟的拓扑结构,其中 --mac 参数是为了让 mac 地址的值人性化显示,而不像以前那般都是随机值,紧接着设置交换机使用的协议版本:

    #在 s1 窗口中执行
    ovs-vsctl set Bridge s1 protocols=OpenFlow13
    

    2.启动 ryu 控制器,同时与行我们的 simple_switch_rest_13

    #在 c0 窗口中运行
    ryu-manager --verbose ryu.app.simple_switch_rest_13
    

    成功启动之后我们会看到这样的信息:


    image.png

    从 move onto main mode 的结束语我们便可得知我们启动中应该是没有遇到什么问题,我们往上查看信息,我们会看到有 creating context wsgi 以及 (9926) wsgi starting up on http://0.0.0.0:8080 这样的提示信息。
    说明我们成功的启动了 wsgi,并且 wsgi 的相关端口运行在 8080,也就是说若是在这之前有应用占用了 8080 端口,此处启动的时候会报错,若是报错了请用 sudo lsof -i:8080 查看相关端口运行的信息,停掉相关应用在尝试启动(tomcat 就是典型会占用 8080 端口的应用)。

    3.使用相关 API
    还记得源码中在引入文件之后定义了两个全局变量:
    simple_switch_instance_name
    url

    第一个变量用于 wsgi 注册时与 controller 对 SimpleSwitchRest13 实例的绑定,而第二变量便是我们将要使用接口的地址,仔细观察每个 route 装置器便可得知。
    所以若是此时我们想获取 s1 交换机的 Mac 地址表,我们只需要在新的终端中运行这样的命令:

    curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/(交换机对应的datapath id)
    

    若是不清楚我们即将访问的 switch 的 datapath id 值,我们可以使用这样的方式获取:

    ovs-ofctl -O openflow13 show s1
    
    image.png

    再在我们的终端中执行这样的语句:

    curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
    

    其实我们得到了这样的结果:


    image.png

    这是因为刚刚启动的 switch,其中的 Mac 地址当然是空的,我们在 mininet 中执行:

    pingall
    

    然后我们在尝试同样的命令:


    image.png

    我们可以看到有两条记录,分别是 h1 对应一号端口,h2 对应二号端口:


    image.png
    因为这是使用的 GET 方法,若是你不喜欢使用命令行,以 curl 来获取信息,你也可以在浏览器中访问该地址:
    image.png

    而实现这样功能的就是 list_mac_table()。
    我们还有另外一个方法 put_mac_table() 可以用来插入新的记录,以此更新 Mac 地址表,我们只需执行这样的命令:

    curl -v -X PUT -d '{"mac" : "00:00:00:00:00:01", "port" : 1}' http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
    

    我们会从返回的状态码中发现我们添加成功,因为返回的是 200:

    image.png
    但是有的同学会认为,Mac 地址表中本来就拥有该表项,这并不能说明什么,我们可以关掉控制器,再启动,重新启动的控制数据便是空的,此时我们在 put 一次,然后在 get 一次,就能证明确实是添加成功了的。
    这便是 Ryu 运行 app 的方法,以及对 app 的 API 使用的方法,其实往简单的来说就是对 datapath 数据的一个接受与处理,若 API 接收到请求的处理,最重要的就是我们希望操作的流程我们是否清楚,若是清楚实现起来变简单不少。
    这样的代码只是一个实例代码,并不是非常的完美,例如当我们刚刚启动应用时便 put 表项,但是 put 时我们一不小心将 mac 地址写错了,多加了一对 0,成了 curl -v -X PUT -d '{"mac" : "00:00:00:00:00:00:01", "port" : 1}' http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001 这样,我们依然会插入成功,我们 get 也能够看到相应的数据,但是当我们在插入数据就会失败,会返回一个 500 的错误,这是因为尝试更新 mac 地址表的时候出错了。
    当我们想尝试修改这个 app 的代码时,亦或者书写我们自己的 app 代码,直接修改此处的代码在运行时没有用的,因为真正运行读取的是 /usr/local/lib/python2.7/dist-packages/ryu/ryu/app 目录中编译好的 python 文件,所以我们需要这样来运行我们修改好的代码:
    ryu-manager /home/shiyanlou/ryu/ryu/app/simple_switch_rest_13.py
    

    若是自己编写的 app,便将此处的路径换成代码所在的路径,将执行文件名换成自己写的 python 文件名。

    作业

    1.通过 APP 使用方式启动 Ryu 所带的 GUI。(提示位于 app 中的 gui_topology 中)
    成功的效果图应该是这样的:


    image.png

    2.有兴趣的朋友可以探究在 put 一次错误数据之后,在此 put 相同数据没有影响,但是 put 其他无论正确与否的信息都会报错。(不适合初学者,提示关键点在于 OFPMATCH() 上,调试过程较为麻烦,但是通过这样的一个过程可以进一步理解 opfenflow 数据解析的过程)
    给大家分享一下,这是我 debug 出来的结果:


    image.png

    相关文章

      网友评论

          本文标题:131SDN 软件定义网络动手实验--Ryu 的 REST AP

          本文链接:https://www.haomeiwen.com/subject/oturwltx.html