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. 闲谈CDN网络架构

    CDN也就是内容分布网络(Context Delivery Network),它是构筑在现有interent上的一种先进的流量分配网络.其目的是通过现有的Internet中增加一层新的网络架构,将网站 ...

  2. ES6对抽象工厂模式与策略模式结合的实践

    这段代码是我在学习了java版的抽象工厂模式后,实现的ES6版抽象工厂,后期大幅修改,加入了策略模式,看起来很多逻辑看似繁琐,不必要写这么多,但是为了练习设计模式,所以才这样做.当所需的工厂种类增多后 ...

  3. 【[AHOI2013]差异】

    这个题一看就是为后缀家族设计的 我们看到我们要求的这个柿子 \[\sum_{i=1}^n\sum_{j=i+1}^nT_i+T_j-2\times lcp(T_i,T_j)\] 显然的是前面的那些东西 ...

  4. Git——新手入门与上传项目到远程仓库GitHub(转)

    Git概述 什么是Git? 刚开始对这个东西也感到挺迷茫,并且问了好多已经学习android一段时间的同学也是一头雾水,直到了解并使用之后,才体会到Git的好处以及重要意义. Git:是目前世界上最先 ...

  5. ethereum/EIPs-725

    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md eip title author discussions-to status ...

  6. find和find_if

    find函数 是在一个迭代器范围内查找特定元素得函数,可将将他用于任意容器类型得元素.这个函数返回的是所找元素得引用,如果没有找到元素就会返回这个容器得尾迭代器. #include <iostr ...

  7. 配置使用;yum安装slatstack的master,minion<at>centos6_x86_64

    使用: ####################################### 配置: ####################################### 安装: 服务端安装: [ ...

  8. docker镜像的创建方法docker commit方式

    Docker 提供了两种构建镜像的方法: docker commit 命令(交互式修改创建) Dockerfile 构建文件 (文本命令定义) Docker commit方法: 1.运行一个现有容器 ...

  9. leetcode15—3Sum

    Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find ...

  10. CentOS中配置Kafka集群

    环境:三台虚拟机Host0,Host1,Host2 Host0:192.168.10.2 Host1:  192.168.10.3 Host2:  192.168.10.4 在三台虚拟机上配置zook ...