实验5实验6_102101310_黄心怡
实验5:开源控制器实践——POX
一、实验目的
- 能够理解POX控制器的工作原理;
- 通过验证POX的forwarding.hub和forwarding.l2_learning模块,初步掌握POX控制器的使用方法;
- 能够运用POX控制器编写自定义网络应用程序,进一步熟悉POX控制器流表下发的方法。
二、实验环境
Ubuntu 21.10
三、实验内容
1.搭建SDN拓扑,协议使用Open Flow 1.0,控制器使用部署于本地的POX(默认监听6633端口)
2.使用 tcpdump 验证Hub模块
生成拓扑后,开启POX
h1 ping h2时h2和h3都能收到数据包
h1 ping h3时h2和h3都能收到数据包
3.使用 tcpdump 验证Switch模块
生成拓扑后,开启POX
h1 ping h2时h2能收到数据包、h3不能收到数据包
h1 ping h3时h2不能收到数据包、h3能收到数据包
4.Hub模块与Switch模块抓包现象的原因
Hub模块在每个交换机上安装泛洪通配符,将数据包广播转发。
Switch模块让OpenFlow交换机实现L2自学习。
四、实验总结
在启动ryu时遇到了 TypeError: cannot set 'is_timeout' attribute of immutable type 'TimeoutError' 的错误,通过网上他人的分享,使用pip install https://ghproxy.com/https://github.com/eventlet/eventlet/archive/master.zip的命令成功解决,而后再启动ryu又遇到 module 'collections' has no attribute 'MutableMapping' 的错误,于是修改了 /usr/local/lib/python3.10/dist-packages/dns/namedict.py 第35行,将 collections.MutableMapping 替换为 collections.abc.MutableMapping ,成功解决这个错误,ryu就可以启动了。
实验6:开源控制器实践——RYU
一、实验目的
- 能够独立部署RYU控制器;
- 能够理解RYU控制器实现软件定义的集线器原理;
- 能够理解RYU控制器实现软件定义的交换机原理。
二、实验环境
Ubuntu 21.10
三、实验内容
1.搭建SDN拓扑,协议使用Open Flow 1.0,并连接Ryu控制器,通过Ryu的图形界面查看网络拓扑。
搭建SDN拓扑
启动控制器,利用Web图形界面查看网络拓扑(默认web端口8080)
2.运行L2Switch;h1 ping h2、h3,在目标主机使用 tcpdump 验证L2Switch;分析L2Switch和POX的Hub模块有何不同;编程修改L2Switch,使之和POX的Hub功能一致。
运行L2Switch
使用tcpdump验证L2Switch
分析L2Switch和POX的Hub模块
查看流表
(1)L2Switch
(2)POX的Hub模块
编程修改L2Switch,使之和POX的Hub功能一致
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
class hub(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(hub, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_feathers_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
# install flow table-miss flow entry
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]
# 1\OUTPUT PORT, 2\BUFF IN SWITCH?
self.add_flow(datapath, 0, match, actions)
def add_flow(self, datapath, priority, match, actions):
# 1\ datapath for the switch, 2\priority for flow entry, 3\match field, 4\action for packet
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
# install flow
inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst)
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
ofp_parser = datapath.ofproto_parser
in_port = msg.match['in_port'] # get in port of the packet
# add a flow entry for the packet
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
self.add_flow(datapath, 1, match, actions)
# to output the current packet. for install rules only output later packets
out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions)
# buffer id: locate the buffered packet
datapath.send_msg(out)
运行RYU并查看流表
3.编程实现和OpenDaylight实验的一样的硬超时功能。
# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
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
class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, 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
# install table-miss flow entry
#
# We specify NO BUFFER to max_len of the output action due to
# OVS bug. At this moment, if we specify a lesser number, e.g.,
# 128, OVS will send Packet-In with invalid buffer_id and
# truncated packet data. In that case, we cannot output packets
# correctly. The bug has been fixed in OVS v2.1.0.
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
def add_flow(self, datapath, priority, match, actions, buffer_id=None, hard_timeout=0):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
if buffer_id:
mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
priority=priority, match=match,
instructions=inst, hard_timeout=hard_timeout)
else:
mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
match=match, instructions=inst, hard_timeout=hard_timeout)
datapath.send_msg(mod)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
# If you hit this you might want to increase
# the "miss_send_length" of your switch
if ev.msg.msg_len < ev.msg.total_len:
self.logger.debug("packet truncated: only %s of %s bytes",
ev.msg.msg_len, ev.msg.total_len)
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
if eth.ethertype == ether_types.ETH_TYPE_LLDP:
# ignore lldp packet
return
dst = eth.dst
src = eth.src
dpid = format(datapath.id, "d").zfill(16)
self.mac_to_port.setdefault(dpid, {})
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)]\
actions_timeout=[]
# 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
hard_timeout=10
if msg.buffer_id != ofproto.OFP_NO_BUFFER:
self.add_flow(datapath, 2, match,actions_timeout, msg.buffer_id,hard_timeout=10)
self.add_flow(datapath, 1, match, actions, msg.buffer_id)
return
else:
self.add_flow(datapath, 2, match, actions_timeout, hard_timeout=10)
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)
运行RYU并查看流表
4.回答问题
1.分析L2Switch和POX的Hub模块有何不同?
RYU的L2Switch模块不能查看下发的流表,而POX的Hub模块可以查看下发的流表。
四、总结
通过实验学习了RYU控制器实现软件定义的集线器原理及交换机原理,对于L2Switch和POX的Hub模块两者之间的不同也进行了深入了解。实验过程中也学习了RYU控制器的相关知识。
标签:self,parser,datapath,黄心怡,msg,实验,ofproto,102101310,port From: https://www.cnblogs.com/102101310hxy/p/17762703.html