Switching hub

Switching hub,即交换式集线器,是一个能在共享网络拓扑结构中减少竞争的设备。
假如你有一个由20个用户组成的网,因为信息传输量超载而停止运行,你可以将其分拆成两个段并桥接它们,这样就会减少整个系统的数据传输负载,并减少每一个新网络段上的竞争访问。位于同一网段上的所有用户或设备彼此之间能正常通信,只有这样才会减少段之间的通信量。如果通信量仍有问题,你还可以将LAN分成4段、6段等等。交换式集线器可恰到好处地完成这种分段。一个集线器上有很多端口,每一个端口是一个专用LAN段。

交换集线器有许多功能,在这里介绍以下几个简单的功能:

  1. 学习连接到端口的主机得MAC地址,并将其保留在MAC地址表中。
  2. 当接收到一个数据包且其MAC地址已经存在MAC地址表中时,直接将包转发到目的端口所连接的主机中。
  3. 当接收到的数据包没有在其MAC地址表中时,则进行泛洪。

Switching Hub by OpenFlow

OpenFlow交换机根据OpenFlow控制器(如RYU)的指令来执行以下操作:

  1. 重写接收包的地址或将包转发到指定端口。
  2. 转发包到控制器(packet-in消息,即用于交换机传递包到控制器,通常是为了异常情况的处理)
  3. 控制器使用packet-out消息把数据包发送给交换机,交换机再转发到指定端口中。

类似,Switching hub的执行过程如下:
首先,控制器使用packet-in功能来接收交换机传递过来的包,交换机则分析该包来学习源端口所连接主机的MAC地址以及端口信息。
学习之后,交换机转发所接收到的数据包。它先检查该数据包的目的MAC地址是否在MAC地址表中,如果在,则使用packet-out功能来转发包到目的端口中,反之,则执行泛洪操作。

举个例子:

  1. 初始化状态

此时的流表为空。主机A连接端口1,主机B连接端口3,主机C连接端口4.

2. HostA->HostB
当主机A向主机B发送一个数据包时,一个packet-in消息被发送,交换机通过端口1学习到主机A的MAC地址并保存在MAC地址表中。而此时连接端口4的主机B的MAC地址没有在MAC地址表中,所以该包被泛洪,询问谁有该目的MAC地址。此时主机B和主机C均可接收到该包。

Packet-in:

in-port: 1
eth-dst: Host B
eth-src: Host A

Packet-Out:

action: OUTPUT:Flooding

  1. HostB->HostA
    主机B接收到主机A发送的包之后,发现该目的地址和自己匹配,因此封装自己的MAC地址到该包中并发回给主机A,主机B的MAC地址被保留在MAC地址表中,并且一条流表项加进流表中。因为此时主机A的MAC地址已经存在表中,所以不需要泛洪,直接发送到连接主机A的端口1即可。主机C不再接受该包。

    Packet-In:

in-port: 4
eth-dst: Host A
eth-src: Host B

Packet-Out:

action: OUTPUT:Port 1

  1. HostA->HostB
    当主机A再次向主机B发送数据包时,流表又会新加一条流表项。
    Packet-In:

in-port: 1
eth-dst: Host B
eth-src: Host A

Packet-Out:

action: OUTPUT:Port 4

Implementation of Switching Hub Using Ryu

在ryu/app中的simple_switch_13.py实现了Switching hub,后面的13表示支持OpenFlow1.3的版本。
源代码如下:

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 ethernetclass 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.datapathofproto = datapath.ofprotoparser = 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.ofprotoparser = 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.msgdatapath = msg.datapathofproto = datapath.ofprotoparser = datapath.ofproto_parser# get Datapath ID to identify OpenFlow switches.dpid = datapath.idself.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.dstsrc = 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)

Class Definition and Initialization

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 = {}# ...

首先是类定义和初始化。
app_manager.RyuApp:当要实现一个Ryu应用时,首先需要继承ryu.base.app_manager.RyuApp
OFP_VERSIONS:用来指定OpenFlow的版本号
mac_to_port:定义了MAC地址表,初始为空表。

在OpenFlow协议中,定义了OpenFlow交换机和控制器握手的过程,但这些都有Ryu框架来进行处理,因此在这里我们不再深入了解。

Event Handler

当一个OpenFlow消息被接受后,就会生成一个对应的事件,Ryu应用程序实现对应消息的事件处理函数。
事件处理程序为参数定义一个具有事件对象的函数,使用ryu.controller.handler.set_ev_cls函数装饰器来装饰。
set_ev_cls为参数指定支持接受消息的事件的类以及OpenFlow交换机的状态。
事件类名为ryu.controller.ofp_event.EventOFP + “OpenFlow message name”,
例如,如果是packet-in消息,则类名为 EventOFPPacketIn。
交换机状态则根据情况指定下面列表中的其中之一。

Adding Table-miss Flow Entry

握手完成后,当一个packet-in消息到来时,就会添加一个Table-miss流条目到流表里。
这里首先接收到含有交换机特性的消息,然后将该条Table-miss流条目添加进去。

@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):datapath = ev.msg.datapathofproto = datapath.ofprotoparser = datapath.ofproto_parser# ...

ev.msg:用于存储于事件消息对应类的实例。
Datapath类执行重要的处理,如与OpenFlow交换机的实际通信和发出与接收到的消息对应的事件。
Ryu应用程序的主要属性如下:

def switch_features_handler(self, ev):
# ...# 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)

match:用于匹配所有包
actions:是交换机所要执行的动作。
ofproto.OFPP_CONTROLLER:控制器为输出目的端口
ofproto.OFPCML_NO_BUFFER:将OFPCML_NO_BUFFER指定为max_len,以便将所有数据包发送到控制器。

Packet-in Message

当接收到位置目的地的包时则执行packet-in事件处理程序

@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):msg = ev.msgdatapath = msg.datapathofproto = datapath.ofprotoparser = datapath.ofproto_parser# ...

OFPPacketIn类属性如下:

Updating the MAC Address Table

def _packet_in_handler(self, ev):
# ...# 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# ...

dpid为OpenFlow switches的标识符,因为一个控制器可以支持连接多个交换机,所以需指定dpid来定义每个OpenFlow交换机。

Execution of Ryu Application

理解了源代码的过程,就可以直接用mininet进行实验。
首先建立一个简单的拓扑结构,即三个主机连接同一个交换机。

$ sudo mn --topo single,3 --mac --switch ovsk --controller remote -x
*** Creating network
*** Adding controller
Unable to contact the remote controller at 127.0.0.1:6633
*** Adding hosts:
h1 h2 h3
*** Adding switches:
s1
*** Adding links:
(h1, s1) (h2, s1) (h3, s1)
*** Configuring hosts
h1 h2 h3
*** Running terms on localhost:10.0
*** Starting controller
*** Starting 1 switches
s1
*** Starting CLI:
mininet>

mn后面所跟着的属性如下:

当执行完上述命令后,会产生如下5个终端模拟器,即三个主机h1,h2,h3,一个交换机s1,一个控制器c0.

第一步首先查看Open vSwitch的状态

#ovs-vsctl show


接着设置OpenFlow版本为1.3

# ovs-vsctl set Bridge s1 protocols=OpenFlow13
#

查看流表,初始为空

# ovs-ofctl -O OpenFlow13 dump-flows s1

Executing the Switching Hub

在控制器c0上运行Ryu程序

# ryu-manager --verbose ryu.app.example_switch_13


OVS连接之后,即控制器和交换机之间的握手已经完成,并添加了Table-miss流条目,switching hub此时处于等到分组到来的状态。

Confirming Operation

对主机,首先执行tcpdump命令来检查每个主机都收了哪些包。
h1:

# tcpdump -en -i h1-eth0

h2,h3同理。

然后在mininet控制台上执行ping操作。这里我们进行h1 ping h2。

这里分析一下h1 ping h2的过程。
1、ARP请求
刚开始时,h1并不知道h2的MAC地址,因此在发送ICMP echo请求前,需要广播一个ARP请求,在上述例子上,这个广播将被h2和h3接收到。
2、ARP应答
h2看到ARP请求中的IP地址与自己匹配之后,于是向主机h1发送ARP响应报文。
3、ICMP echo请求
此时h1已经知道了h2的MAC地址,于是向h2发送一个 echo 请求。
4、ICMP echo应答
因为h2已经知道了h2的MAC地址,因此h2可以直接返回一个echo应答给h1.


现在检查一下s1中的流表

再看一下控制器c0中的log。

最后检查下每个主机,这里只贴h1,h2,h3同理。
h1:

使用Ryu实现交换式集线器(Switching hub)相关推荐

  1. 集线器(Hub)、交换机(Switch)与路由器(Router)

    转自http://zhidao.baidu.com/question/5142729.html ---------------------------------------------------- ...

  2. 共享式以太网和交换式以太网的区别

    集线器在OSI模型中属于物理层,但由于集线器属于共享型设备,使得它在网络中的效率十分低下,非常容易产生广播风暴,因此在中大型的网络中通常看不到集线器的身影.而交换机则属于数据链路层,是一种基于MAC地 ...

  3. 集线器(Hub)、交换机(SW)、路由器(router)对比区别

    先从技术上分析: 我们现在使用的以太网采用的工作方式是CSMA/CD(载波监听多路访问/冲突检测),对于发送端来说,它每发送一个数据时,首先对网络进行监听,当它检测到线路正好有空,便立即发送数据,否则 ...

  4. 交换式以太网和共享式以太网区别

    交换式以太网和共享式以太网区别 集线器,又称Hub,在OSI模型中属于数据链路层.但由于集线器属于共享型设备,导致了在繁重的网络中,效率变得十分低下,易产生广播风暴.所以我们在中.大型的网络中看不到集 ...

  5. 集线器(Hub)、交换机(Switch)与路由器(Router)之间的区别和联系

    集线器--集线器也叫Hub,工作在物理层(最底层),没有匹配的软件系统,是纯硬件设备.集线器主要用来连接计算机等网络终端.集线器为共享带宽,连接在集线器上的任何一个设备发送数据时,其他所有设备必须等待 ...

  6. 交换机与集线器(HUB)抓包上的区别

    当你想要知道一台网络设备,例如网络摄像机(IPC)往外发送了什么数据,你可以怎么抓包呢,考虑一些网段等因素,可以直接使用集线器(HUB)进行抓包. HUB抓包方式 一般通过下图的连接方式就可以在PC机 ...

  7. pygame交换式拼图设计

    运行截图 完成时候的截图 游戏设计思想 在600*600的屏幕上,进行拼图划分.(可以是N * M不一定是N * N) 利用鼠标来操作拼图移动 游戏设计 制作一个类:PartPicture用来保存分块 ...

  8. 交换式多兆位数据服务(SMDS)--网络大典

    交换式多兆位数据服务(SMDS)是一种宽带网技术,由 Bellcore 公司开发,基于 IEEE 802.6 DQDB(Distributed Queue Dual Bus 分布式队列双总线)的 MA ...

  9. SMDS:交换式多兆位数据服务--网络大典

    交换式多兆位数据服务 SMDS 是一种基于 IEEE 802.6 DQDB(Distributed Queue Dual Bus 分布式队列双总线)的宽带网 MAN 技术,由 Bellcore 公司开 ...

  10. 交换式路由器与路由式交换机

    现在路由器和交换机之间的区别也越来越模糊,多层路由器与交换机都可以同时实现交换和路由的功能,它们之间还有不同吗?各自特点何在?如何更好地根据应用需求进行选择?     一.传统的交换机和路由器 普通交 ...

最新文章

  1. 缩小规模,OpenAI文本生成图像新模型GLIDE用35亿参数媲美DALL-E
  2. 不可思议的数字:互联网每天到底能产生多少数据?
  3. 使用Feign时如何设置Feign的Header信息
  4. linux http请求监控工具httpry---官方文档
  5. 每天一道LeetCode-----最长回文子串/序列,从头开始的最长回文子串长度
  6. Python 21 Django 实用小案例1
  7. 月蚀动漫获快看漫画600万元A轮战略投资,走国漫精品化路线
  8. Nessus进行漏洞扫描的过程
  9. oracle重新生成控制文件,Oracle重建控制文件的语法
  10. shell脚本练习题
  11. Skype国际版最新版及老版本下载
  12. Uploadify-中文帮助手册
  13. ITIL 2011服务管理与认证读书笔记一——IT服务管理与ITIL
  14. java中特殊符号_java中的特殊字符集合
  15. 快速构建一款 AR App 入门指南
  16. 解决Idea中yml文件不显示小绿叶图标
  17. p-sum结构解释+代码 二叉区间树
  18. linux 查看ln链接地址,linux ln链接详解
  19. Java实现简单的数字雨
  20. 学习笔记——【python】GetGeoTransform()使用,gdal截取图像,使用GDAL进行影像投影坐标、地理坐标、图上坐标的转换

热门文章

  1. 【计算机基础恶补】南桥北桥
  2. 为什么visio输出图片俩边有留白_Microsoft Office Visio导出图片添加边界的操作教程...
  3. 【3D音效增强神器】Boom 3D for Mac中文版 v1.2.2
  4. ReactNative实现ListView分组,悬浮效果
  5. mysql 时间 本周 本月_MySQL日期查询:本周、本月、本季、本年
  6. window 10 金蝶KIS SPR32X30.OCX不能正确注册
  7. 中文地址识别api的使用测试,快递地址自动补全,自动识别省市区,地址清洗,到底哪个好用?
  8. 关于深度学习人工智能模型的探讨(一)(1)
  9. 在windows系统上搭建CTS测试环境过程记录
  10. Ubuntu 机箱前置耳机没声音的问题(彻底解决)