Skip to content
This repository was archived by the owner on Apr 22, 2024. It is now read-only.

Commit 26ca9e3

Browse files
authored
Merge pull request #444 from macartur/issue-#381
Add generic unpack method
2 parents f92a11c + 1fecb55 commit 26ca9e3

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

pyof/utils.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""General Unpack utils for python-openflow.
2+
3+
This package was moved from kytos/of_core for the purpose of creating a generic
4+
method to perform package unpack independent of the OpenFlow version.
5+
"""
6+
from pyof import v0x01, v0x04
7+
from pyof.foundation.exceptions import UnpackException
8+
9+
PYOF_VERSION_LIBS = {0x01: v0x01,
10+
0x04: v0x04}
11+
12+
13+
def validate_packet(packet):
14+
"""Check if packet is valid OF packet.
15+
16+
Raises:
17+
UnpackException: If the packet is invalid.
18+
"""
19+
if not isinstance(packet, bytes):
20+
raise UnpackException('invalid packet')
21+
22+
packet_length = len(packet)
23+
24+
if packet_length < 8 or packet_length > 2**16:
25+
raise UnpackException('invalid packet')
26+
27+
if packet_length != int.from_bytes(packet[2:4],
28+
byteorder='big'):
29+
raise UnpackException('invalid packet')
30+
31+
version = packet[0]
32+
if version == 0 or version >= 128:
33+
raise UnpackException('invalid packet')
34+
35+
36+
def unpack(packet):
37+
"""Unpack the OpenFlow Packet and returns a message.
38+
39+
Returns:
40+
GenericMessage: Message unpacked based on openflow packet.
41+
42+
Raises:
43+
UnpackException: if the packet can't be unpacked.
44+
"""
45+
validate_packet(packet)
46+
47+
version = packet[0]
48+
try:
49+
pyof_lib = PYOF_VERSION_LIBS[version]
50+
except KeyError:
51+
raise UnpackException('Version not supported')
52+
53+
try:
54+
header = pyof_lib.common.header.Header()
55+
header.unpack(packet[:header.get_size()])
56+
message = pyof_lib.common.utils.new_message_from_header(header)
57+
58+
binary_data = packet[header.get_size():]
59+
binary_data_size = header.length - header.get_size()
60+
61+
if binary_data and len(binary_data) == binary_data_size:
62+
message.unpack(binary_data)
63+
return message
64+
except (UnpackException, ValueError) as exception:
65+
raise UnpackException(exception)

tests/test_utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Automate utils tests."""
2+
import unittest
3+
4+
from pyof.utils import UnpackException, unpack, validate_packet
5+
from pyof.v0x01.symmetric.hello import Hello as Hello_v0x01
6+
from pyof.v0x04.symmetric.hello import Hello as Hello_v0x04
7+
8+
9+
class TestUtils(unittest.TestCase):
10+
"""Run tests to verify unpack independent of version."""
11+
12+
def test_unpack_v0x01_packet(self):
13+
"""Test if the package in version v0x01 is properly unpacked."""
14+
data = Hello_v0x01().pack()
15+
expected = unpack(data)
16+
self.assertEqual(expected.pack(), data)
17+
18+
def test_unpack_v0x04_packet(self):
19+
"""Test if the package in version v0x04 is properly unpacked."""
20+
data = Hello_v0x04().pack()
21+
expected = unpack(data)
22+
self.assertEqual(expected.pack(), data)
23+
24+
def test_invalid_packet_with_version_more_then_128(self):
25+
"""Test validate a invalid packet with version more than 128."""
26+
hello = Hello_v0x04()
27+
hello.header.version = 129
28+
29+
self.assertRaises(UnpackException, validate_packet, hello.pack())
30+
31+
def test_validate_packet_with_invalid_packets(self):
32+
"""Test validate a invalid packet with invalid packets."""
33+
hello = Hello_v0x04()
34+
35+
hello.header.version = 128
36+
self.assertRaises(UnpackException, validate_packet, hello.pack())
37+
38+
hello.header.version = 0
39+
self.assertRaises(UnpackException, validate_packet, hello.pack())

0 commit comments

Comments
 (0)