Skip to content

Commit

Permalink
Improve unpack method in pyof/utils
Browse files Browse the repository at this point in the history
Reuse the methods unpack_message from pyof.[version].common.utils
Create a constant called MESSAGE_TYPES
Fix kytos#344
  • Loading branch information
macartur committed Nov 22, 2017
1 parent 1eeec4a commit 2738317
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 106 deletions.
18 changes: 7 additions & 11 deletions pyof/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"""
from pyof import v0x01, v0x04
from pyof.foundation.exceptions import UnpackException
from pyof.v0x01.common import utils as u_v0x01 # pylint: disable=unused-import
from pyof.v0x04.common import utils as u_v0x04 # pylint: disable=unused-import

PYOF_VERSION_LIBS = {0x01: v0x01,
0x04: v0x04}
Expand All @@ -25,8 +27,7 @@ def validate_packet(packet):
if packet_length < 8 or packet_length > 2**16:
raise UnpackException('invalid packet')

if packet_length != int.from_bytes(packet[2:4],
byteorder='big'):
if packet_length != int.from_bytes(packet[2:4], byteorder='big'):
raise UnpackException('invalid packet')

version = packet[0]
Expand All @@ -37,6 +38,9 @@ def validate_packet(packet):
def unpack(packet):
"""Unpack the OpenFlow Packet and returns a message.
Args:
packet: buffer with the openflow packet.
Returns:
GenericMessage: Message unpacked based on openflow packet.
Expand All @@ -53,15 +57,7 @@ def unpack(packet):
raise UnpackException('Version not supported')

try:
header = pyof_lib.common.header.Header()
header.unpack(packet[:header.get_size()])
message = pyof_lib.common.utils.new_message_from_header(header)

binary_data = packet[header.get_size():]
binary_data_size = header.length - header.get_size()

if binary_data and len(binary_data) == binary_data_size:
message.unpack(binary_data)
message = pyof_lib.common.utils.unpack_message(packet)
return message
except (UnpackException, ValueError) as exception:
raise UnpackException(exception)
58 changes: 29 additions & 29 deletions pyof/v0x01/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,33 @@
from pyof.v0x01.symmetric.hello import Hello
from pyof.v0x01.symmetric.vendor_header import VendorHeader

__all__ = ('new_message_from_header', 'new_message_from_message_type',
'unpack_message')
__all__ = ('MESSAGE_TYPES', 'new_message_from_header',
'new_message_from_message_type', 'unpack_message')

MESSAGE_TYPES = {
str(Type.OFPT_HELLO): Hello,
str(Type.OFPT_ERROR): ErrorMsg,
str(Type.OFPT_ECHO_REQUEST): EchoRequest,
str(Type.OFPT_ECHO_REPLY): EchoReply,
str(Type.OFPT_VENDOR): VendorHeader,
str(Type.OFPT_FEATURES_REQUEST): FeaturesRequest,
str(Type.OFPT_FEATURES_REPLY): FeaturesReply,
str(Type.OFPT_GET_CONFIG_REQUEST): GetConfigRequest,
str(Type.OFPT_GET_CONFIG_REPLY): GetConfigReply,
str(Type.OFPT_SET_CONFIG): SetConfig,
str(Type.OFPT_PACKET_IN): PacketIn,
str(Type.OFPT_FLOW_REMOVED): FlowRemoved,
str(Type.OFPT_PORT_STATUS): PortStatus,
str(Type.OFPT_PACKET_OUT): PacketOut,
str(Type.OFPT_FLOW_MOD): FlowMod,
str(Type.OFPT_PORT_MOD): PortMod,
str(Type.OFPT_STATS_REQUEST): StatsRequest,
str(Type.OFPT_STATS_REPLY): StatsReply,
str(Type.OFPT_BARRIER_REQUEST): BarrierRequest,
str(Type.OFPT_BARRIER_REPLY): BarrierReply,
str(Type.OFPT_QUEUE_GET_CONFIG_REQUEST): QueueGetConfigRequest,
str(Type.OFPT_QUEUE_GET_CONFIG_REPLY): QueueGetConfigReply
}


def new_message_from_message_type(message_type):
Expand All @@ -54,35 +79,10 @@ def new_message_from_message_type(message_type):
"""
message_type = str(message_type)

available_classes = {
str(Type.OFPT_HELLO): Hello,
str(Type.OFPT_ERROR): ErrorMsg,
str(Type.OFPT_ECHO_REQUEST): EchoRequest,
str(Type.OFPT_ECHO_REPLY): EchoReply,
str(Type.OFPT_VENDOR): VendorHeader,
str(Type.OFPT_FEATURES_REQUEST): FeaturesRequest,
str(Type.OFPT_FEATURES_REPLY): FeaturesReply,
str(Type.OFPT_GET_CONFIG_REQUEST): GetConfigRequest,
str(Type.OFPT_GET_CONFIG_REPLY): GetConfigReply,
str(Type.OFPT_SET_CONFIG): SetConfig,
str(Type.OFPT_PACKET_IN): PacketIn,
str(Type.OFPT_FLOW_REMOVED): FlowRemoved,
str(Type.OFPT_PORT_STATUS): PortStatus,
str(Type.OFPT_PACKET_OUT): PacketOut,
str(Type.OFPT_FLOW_MOD): FlowMod,
str(Type.OFPT_PORT_MOD): PortMod,
str(Type.OFPT_STATS_REQUEST): StatsRequest,
str(Type.OFPT_STATS_REPLY): StatsReply,
str(Type.OFPT_BARRIER_REQUEST): BarrierRequest,
str(Type.OFPT_BARRIER_REPLY): BarrierReply,
str(Type.OFPT_QUEUE_GET_CONFIG_REQUEST): QueueGetConfigRequest,
str(Type.OFPT_QUEUE_GET_CONFIG_REPLY): QueueGetConfigReply
}

if message_type not in available_classes:
if message_type not in MESSAGE_TYPES:
raise ValueError('"{}" is not known.'.format(message_type))

message_class = available_classes.get(message_type)
message_class = MESSAGE_TYPES.get(message_type)
message_instance = message_class()

return message_instance
Expand Down
140 changes: 74 additions & 66 deletions pyof/v0x04/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,69 @@
from pyof.v0x04.symmetric.experimenter import ExperimenterHeader
from pyof.v0x04.symmetric.hello import Hello

__all__ = ('new_message_from_header', 'new_message_from_message_type')
__all__ = ('MESSAGE_TYPES', 'new_message_from_header',
'new_message_from_message_type', 'unpack_message')

MESSAGE_TYPES = {

# Symetric/Immutable messages
str(Type.OFPT_HELLO): Hello,
str(Type.OFPT_ERROR): ErrorMsg,
str(Type.OFPT_ECHO_REQUEST): EchoRequest,
str(Type.OFPT_ECHO_REPLY): EchoReply,
str(Type.OFPT_EXPERIMENTER): ExperimenterHeader,

# Switch configuration messages
# Controller/Switch messages
str(Type.OFPT_FEATURES_REQUEST): FeaturesRequest,
str(Type.OFPT_FEATURES_REPLY): FeaturesReply,
str(Type.OFPT_GET_CONFIG_REQUEST): GetConfigRequest,
str(Type.OFPT_GET_CONFIG_REPLY): GetConfigReply,
str(Type.OFPT_SET_CONFIG): SetConfig,

# Async messages
str(Type.OFPT_PACKET_IN): PacketIn,
str(Type.OFPT_FLOW_REMOVED): FlowRemoved,
str(Type.OFPT_PORT_STATUS): PortStatus,

# Controller command messages
# Controller/Switch message
str(Type.OFPT_PACKET_OUT): PacketOut,
str(Type.OFPT_FLOW_MOD): FlowMod,
str(Type.OFPT_GROUP_MOD): GroupMod,
str(Type.OFPT_PORT_MOD): PortMod,
str(Type.OFPT_TABLE_MOD): TableMod,

# Multipart messages.
# Controller/Switch message
str(Type.OFPT_MULTIPART_REPLY): MultipartReply,
str(Type.OFPT_MULTIPART_REQUEST): MultipartRequest,

# Barrier messages
# Controller/Switch message
str(Type.OFPT_BARRIER_REQUEST): BarrierRequest,
str(Type.OFPT_BARRIER_REPLY): BarrierReply,

# Queue Configuration messages
# Controller/Switch message
str(Type.OFPT_QUEUE_GET_CONFIG_REQUEST): QueueGetConfigRequest,
str(Type.OFPT_QUEUE_GET_CONFIG_REPLY): QueueGetConfigReply,

# Controller role change request message
# Controller/Switch message
str(Type.OFPT_ROLE_REQUEST): RoleRequest,
str(Type.OFPT_ROLE_REPLY): RoleReply,

# Asynchronous message configuration
# Controller/Switch message
str(Type.OFPT_GET_ASYNC_REQUEST): GetAsyncRequest,
str(Type.OFPT_GET_ASYNC_REPLY): GetAsyncReply,
str(Type.OFPT_SET_ASYNC): SetAsync,

# Meters and rate limiters configuration messages
# Controller/Switch message
str(Type.OFPT_METER_MOD): MeterMod,
}


def new_message_from_message_type(message_type):
Expand All @@ -60,73 +122,11 @@ def new_message_from_message_type(message_type):
"""
message_type = str(message_type)

available_classes = {

# Symetric/Immutable messages
str(Type.OFPT_HELLO): Hello,
str(Type.OFPT_ERROR): ErrorMsg,
str(Type.OFPT_ECHO_REQUEST): EchoRequest,
str(Type.OFPT_ECHO_REPLY): EchoReply,
str(Type.OFPT_EXPERIMENTER): ExperimenterHeader,

# Switch configuration messages
# Controller/Switch messages
str(Type.OFPT_FEATURES_REQUEST): FeaturesRequest,
str(Type.OFPT_FEATURES_REPLY): FeaturesReply,
str(Type.OFPT_GET_CONFIG_REQUEST): GetConfigRequest,
str(Type.OFPT_GET_CONFIG_REPLY): GetConfigReply,
str(Type.OFPT_SET_CONFIG): SetConfig,

# Async messages
str(Type.OFPT_PACKET_IN): PacketIn,
str(Type.OFPT_FLOW_REMOVED): FlowRemoved,
str(Type.OFPT_PORT_STATUS): PortStatus,

# Controller command messages
# Controller/Switch message
str(Type.OFPT_PACKET_OUT): PacketOut,
str(Type.OFPT_FLOW_MOD): FlowMod,
str(Type.OFPT_GROUP_MOD): GroupMod,
str(Type.OFPT_PORT_MOD): PortMod,
str(Type.OFPT_TABLE_MOD): TableMod,

# Multipart messages.
# Controller/Switch message
str(Type.OFPT_MULTIPART_REPLY): MultipartReply,
str(Type.OFPT_MULTIPART_REQUEST): MultipartRequest,

# Barrier messages
# Controller/Switch message
str(Type.OFPT_BARRIER_REQUEST): BarrierRequest,
str(Type.OFPT_BARRIER_REPLY): BarrierReply,

# Queue Configuration messages
# Controller/Switch message
str(Type.OFPT_QUEUE_GET_CONFIG_REQUEST): QueueGetConfigRequest,
str(Type.OFPT_QUEUE_GET_CONFIG_REPLY): QueueGetConfigReply,

# Controller role change request message
# Controller/Switch message
str(Type.OFPT_ROLE_REQUEST): RoleRequest,
str(Type.OFPT_ROLE_REPLY): RoleReply,

# Asynchronous message configuration
# Controller/Switch message
str(Type.OFPT_GET_ASYNC_REQUEST): GetAsyncRequest,
str(Type.OFPT_GET_ASYNC_REPLY): GetAsyncReply,
str(Type.OFPT_SET_ASYNC): SetAsync,

# Meters and rate limiters configuration messages
# Controller/Switch message
str(Type.OFPT_METER_MOD): MeterMod,
}

if message_type not in available_classes:
if message_type not in MESSAGE_TYPES:
msg = "Define class for {} in {}".format(message_type, __file__)
raise ValueError(msg)

message_class = available_classes.get(message_type)
message_class = MESSAGE_TYPES.get(message_type)
message_instance = message_class()

return message_instance
Expand Down Expand Up @@ -166,7 +166,15 @@ def new_message_from_header(header):


def unpack_message(buffer):
"""Unpack the whole buffer, including header pack."""
"""Unpack the whole buffer, including header pack.
Args:
buffer (bytes): Bytes representation of a openflow message.
Returns:
object: Instance of openflow message.
"""
hdr_size = Header().get_size()
hdr_buff, msg_buff = buffer[:hdr_size], buffer[hdr_size:]
header = Header()
Expand Down

0 comments on commit 2738317

Please sign in to comment.