我正在使用带有Open vSwitch的Ryu SDN控制器使用OpenFlow 1.3来解析DHCP数据包 . 根据在线示例和Ryu资源,我实现了一个DHCP数据包解析器 . 但是,它不能像我预期的那样工作,我想知道是否有人对我的第一个解决方案不起作用的原因有任何见解?
用于解析DHCP数据包的代码片段示例如下:
from ryu.lib.packet import dhcp
...
...
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
pkt = packet.Packet(msg.data)
dhcpPacket = pkt.get_protocol(dhcp.dhcp)
我的代码遵循类似的方式:
from ryu.lib.packet import dhcp
...
...
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
pkt = {}
pkt['msg'] = ev.msg
pkt['dp'] = pkt['msg'].datapath
pkt['pkt'] = packet.Packet(pkt['msg'].data)
pkt['dhcp'] = pkt['pkt'].get_protocol(dhcp.dhcp)
这似乎是合理的,因为我正在使用其他协议,如ARP,ICMP,IP等,遵循这个确切的顺序 . 下面的例子 .
pkt['arp'] = pkt['pkt'].get_protocol(arp.arp)
pkt['ip'] = pkt['pkt'].get_protocol(ipv4.ipv4)
pkt['icmp'] = pkt['pkt'].get_protocol(icmp.icmp)
唯一的问题是我上面列出的三个解析器实际上返回数据,而DHCP的get_protocol一直返回None . 我已经通过我的交换机发送DHCP数据包进行了测试 .
以下代码片段的作用是什么,我在其中识别具有三个以上值的数据包列表 . 我将值保存在索引3并将其设置为我的DHCP数据包 . 在DHCP数据包中,我专注于在索引2处解析字符串 . 这包含我感兴趣的数据 .
# pkt['dhcp'] = pkt['pkt'].get_protocol(dhcp.dhcp)
# Check if pkt['pkt]] > 3 elements, if so, parse DHCP string
#Standard pkt['dhcp'] = (None, None, String)
if len(pkt['pkt']) > 3:
pkt['dhcp'] = dhcp.dhcp.parser(pkt['pkt'][3])
pkt['op'] = hex(ord(dhcp_p[2][0]))
pkt['htype'] = hex(ord(dhcp_p[2][1]))
pkt['hlen'] = hex(ord(dhcp_p[2][2]))
pkt['hops'] = hex(ord(dhcp_p[2][3]))
def parseDHCP(pkt_d,start,stop):
s_value = ''
stop += 1
for val in range(start,stop):
s_value += str(hex(ord(pkt_d[val])))
return s_value
pkt['xid'] = parseDHCP(dhcp_p[2],4,7)
pkt['secs'] = parseDHCP(dhcp_p[2],8,9)
pkt['flags'] = parseDHCP(dhcp_p[2],10,11)
pkt['ciaddr'] = parseDHCP(dhcp_p[2],12,15)
pkt['yiaddr'] = parseDHCP(dhcp_p[2],16,19)
pkt['siaddr'] = parseDHCP(dhcp_p[2],20,23)
pkt['giaddr'] = parseDHCP(dhcp_p[2],24,27)
pkt['chaddr'] = parseDHCP(dhcp_p[2],28,33)
pkt['pad'] = parseDHCP(dhcp_p[2],34,43)
打印出这些值看起来像这样:
0x1
0x1
0x6
0x0
0x440x30x980x11
0x00x0
0x00x0
0x00x00x00x0
0x00x00x00x0
0x00x00x00x0
0x00x00x00x0
0x7e0x1d0xcc0xe70xee0x4f
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
上面的代码允许我观察DHCP数据包的内容,但我真的想弄清楚为什么我没有使用pkt ['pkt'] . get_protocol(dhcp.dhcp)方法实现类似的结果?
1 回答
好的,我发现了问题 . 在dhcp.py的第200-218行中有一个try except语句 . 我把cls._parser拉出试试,看看它抛出的错误,我得到了这个:
因此,dhcp.py没有收到它需要的233个字节 . 不幸的是,我在SDN集线器提供的VM上使用Open vSwitch,128字节似乎是一个限制 . 所以,我与Ryu的dhcp.py文件存在冲突 . 我的解决方案是修改dhcp.py.如何做到如下 .
在修改代码之前,我建议您先更新Ryu控制器 . 程序如下:
第1步:如果您使用的是VM . 拍摄快照或立即克隆它 .
第2步:更新Ryu
如果您运行的是旧版本,那么下次尝试运行Ryu控制器时可能会出现以下错误:
第3步:更新您的oslo_config文件
现在应该解决步骤2中的TypeError . (希望你克隆你的VM以防万一 . )
第3步:修改Ryu的dhcp.py文件
Ryu的dhcp.py文件(位于/ ryu / ryu / lib / packet)期望接收超过235字节的缓冲区 . 否则,它抛出并发生错误并且不向控制器返回任何内容 . 由于我的缓冲区只接收大约81字节的缓冲区大小 . 我修改了Ryu dhcp.py文件,如下所示 .
发生此错误是因为dhcp.py指定字符串格式为'!BBBBIHH4s4s4s4s16s64s128s' . 在#1中,我创建了第二个选项 . 这样做,允许我插入一些if语句,以便在数据包到达小于100字节时以不同方式处理数据包 . 同样,如果数据包大于235字节,则dhcp.py将正常处理数据包并返回额外值 .
完整的文件很快就会出现在https://github.com/Ryuretic/RyureticLabs/tree/master/ryu/ryu/app/Ryuretic/Support_Files上 .
如果对dhcp.py文件进行这些调整,则可以访问以下标头字段: