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 from ryu.lib.packet import ether_types
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
# 判断转发的数据包的连接端口 # 目的 MAC 位址若存在于 MAC 地址表,则判断该连接端口号码为输出。 # 反之若不存在于 MAC 地址表则 OUTPUT action 类别的实体并生成 flooding( OFPP_FLOOD )给目的连接端口使用。 if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD
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, eth_src=src) # verify if we have a valid buffer_id, if yes avoid to send both # flow_mod & packet_out if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(datapath, 1, match, actions, msg.buffer_id) return else: self.add_flow(datapath, 1, match, actions)
# 在 MAC 地址表中找寻目的 MAC 地址,若是有找到则发送 Packet-Out 讯息,并且转送数据包。 data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)
from ryu.app import simple_switch_13 from ryu.controller import ofp_event from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.lib import hub
REST:表征性状态传输(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。REST架构风格中,资源是通过URI来描述的。对资源的操作采用了HTTP的GET,POST,PUT和DELETE方法相对应。资源的表现形式可以是json或xml。REST的架构是Client-Server架构,同时链接是无状态的。所以要求在传输的过程中需要包含状态信息。
from ryu.app import simple_switch_13 from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.app.wsgi import ControllerBase from ryu.app.wsgi import Response from ryu.app.wsgi import route from ryu.app.wsgi import WSGIApplication from ryu.lib import dpid as dpid_lib
if datapath isnotNone: parser = datapath.ofproto_parser # # 如果entry_port不在mac_table中 if entry_port notin mac_table.values(): # 下发流表 for mac, port in mac_table.items():
# from known device to new device actions = [parser.OFPActionOutput(entry_port)] match = parser.OFPMatch(in_port=port, eth_dst=entry_mac) self.add_flow(datapath, 1, match, actions)
# from new device to known device actions = [parser.OFPActionOutput(port)] match = parser.OFPMatch(in_port=entry_port, eth_dst=mac) self.add_flow(datapath, 1, match, actions) # 添加entry_mac, entry_port到mac_table mac_table.update({entry_mac: entry_port}) return mac_table
from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER from ryu.controller.handler import MAIN_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib import lacplib from ryu.lib.dpid import str_to_dpid from ryu.lib.packet import packet from ryu.lib.packet import ethernet from ryu.app import simple_switch_13
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 dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD
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)
data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)
@set_ev_cls(lacplib.EventSlaveStateChanged, MAIN_DISPATCHER) def_slave_state_changed_handler(self, ev): """ 当端口的状态变更为有效或者无效时,需要通过EventSlaveStateChanged事件来进行处理 """ datapath = ev.datapath dpid = datapath.id port_no = ev.port enabled = ev.enabled self.logger.info("slave state changed port: %d enabled: %s", port_no, enabled) if dpid in self.mac_to_port: for mac in self.mac_to_port[dpid]: match = datapath.ofproto_parser.OFPMatch(eth_dst=mac) self.del_flow(datapath, match) del self.mac_to_port[dpid] self.mac_to_port.setdefault(dpid, {})
STP可以消除网络中的环路。其基本理论依据是根据网络拓扑构建(生成)无回路的连通图(就是树),从而保证数据传输路径的唯一性,避免出现环路导致报文流量的增加和循环。STP是工作在OSI第二层(Data Link Layer)的协议,通过在交换机之间传递特殊的消息并进行分布式的计算,来决定在一个有环路的网络中,某台交换机的某个端口应该被阻塞,用这种方法来避免掉环路。
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 import dpid as dpid_lib from ryu.lib import stplib from ryu.lib.packet import packet from ryu.lib.packet import ethernet from ryu.app import simple_switch_13
for dst in self.mac_to_port[datapath.id].keys(): match = parser.OFPMatch(eth_dst=dst) mod = parser.OFPFlowMod( datapath, command=ofproto.OFPFC_DELETE, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, priority=1, match=match) datapath.send_msg(mod)
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 dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD
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)
data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)
log.init_log() # 初始化打印log logger = logging.getLogger(__name__) # 根据配置文件的配置执行 log、pidfile if CONF.enable_debugger: msg = 'debugging is available (--enable-debugger option is turned on)' logger.info(msg) else: hub.patch(thread=True)
if CONF.pid_file: withopen(CONF.pid_file, 'w') as pid_file: pid_file.write(str(os.getpid())) # 启动applist中的应用,若applist为空,则启动ofp_handler应用 app_lists = CONF.app_lists + CONF.app # keep old behavior, run ofp if no application is specified. ifnot app_lists: app_lists = ['ryu.controller.ofp_handler']