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的更多相关文章

  1. RYU 灭龙战 fourth day (2)

    RYU 灭龙战 fourth day (2) 前言 之前试过在ODL调用他们的rest api,一直想自己写一个基于ODL的rest api,结果还是无果而终.这个小目标却在RYU身上实现了.今日说法 ...

  2. RYU 灭龙战 fourth day (1)

    RYU 灭龙战 fourth day (1) 前言 对于流量的监控,对于一个网络管理人员来说是非常重要的,可以从可视化的角度,方便检测出哪里的设备出了问题:而在传统网络中,如果是哪里的设备出了问题的话 ...

  3. RYU 灭龙战 second day(内容大部分引自网络)

    RYU 灭龙战 second day(内容大部分引自网络) 写好的markdown重启忘了保存...再写一次RLG 巨龙的稀有装备-RYU代码结构 RYU控制器代码结构的总结 RYU入门教程 RYU基 ...

  4. RYU 灭龙战 first day

    RYU 灭龙战 first day 前言 由于RYU翻译过来是龙的意思,此次主题就叫灭龙战吧 灵感来源 恶龙的三位真火-问题所在 参照了官方文档的基本操作 笔者以此执行 一个终端里 sudo mn - ...

  5. mininet和ryu控制器的连接

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

  6. Ubuntu下搭建ryu环境

    RYU环境搭建总共四步: step1:首先下载相应的python套件,并且更新pip $ sudo apt-get install python-pip python-dev build-essent ...

  7. Ryu

    What's Ryu? Ryu is a component-based software defined networking framework. Ryu provides software co ...

  8. PIC12F629帮我用C语言写个程序,控制三个LED亮灭

    http://power.baidu.com/question/240873584599025684.html?entry=browse_difficult PIC12F629帮我用C语言写个程序,控 ...

  9. (三)开关检测来控制LED灯的亮灭

    开关检测案例一: 具体电路图如下: K1--K4闭合,控制 D1—D4 亮灭 产生的问题: 1.关于 R8 R9 R7 R10 的阻值选择问题,倘若太大的话,  比如10K 不管开关断开还是闭合,好像 ...

随机推荐

  1. 8.3Solr API使用(StatsComponent聚合统计)

    转载请出自出处:http://eksliang.iteye.com/blog/2169134 一.概述 Solr可以利用StatsComponent 实现数据库的聚合统计查询,也就是min.max.a ...

  2. leetcode 460. LFU Cache

    hash:存储的key.value.freq freq:存储的freq.key,也就是说出现1次的所有key在一起,用list连接 class LFUCache { public: LFUCache( ...

  3. Node.js实战(十二)之Stream

    Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出). Node.js,Str ...

  4. sublime出现 unable download.......

    I managed to fix this by changing my package settings. I made my osx downloader preference curl, and ...

  5. AMD、CMD和Common规范

    1.名词解释AMD:Asynchronous Modules Definition异步模块定义,提供定义模块及异步加载该模块依赖的机制.CMD:Common Module Definition 通用模 ...

  6. scapy学习笔记(4)简单的sniffing 嗅探

    转载请注明:@小五义:http://www.cnblogs/xiaowuyi 利用sniff命令进行简单的嗅探,可以抓到一些简单的包.当不指定接口时,将对每一个接口进行嗅探,当指定接口时,仅对该接口进 ...

  7. 关于OpenCV2.4.9在VS2012上的配置

    今天写着篇文章是由于自从上次电脑换硬盘今天再次安装OpenCV又遇到了一些问题,最后终于搞定,,,,用的版本是2.4.9,,,因为第一次配置用3.0的没有配置成功,而2.4.9的配置成功. 首先当然是 ...

  8. WebHook之PHP实践@coding.net

    次写完代码, 打开FileZilla, 把写好的文件上传到vps上, 久而久之觉得腻烦, 寻思有没有更geek的方法, 便有此文. WebHook是跟随着Git而兴起的技术, 当你push到服务器的时 ...

  9. Docker服务器的图形显示方案

    问题描述:一般docker实操时都是作为服务器,以字符方式交互,非常不方便.本人尝试各种图形解决方案,最终找到完美方案. 最初本人尝试过VNC和SSH方式,最终被否定了.1, 本来docker服务器是 ...

  10. Kafka 集群部署

    kafka是一个分布式消息队列,需要依赖ZooKeeper,请先安装好zk集群 kafka安装包解压 $ -0.9.0.1.tgz $ -0.9.0.1 /usr/kafka $ cd /usr/ka ...