记录ryu代码学习过程。
一、ev.msg.data学习
本节记录ryu是如何对数据包进行解析的。
首先,数据包解析是指控制器对从交换机收到的数据包进行解析,根据官网给出的开发文档,知道数据包主要指的是msg.data,如下图所示:
可以看出data数据是由一串16进制数字串组成。
接下来的代码完成解析功能的开发(代码来源于ryu实例—数据包解析
from ryu.lib.packet import packet
import array
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
msg = ev.msg
# msf.data就是发送过来的数据包,从中可以解析出协议、源ip、mac地址等信息
print('msg.data:', msg.data)
pkt = packet.Packet(array.array('B', msg.data))
# 几种协议
pName = []
for p in pkt.protocols:
print('received protocol data:', p)
pName.append(p.protocol_name)
if p.protocol_name == 'arp':
print('src_ip: {0}, dst_ip: {1}'.format(p.src_ip, p.dst_ip))
print('protocol category:', pName)
这里主要导入packet包后,将数据msg.data按照数组形式传入,最终会返回协议的列表,通过对协议列表的遍历,就可以解析出各种协议以及目的ip,源ip等信息。
二、switch_features_handle(self,ev)函数学习
在编写属于自己的app时,其实是需要一个函数来处理openswitch的连接,即下发默认流表(但可能不是以以下呈现的代码出现,或者有些app省略了,待补充)。同时需要开启一个监听,监听交换机事件。
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_feathers_handler(self, ev):
msg=ev.msg
datapath = 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)]
#OFPActionOutput是指将数据包发送出去,
#第一个参数为接收端口,OFPP_CONTROLLER
#第二个是数据包在交换机上缓存buffer_id,由于我们将数据包全部传送到控制器,所以不在交换机上缓存
# 1\OUTPUT PORT, 2\BUFF IN SWITCH?
self.add_flow(datapath, 0, match, actions)
#调用add_flow函数将默认流表添加到交换机上,该函数在下述代码里呈现
对于添加流表,将其单独拿出了写一个函数,这也是需在自己的app添加的函数。
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)
三、packet_in_handler(self,ev)函数学习
定义packet in函数,用来处理交换机和控制器的流表交互。这个函数在自己的app里根据需求可以添加相应的功能,比如处理到达的LLDP报文而获得LLDP时延,正常处理达到主机的转发消息(如下代码)
@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'] # 获得数据包中的in_port
# 为该数据包添加一个流表项
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: 定位缓冲的数据包
datapath.send_msg(out)