广告
返回顶部
首页 > 资讯 > 后端开发 > Python >RyuBook1.0案例三:REST L
  • 236
分享到

RyuBook1.0案例三:REST L

案例REST 2023-01-30 22:01:40 236人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

该小结主要介绍如何添加一个REST Link 函数 RYU本身提供了一个类似WSGI的WEB服务器功能。借助这个功能,我们可以创建一个REST api。 基于创建的REST API,可以快速的将RYU系统与其他系统或者是浏览器相连接,非

该小结主要介绍如何添加一个REST Link 函数

RYU本身提供了一个类似WSGI的WEB服务器功能。借助这个功能,我们可以创建一个REST api
基于创建的REST API,可以快速的将RYU系统与其他系统或者是浏览器相连接,非常实用的一个功能。

程序解析

在案例中,实现了两个类

  • SimpleSwitchRest13
    • 继承SimpleSwitch13的功能,即具备父类的三层交换机的基本功能。
    • 注册WSGI服务
    • 配置Mac_to_port
  • SimpleSwitchController
    • REST API功能实现的主体类
    • 返回指定交换机的mac_table
    • 更新指定的mac_table条目

SimpleSwitchRest13类实现

_CONTEXTS = {'wsgi': WSGIApplication}

该成员变量用于指明Ryu的兼容WSGI的web服务对象。

wsgi = kwargs['wsgi']
wsgi.reGISter(SimpleSwitchController,
              {simple_switch_instance_name: self})

通过上一步设置的_CONTEXTS成员变量,可以通过kwargs进行实例化一个WSGIApplication。同时使用register方法注册该服务到
controller类上。

@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
    super(SimpleSwitchRest13, self).switch_features_handler(ev)
    datapath = ev.msg.datapath
    self.switches[datapath.id] = datapath
    self.mac_to_port.setdefault(datapath.id, {})

重写父类的switch_features_handler函数

  • 存储datapath到switches
  • 初始化MAC 地址表
def set_mac_to_port(self, dpid, entry):
    # 获取MAC table
    mac_table = self.mac_to_port.setdefault(dpid, {})
    
    # 获取datapath,如果为None,证明没有该交换机
    datapath = self.switches.get(dpid)

    entry_port = entry['port']
    entry_mac = entry['mac']

    if datapath is not None:
        parser = datapath.ofproto_parser
        # 如果entry_port不在mac_table中
        if entry_port not in mac_table.values():
            # 下发流表
            for mac, port in mac_table.items():

                # from known device to new device
                actions = [parser.OFPActionOutput(entry_port)]
                match = parser.OFPMatch(in_port=port, eth_dst=entry_mac)
                self.add_flow(datapath, 1, match, actions)

                # from new device to known device
                actions = [parser.OFPActionOutput(port)]
                match = parser.OFPMatch(in_port=entry_port, eth_dst=mac)
                self.add_flow(datapath, 1, match, actions)

            # 添加entry_mac, entry_port到mac_table
            mac_table.update({entry_mac: entry_port})
    return mac_table

该方法将MAC地址和端口注册到指定的交换机。该方法主要被REST API的PUT方法所调用。

SimpleSwitchController类实现

@route('simpleswitch', url, methods=['GET'],
           requirements={'dpid': dpid_lib.DPID_PATTERN})

借助route装饰器关联方法和URL。参数如下:

  • 第一个参数:任何自定义名称
  • 第二个参数:指明URL
  • 第三个参数:指定Http方法
  • 第四个参数:指明指定位置的格式,URL(/simpleswitch/mactable/{dpid} 匹配DPID_PATTERN的描述

当使用GET方式访问到该REST API接口时,调用list_mac_table函数

def list_mac_table(self, req, **kwargs):
    simple_switch = self.simple_switch_app
    # 获取{dpid}
    dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
    
    # 如果没有dpid,返回404
    if dpid not in simple_switch.mac_to_port:
        return Response(status=404)

    # 获取mac_table
    mac_table = simple_switch.mac_to_port.get(dpid, {})
    body = JSON.dumps(mac_table)
    return Response(content_type='application/json', body=body)
# 使用PUT方式设置mac_table
@route('simpleswitch', url, methods=['PUT'],
           requirements={'dpid': dpid_lib.DPID_PATTERN})
    def put_mac_table(self, req, **kwargs):
        simple_switch = self.simple_switch_app
        dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
        try:
            new_entry = req.json if req.body else {}
        except ValueError:
            raise Response(status=400)

        if dpid not in simple_switch.mac_to_port:
            return Response(status=404)

        try:
            mac_table = simple_switch.set_mac_to_port(dpid, new_entry)
            body = json.dumps(mac_table)
            return Response(content_type='application/json', body=body)
        except Exception as e:
            return Response(status=500)

运行分析

启动mininet创建网络拓扑图

sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote -x

启动控制器程序,打印log信息如下:

debugging is available (--enable-debugger option is turned on)
loading app SimpleSwitchRest13
loading app ryu.controller.ofp_handler
creating context wsgi
instantiating app SimpleSwitchRest13 of SimpleSwitchRest13
instantiating app ryu.controller.ofp_handler of OFPHandler
BRICK SimpleSwitchRest13
  CONSUMES EventOFPPacketIn
  CONSUMES EventOFPSwitchFeatures
BRICK ofp_event
  PROVIDES EventOFPPacketIn TO {'SimpleSwitchRest13': set(['main'])}
  PROVIDES EventOFPSwitchFeatures TO {'SimpleSwitchRest13': set(['config'])}
  CONSUMES EventOFPEchoReply
  CONSUMES EventOFPSwitchFeatures
  CONSUMES EventOFPPortDescStatsReply
  CONSUMES EventOFPHello
  CONSUMES EventOFPErrORMsg
  CONSUMES EventOFPEchoRequest
  CONSUMES EventOFPPortStatus
(22238) wsgi starting up on http://0.0.0.0:8080

这里我们可以看到,wsgi服务已经启动,端口号为8080

查询s1的默认MAC table

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

返回为{}

在mininet中执行

mininet> h1 ping -c 1 h2

log信息打印如下信息:

EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:02 00:00:00:00:00:01 2
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 00:00:00:00:00:02 1

返回了三条PackageIn消息(ARP过程)

  1. host1发起的ARP请求,并广播
  2. host2发起的ARP请求,MAC地址是host1
  3. ICMP echo reply request 从host1 发生到host2

此刻按照设计,已经添加了两条条目到MAC table,再次查询进行验证。

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

返回如下,证明符合实验预期:

{"00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}

测试POST API接口,添加h3到MAC Table

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

返回:

{"00:00:00:00:00:03": 3, "00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}

证明h3 mac已经被添加到MAC table。因为h3已经被添加到MAC Table中,所以理论上当h1 ping h3时将不再通过ARP查找到h3.

测试:在mininet中执行命令

mininet> h1 ping c1 h3
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=2.48 ms

--- 10.0.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.480/2.480/2.480/0.000 ms

控制器log信息如下:

EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1

我们可以看到,只有h1在不知道h3地址的情况下,发起ARP广播,将PackageIn消息发送到控制器,而不再出现以后的一系列消息。这证明
MAC Table中添加的条目成功生效,符合预期情况。

--结束END--

本文标题: RyuBook1.0案例三:REST L

本文链接: https://www.lsjlt.com/news/179319.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • RyuBook1.0案例三:REST L
    该小结主要介绍如何添加一个REST Link 函数 RYU本身提供了一个类似WSGI的web服务器功能。借助这个功能,我们可以创建一个REST API。 基于创建的REST API,可以快速的将RYU系统与其他系统或者是浏览器相连接,非...
    99+
    2023-01-30
    案例 REST
  • 利用Spring Boot开发REST服务的案例
    这篇文章主要介绍了利用Spring Boot开发REST服务的案例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。REST服务介绍RESTful service是一种架构模式,...
    99+
    2023-05-30
    springboot rest
  • 【MySQL】死锁案例之三
    一 前言       死锁,其实是一个很有意思,也很有挑战的技术问题,大概每个DBA和部分开发朋友都会在工作过程中遇见过。关于死锁我会持续写一个系列的案例分析,希望能...
    99+
    2022-10-18
  • Oracle SQL*Loader使用案例(三)
          上两篇文章中,介绍了SQL*Loader的使用方法及使用案例,本篇将根据实际的使用案例来更深层次的来解读SQL*Loader     &nbs...
    99+
    2022-10-18
  • python学习实操案例(三)
    目录任务1、循环输出26个字母对应的ASCII码值任务2、模拟用户登录任务3、猜数游戏任务4、计算100-999之间的水仙花数 任务1、循环输出26个字母对应的ASCII码值 x=...
    99+
    2022-11-13
  • Java三目运算符的实战案例
    目录1.什么是条件分支语句?条件分支语句共有几种写法?2. 三目元算符又称为三元运算符也称为条件运算符,目的就是根据条件得到数据结果,语法结构:3. switch语句的语法结构如下:...
    99+
    2022-11-13
  • Redis集群的三种配置方式案例
    前言 Redis有三种集群模式: 主从复制哨兵(Sentinel)集群(Cluster) 💕主从复制 读写分离 在多个redis实例建立起主从关系,当主redis 中的数据发生变化,从redis 中的数据也会同步变化。 通...
    99+
    2023-09-09
    redis 数据库 java
  • Python三种打包exe方法案例教程
    cxfreeze,pyinstaller,py2exe三种方式 目前网上能获取的免费的Python打包工具主要有三种:py2exe、PyInstaller和cx_Freeze。其中P...
    99+
    2022-11-12
  • DFL东芝使用案例基础三部曲
    很多人都在问如何修理东芝硬盘,本次三部曲将友简入深的给大家介绍三种方式方法。...
    99+
    2023-06-04
  • Java 高并发的三种实现案例详解
    提到锁,大家肯定想到的是sychronized关键字。是用它可以解决一切并发问题,但是,对于系统吞吐量要求更高的话,我们这提供几个小技巧。帮助大家减小锁颗粒度,提高并发能力。 初级技...
    99+
    2022-11-12
  • 使用python实现三维图可视化的案例
    这篇文章将为大家详细讲解有关使用python实现三维图可视化的案例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。这是学习tensorflow框架中遇到的知识,这里定义函数的时候选用的是将x和y封装起来,方...
    99+
    2023-06-14
  • Oracle中表空间offline的三种参数对比案例
    Oracle数据库管理中,对表空间操作是基础中的基础。其中,表空间Offline是我们经常接触的。同数据文件Offline一起,构成了Oracle维护数据一致性的重要体系结构。 &n...
    99+
    2022-10-18
  • CSS中经典三栏布局方案的示例分析
    这篇文章主要介绍CSS中经典三栏布局方案的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. float布局最简单的三栏布局就是利用float进行布局。首先来绘制左、右栏:&...
    99+
    2022-10-19
  • C语言实现简单的<三子棋>案例
    棋盘的实现 众所周知,三子棋棋盘其实是一个就九方格,所以我们首先要定义一个二维数组来实现存放棋子。每一个方格我们规定为占三个小格例如 ' X ',且必须有分隔符来分开棋子。 棋盘的初...
    99+
    2022-11-12
  • C#使用三层架构开发Winform的详细案例
    目录一、案例需求二、项目结构三、实体类编写四、数据访问层编写五、业务逻辑层编写六、界面UI层代码编写三层架构将整个业务应用划分为: (1)界面UI层(2)业务逻辑层(3)数据访问层 ...
    99+
    2022-11-13
  • 使用CSS3三角形实现不断放大的案例
    小编给大家分享一下使用CSS3三角形实现不断放大的案例,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!CSS3三角形不断放大特效图片预览index.html代码<!DOCTYPE html><ht...
    99+
    2023-06-14
  • Android Handle原理(Looper,Handler和Message)三者关系案例详解
    介绍 前面的内容对Handler做了介绍,也讲解了如何使用handler,但是我们并不知道他的实现原理。本文从源码的角度来分析如何实现的。 首先我们得知道Handler,Looper...
    99+
    2022-11-12
  • JavaScript es6中var、let以及const三者区别案例详解
    首先,一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?         ECMAScript是一个国际通过的...
    99+
    2022-11-12
  • iOS13适配三指撤销和文案限长实例详解
    目录正文Bugly报错堆栈信息问题定位解决方案数字截断后 crash正文 在适配iOS13的过程中,UITextField输入中文的时候三指撤销产生了 crash。 Bugly报错 ...
    99+
    2023-01-29
    iOS13适配三指撤销文案限长 iOS 三指撤销文案限长
  • Online Redefinition在线重定义(三)--多表关联重定义案例
    之前的两篇博文中,列举了两个单表在线重定义的过程: Online Redefinition在线重定义(一):http://blog.itpub.net/31015730/viewspace-214...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作