2019 SDN上机第5次作业 CWC
1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交你对于教程代码的理解,包括但不限于:
- 描述官方教程实现了一个什么样的交换机功能?
functionality that sends a received packet to all the ports.
- 控制器设定交换机支持什么版本的OpenFlow?
OpenFlow v1.0
- 控制器设定了交换机如何处理数据包?
A new method 'packet_in_handler' is added to the L2Switch class. This is called when Ryu receives an OpenFlow packet_in message. The trick is the 'set_ev_cls' decorator. This decorator tells Ryu when the decorated function should be called.
The first argument of the decorator indicates which type of event this function should be called for. As you might expect, every time Ryu gets a packet_in message, this function is called.
The second argument indicates the state of the switch. You probably want to ignore packet_in messages before the negotiation between Ryu and the switch is finished. Using 'MAIN_DISPATCHER' as the second argument means this function is called only after the negotiation completes.
Next let's look at the first half of the 'packet_in_handler' function.
- ev.msg is an object that represents a packet_in data structure.
- msg.dp is an object that represents a datapath (switch).
- dp.ofproto and dp.ofproto_parser are objects that represent the OpenFlow protocol that Ryu and the switch negotiated.
Ready for the second half.
- OFPActionOutput class is used with a packet_out message to specify a switch port that you want to send the packet out of. This application uses the OFPP_FLOOD flag to indicate that the packet should be sent out on all ports.
- OFPPacketOut class is used to build a packet_out message.
- If you call Datapath class's send_msg method with a OpenFlow message class object, Ryu builds and sends the on-wire data format to the switch.
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]
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
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
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
# TODO define the OpenFlow Packet Out
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)
print("PACKET_OUT...")
3.在mininet创建一个最简拓扑,并连接RYU控制器
- 使用命令行创建该最简拓扑
sudo mn --controller=remote,ip=127.0.0.1,port=6633
- 连接RYU控制器
ryu-manager SelfLearning.py


4.验证自学习交换机的功能,提交分析过程和验证结果
- 连接ryu控制器前, 查看 s1 流表
sudo ovs-ofctl dump-flows s1

- 连接后则显示

5.写下你的实验体会
本次实验除了RYU控制器安装时有点麻烦之外(例如依赖的安装由于换国内源之前是巨慢!而且还失败),其他部分仅要按照步骤进行还挺顺利的。
Python的部分不是很熟悉,应继续加强


浙公网安备 33010602011771号