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过程)

  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中添加的条目成功生效,符合预期情况。

RyuBook1.0案例三:REST Linkage的更多相关文章

  1. RyuBook1.0案例二:Traffic Monitor项目源码分析

    Traffic Monitor源码分析 从simple_switch_13.SimpleSwitch13控制器继承并开发 class SimpleMonitor13(simple_switch_13. ...

  2. RyuBook1.0案例一:Switching Hub项目源码分析

    开发目标 实现一个带MAC地址学习功能的二层交换机 Openflow交换机与Openflow控制器安全通道建立步骤 switch and controller建立未加密TCP连接或者加密的TLS连接 ...

  3. Android实训案例(三)——实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果!

    Android实训案例(三)--实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果! 感叹离春节将至,也同时感叹时间不等人,一年又一年,可是我依然是android道路上的小菜鸟,这篇讲 ...

  4. 案例学python——案例三:豆瓣电影信息入库

    闲扯皮 昨晚给高中的妹妹微信讲题,函数题,小姑娘都十二点了还迷迷糊糊.今天凌晨三点多,被连续的警报声给惊醒了,以为上海拉了防空警报,难不成地震,空袭?难道是楼下那个车主车子被堵了,长按喇叭?开窗看看, ...

  5. 七、Dockerfile案例三(Mysql安装)

    七.Dockerfile案例三(Mysql安装) *特别提醒:新版的mysql:5.7数据库下的user表中已经没有Password字段了(5.5的user表还有) 一.查看docker hub上的版 ...

  6. 【JavaScript】案例三:使用JS完成页面定时弹出广告——事件(onload)

     事件(onload) *注意点: 变量加var局部变量,不加var全局变量 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭. 返回值:返回 ...

  7. zabbix生产环境案例(三)

    生产环境案例(三) 链接:https://pan.baidu.com/s/1q5YwJMTcZLcS5OQ0iOu44A 提取码:8gdi 复制这段内容后打开百度网盘手机App,操作更方便哦 1. Z ...

  8. C++ //多态案例三 ---电脑组装

    1 //多态案例三 ---电脑组装 2 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...

  9. KingbaseES R6 集群repmgr.conf参数'recovery'测试案例(三)

    案例三:测试'recovery = manual' 1.查看集群节点状态信息: [kingbase@node1 bin]$ ./repmgr cluster show ID | Name | Role ...

随机推荐

  1. CCF认证201809-2买菜

    问题描述 小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广场把菜装上车,两人都要买n种菜,所以也都要装n次车.具体的,对于小H来说有n个不相交的时间段 ...

  2. 【星云测试】开发者测试(2)-采用精准测试工具对J2EE Guns开发框架进行测试

    配置测试Guns Guns简介 Guns是一个近几年来基于SpringBoot的开源便利且较新的JavaEE项目开发框架,它整合了springmvc + shiro + mybatis-plus + ...

  3. Notes 20180311 : String第三讲_深入了解String

    很多前辈我可能对于我的这节文章很困惑,觉得String这个东西还有什么需要特别了解的吗?其实不然,String是一个使用十分频繁的工具类,不可避免地我们也会遇到一些陷阱,深入了解String对于我们避 ...

  4. oracle 11G dataguard 恢复

    检查主备机的sys 密码是否一致,忘记密码可以修改,同步 .alter user sys identified by xxx: orapwd file=oraxxx.ora password=admi ...

  5. iOS:手势与矩形、点运算相关(18-01-24更)

    1.矩形.点运算 1.获取当前的View在Window的frame 2.包含判断 3.获取点击在响应者 touchesBegan 的位置 4.UIScrollView.UITableView 实时 位 ...

  6. H5页面手机端禁止缩放的正确方式

    H5页面禁止手机端缩放是个常见问题了 首先说meta方式 <meta content="width=device-width, initial-scale=1.0, maximum-s ...

  7. Java并发编程(三)什么是线程池

    什么是线程池 学习编程的小伙伴们会经常听到“线程池”.“连接池”这类的词语,可是到底“池”是什么意思呢?我讲个故事大家就理解了:在很久很久以前有一家银行,一年之中只有一个客户来办理业务,随着时间的推移 ...

  8. Mysql浅析-基础命令(一)

    主要从以上篇幅来介绍mysql的一些知识点 一.Mysql简介 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数 ...

  9. else的妙用--if-else 成对出现,可以检测意外的放生,方便找bug

    else用于意外情况的检测.可以写入log,或者串口打印出来. 养成这样的习惯,好处 1 提高程序稳定性,可靠性. 2 遇到bug有头绪.

  10. Vue2.5入门-2

    todolist功能开发 代码 <!DOCTYPE html> <html> <head> <title>vue 入门</title> &l ...