当前位置: 首页 > 工具软件 > Ryu > 使用案例 >

openflow交换机 ryu_ryu—交换机

宿景曜
2023-12-01

1. 代码解析

ryu/app/example_switch_13.py:

from ryu.base importapp_managerfrom ryu.controller importofp_eventfrom ryu.controller.handler importCONFIG_DISPATCHER, MAIN_DISPATCHERfrom ryu.controller.handler importset_ev_clsfrom ryu.ofproto importofproto_v1_3from ryu.lib.packet importpacketfrom ryu.lib.packet importethernetclassExampleSwitch13(app_manager.RyuApp):

OFP_VERSIONS=[ofproto_v1_3.OFP_VERSION]def __init__(self, *args, **kwargs):

super(ExampleSwitch13, self).__init__(*args, **kwargs)#initialize mac address table.

self.mac_to_port ={}

@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)defswitch_features_handler(self, ev):

datapath=ev.msg.datapath

ofproto=datapath.ofproto

parser=datapath.ofproto_parser#install the table-miss flow entry.

match =parser.OFPMatch()#OFPCML_NO_BUFFER: 不缓冲,将发送整个数据包

actions =[parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,

ofproto.OFPCML_NO_BUFFER)]

self.add_flow(datapath, 0, match, actions)defadd_flow(self, datapath, priority, match, actions):

ofproto=datapath.ofproto

parser=datapath.ofproto_parser#construct flow_mod message and send it.

inst =[parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,

actions)]

mod= 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

parser=datapath.ofproto_parser#get Datapath ID to identify OpenFlow switches.

dpid =datapath.id

self.mac_to_port.setdefault(dpid, {})#analyse the received packets using the packet library.

pkt =packet.Packet(msg.data)

eth_pkt=pkt.get_protocol(ethernet.ethernet)

dst=eth_pkt.dst

src=eth_pkt.src#get the received port number from packet_in message.

in_port = msg.match['in_port']

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 the destination mac address is already learned,

#decide which port to output the packet, otherwise FLOOD.

if dst inself.mac_to_port[dpid]:

out_port=self.mac_to_port[dpid][dst]else:

out_port=ofproto.OFPP_FLOOD#construct action list.

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)#construct packet_out message and send it.

out = parser.OFPPacketOut(datapath=datapath,

buffer_id=ofproto.OFP_NO_BUFFER,

in_port=in_port, actions=actions,

data=msg.data)

datapath.send_msg(out)

Ryu 应用需要继承 ryu.base.app_manager.RyuApp;

OFP_VERSIONS指定支持的OpenFlow版本;

Ryu 会自己完成交换机和控制器间的握手等初始化过程;

每当 Ryu 接收到一个OpenFlow消息时,便会生成对应的事件;使用 ryu.controller.handler.set_ev_cls装饰器可以指定事件处理器:

第一个参数指定事件类型;

第二个参数指定交换机状态;

状态

解释

HANDSHAKE_DISPATCHER

Exchange of HELLO message

CONFIG_DISPATCHER

Waiting to receive SwitchFeatures message

MAIN_DISPATCHER

Normal status

DEAD_DISPATCHER

Disconnection of connection

ryu.controller.controller.Datapath类表示和控制器相连的交换机;主要属性如下,

==================================== ======================================Attribute Description==================================== ======================================id64-bit OpenFlow Datapath ID.

Only availableforryu.controller.handler.MAIN_DISPATCHER

phase.

ofproto A module which exports OpenFlow

definitions, mainly constants appearedin the specification, forthe

negotiated OpenFlow version. For

example, ryu.ofproto.ofproto_v1_0forOpenFlow1.0.

ofproto_parser A module which exports OpenFlow wire

message encoderand decoder forthe

negotiated OpenFlow version.

For example,

ryu.ofproto.ofproto_v1_0_parserfor OpenFlow 1.0.

ofproto_parser.OFPxxxx(datapath,...) A callable to prepare an OpenFlow

messageforthe given switch. It can

be sent with Datapath.send_msg later.

xxxxisa name of the message. For

example OFPFlowModfor flow-mod

message. Arguemnts depend on the

message.

set_xid(self, msg) Generate an OpenFlow XIDandput itinmsg.xid.

send_msg(self, msg) Queue an OpenFlow message to send to

the corresponding switch. If msg.xidis None, set_xid isautomatically

called on the message before queueing.

send_barrier Queue an OpenFlow barrier message to

send to the switch.==================================== ======================================

ryu.ofproto.ofproto_v1_3_parser.OFPMatch类表示流匹配结构体;

================ =============== ==================================Argument Value Description================ =============== ==================================in_port Integer 32bit Switch input port

in_phy_port Integer 32bit Switch physical input port

metadata Integer 64bit Metadata passed between tables

eth_dst MAC address Ethernet destination address

eth_src MAC address Ethernet source address

eth_type Integer 16bit Ethernet frame type

vlan_vid Integer 16bit VLAN id

vlan_pcp Integer 8bit VLAN priority

ip_dscp Integer 8bit IP DSCP (6 bits inToS field)

ip_ecn Integer 8bit IP ECN (2 bits inToS field)

ip_proto Integer 8bit IP protocol

ipv4_src IPv4 address IPv4 source address

ipv4_dst IPv4 address IPv4 destination address

tcp_src Integer 16bit TCP source port

tcp_dst Integer 16bit TCP destination port

udp_src Integer 16bit UDP source port

udp_dst Integer 16bit UDP destination port

sctp_src Integer 16bit SCTP source port

sctp_dst Integer 16bit SCTP destination port

icmpv4_type Integer 8bit ICMP type

icmpv4_code Integer 8bit ICMP code

arp_op Integer 16bit ARP opcode

arp_spa IPv4 address ARP source IPv4 address

arp_tpa IPv4 address ARP target IPv4 address

arp_sha MAC address ARP source hardware address

arp_tha MAC address ARP target hardware address

ipv6_src IPv6 address IPv6 source address

ipv6_dst IPv6 address IPv6 destination address

ipv6_flabel Integer 32bit IPv6 Flow Label

icmpv6_type Integer 8bit ICMPv6 type

icmpv6_code Integer 8bit ICMPv6 code

ipv6_nd_target IPv6 address Target addressforND

ipv6_nd_sll MAC address Source link-layer forND

ipv6_nd_tll MAC address Target link-layer forND

mpls_label Integer 32bit MPLS label

mpls_tc Integer 8bit MPLS TC

mpls_bos Integer 8bit MPLS BoS bit

pbb_isid Integer 24bit PBB I-SID

tunnel_id Integer 64bit Logical Port Metadata

ipv6_exthdr Integer 16bit IPv6 Extension Header pseudo-field

pbb_uca Integer 8bit PBB UCA header field

(EXT-256Old version of ONF Extension)

tcp_flags Integer 16bit TCP flags

(EXT-109ONF Extension)

actset_output Integer 32bit Output portfromaction set metadata

(EXT-233ONF Extension)================ =============== ==================================

ryu.ofproto.ofproto_v1_3_parser.OFPFlowMod类表示Flow Mod消息,即修改流项;支持以下参数:

================ ======================================================Attribute Description================ ======================================================cookie Opaque controller-issued identifier

cookie_mask Mask used to restrict the cookie bits that must match

when the commandis OPFFC_MODIFY* orOFPFC_DELETE*table_id ID of the table to put the flowincommand One of the following values.|OFPFC_ADD|OFPFC_MODIFY|OFPFC_MODIFY_STRICT|OFPFC_DELETE|OFPFC_DELETE_STRICT

idle_timeout Idle time before discarding (seconds)

hard_timeout Max time before discarding (seconds)

priority Priority level of flow entry

buffer_id Buffered packet to apply to (orOFP_NO_BUFFER)

out_port For OFPFC_DELETE*commands, require matching

entries to include this as an output port

out_group For OFPFC_DELETE*commands, require matching

entries to include this as an output group

flags Bitmap of the following flags.|OFPFF_SEND_FLOW_REM|OFPFF_CHECK_OVERLAP|OFPFF_RESET_COUNTS|OFPFF_NO_PKT_COUNTS|OFPFF_NO_BYT_COUNTS

match Instance of OFPMatch

instructions list of OFPInstruction*instance================ ======================================================

ryu.ofproto.ofproto_v1_3_parser.OFPPacketIn类表示Packet-In消息,即交换机发向控制器;包含以下属性:

============= =========================================================Attribute Description============= =========================================================buffer_id ID assigned by datapath

total_len Full length of frame

reason Reason packetisbeing sent.|OFPR_NO_MATCH|OFPR_ACTION|OFPR_INVALID_TTL

table_id ID of the table that was looked up

cookie Cookie of the flow entry that was looked up

match Instance of OFPMatch

data Ethernet frame============= =========================================================

ryu.ofproto.ofproto_v1_3_parser.OFPPacketOut类表示Packet-Out消息,即控制器发向交换机;包含以下属性:

================ ======================================================Attribute Description================ ======================================================buffer_id ID assigned by datapath (OFP_NO_BUFFERifnone)

in_port Packet's input port or OFPP_CONTROLLER

actions list of OpenFlow action classdata Packet data of a binary type valueoran instances of packet.Packet.================ ======================================================

ryu.ofproto.ofproto_v1_3_parser.OFPActionOutput类表示输出动作;支持以下参数:

================ ======================================================Attribute Description================ ======================================================port Output port

max_len Max length to send to controller================ ======================================================

ryu.ofproto.ofproto_v1_3_parser.OFPInstructionActions表示写/应用/清空 actions 的指令:

================ ======================================================Attribute Description================ ======================================================type One of following values.|OFPIT_WRITE_ACTIONS|OFPIT_APPLY_ACTIONS|OFPIT_CLEAR_ACTIONS

actions list of OpenFlow action class================ ======================================================

支持的指令如下:

OFPIT_GOTO_TABLE = 1 #Setup the next table in the lookup pipeline.

OFPIT_WRITE_METADATA = 2 #Setup the metadata field for use later in

#pipeline.

OFPIT_WRITE_ACTIONS = 3 #Write the action(s) onto the datapath

#action set

OFPIT_APPLY_ACTIONS = 4 #Applies the action(s) immediately

OFPIT_CLEAR_ACTIONS = 5 #Clears all actions from the datapath action

#set

OFPIT_METER = 6 #Apply meter (rate limiter)

OFPIT_EXPERIMENTER = 0xFFFF #Experimenter instruction

2. 运行

# --topo sigle,3: 单个交换机,3个主机

#--mac: 自动设置主机的MAC地址

#--switch ovsk: 使用 ovs

#--controller remote: 使用外部OpenFlow控制器

#-x: 启动xterm

$sudo mn --topo single,3 --mac --switch ovsk --controller remote -x

此时会启动5个xterm:h1~h3, switch, controller.

设置OpenFlow版本:switch: s1

# ovs-vsctl set Bridge s1 protocols=OpenFlow13

启动控制器:controller: c0

# ryu-manager --verbose ryu/app/example_switch_13.py

查看Table-miss流项:switch: s1

# ovs-ofctl -O OpenFlow13 dump-flows s1

ping:

mininet> h1 ping -c1 h2

再次查看流项:switch: s1

# ovs-ofctl -O OpenFlow13 dump-flows s1

参考资料

https://osrg.github.io/ryu-book/en/Ryubook.pdf

 类似资料: