Ryu部分整理
一.学前知识
- 网络部分:了解基本的路由与交换,最好了解一点常见协议的细节(主要是二三层协议)
- Linux:了解一款Linux系统,推荐使用Ubuntu;熟练使用常见的命令
- 编程语言:如果选择Ryu控制器的话需要了解Python(掌握Python的使用,了解面向对象的知识[封装,继承,多态],了解一点Python的特性,装饰器,GC,协程----)
- 多一句嘴:如果做的应用打算放在简历上,建议阅读一下底层实现的源码(很优美)
二.一点推荐的资料
网络部分:
可以直接看计算机网络相关的书籍(黑书[自顶向下]比教科书要易懂而且有深度)
Linux:
- 菜鸟教程Linux部分
- 鸟哥的Linux私房菜
- 自己去Bilibili找视频xuexi
编程语言:
安装一个编译器(建议Pycharm)--学生邮箱可以***一年
SDN相关:
三.Ryu的安装配置
0.虚拟机不知道怎么安装的请看---》VMware安装Ubuntu18.04(必会)
1.需要安装一些必要的模块
sudo apt-get install python-pip python-dev build-essential sudo pip install --upgrade pip//对pip进行版本升级 sudo apt-get install python-eventlet//高并发网络编程并发框架 sudo apt-get install python-routes//将不同的URL自动匹配到不同的应用 sudo apt-get install python-webob//在WSGI中对请求的环境变量进行封装 sudo apt-get install python-paramiko//支持以加密和认证的方式,进行远程服务器的连接
2.安装(二选一)
- (1)Pip安装:
pip install ryu
- (2)源码安装:
git clone git://github.com/osrg/ryu.git cd ryu sudo pip install -r tools/pip-requires sudo python setup.py install
3.出现问题请自行Google
4.验证
执行ryu-manager,如果可以显示
loading app ryu.controller.ofp_handler
instantiating app ryu.controller.ofp_handler of OFPHandler
表示安装成功
5.补充资料:
- 结构与目录分析
1./base:base中有app_manager.py,其作用为Ryu的管理中心.用于加载Ryu的应用程序,接受从app发送来的信息,同时也完成消息的路由.主要的函数有app的注册,注销,查找,并定义了ryuapp基类,定义了ryuapp的基本属性.包含name,threads,events,event_handlers和observers等,以及对应的很多函数,例如:start(),stop()
2./controller:controller.py中定义了OpenFlowController基类,用于定义控制器.在ofp_handler.py中定义了handler句柄(句柄可以理解为编号,为虚拟地址,可以通过编号找到[由操作系统来维护]),完成了例如握手,错误信息处理和keep alive等功能
3./lib:定义了需要使用到的数据结构,例如dpid,mac和ip等.在lib/packet目录下,还有icmp,dhcp,mpls和igmp等内容.而每一个数据包的类中都有parser和serialize两个函数用于解析和序列化数据包.
4./ofproto:内部有数据结构的定义与协议的解析部分
5./topology:switches.py中定义了一套交换机的数据结构
event.py中定义了交换上的事件
dumper.py定义了获取网络拓扑的内容
api.py向上提供了一套调用topology目录中定义函数的接口
6./contrib:开源社区贡献的代码
7./cmd:定义了ryu的命令系统
8./services:实现了vrrp,bgp,ovsdb协议的内容
9./tests:存放了单元测试和集成测试的代码
10./app:自己开发的小应用- ryu学习的第一步
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
class ExampleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(ExampleSwitch13, self).__init__(*args, **kwargs)
# initialize mac address table.
self.mac_to_port = {}
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# install the table-miss flow entry.
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
def add_flow(self, datapath, priority, match, actions):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# construct flow_mod message and send it.
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
match=match, instructions=inst)
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
parser = datapath.ofproto_parser
# get Datapath ID to identify OpenFlow switches.
dpid = datapath.id
self.mac_to_port.setdefault(dpid, {})
# analyse the received packets using the packet library.
pkt = packet.Packet(msg.data)
eth_pkt = pkt.get_protocol(ethernet.ethernet)
dst = eth_pkt.dst
src = eth_pkt.src
# get the received port number from packet_in message.
in_port = msg.match['in_port']
self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# learn a mac address to avoid FLOOD next time.
self.mac_to_port[dpid][src] = in_port
# if the destination mac address is already learned,
# decide which port to output the packet, otherwise FLOOD.
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
# construct action list.
actions = [parser.OFPActionOutput(out_port)]
# install a flow to avoid packet_in next time.
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
self.add_flow(datapath, 1, match, actions)
# construct packet_out message and send it.
out = parser.OFPPacketOut(datapath=datapath,
buffer_id=ofproto.OFP_NO_BUFFER,
in_port=in_port, actions=actions,
data=msg.data)
datapath.send_msg(out) 6.执行
ryu-manager yourapp.py --verbose
四.Mininet的安装
1.安装mininet
sudo apt-get install mininet
2.运行mininet
sudo mn//进行检验
3.补充资料:
- 文件目录结构
/bin:主运行文件 /util:辅助文件,安装脚本,文档辅助生成等 /build:不怎么用 /debian:deb包的配置文件,不怎么用 /mininet:核心代码部分,定义了addNode,addHost,addSwitch,addLink,addPort函数,topo文件中定义简单拓扑 /examples:含有很多案例,包括miniedit可视化 /custom:放置自定义的python文件,可以自定义拓扑
- 命令详解:
网络构建启动参数:
一.topo:规定拓扑结构
1.单一拓扑(1->3)
sudo mn --topo=single,3
2.线型拓扑(4->4)
sudo mn --topo=linear,4
3.树型拓扑(高度为2+1的2叉树)
sudo mn --topo=tree,depth=2,fanout=2
4.自定义的拓扑
sudo mn --custom myfile.py --topo mytopo
二.custom
三.switch:规定交换机的特性
--switch定义mininet要使用的交换机(默认使用的是OVSK,即OpenVSwitch)
lxbr为内核态
user为用户态
四.controller:规定控制器的特性
连接远程控制器,可以指定存在于本机或者是与之相连接设备上的控制器,指定远程控制器方法:
sudo mn --controller=remote,--ip=[controller IP],--port=[port]
五.mac:规定mac地址
自动设置设备的MAC地址
让Mac地址容易读,即设置交换机的Mac,容易肉眼识别Id
sudo mn --topo=tree,depth=2,fanout=2,--mac- 内部交互命令
内部交互命令:
dump:查看所有的结点的信息
net:网络的特性
nodes:结点的性质
dpctl:分配修改管理流表(所有交换机上操作)
dpctl dump-flows
dpctl add-flow in_port=2,actions=drop
iperf:测量结点之间的带宽
iperf h1 h2
xterm:结点开启xterm进入可视化操作界面
xterm h2
py:执行python表达式
py net.addSwtich("s3")
py net.addLink(s1,net.get('h3'))
py attach('s1-eth3')
py net.get('h3').cmd('ifconfig h3-eth0 10.3')
添加之后要ping一下才可以获取到ip地址
pingpair:只是验证前两个host的连通性
pingall:验证所有主机之间的通信
iperfudp:两个节点之间进行带宽测试
iperfudp bw h1 h2- 外部运行参数
外部运行参数: -c 清除配置信息 -h 帮助 examples/miniedit.py可以图形化生成拓扑(./miniedit.py)
- 代码分析
1.Mininet在mininet/node.py中定义了Node,OVSSwtich和Controller等重要的类,在Ovsswitch中通过OVS的命令创建交换机从而得到一个OVS实例.
2.Mininet创建的host和switch等实例实际上是运行在不同的namespace下的某个进程.默认情况下Host运行在自己的namespace中,交换结点运行在root namespace中.
3.自定义拓扑
import Topo类用于派生Mytopo类
addHost为添加主机
addSwitch为添加交换机
addLink为添加链
在topos中添加mytopo,值为MyTopo()类4.运行
sudo mn --controller=remote --topo=tree,2,2 //只是实例,尽量自定义拓扑

京公网安备 11010502036488号