• 2019 SDN上机第5次作业


    1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交你对于教程代码的理解,包括但不限于:


    描述官方教程实现了一个什么样的交换机功能?

    Add some features to enable the switch to forward the received packets to all ports.

    控制器设定交换机支持什么版本的OpenFlow?

    支持OpenFlow v1.0

    控制器设定了交换机如何处理数据包?

    	@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
         //表明当Ryu收到OpenFlow packet_in消息时,将产生事件(调用“packet_in_handler”方法)
        def packet_in_handler(self, ev):
            msg = ev.msg
            dp = msg.datapath
            ofp = dp.ofproto
            ofp_parser = dp.ofproto_parser
            actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
               //动作列表。OFPActionOutput类与packet_out消息一起使用,以指定要从中发送数据包的交换机端口。该应用程序使用OFPP_FLOOD标志来指示应在所有端口上发送数据包。
            out = ofp_parser.OFPPacketOut(
                datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
                actions=actions)
            dp.send_msg(out)
    

    2.根据官方教程和提供的示例代码(SimpleSwitch.py),将具有自学习功能的交换机代码(SelfLearning.py)补充完整


    补充后的完整代码:

    from ryu.base import app_manager
    from ryu.controller import ofp_event
    from ryu.controller.handler import MAIN_DISPATCHER
    from ryu.controller.handler import set_ev_cls
    from ryu.ofproto import ofproto_v1_0
    
    from ryu.lib.mac import haddr_to_bin
    from ryu.lib.packet import packet
    from ryu.lib.packet import ethernet
    from ryu.lib.packet import ether_types
    
    class SimpleSwitch(app_manager.RyuApp):
    	# TODO define OpenFlow 1.0 version for the switch
    	OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
    	# add your code here
    
    	def __init__(self, *args, **kwargs):
    		super(SimpleSwitch, self).__init__(*args, **kwargs)
    		self.mac_to_port = {}
        
    	def add_flow(self, datapath, in_port, dst, src, actions):
    		ofproto = datapath.ofproto
    
    		match = datapath.ofproto_parser.OFPMatch(
                in_port=in_port,
                dl_dst=haddr_to_bin(dst), dl_src=haddr_to_bin(src))
    
    		mod = datapath.ofproto_parser.OFPFlowMod(
                datapath=datapath, match=match, cookie=0,
                command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
                priority=ofproto.OFP_DEFAULT_PRIORITY,
                flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
    		# TODO send modified message out
    		# add your code here
    		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
    
    		pkt = packet.Packet(msg.data)
    		eth = pkt.get_protocol(ethernet.ethernet)
    
    		if eth.ethertype == ether_types.ETH_TYPE_LLDP:
    			# ignore lldp packet
    			return
    		if eth.ethertype == ether_types.ETH_TYPE_IPV6:
    			# ignore ipv6 packet
    			return       
    		
    		dst = eth.dst
    		src = eth.src
    		dpid = datapath.id
    		self.mac_to_port.setdefault(dpid, {})
    
    		self.logger.info("packet in DPID:%s MAC_SRC:%s MAC_DST:%s IN_PORT:%s", dpid, src, dst, msg.in_port)
    
    		# learn a mac address to avoid FLOOD next time.
    		self.mac_to_port[dpid][src] = msg.in_port
    
    		if dst in self.mac_to_port[dpid]:
    			out_port = self.mac_to_port[dpid][dst]
    		else:
    			out_port = ofproto.OFPP_FLOOD
    
    		# TODO define the action for output
    		# add your code here
    		actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
    
    
            # install a flow to avoid packet_in next time
    		if out_port != ofproto.OFPP_FLOOD:
    			self.logger.info("add flow s:DPID:%s Match:[ MAC_SRC:%s MAC_DST:%s IN_PORT:%s ], Action:[OUT_PUT:%s] ", dpid, src, dst, msg.in_port, out_port)
    			self.add_flow(datapath, msg.in_port, dst, src, actions)
    
    		data = None
    		if msg.buffer_id == ofproto.OFP_NO_BUFFER:
    			data = msg.data
    
    		out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,actions=actions, data=data)
    		datapath.send_msg(out)
    

    3.创建一个最简拓扑,并连接RYU控制器


    在SimpleSwitch.py目录下运行:

    ryu-manager selflearning.py
    

    在本机使用mininet创建最简拓扑:

    sudo mn --controller=remote,ip=127.0.0.1,port=6633
    

    4.验证自学习交换机的功能,提交分析过程和验证结果


    此时交换机s1上并无流表:

    在Mininet CLI运行h1 ping h2,h1发送广播寻找h2,

    再次使用sudo ovs-ofctl dump-flows s1查看流表:

    h1 ping h2时,在wireshark抓包分析如下:


    5.写下你的实验体会



    安装是个漫长又艰难的过程,面临着虚拟机随时可能崩溃的危险,但按照老师的教程一步一步走下来,最终还是成功安装好了。ryu控制器的框架理解起来也有一定的困难,看了不少教程,稍微有些理解,通过实践,进一步加深理解。ryu比较灵活,可以用来打造属于自己风格的自定义控制器。

  • 相关阅读:
    vue form dynamic validator All In one
    TypeScript api response interface All In One
    closable VS closeable All In One
    macOS 如何开启 WiFi 热点 All In One
    vue css inline style All In One
    vs2010里面 新建网站里面的 asp.net网站 和 新建项目里面的 asp.net Web应用程序 的区别 (下)
    牛腩新闻 59 整合添加新闻页 FreeTextBox 富文本编辑器,检测到有潜在危险的 Request.Form 值,DropDownList 的使用
    牛腩新闻 61尾声: error.aspx的使用 防止报错
    vs2010里面 新建网站里面的 asp.net网站 和 新建项目里面的 asp.net Web应用程序 的区别 (上)
    牛腩新闻 62:尾声续2 asp.net的编译和发布
  • 原文地址:https://www.cnblogs.com/0717fei/p/11946303.html
Copyright © 2020-2023  润新知