本文章基于https://ryu.readthedocs.io/en/latest/library_packet.html里面的Packet library的内容进行讲解的,即数据包解析的简单实现。ryu包库可以帮助我们去解析和构造各种数据协议包。
下面就着重讲一下,ryu如何对数据包进行解析。
首先,数据包解析是指控制器对从交换机收到的数据包进行解析。那么这个数据包在哪呢,按照官网的给出的开发文档,我们知道数据包主要指的是msg.data,如下图所示。
可以看出data数据是由一串16进制的数字串组成。接下来,我们就开始编码进行解析。
第一部分:代码
新建一个类Pktparser,内容如下:
from ryu.base import app_manager
class Pktparser(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
从ryu.base import app_manager,在开发APP的时候只需要继承这个基类,就获得你想要的一个APP的一切了。from ryu.ofproto import ofproto_v1_3意思是导入openflow1.3协议的数据,本次开发就是使用openflow1.3协议。此时,这个程序就是一个完整的程序了,运行并没有错误,但是由于尚未添加如何处理代码,所以这段程序说明也做不了。
接下来,接需要继续向类中添加代码以完成解析功能的开发。
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包,至于ryu各个包的含义请参考官网的开发文档。导入packet包后,将数据msg.data按照数组形式传入,最终会返回协议的列表,通过对列表的遍历,就可以解析出各种协议以及目的ip,源ip等信息。
至此,一个简单的数据包解析程序就完成了。
第二部分:实验
首先,利用mininet构建网络拓扑,如下所示。
在Ubuntu终端命令行中运行HUB程序,命令如下。
root@yang-VirtualBox:/home/yang/ryu/ryu/app# ryu-manager packet_parser_yjl.py
接下来,设置c0控制器,h1、h2、h3的ip地址分别为10.0.0.1、10.0.0.2、10.0.0.3。全部设置完成后,运行拓扑。
运行拓扑后,在Ubuntu命令行查看交换机s1的流表,可以发现s1并未有任何流表项存在,所以此时需要手动添加默认流表项,如下所示。
在mininet命令行中输入命令 h1 ping h3,此时观察控制器输出的日志信息,如下所示。
可以清晰的发现协议,目的ip,源ip等信息。
完整代码如下:
import array
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller.handler import set_ev_cls
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.lib.packet import packet
'''
实现了数据包的解析功能
即:控制器从交换机收到数据之后,对数据进行解析
提取出协议,目的ip,源ip等信息
'''
class Pktparser(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@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)
github地址:https://github.com/Yang-Jianlin/ryu/blob/master/ryu/app/packet_parser_yjl.py