|
| 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) |
0 commit comments