2.2 Hub+Learning Switch应用开发(下)

Learning Switch/自学习交换机

  1. 明确问题–如何实现软件定义的自学习交换机?
  2. 设计解决方案–通过控制器来实现自学习交换算法,然后指导数据平面实现交换机操作。
  3. 确定具体技术方案–控制器选用Ryu,数据平面用Mininet模拟
  4. 部署实施–在控制器上编程开发集线器应用。创建实验网络为验证方案网络做准备。
  5. 验证方案–运行、调试、验证程序。
  6. 优化–验证成功后

集线器是物理层设备,功能是对接受到的数据进行再生整形放大,以扩大传输距离,把所有节点集中在中心节点。没有“学习能力”,发送数据没有针对性,采用广播方式发送,当要向某个节点发送数据的时候,是把数据包发送到相连的所有节点。

交换机:光电信号转发的网络设备,为介入交换机的任意两个网络节点提供独享的电信号通路。

自学习交换机的原理/Learning Switch

在这里插入图片描述

交换机的1 3 4端口分别连接主机A C B,交换机里面有两个表,分别是MAC地址表和流表

在这里插入图片描述

主机A给交换机发消息说我要找主机B,刚开始流表是默认的,没有可以用来指导处理的信息,这时候交换机就会找控制器,这时候控制机就会记录下来A主机连接在哪个端口在MAC地址表中。这时候控制器也不知道B是谁,那就跟交换机说你泛洪一下,发给其他所有的主机,然后B和C主机都能收到消息。

在这里插入图片描述

B收到信息知道A是找它的,C收到发现不是找他的就丢掉信息。然后B发送回复,B先发给交换机,交换机不知道怎么处理,给控制器发信息,控制器发现B找A,A在1端口,这时候还学习了一下B在端口4。现在知道了入端口和出端口,就需要下发一条流表项。流表中记录从端口4进入,目的端口是1.

在这里插入图片描述

A继续回复,交换机中只有B到A,还不知道A到B,还需要询问控制器,这时候控制器有A和B的MAC地址信息,所以可以下发流表项信息。之后再进行数据转发的时候就可以不询问控制器,直接在交换机中进行转发操作。

Learning Switch/自学习交换机验证(Ryu控制器的API使用)

from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller.handler import CONFIG_DISPATCHER,MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.controller import ofp_event
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet

# 编写自学习交换机程序
class ExampleSwitch(app_manager.RyuApp):

	# 获取OpenFlowProtocol版本号
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    
    def _init_(self,*args,**kwargs):
        super(ExampleSwitch,self)._init_(*args,**kwargs)
        # mac 地址表
        self.mac_to_port={}
    
    # 见上一篇2.1博文
    def switch_features_handler(self,ev): 
        datapath = ev.msg.datapath
        ofproto = datapath
        ofp_parser = datapath.ofproto_parser
        
        match = ofp_parser.OFPMatch()
        actions = [ofp_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
        ofp_parser = datapath.ofproto_parser
        
        inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                        actions)]
        mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority,
                    match=match,instryction=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
        ofp_parser = datapath.ofproto_parser
        
        # get datapath id to identify OpenFlow switch
        # 一个交换机对应一个dpid
        dpid = datapath.id
        # 设置mac地址表默认格式
        self.mac_to_port.setdefault(dpid,{})
        
        # store the info 
        # parser and analylize the received packets
        # 利用提供的方法进行解析数据
        pkt = packet.Packet(msg.data)
        # 获取以太网协议
        eth_pkt = pkt.get_protocol(ethernet.ethernet)
        dst = eth_pkt.dst
        src = eth_pkt.src
        # 获取 in_port
        in_port = msg.match['in_port']
        
        # dpid 交换机的编号
        # src 输入主机ip
        # dst 输出主机ip
        # 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 dst mac address has already learned.
        # decide which port to send the packets, otherwise, flood.
        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD
        
        # contruct actions
        actions=[ofp_parser.OFPActionOutput(out_port)]
        
        # install a flow mod msq
        if out_port != ofproto.OFPP_FLOOD:
            match = ofp_parser.OFPMatch(in_port=in_port,eth_dst=dst)
            # 下发流表项
            self.add_flow(datapath,1,match,actions)
        
        # send a packet out
        out = ofp_parser.OFPPacketOut(
            datapath=datapath,buffer_id=msg.buffer_id,in_port=in_port,
            actions=actions)
        datapath.send_msg(out)
  • sudo mn --controller=remote
  • pingall
  • sudo mn --controller=remote --mac
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蒋的学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值