RYU控制器代码解析-简单交换机

  上一篇文章是关于Hub的,有关一些函数的用法都在上一篇文章里,大家有需要可以自行查看。
  一个简单的交换机需要具有以下功能:
  1.能够学习MAC地址,并且把MAC地址和接口联合起来填充MAC地址表。
  2.当收到数据包的目的MAC地址在MAC地址表里面时,将数据包发送出去。
  3.当收到的数据包目的MAC地址不在MAC地址表里面的时候,进行泛洪。

下面我们开始讲一下需要的算法:
  1.使用Packet-In报文来学习MAC地址。
  2.在学习到MAC地址之后,再收到数据包,交换机会先检查MAC地址表里面有没有目标地址,如果有,就用Packet-Out报文来把数据包送出去;如果没有,就泛洪数据包。
  3.所谓的流表,就是包含了源和目的一个表,它是根据MAC地址表建立的,只有MAC地址表里面同时包含源和目的的时候,才会增加流表项。流表是在源和目的双向通信完成后建立的(这个表述可能有点牵强,我举个例子说明一下)
  一台交换机连接两个主机,主机A向主机B发了数据包,主机B应答A的数据包经过交换机后,就建立了一条流表项,但是要注意:这个流表项的源是主机B,目的是A,大家可以分析一下为什么。
  如果流表里面没有对应的流表项,在OpenFlow1.3版本,交换机可以选择丢弃数据包,或者匹配下一个流表,或者是传输给控制器,默认是丢弃数据包的,而在1.0,交换机只会Packet-In上报控制器。
  控制器和交换机握手完成之后,一条默认流表项应该被添加进流表。它的作用是为了让交换机发送Packet-In消息。这条默认流表项被称为Table-Miss,不过Table-Miss不是默认存在的,他也是由控制器下发的。
  我们在控制器代码里面定义的MAC地址表是只有控制器知道的,对于交换机来说,只有流表才能帮助它转发,所以控制器要给交换机下发流表,如果你不在交换机添加详细的流表项,那么你应该让交换机收到每一个数据包都上报控制器,由控制器下发Packet-Out报文进行处理,否则数据包会被丢弃。
  下面展示源代码,源代码是ryu/app目录下面的simple_switch_13.py。13对应的是OpenFlow1.3版本。

#!/usr/bin/env python

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
  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一份示例代码,但需要注意的是,这份代码只是一个简单的示例,仅能实现基本的交换机功能,您需要根据实际情况进行修改和完善。 ```python 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_0 from ryu.ofproto import ofproto_v1_0_parser from ryu.lib.packet import packet from ryu.lib.packet import ethernet class SimpleSwitch(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION] def __init__(self, *args, **kwargs): super(SimpleSwitch, self).__init__(*args, **kwargs) self.mac_to_port = {} @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): datapath = ev.msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser # 添加默认流表,将所有流量转发至控制器 match = parser.OFPMatch() actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.in_port pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # 记录源 MAC 地址和端口号 self.mac_to_port[dpid][src] = in_port # 如果目的 MAC 地址在交换机已知主机列表中,则直接转发 if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: # 如果目的 MAC 地址未知,则广播到所有端口 out_port = ofproto_v1_0.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] # 发送流表 if out_port != ofproto_v1_0.OFPP_FLOOD: match = parser.OFPMatch(in_port=in_port, dl_dst=dst) self.add_flow(datapath, 1, match, actions) # 发送数据包 out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions) datapath.send_msg(out) def add_flow(self, datapath, priority, match, actions): ofproto = datapath.ofproto parser = datapath.ofproto_parser # 构造流表 inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst) datapath.send_msg(mod) ``` 这是一个基于 OpenFlow 协议的简单交换机实现。当交换机收到数据包时,会将源 MAC 地址和端口号记录在一个字典中,然后查找目的 MAC 地址所对应的端口号并转发数据包。如果目的 MAC 地址未知,则广播到所有端口。 请注意,这个示例代码只适用于 OpenFlow1.0,如果您使用的是其他版本的 OpenFlow 协议,需要对代码进行相应的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值