Ryu

在Mininet环境下实现Ryu为控制器控制ARP报文的实验中学习了Ryu相关的知识,记录如下

官方文档:http://ryu.readthedocs.io/en/latest/getting_started.html

李呈:https://www.sdnlab.com/1785.html

另一篇非常详细的博客:https://www.cnblogs.com/zxqstrong/p/4789105.html

安装

  • pip安装
  • 源码安装(更推荐)
git clone git://github.com/osrg/ryu.git
cd ryu
sudo pip install -r tools/pip-requires
sudo python setup.py install

若有更多问题,可参考http://linton.tw/2014/02/15/note-install-ryu-36-sdn-framework/

源码分析

介绍ryu/ryu下的主要目录

  • base

app_manager.py,其作用是RYU应用的管理中心,用于加载RYU应用程序,接受从APP发送过来的信息,同时也完成消息的路由。

其主要的函数有app注册、注销、查找、并定义了RyuApp基类,定义了RyuApp的基本属性。包含name, threads, events, event_handlers和observers等成员,以及对应的许多基本函数。如:start(), stop()等

  • controller

controller文件夹中许多非常重要的文件,如events.py, ofp_handler.py, controller.py等。

其中controller.py中定义了OpenFlowController基类。用于定义OpenFlow的控制器,用于处理交换机和控制器的连接等事件,同时还可以产生事件和路由事件。其事件系统的定义,可以查看events.py和ofp_events.py。

在ofp_handler.py中定义了基本的handler,完成了基本的如:握手,错误信息处理和keep alive 等功能。更多的如packet_in_handler应该在app中定义。

在dpset.py文件中,定义了交换机端的一些消息,如端口状态信息等,用于描述和操作交换机。如添加端口,删除端口等操作。

  • lib

lib中定义了我们需要使用到的基本的数据结构,如dpid, mac和ip等数据结构。在lib/packet目录下,还定义了许多网络协议,如ICMP, DHCP, MPLS和IGMP等协议内容。而每一个数据包的类中都有parser和serialize两个函数。用于解析和序列化数据包。

lib目录下,还有ovs, netconf目录,对应的目录下有一些定义好的数据类型,不再赘述。

  • ofproto

基本分为两类文件,一类是协议的数据结构定义,另一类是协议解析,也即数据包处理函数文件。

如ofproto_v1_0.py是1.0版本的OpenFlow协议数据结构的定义,而ofproto_v1_0_parser.py则定义了1.0版本的协议编码和解码。具体内容不赘述,实现功能与协议相同。

  • topology

包含了switches.py等文件,基本定义了一套交换机的数据结构。event.py定义了交换上的事件。dumper.py定义了获取网络拓扑的内容。最后api.py向上提供了一套调用topology目录中定义函数的接口。

  • cmd

ryu的命令系统

  • services

完成了BGP和vrrp的实现

  • tests

单元测试

二次交换机样例

# 导入ryu的应用管理中心
from ryu.base import app_manager # 继承app_manager.RyuApp基类,其中定义了Ryu的App基本的属性,类定义在ryu/ryu/base/app_manager.py
class L2Switch(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
# 调用父类的构造函数
super(L2Switch, self).__init__(*args, **kwargs)

样例来自官网。运行

ryu-manager L2Switch.py

继续添加内容

from ryu.base import app_manager

# ofp_event完成了事件的定义,从而我们可以在函数中注册handler,监听事件,并作出回应
from ryu.controller import ofp_event # OF协议的四个状态
# MAIN_DISPATCHER 控制器收到feature-reply,下发配置消息,
# HANDSHAKE_DISPATCHER 发送并等待hello消息
# CONFIG_DISPATCHER 商议协议版本,发送feature-request
# DEAD_DISPATCHER 断开连接
# 在ryu/ryu/controller/handler.py中有详细的注释
from ryu.controller.handler import MAIN_DISPATCHER # 装饰器 set_event_class,RyuApp用来声明一个事件handler
from ryu.controller.handler import set_ev_cls class L2Switch(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs) # 调用修饰器,第一个参数表示事件发生时应该调用的函数,第二个参数告诉交换机只有在握手之后被调用。
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
out = ofp_parser.OFPPacketOut(
datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
actions=actions)
datapath.send_msg(out)

分析具体的数据操作:

  • ev.msg:每一个事件类ev中都有msg成员,用于携带触发事件的数据包。
  • msg.datapath:已经格式化的msg其实就是一个packet_in报文,msg.datapath直接可以获得packet_in报文的datapath结构。datapath用于描述一个交换网桥。也是和控制器通信的实体单元。datapath.send_msg()函数用于发送数据到指定datapath。通过datapath.id可获得dpid数据,在后续的教程中会有使用。
  • datapath.ofproto对象是一个OpenFlow协议数据结构的对象,成员包含OpenFlow协议的数据结构,如动作类型OFPP_FLOOD。
  • datapath.ofp_parser则是一个按照OpenFlow解析的数据结构。
  • actions是一个列表,用于存放action list,可在其中添加动作。
  • 通过ofp_parser类,可以构造构造packet_out数据结构。括弧中填写对应字段的赋值即可。

如果datapath.send_msg()函数发送的是一个OpenFlow的数据结构,RYU将把这个数据发送到对应的datapath。

继续修改完成二层交换机如下:

import struct
import logging from ryu.base import app_manager
from ryu.controller import mac_to_port
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_0
from ryu.lib.mac import haddr_to_bin
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet class L2Switch(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]#define the version of OpenFlow def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
self.mac_to_port = {} def add_flow(self, datapath, in_port, dst, actions):
ofproto = datapath.ofproto match = datapath.ofproto_parser.OFPMatch(
in_port = in_port, dl_dst = haddr_to_bin(dst)) mod = datapath.ofproto_parser.OFPFlowMod(
datapath = datapath, match = match, cookie = 0,
command = ofproto.OFPFC_ADD, idle_timeout = 10,hard_timeout = 30,
priority = ofproto.OFP_DEFAULT_PRIORITY,
flags =ofproto.OFPFF_SEND_FLOW_REM, actions = actions) datapath.send_msg(mod) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto pkt = packet.Packet(msg.data)
eth = pkt.get_protocol(ethernet.ethernet) dst = eth.dst
src = eth.src dpid = datapath.id #get the dpid
self.mac_to_port.setdefault(dpid, {}) self.logger.info("packet in %s %s %s %s", dpid, src, dst , msg.in_port)
#To learn a mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = msg.in_port out_port = ofproto.OFPP_FLOOD #Look up the out_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst] ofp_parser = datapath.ofproto_parser actions = [ofp_parser.OFPActionOutput(out_port)] if out_port != ofproto.OFPP_FLOOD:
self.add_flow(datapath, msg.in_port, dst, actions) #We always send the packet_out to handle the first packet.
packet_out = ofp_parser.OFPPacketOut(datapath = datapath, buffer_id = msg.buffer_id,
in_port = msg.in_port, actions = actions)
datapath.send_msg(packet_out)
#To show the message of ports' status.
@set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
def _port_status_handler(self, ev):
msg = ev.msg
reason = msg.reason
port_no = msg.desc.port_no ofproto = msg.datapath.ofproto if reason == ofproto.OFPPR_ADD:
self.logger.info("port added %s", port_no)
elif reason == ofproto.OFPPR_DELETE:
self.logger.info("port deleted %s", port_no)
elif reason == ofproto.OFPPR_MODIFY:
self.logger.info("port modified %s", port_no)
else:
self.logger.info("Illeagal port state %s %s", port_no, reason)

运行

在mininet环境下搭建网络拓扑:

运行RyuAPP

ryu-manager simple_switch.py

h1 ping h2结果如下

Ryu控制器学习的更多相关文章

  1. 基于RYU控制器(controller)上的simple-switch 的APP做的測试-SDN/OpenFlow

    近期一直在学习RYU控制器,在使用的过程中,发现有下面几方面的长处:RYU控制器全然使用Python语言编写,在理解起来和上手速度上是挺快的:RYU控制器的总体架构清晰明了,在日后有时间我会整理一个关 ...

  2. 通过源码安装RYU控制器

    目录 安装 测试 安装 安装pip3 sudo apt-get install python3-pip 获取ryu源码 git clone https://github.com/osrg/ryu.gi ...

  3. Ryu控制器编程开发——packet_in和packet_out简易交换机实现

    Ryu控制器二次开发,实现一个简单的只能够简单地广播数据包的交换机. from ryu.base import app_manager from ryu.controller import ofp_e ...

  4. mininet和ryu控制器的连接

    1.执行ryu应用程式:ryu-manager --verbose ryu.app.simple_switch_13 2.启动mininet,配置如下:创建3个host,1个交换器(open vSwi ...

  5. Ryu控制器安装部署和入门

    Ryu官网简介,原滋原味 Ryu is a component-based software defined networking framework. Ryu provides software c ...

  6. Altera DDR2控制器学习笔记

    Altera DDR2控制器使用IP的方式实现,一般很少自己写控制器代码. ddr22 ddr22_inst ( .aux_full_rate_clk (mem_aux_full_rate_clk), ...

  7. S3C2440之存储控制器学习记录

    /==========翻译S3C2440存储控制器部分================/ 5 存储控制器 概述 S3C2440内存控制器为外部存储访问提供内存控制信号. S3C2440A有如下特征: ...

  8. Ryu学习总结(持续更新)

    Ryu学习总结 该篇学习笔记,与其他分析Ryu控制器代码的笔记不同,主要按照程序的构成来进行分块总结,由于本人为新手入门,不能保证没有错误,如果发现错误,欢迎指教. 以下的内容主要来源: 源码 官方文 ...

  9. 实验6:开源控制器实践——RYU

    实验目的 能够独立部署RYU控制器 能够理解RYU控制器实现软件定义的集线器原理 能够理解RYU控制器实现软件定义的交换机原理 二.实验环境 下载虚拟机软件Oracle VisualBox或VMwar ...

随机推荐

  1. bzoj 4827 礼物

    bzoj 4827 礼物 可以看做将其中一个数列(假定为 \(a\) )都加上 \(c\) , \(c\) 可以为负数.易知这里 \(-m\leq c\leq m\). 记要求的答案为 \(ans\) ...

  2. BZOJ1015: [JSOI2008]星球大战starwar【并查集】【傻逼题】

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...

  3. BZOJ2565 最长双回文串 【Manacher】

    BZOJ2565 最长双回文串 Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"c ...

  4. MySQL Geometry扩展在地理位置计算中的效率优势

    由于在Geometry中,有相关自带函数和SPATIAL INDEX的性能优化,可以让某些位置计算的效率提升.以下是几种计算方法的效果对比. 1. 数据准备 首先创建一个数据表,这是一个店铺数据表,结 ...

  5. thinkphp 使每一个模板页都包括一个header文件和一个footer文件

    在开发的过程中,常常遇到要使每一个模板页都包括一个header文件和一个footer文件.thinkPHP的模板布局为我们提供了一个叫全局配置方式可以解决问题. 1. 在配置文件里开启LAYOUT_O ...

  6. Oracle之 等待事件log file sync + log file parallel write (awr优化)

    这是3月份某客户的情况,原因是server硬件故障后进行更换之后,业务翻译偶尔出现提交缓慢的情况.我们先来看下awr的情况. 我们能够看到,该系统的load profile信息事实上并不高,每秒才21 ...

  7. CF 360E Levko and Game——贪心

    题目:http://codeforces.com/contest/360/problem/E 官方题解与证明:http://codeforces.com/blog/entry/9529 一条可以调整的 ...

  8. CentOS(五)--Linux系统的分区概念

    一.系统分区 首先先普及一下有关系统分区的一些知识: 硬盘分区有三种,主磁盘分区.扩展磁盘分区.逻辑分区. 一个硬盘主分区至少有1个,最多4个,扩展分区可以没有,最多1个.且主分区+扩展分区总共不能超 ...

  9. struts2学习(10)struts2国际化

    一.国际化简介: 二.struts2国际化设置: struts.xml: <?xml version="1.0" encoding="UTF-8" ?&g ...

  10. [转]java中byte转换int时为何与0xff进行与运算

    在剖析该问题前请看如下代码public static String bytes2HexString(byte[] b) {  String ret = "";  for (int ...