2019 SDN上机第5次作业

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

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

让交换机在各个端口发送它接收到的数据包

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

OpenFlow v1.0

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

这里把官方给出的代码放上来,备注中解释处理函数的部分

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

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

#coding=utf-8
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

class L2Switch(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]  #定下使用的OpenFlow版本

    def __init__(self, *args, **kwargs):
        super(L2Switch, self).__init__(*args, **kwargs)
        self.mac_to_port = {}

    def add_flow(self, datapath, in_port, dst, actions):
        ofproto = datapath.ofproto

        match = datapath.ofproto_parser.OFPMatch(
            in_port = in_port, dl_dst = haddr_to_bin(dst))

        mod = datapath.ofproto_parser.OFPFlowMod(
            datapath = datapath, match = match, cookie = 0,
            command = ofproto.OFPFC_ADD, idle_timeout = 10,hard_timeout = 30,
            priority = ofproto.OFP_DEFAULT_PRIORITY,
            flags =ofproto.OFPFF_SEND_FLOW_REM, actions = actions)

        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)

        dst = eth.dst
        src = eth.src

        dpid = datapath.id    #获取dpid
        self.mac_to_port.setdefault(dpid, {}) #设置交换机的mac地址表

        self.logger.info("packet in %s %s %s %s", dpid, src, dst , msg.in_port)  #显示dpid,映射host的mac地址与交换机那块对应的端口号

        self.mac_to_port[dpid][src] = msg.in_port  #判断目的mac地址是否存在于mac位址表中,若不存在,进行洪泛

        out_port = ofproto.OFPP_FLOOD #将输出端口指定为洪泛

        if dst in self.mac_to_port[dpid]:  #如果已经获取目的mac地址,查询输出用端口
            out_port = self.mac_to_port[dpid][dst]

        ofp_parser = datapath.ofproto_parser

        actions = [ofp_parser.OFPActionOutput(out_port)]

        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) #显示datapath id,目标的MAC地址,源的MAC地址,进入端口,输出端口等信息
            self.add_flow(datapath, msg.in_port, dst, actions)

        packet_out = ofp_parser.OFPPacketOut(datapath = datapath, buffer_id = msg.buffer_id,in_port = msg.in_port, actions = actions)  #发送packet_out消息以处理数据包
        datapath.send_msg(packet_out)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER) #这里则是展示端口状态
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no

        ofproto = msg.datapath.ofproto

        if reason == ofproto.OFPPR_ADD:
            self.logger.info("port added %s", port_no)
        elif reason == ofproto.OFPPR_DELETE:
            self.logger.info("port deleted %s", port_no)
        elif reason == ofproto.OFPPR_MODIFY:
            self.logger.info("port modified %s", port_no)
        else:
            self.logger.info("Illeagal port state %s %s", port_no, reason)

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

用命令创建拓扑
image.png

创建成功

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

在mininet中查看此时s1的流表
image.png

开启具有SelfLearning功能的控制器
image.png

进行h1对h2的ping操作
image.png

控制器中显示出预期信息
image.png

此时再次查看s1的流表

image.png

至此,Selflearning简单验证成功

5.写下你的实验体会

主要繁琐在安装RYU的过程,代码也花了时间去看,觉得还是opendayly简单

原文地址:https://www.cnblogs.com/zuodengfeng/p/11969933.html