数据包库¶
介绍¶
OS-Ken 数据包库帮助您解析和构建各种协议数据包。dpkt 是用于相同目的的流行库,但是它并非设计用于处理交错协议;vlan、mpls、gre 等。因此,我们实现了我们自己的数据包库。
网络地址¶
除非另有说明,否则此库中的 MAC/IPv4/IPv6 地址使用人类可读的字符串指定。例如,'08:60:6e:7f:74:e7'、'192.0.2.1'、'fe80::a60:6eff:fe7f:74e7'。
解析数据包¶
首先,让我们看看如何使用该库来解析 OFPPacketIn 消息的处理程序中接收到的数据包。
from os_ken.lib.packet import packet
@handler.set_ev_cls(ofp_event.EventOFPPacketIn, handler.MAIN_DISPATCHER)
def packet_in_handler(self, ev):
pkt = packet.Packet(array.array('B', ev.msg.data))
for p in pkt.protocols:
print p
您可以使用接收到的原始数据创建一个 Packet 类实例。然后,数据包库将解析数据并创建包含数据的协议类实例。数据包类的 'protocols' 属性包含协议类实例。
如果收到 TCP 数据包,将打印如下内容
<os_ken.lib.packet.ethernet.ethernet object at 0x107a5d790>
<os_ken.lib.packet.vlan.vlan object at 0x107a5d7d0>
<os_ken.lib.packet.ipv4.ipv4 object at 0x107a5d810>
<os_ken.lib.packet.tcp.tcp object at 0x107a5d850>
如果未使用 VLAN,您将看到如下内容
<os_ken.lib.packet.ethernet.ethernet object at 0x107a5d790>
<os_ken.lib.packet.ipv4.ipv4 object at 0x107a5d810>
<os_ken.lib.packet.tcp.tcp object at 0x107a5d850>
您可以使用数据包类迭代器访问特定的协议类实例。让我们尝试检查是否使用了 VLAN,如果是,则检查 VLAN ID
from os_ken.lib.packet import packet
@handler.set_ev_cls(ofp_event.EventOFPPacketIn, handler.MAIN_DISPATCHER)
def packet_in_handler(self, ev):
pkt = packet.Packet(array.array('B', ev.msg.data))
for p in pkt:
print p.protocol_name, p
if p.protocol_name == 'vlan':
print 'vid = ', p.vid
您将看到如下内容
ethernet <os_ken.lib.packet.ethernet.ethernet object at 0x107a5d790>
vlan <os_ken.lib.packet.vlan.vlan object at 0x107a5d7d0>
vid = 10
ipv4 <os_ken.lib.packet.ipv4.ipv4 object at 0x107a5d810>
tcp <os_ken.lib.packet.tcp.tcp object at 0x107a5d850>
构建数据包¶
您需要创建要发送的协议类实例,通过 add_protocol 方法将其添加到数据包类实例,然后调用 serialize 方法。您将获得要发送的原始数据。以下示例是构建一个 ARP 数据包。
from os_ken.ofproto import ether
from os_ken.lib.packet import ethernet, arp, packet
e = ethernet.ethernet(dst='ff:ff:ff:ff:ff:ff',
src='08:60:6e:7f:74:e7',
ethertype=ether.ETH_TYPE_ARP)
a = arp.arp(hwtype=1, proto=0x0800, hlen=6, plen=4, opcode=2,
src_mac='08:60:6e:7f:74:e7', src_ip='192.0.2.1',
dst_mac='00:00:00:00:00:00', dst_ip='192.0.2.2')
p = packet.Packet()
p.add_protocol(e)
p.add_protocol(a)
p.serialize()
print repr(p.data) # the on-wire packet