RyuBook1.0案例三:REST Linkage
REST Linkage
该小结主要介绍如何添加一个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过程)
- host1发起的ARP请求,并广播
 - host2发起的ARP请求,MAC地址是host1
 - 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中添加的条目成功生效,符合预期情况。
RyuBook1.0案例三:REST Linkage的更多相关文章
- RyuBook1.0案例二:Traffic Monitor项目源码分析
		
Traffic Monitor源码分析 从simple_switch_13.SimpleSwitch13控制器继承并开发 class SimpleMonitor13(simple_switch_13. ...
 - RyuBook1.0案例一:Switching Hub项目源码分析
		
开发目标 实现一个带MAC地址学习功能的二层交换机 Openflow交换机与Openflow控制器安全通道建立步骤 switch and controller建立未加密TCP连接或者加密的TLS连接 ...
 - Android实训案例(三)——实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果!
		
Android实训案例(三)--实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果! 感叹离春节将至,也同时感叹时间不等人,一年又一年,可是我依然是android道路上的小菜鸟,这篇讲 ...
 - 案例学python——案例三:豆瓣电影信息入库
		
闲扯皮 昨晚给高中的妹妹微信讲题,函数题,小姑娘都十二点了还迷迷糊糊.今天凌晨三点多,被连续的警报声给惊醒了,以为上海拉了防空警报,难不成地震,空袭?难道是楼下那个车主车子被堵了,长按喇叭?开窗看看, ...
 - 七、Dockerfile案例三(Mysql安装)
		
七.Dockerfile案例三(Mysql安装) *特别提醒:新版的mysql:5.7数据库下的user表中已经没有Password字段了(5.5的user表还有) 一.查看docker hub上的版 ...
 - 【JavaScript】案例三:使用JS完成页面定时弹出广告——事件(onload)
		
事件(onload) *注意点: 变量加var局部变量,不加var全局变量 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭. 返回值:返回 ...
 - zabbix生产环境案例(三)
		
生产环境案例(三) 链接:https://pan.baidu.com/s/1q5YwJMTcZLcS5OQ0iOu44A 提取码:8gdi 复制这段内容后打开百度网盘手机App,操作更方便哦 1. Z ...
 - C++  //多态案例三 ---电脑组装
		
1 //多态案例三 ---电脑组装 2 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...
 - KingbaseES R6 集群repmgr.conf参数'recovery'测试案例(三)
		
案例三:测试'recovery = manual' 1.查看集群节点状态信息: [kingbase@node1 bin]$ ./repmgr cluster show ID | Name | Role ...
 
随机推荐
- Android 面试题之编程
			
1.排序 package cn.java.suanfa; public class SuanFa { public static void main(String[] args) { int[] ar ...
 - Microsoft Visio / Project professional 2013 官方版本(下载)
			
Microsoft Visio微软开发的一款软件, 它有助于 IT 和商务专业人员轻松地可视化.分析和交流复杂信息. 它能够将难以理解的复杂文本和表格转换为一目了然的 Visio 图表. 该软件通过创 ...
 - AutoMapper 帮助类
			
AutoMapper帮助类 /// <summary> /// AutoMapper帮助类 /// </summary> public static class AutoMap ...
 - C++获取毫秒级时间戳
			
#include<chrono> auto timeNow = chrono::duration_cast<chrono::milliseconds>(chrono::sy ...
 - [原创]HBase学习笔记(2)- 基本操作
			
1.使用hbase shell连接hbase 2.输入help可以查看帮助 3.输入list查看当前hbase中的所有表 4.使用create创建表test 其中test是表名,cf是列族.该表只创建 ...
 - DDL-库的管理
			
一.创建库create database [if not exists] 库名[ character set 字符集名]; 二.修改库alter database 库名 character set 字 ...
 - NFS网络文件系统
			
FFS服务端概述 NFS,是Network File System的简写,即网络文件系统.网络文件系统是FreeBSD支持的文件系统中的一种,也被称为NFS: NFS允许一个系统在网络上与他人共享目录 ...
 - JavaScript日期格式转换
			
//日期格式转换 function dateFormat(val) {//val需要转换的日期 var fmt = "yyyy-MM-dd";//日期格式 val = val.re ...
 - Python学习 :多线程
			
多线程 什么是线程? - 能独立运行的基本单位——线程(Threads). - 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. - 一条线程指的是进程中一个单一 ...
 - Python学习:18.Python异常处理
			
一.为什么使用异常处理 当程序运行的时候出现了异常,导致程序终止运行,为了解决这种情况,我们需要预先对可能出现的异常进行处理,一旦出现这种异常,就使用另一种方式解决问题,还有就是错误信息是使用者没有必 ...