RYU 灭龙战 third day
RYU 灭龙战 third day
前言
传统的交换机有自学习能力。然而你知道在SDN的世界里,脑子空空的OpenFlow交换机是如何学习的吗?今日说法带你领略SDN的mac学习能力。
RYUBook从中学习
场景描述
传统交换机原理
- 学习连接到传统交换机的主机的mac地址,并把其存在mac地址表中
- 对于已经记录下来的mac地址,若是收到送往该mac地址的数据包时,就往对应的端口进行转发
- 对于mac地址表中没有的数据包,则进行flooding
OpenFlow交换机实现传统交换机功能
- 对于接收到的数据包针对指定的端口转发
- 把接收到的数据包发送给控制器(Packet-In)
- 把从控制器接收到的数据包转发到指定的端口(Packet-Out)
图示
1.初始状态
mac地址表和交换机的流表均为空的表项
2.Host A -> Host B
当Host A 向 Host B 发送数据包时。这个时候会出发PacketIn消息。Host A的mac地址以及对应的端口会记录到mac地址表内。然后由于Host B的mac不在mac地址表内,此时会flooding
3.Host B -> Host A
数据包从host B回复给Host B时,在Flow table上新增一条流表,讲数据包转发给端口1
4.Host A -> Host B
再次由主机A向主机B发送数据包,新增流表,将数据包转发到端口4
场景实现
代码附录(附加注释)simple_switch_13.py
# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
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
from ryu.lib.packet import ether_types
class SimpleSwitch13(app_manager.RyuApp):
#OF版本为1.3
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
#初始化函数
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
#MAC地址表的定义
self.mac_to_port = {}
#"ryu.controller.handler.set_ev_cls作为修饰器,参数为指定事件类别的接受信息,以及交换机的状态
#此时接收到的是SwitchFeatures,即交换机的功能,CONFIG_DISPATCHER则是交换机的状态为接收SwitchFeatures消息
#每一个事件管理(Envent Handler)都需要有一个事件event作为参数
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
#ev.msg是用来存对应事件的OpenFlow消息类别实体,这里指的是OFPSwitchFeatures
#datapath是用来处理OpenFlow交换机重要的消息,比如与交换机的通讯和触发接收消息相关的实践
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# install table-miss flow entry
#
# We specify NO BUFFER to max_len of the output action due to
# OVS bug. At this moment, if we specify a lesser number, e.g.,
# 128, OVS will send Packet-In with invalid buffer_id and
# truncated packet data. In that case, we cannot output packets
# correctly. The bug has been fixed in OVS v2.1.0.
#下发Table-miss Flow Entry优先级为0的流表,即如果报文都没有匹配的话,则匹配该报文,并将其发送给控制器
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
#add_flow方法用来发送Flow Mod消息
def add_flow(self, datapath, priority, match, actions, buffer_id=None):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
if buffer_id:
mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
priority=priority, match=match,
instructions=inst)
else:
mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
match=match, instructions=inst)
#用FlowMod消息去更新,增加,删除流表
datapath.send_msg(mod)
#处理Packet-in数据包,交换机状态为一般状态
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
# If you hit this you might want to increase
# the "miss_send_length" of your switch
if ev.msg.msg_len < ev.msg.total_len:
self.logger.debug("packet truncated: only %s of %s bytes",
ev.msg.msg_len, ev.msg.total_len)
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
#match用来存储数据包的Meta元数据
in_port = msg.match['in_port']
#data接受数据包本身的消息
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
#忽略LLDP数据包
if eth.ethertype == ether_types.ETH_TYPE_LLDP:
# ignore lldp packet
return
#源目mac
dst = eth.dst
src = eth.src
#id为交换机的id
dpid = datapath.id
#更新mac地址表,每台交换机独立的dpid对应一个表
self.mac_to_port.setdefault(dpid, {})
self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# learn a mac address to avoid FLOOD next time.
#学习mac地址表,源mac和端口对应起来
self.mac_to_port[dpid][src] = in_port
#如果目的mac在mac地址表里面,则将出端口置位对应目的mac对应的端口,否则就泛洪flooding
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
actions = [parser.OFPActionOutput(out_port)]
# install a flow to avoid packet_in next time
#下发对应的目的端口到目的mac的流表,优先级为1,比之前的table_miss的优先级高
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
# verify if we have a valid buffer_id, if yes avoid to send both
# flow_mod & packet_out
if msg.buffer_id != ofproto.OFP_NO_BUFFER:
self.add_flow(datapath, 1, match, actions, msg.buffer_id)
return
else:
self.add_flow(datapath, 1, match, actions)
data = None
if msg.buffer_id == ofproto.OFP_NO_BUFFER:
data = msg.data
#将经过上述处理的消息通过PacketOut数据包发送给交换机
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)
运行测试
- 一个终端执行
sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote
- 另一终端执行
sudo ovs-vsctl show
继续执行,查看交换机流表
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
- 在mininet端执行pingall,结果可想肯定是丢包
- 再开一个终端,开启RYU
进入到RYU目录下,执行
ryu-manager --verbose ryu.app.simple_switch_13
- 在ovs端查看流表
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
如今正如代码所示 Table-miss Flow Entry 加入OVS
- mininet端
h1 ping -c1 h2
ping通
- 再次查看OVS流表
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
- 查看ryu端的新增输出
共发出三次PacketIn,下发三次流表
总结
1、相比与传统交换机,OpenFlow交换机的mac地址表维护都是在控制器内部。控制器的压力实在是太大了,毕竟可能要管理多台交换机;
2、借鉴该应用中,处理对应OpenFlow数据包的方法,接下来可以做一些相应的尝试。
RYU 灭龙战 third day的更多相关文章
- RYU 灭龙战 fourth day (2)
RYU 灭龙战 fourth day (2) 前言 之前试过在ODL调用他们的rest api,一直想自己写一个基于ODL的rest api,结果还是无果而终.这个小目标却在RYU身上实现了.今日说法 ...
- RYU 灭龙战 fourth day (1)
RYU 灭龙战 fourth day (1) 前言 对于流量的监控,对于一个网络管理人员来说是非常重要的,可以从可视化的角度,方便检测出哪里的设备出了问题:而在传统网络中,如果是哪里的设备出了问题的话 ...
- RYU 灭龙战 second day(内容大部分引自网络)
RYU 灭龙战 second day(内容大部分引自网络) 写好的markdown重启忘了保存...再写一次RLG 巨龙的稀有装备-RYU代码结构 RYU控制器代码结构的总结 RYU入门教程 RYU基 ...
- RYU 灭龙战 first day
RYU 灭龙战 first day 前言 由于RYU翻译过来是龙的意思,此次主题就叫灭龙战吧 灵感来源 恶龙的三位真火-问题所在 参照了官方文档的基本操作 笔者以此执行 一个终端里 sudo mn - ...
- mininet和ryu控制器的连接
1.执行ryu应用程式:ryu-manager --verbose ryu.app.simple_switch_13 2.启动mininet,配置如下:创建3个host,1个交换器(open vSwi ...
- Ubuntu下搭建ryu环境
RYU环境搭建总共四步: step1:首先下载相应的python套件,并且更新pip $ sudo apt-get install python-pip python-dev build-essent ...
- Ryu
What's Ryu? Ryu is a component-based software defined networking framework. Ryu provides software co ...
- PIC12F629帮我用C语言写个程序,控制三个LED亮灭
http://power.baidu.com/question/240873584599025684.html?entry=browse_difficult PIC12F629帮我用C语言写个程序,控 ...
- (三)开关检测来控制LED灯的亮灭
开关检测案例一: 具体电路图如下: K1--K4闭合,控制 D1—D4 亮灭 产生的问题: 1.关于 R8 R9 R7 R10 的阻值选择问题,倘若太大的话, 比如10K 不管开关断开还是闭合,好像 ...
随机推荐
- BZOJ3533:[SDOI2014]向量集(线段树,三分,凸包)
Description 维护一个向量集合,在线支持以下操作: "A x y (|x|,|y| < =10^8)":加入向量(x,y); " Q x y l r (| ...
- 【转】Tomcat连接器:Coyote框架
不论Tomcat的容器设计得如何精妙,本质上Tomcat就是个http服务器,需要从socket中获得HTTP数据流:另一方面,容器只能处理封装好的org.apache.coyote.Request ...
- 哪些地方会出现css阻塞,哪些地方会出现js阻塞?
Js的阻塞特性: 所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等.直到JS下载.解析.执行完毕后才开始继续并行下载其他资源并呈现内容.为了提高用户体验,新一代浏览器 ...
- RMAN常用命令汇总!
进入RMAN:$ rman target sys/oracle@orcl --远程连接到rman$ rman target sys/oracle@orcl @backup_db.ram --远 ...
- PAT B1048 数字加密 (20 分)
本题要求实现一种数字加密方法.首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 ...
- PAT B1002 写出这个数
读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10100. 输出格式:在一行内输出n的各位数字之和的每 ...
- kubernetes 生命周期问题分析
1.Failed -- pod里至少一个容器以非0code退出,说明应用有问题,需要debug应用容器 2.pending -- 说明API对象已经被创建和保存在etcd数据库里,但是创建过程出了问 ...
- Swift使用AlamoFire超时设置和事件处理
一直在写swift项目,正好碰到服务器部署,请求超时或者请求失败的问题,页面就卡着不动了.顺手解决一下吧 差了些资料,说要设置超时时间 方法一: static let sharedSessionMan ...
- c# WPF 获取网络图片,验证码
c# WPF 获取网络图片,验证码 public static BitmapImage getValidCodeBitmap() { string url = "http://my.baaa ...
- c# 无边框窗体的边框阴影
Windows API: using System; using System.Collections.Generic; using System.ComponentModel; using Syst ...