From 7b797a60dc15f2fe8254023a789e96d265959582 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Date: Mon, 8 Apr 2019 15:53:44 -0400 Subject: [PATCH 01/81] Create the packages v0x05 and symmetric --- .idea/libraries/R_User_Library.xml | 6 ++++++ .idea/vcs.xml | 6 ++++++ pyof/v0x05/__init__.py | 0 pyof/v0x05/symmetric/__init__.py | 0 4 files changed, 12 insertions(+) create mode 100644 .idea/libraries/R_User_Library.xml create mode 100644 .idea/vcs.xml create mode 100644 pyof/v0x05/__init__.py create mode 100644 pyof/v0x05/symmetric/__init__.py diff --git a/.idea/libraries/R_User_Library.xml b/.idea/libraries/R_User_Library.xml new file mode 100644 index 000000000..71f5ff749 --- /dev/null +++ b/.idea/libraries/R_User_Library.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pyof/v0x05/__init__.py b/pyof/v0x05/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyof/v0x05/symmetric/__init__.py b/pyof/v0x05/symmetric/__init__.py new file mode 100644 index 000000000..e69de29bb From 60465df5d69bcd64ce51c25ce794438da45b9822 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Date: Mon, 8 Apr 2019 15:57:18 -0400 Subject: [PATCH 02/81] Created the file hello and its classes. There missing files that will be entered later. --- pyof/v0x05/symmetric/hello.py | 167 ++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 pyof/v0x05/symmetric/hello.py diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py new file mode 100644 index 000000000..8508318c4 --- /dev/null +++ b/pyof/v0x05/symmetric/hello.py @@ -0,0 +1,167 @@ +"""Defines Hello message.""" + +# System imports + +from enum import IntEnum + +from pyof.foundation.base import GenericMessage, GenericStruct +from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16, UBInt32, TypeList +from pyof.foundation.exceptions import PackException +from pyof.v0x05.common.header import Header, Type + +# Third-party imports + +__all__ = ('Hello', 'HelloElemHeader', 'HelloElemType', 'ListOfHelloElements', 'HelloElemVersionBitmap') + +# Enums + + +class HelloElemType(IntEnum): + """Hello element types.""" + + #: Bitmap of version supported. + OFPHET_VERSIONBITMAP = 1 + + +# Classes + + +class HelloElemHeader(GenericStruct): + """Common header for all Hello Elements.""" + + # One of OFPHET_*. + type = UBInt16() + # Length in bytes of element, including this header, excluding padding. + length = UBInt16() + # This variable does NOT appear in 1.4 specification + # content = BinaryData() + + def __init__(self, element_type=None, length=None, content=b''): + """Create a HelloElemHeader with the optional parameters below. + + Args: + element_type: One of OFPHET_*. + length: Length in bytes of the element, including this header, + excluding padding. + """ + super().__init__() + self.type = element_type + self.length = length + # self.content = content + + def pack(self, value=None): + """Update the length and pack the message into binary data. + + Returns: + bytes: A binary data that represents the Message. + + Raises: + Exception: If there are validation errors. + + """ + if value is None: + self.update_length() + return super().pack() + elif isinstance(value, type(self)): + return value.pack() + else: + msg = "{} is not an instance of {}".format(value, + type(self).__name__) + raise PackException(msg) + + def update_length(self): + """Update length attribute.""" + self.length = self.get_size() + + def unpack(self, buff=None, offset=0): + """Unpack *buff* into this object. + + This method will convert a binary data into a readable value according + to the attribute format. + + Args: + buff (bytes): Binary buffer. + offset (int): Where to begin unpacking. + + Raises: + :exc:`~.exceptions.UnpackException`: If unpack fails. + + """ + # length = UBInt16() + self.length.unpack(buff, offset=offset+2) + + super().unpack(buff[:offset+self.length.value], offset) + + +class ListOfHelloElements(FixedTypeList): + """List of Hello elements. + + Represented by instances of HelloElemHeader and used on Hello + objects. + """ + + def __init__(self, items=None): + """Create a ListOfHelloElements with the optional parameters below. + + Args: + items (HelloElemHeader): Instance or a list of instances. + """ + super().__init__(pyof_class=HelloElemHeader, items=items) + # if (items != None and isinstance(HelloElemHeader,items)): + # super().append(items) + + + +class Hello(GenericMessage): + """OpenFlow Hello Message OFPT_HELLO. + + This message includes zero or more hello elements having variable size. + Unknown element types must be ignored/skipped, to allow for future + extensions. + """ + + header = Header(Type.OFPT_HELLO) + + #: Hello element list + #: List of elements - 0 or more + elements = ListOfHelloElements() + + def __init__(self, xid=None, elements=None): + """Create a Hello with the optional parameters below. + + Args: + xid (int): xid to be used on the message header. + elements: List of elements - 0 or more + """ + super().__init__(xid) + self.elements = elements + + +class HelloElemVersionBitmap(HelloElemHeader): + """ Version bitmap Hello Element + There is not need to enter the Version bitmap because is entered automatically as the type of message + Followed by: + - Exactly (length - 4) bytes containing the bitmaps, then + - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) + bytes of all-zero bytes. + """ + # List of bitmaps - supported versions + bitmaps = BinaryData() + + # Under Review + def __init__(self, length=None, bitmaps=None): + """ + Create the HelloElemVersionBitmap. + :param length: + Followed by: + - Exactly (length - 4) bytes containing the bitmaps, then + - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) + bytes of all-zero bytes. + :param bitmaps: List of bitmaps - supported versions + """ + super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) + self.bitmaps = bitmaps + + + + From 992480decbb87e6de92f4b37ead9e56e7ea131df Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Date: Mon, 8 Apr 2019 16:31:00 -0400 Subject: [PATCH 03/81] Change an import from the system to one of the classes IntEnum --- pyof/v0x05/symmetric/hello.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 8508318c4..50605a98e 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -2,9 +2,9 @@ # System imports -from enum import IntEnum -from pyof.foundation.base import GenericMessage, GenericStruct + +from pyof.foundation.base import GenericMessage, GenericStruct, IntEnum from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16, UBInt32, TypeList from pyof.foundation.exceptions import PackException from pyof.v0x05.common.header import Header, Type From 803475897ba958ee99c8c64d41a125f09073aec8 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Date: Wed, 10 Apr 2019 14:27:37 -0400 Subject: [PATCH 04/81] Created missing files for the hello messages. Added the Header and constants files --- pyof/v0x05/common/__init__.py | 0 pyof/v0x05/common/constants.py | 4 ++ pyof/v0x05/common/header.py | 125 +++++++++++++++++++++++++++++++++ pyof/v0x05/symmetric/hello.py | 2 - 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 pyof/v0x05/common/__init__.py create mode 100644 pyof/v0x05/common/constants.py create mode 100644 pyof/v0x05/common/header.py diff --git a/pyof/v0x05/common/__init__.py b/pyof/v0x05/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyof/v0x05/common/constants.py b/pyof/v0x05/common/constants.py new file mode 100644 index 000000000..c6f62ed78 --- /dev/null +++ b/pyof/v0x05/common/constants.py @@ -0,0 +1,4 @@ +"""Here we have the constants related to v0x05 version.""" + +OFP_VERSION = 0x05 +OFP_NO_BUFFER = 0xffffffff diff --git a/pyof/v0x05/common/header.py b/pyof/v0x05/common/header.py new file mode 100644 index 000000000..1aff0084c --- /dev/null +++ b/pyof/v0x05/common/header.py @@ -0,0 +1,125 @@ +"""Defines Header classes and related items.""" + +# System imports +from enum import IntEnum + +# Local source tree imports +from pyof.foundation.base import GenericStruct +from pyof.foundation.basic_types import UBInt8, UBInt16, UBInt32 +from pyof.v0x05.common.constants import OFP_VERSION + +# Third-party imports + +__all__ = ('Header', 'Type') + +# Enums + + +class Type(IntEnum): + """Enumeration of Message Types.""" + + # Symmetric/Immutable messages + + OFPT_HELLO = 0 + OFPT_ERROR = 1 + OFPT_ECHO_REQUEST = 2 + OFPT_ECHO_REPLY = 3 + OFPT_EXPERIMENTER = 4 + + # Switch configuration messages + # Controller/Switch messages + OFPT_FEATURES_REQUEST = 5 + OFPT_FEATURES_REPLY = 6 + OFPT_GET_CONFIG_REQUEST = 7 + OFPT_GET_CONFIG_REPLY = 8 + OFPT_SET_CONFIG = 9 + + # Async messages + OFPT_PACKET_IN = 10 + OFPT_FLOW_REMOVED = 11 + OFPT_PORT_STATUS = 12 + + # Controller command messages + # Controller/Switch message + OFPT_PACKET_OUT = 13 + OFPT_FLOW_MOD = 14 + OFPT_GROUP_MOD = 15 + OFPT_PORT_MOD = 16 + OFPT_TABLE_MOD = 17 + + # Multipart messages. + # Controller/Switch message + OFPT_MULTIPART_REQUEST = 18 + OFPT_MULTIPART_REPLY = 19 + + # Barrier messages + # Controller/Switch message + OFPT_BARRIER_REQUEST = 20 + OFPT_BARRIER_REPLY = 21 + + # Queue Configuration messages + # Controller/Switch message + + #OFPT_QUEUE_GET_CONFIG_REQUEST = 22 + #OFPT_QUEUE_GET_CONFIG_REPLY = 23 + + + # Controller role change request message + # Controller/Switch message + OFPT_ROLE_REQUEST = 24 + OFPT_ROLE_REPLY = 25 + + # Asynchronous message configuration + # Controller/Switch message + OFPT_GET_ASYNC_REQUEST = 26 + OFPT_GET_ASYNC_REPLY = 27 + OFPT_SET_ASYNC = 28 + + # Meters and rate limiters configuration messages + # Controller/Switch message + OFPT_METER_MOD = 29 + + + #Controller role change event messages + #Async message + OFPT_ROLE_STATUS = 30 + + #Asynchronous message + #Async message + OFPT_TABLE_STATUS = 31 + + #Request forwarding by switch + #Async message + OFPT_REQUESTFORWARD = 32 + + #Bundle operations (Multiple messages as a single operation) + #Controller/Switch message + OFPT_BUNDLE_CONTROL = 33 + OFPT_BUNDLE_ADD_MESSAGE = 34 + + +# Classes + +class Header(GenericStruct): + """Representation of an OpenFlow message Header.""" + + version = UBInt8(OFP_VERSION) # OFP_VERSION + message_type = UBInt8(enum_ref=Type) # One of the OFPT_ constants + length = UBInt16() # Length including this ofp_header + xid = UBInt32() # Transaction id associated with this packet. + # Replies use the same id as was in the request to faciliate pairing. + + def __init__(self, message_type=None, length=None, xid=None): + """Create a Header with the optional parameters below. + + Args: + message_type (~pyof.v0x05.common.header.Type): + One of the OFPT_* constants. + length (int): Length including this ofp_header. + xid (int): Transaction id associated with this packet. Replies use + the same id as was in the request to facilitate pairing. + """ + super().__init__() + self.message_type = message_type + self.length = length + self.xid = xid diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 50605a98e..ee4ff683b 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -2,8 +2,6 @@ # System imports - - from pyof.foundation.base import GenericMessage, GenericStruct, IntEnum from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16, UBInt32, TypeList from pyof.foundation.exceptions import PackException From 0e94dc9bcca834282b19fe234bbbd55a3d5f0925 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 10 Apr 2019 14:34:29 -0400 Subject: [PATCH 05/81] Delete R_User_Library.xml Deleted this files --- .idea/libraries/R_User_Library.xml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .idea/libraries/R_User_Library.xml diff --git a/.idea/libraries/R_User_Library.xml b/.idea/libraries/R_User_Library.xml deleted file mode 100644 index 71f5ff749..000000000 --- a/.idea/libraries/R_User_Library.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 35e1a589c2de766f3549aa0d2f075966c5e9dcb2 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 10 Apr 2019 14:35:17 -0400 Subject: [PATCH 06/81] Delete vcs.xml deleted this files this were submitted because of the IDE --- .idea/vcs.xml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 297539ea8e8847bbff58bfc062e9af8fac707428 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 18:05:49 -0400 Subject: [PATCH 07/81] Deleted repeated comments under HelloElemVersionBitmap. --- pyof/v0x05/symmetric/hello.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index ee4ff683b..392073b16 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -138,10 +138,6 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element There is not need to enter the Version bitmap because is entered automatically as the type of message - Followed by: - - Exactly (length - 4) bytes containing the bitmaps, then - - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) - bytes of all-zero bytes. """ # List of bitmaps - supported versions bitmaps = BinaryData() From e5f4c580241370fa3173b75321cbd7d1541aa8fa Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 18:15:22 -0400 Subject: [PATCH 08/81] Deleted repeated comments in the Header Class. --- pyof/v0x05/common/header.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyof/v0x05/common/header.py b/pyof/v0x05/common/header.py index 1aff0084c..25670d46f 100644 --- a/pyof/v0x05/common/header.py +++ b/pyof/v0x05/common/header.py @@ -103,11 +103,11 @@ class Type(IntEnum): class Header(GenericStruct): """Representation of an OpenFlow message Header.""" - version = UBInt8(OFP_VERSION) # OFP_VERSION - message_type = UBInt8(enum_ref=Type) # One of the OFPT_ constants - length = UBInt16() # Length including this ofp_header - xid = UBInt32() # Transaction id associated with this packet. - # Replies use the same id as was in the request to faciliate pairing. + version = UBInt8(OFP_VERSION) + message_type = UBInt8(enum_ref=Type) + length = UBInt16() + xid = UBInt32() + def __init__(self, message_type=None, length=None, xid=None): """Create a Header with the optional parameters below. From 3b09f3b8314262a2a7cd41c4cea9d8931c5de73f Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 18:23:10 -0400 Subject: [PATCH 09/81] Deleted extra space before the __init__ method --- pyof/v0x05/common/header.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyof/v0x05/common/header.py b/pyof/v0x05/common/header.py index 25670d46f..4a16e1767 100644 --- a/pyof/v0x05/common/header.py +++ b/pyof/v0x05/common/header.py @@ -108,7 +108,6 @@ class Header(GenericStruct): length = UBInt16() xid = UBInt32() - def __init__(self, message_type=None, length=None, xid=None): """Create a Header with the optional parameters below. From 58d87f561f631fa1ee6b93aca487d3899d414335 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 19:22:42 -0400 Subject: [PATCH 10/81] Fix some indentation and spaces in comments --- pyof/v0x05/common/header.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pyof/v0x05/common/header.py b/pyof/v0x05/common/header.py index 4a16e1767..d572bcf6d 100644 --- a/pyof/v0x05/common/header.py +++ b/pyof/v0x05/common/header.py @@ -60,9 +60,8 @@ class Type(IntEnum): # Queue Configuration messages # Controller/Switch message - #OFPT_QUEUE_GET_CONFIG_REQUEST = 22 - #OFPT_QUEUE_GET_CONFIG_REPLY = 23 - + # OFPT_QUEUE_GET_CONFIG_REQUEST = 22 + # OFPT_QUEUE_GET_CONFIG_REPLY = 23 # Controller role change request message # Controller/Switch message @@ -80,20 +79,20 @@ class Type(IntEnum): OFPT_METER_MOD = 29 - #Controller role change event messages - #Async message + # Controller role change event messages + # Async message OFPT_ROLE_STATUS = 30 - #Asynchronous message - #Async message + # Asynchronous message + # Async message OFPT_TABLE_STATUS = 31 - #Request forwarding by switch - #Async message + # Request forwarding by switch + # Async message OFPT_REQUESTFORWARD = 32 - #Bundle operations (Multiple messages as a single operation) - #Controller/Switch message + # Bundle operations (Multiple messages as a single operation) + # Controller/Switch message OFPT_BUNDLE_CONTROL = 33 OFPT_BUNDLE_ADD_MESSAGE = 34 From 81322f9ec497167841e7b4078ee32734ff414988 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 19:24:30 -0400 Subject: [PATCH 11/81] All indentation and spaces in Header files has been fix in relation to PEP8 --- pyof/v0x05/common/header.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyof/v0x05/common/header.py b/pyof/v0x05/common/header.py index d572bcf6d..1acf849a5 100644 --- a/pyof/v0x05/common/header.py +++ b/pyof/v0x05/common/header.py @@ -78,7 +78,6 @@ class Type(IntEnum): # Controller/Switch message OFPT_METER_MOD = 29 - # Controller role change event messages # Async message OFPT_ROLE_STATUS = 30 From 6902c53430ee9ba294948c52e4ecc0e92f4c206a Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 19:36:23 -0400 Subject: [PATCH 12/81] Eliminated the warnings in the hello file --- pyof/v0x05/symmetric/hello.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 392073b16..3a09d4176 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -2,8 +2,8 @@ # System imports -from pyof.foundation.base import GenericMessage, GenericStruct, IntEnum -from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16, UBInt32, TypeList +from pyof.foundation.base import GenericMessage, GenericStruct, Enum +from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16 from pyof.foundation.exceptions import PackException from pyof.v0x05.common.header import Header, Type @@ -14,7 +14,7 @@ # Enums -class HelloElemType(IntEnum): +class HelloElemType(Enum): """Hello element types.""" #: Bitmap of version supported. @@ -23,18 +23,16 @@ class HelloElemType(IntEnum): # Classes - class HelloElemHeader(GenericStruct): """Common header for all Hello Elements.""" - # One of OFPHET_*. type = UBInt16() # Length in bytes of element, including this header, excluding padding. length = UBInt16() # This variable does NOT appear in 1.4 specification # content = BinaryData() - def __init__(self, element_type=None, length=None, content=b''): + def __init__(self, element_type=None, length=None): """Create a HelloElemHeader with the optional parameters below. Args: @@ -109,7 +107,6 @@ def __init__(self, items=None): # super().append(items) - class Hello(GenericMessage): """OpenFlow Hello Message OFPT_HELLO. @@ -121,7 +118,6 @@ class Hello(GenericMessage): header = Header(Type.OFPT_HELLO) #: Hello element list - #: List of elements - 0 or more elements = ListOfHelloElements() def __init__(self, xid=None, elements=None): @@ -155,7 +151,3 @@ def __init__(self, length=None, bitmaps=None): """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) self.bitmaps = bitmaps - - - - From 53540ac9e4f62734ea86b2bf946706f72fc3611b Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 19:52:49 -0400 Subject: [PATCH 13/81] Changing the comment in the HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 3a09d4176..62f94bd14 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -134,11 +134,11 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element There is not need to enter the Version bitmap because is entered automatically as the type of message + This method is under review """ # List of bitmaps - supported versions bitmaps = BinaryData() - # Under Review def __init__(self, length=None, bitmaps=None): """ Create the HelloElemVersionBitmap. From bdc2bb9ecb53e5e00aa4e3766e97b95acf3dcf23 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 19:59:38 -0400 Subject: [PATCH 14/81] Changing the indentation in the HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 62f94bd14..7c7a212fa 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -134,8 +134,7 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element There is not need to enter the Version bitmap because is entered automatically as the type of message - This method is under review - """ + This method is under review. """ # List of bitmaps - supported versions bitmaps = BinaryData() From da312ff740b1726b698b148c5100a22bc9f15bdd Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:00:25 -0400 Subject: [PATCH 15/81] Changing the indentation and creating spaces to the HelloElemVersionBitmap method --- pyof/v0x05/symmetric/hello.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 7c7a212fa..17cd813d4 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -135,6 +135,7 @@ class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element There is not need to enter the Version bitmap because is entered automatically as the type of message This method is under review. """ + # List of bitmaps - supported versions bitmaps = BinaryData() From 22929e5205c79f257b4827e51c9cc356ada63392 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:15:39 -0400 Subject: [PATCH 16/81] Rewrite the method HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 17cd813d4..d3f4dcb11 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -133,20 +133,21 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element - There is not need to enter the Version bitmap because is entered automatically as the type of message - This method is under review. """ + The bitmaps field indicates the set of versions of the OpenFlow + switch protocol a device supports, and may be used during version negotiation. + """ - # List of bitmaps - supported versions bitmaps = BinaryData() def __init__(self, length=None, bitmaps=None): """ - Create the HelloElemVersionBitmap. - :param length: - Followed by: + It will initialize the class with the needed values. + + :param length: Followed by: - Exactly (length - 4) bytes containing the bitmaps, then - - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) + - Exactly (length + 7) / 8 * * - (length) (Between 0 and 7) bytes of all-zero bytes. + :param bitmaps: List of bitmaps - supported versions """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) From dcaa2a59a2b4bb24165ed628ab87fc5a82d35ec5 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:19:39 -0400 Subject: [PATCH 17/81] add some space the method HelloElemVersionBitmap: 3 --- pyof/v0x05/symmetric/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index d3f4dcb11..4a86e50f4 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -133,7 +133,7 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element - The bitmaps field indicates the set of versions of the OpenFlow + The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. """ From 060f1f2040ee1539284ed1705a883e109cebd253 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:25:22 -0400 Subject: [PATCH 18/81] add some space the method HelloElemVersionBitmap: 8 and the method __init__ --- pyof/v0x05/symmetric/hello.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 4a86e50f4..67b6b75a1 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -149,6 +149,9 @@ def __init__(self, length=None, bitmaps=None): bytes of all-zero bytes. :param bitmaps: List of bitmaps - supported versions + """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) self.bitmaps = bitmaps + + From c673841194ba7ca3203c6ce47cc6bd53f51e4367 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:28:10 -0400 Subject: [PATCH 19/81] Add some space to the comment in the method HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 67b6b75a1..3c3f1569f 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -135,6 +135,7 @@ class HelloElemVersionBitmap(HelloElemHeader): """ Version bitmap Hello Element The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. + """ bitmaps = BinaryData() From dc0bb8a42d35b077e8c5e7b487ed2cec9bfa64df Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:43:51 -0400 Subject: [PATCH 20/81] Add some space to the comment in the method HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 3c3f1569f..31a7a1766 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -141,8 +141,9 @@ class HelloElemVersionBitmap(HelloElemHeader): bitmaps = BinaryData() def __init__(self, length=None, bitmaps=None): + """ - It will initialize the class with the needed values. + It will initialize the class with the needed values. :param length: Followed by: - Exactly (length - 4) bytes containing the bitmaps, then From 2338d3285b05b4f2e967e52013fb0bab0b3de1e7 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:48:01 -0400 Subject: [PATCH 21/81] Add some space to the comment in the method HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 31a7a1766..716eddf9f 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -157,3 +157,4 @@ def __init__(self, length=None, bitmaps=None): self.bitmaps = bitmaps + From 0b1a82c4a5d7e9a257508ea11be815308200285d Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 20:55:26 -0400 Subject: [PATCH 22/81] Change the parameter representation to the method __init__ in the class HelloElemVersionBitmap. --- pyof/v0x05/symmetric/hello.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 716eddf9f..25c2c7727 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -145,12 +145,13 @@ def __init__(self, length=None, bitmaps=None): """ It will initialize the class with the needed values. - :param length: Followed by: - - Exactly (length - 4) bytes containing the bitmaps, then - - Exactly (length + 7) / 8 * * - (length) (Between 0 and 7) - bytes of all-zero bytes. + Args: + length(int): Followed by: + - Exactly (length - 4) bytes containing the bitmaps, then + - Exactly (length + 7) / 8 * * - (length) (Between 0 and 7) + bytes of all-zero bytes. - :param bitmaps: List of bitmaps - supported versions + bitmaps(binary): List of bitmaps - supported versions """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) From f5bebf7dd34934d00b8a39e8a2b5a18d853e40fe Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 21:03:34 -0400 Subject: [PATCH 23/81] Changed variable name in the HelloElemHeader --- pyof/v0x05/symmetric/hello.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 25c2c7727..4ecc6a9af 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -26,7 +26,7 @@ class HelloElemType(Enum): class HelloElemHeader(GenericStruct): """Common header for all Hello Elements.""" - type = UBInt16() + element_type = UBInt16() # Length in bytes of element, including this header, excluding padding. length = UBInt16() # This variable does NOT appear in 1.4 specification @@ -41,7 +41,7 @@ def __init__(self, element_type=None, length=None): excluding padding. """ super().__init__() - self.type = element_type + self.element_type = element_type self.length = length # self.content = content @@ -148,13 +148,13 @@ def __init__(self, length=None, bitmaps=None): Args: length(int): Followed by: - Exactly (length - 4) bytes containing the bitmaps, then - - Exactly (length + 7) / 8 * * - (length) (Between 0 and 7) + - Exactly (length + 7) / 8 * 8 - (length) (Between 0 and 7) bytes of all-zero bytes. bitmaps(binary): List of bitmaps - supported versions """ - super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) + super().__init__(HelloElemType.OFPHET_VERSIONBITMAP,length) self.bitmaps = bitmaps From de1c69728733663c843aed33d3e0b2ae1feada1c Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Tue, 7 May 2019 21:07:27 -0400 Subject: [PATCH 24/81] Changed the type its variable name in the HelloElemHeader --- pyof/v0x05/symmetric/hello.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 4ecc6a9af..fae707fce 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -26,22 +26,22 @@ class HelloElemType(Enum): class HelloElemHeader(GenericStruct): """Common header for all Hello Elements.""" - element_type = UBInt16() + hello_element_type = UBInt16() # Length in bytes of element, including this header, excluding padding. length = UBInt16() # This variable does NOT appear in 1.4 specification # content = BinaryData() - def __init__(self, element_type=None, length=None): + def __init__(self, hello_element_type=None, length=None): """Create a HelloElemHeader with the optional parameters below. Args: - element_type: One of OFPHET_*. + hello_element_type: One of OFPHET_*. length: Length in bytes of the element, including this header, excluding padding. """ super().__init__() - self.element_type = element_type + self.hello_element_type = hello_element_type self.length = length # self.content = content From 16bd2bb0630afc19a309a7924615e80f33d00509 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 14:40:51 -0400 Subject: [PATCH 25/81] Change the name of HelloElemHeader to eliminate the cross-reference --- pyof/v0x05/symmetric/hello.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index fae707fce..71c9d1c6d 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -23,7 +23,7 @@ class HelloElemType(Enum): # Classes -class HelloElemHeader(GenericStruct): +class OPFHelloElemHeader(GenericStruct): """Common header for all Hello Elements.""" hello_element_type = UBInt16() @@ -43,7 +43,6 @@ def __init__(self, hello_element_type=None, length=None): super().__init__() self.hello_element_type = hello_element_type self.length = length - # self.content = content def pack(self, value=None): """Update the length and pack the message into binary data. @@ -102,9 +101,7 @@ def __init__(self, items=None): Args: items (HelloElemHeader): Instance or a list of instances. """ - super().__init__(pyof_class=HelloElemHeader, items=items) - # if (items != None and isinstance(HelloElemHeader,items)): - # super().append(items) + super().__init__(pyof_class=OPFHelloElemHeader, items=items) class Hello(GenericMessage): @@ -131,7 +128,7 @@ def __init__(self, xid=None, elements=None): self.elements = elements -class HelloElemVersionBitmap(HelloElemHeader): +class HelloElemVersionBitmap(OPFHelloElemHeader): """ Version bitmap Hello Element The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. From 53452f8eb2fd7a6f442de855e27e111b1bf4dc06 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 14:43:45 -0400 Subject: [PATCH 26/81] Change the name in the all list --- pyof/v0x05/symmetric/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 71c9d1c6d..8814a1e0a 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -9,7 +9,7 @@ # Third-party imports -__all__ = ('Hello', 'HelloElemHeader', 'HelloElemType', 'ListOfHelloElements', 'HelloElemVersionBitmap') +__all__ = ('Hello', 'OPFHelloElemHeader', 'HelloElemType', 'ListOfHelloElements', 'HelloElemVersionBitmap') # Enums From c722bce2456b06d3fe6392e621b94a5847447763 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:02:31 -0400 Subject: [PATCH 27/81] Fix minor changes to comply with the docstring --- pyof/v0x05/common/__init__.py | 1 + pyof/v0x05/symmetric/__init__.py | 1 + pyof/v0x05/symmetric/hello.py | 15 ++++++++------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pyof/v0x05/common/__init__.py b/pyof/v0x05/common/__init__.py index e69de29bb..fe900bde7 100644 --- a/pyof/v0x05/common/__init__.py +++ b/pyof/v0x05/common/__init__.py @@ -0,0 +1 @@ +"""Common structures used on OpenFlow Protocol.""" diff --git a/pyof/v0x05/symmetric/__init__.py b/pyof/v0x05/symmetric/__init__.py index e69de29bb..ecf70ed4a 100644 --- a/pyof/v0x05/symmetric/__init__.py +++ b/pyof/v0x05/symmetric/__init__.py @@ -0,0 +1 @@ +"""Symmetric Messages.""" \ No newline at end of file diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 8814a1e0a..259976054 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -9,7 +9,8 @@ # Third-party imports -__all__ = ('Hello', 'OPFHelloElemHeader', 'HelloElemType', 'ListOfHelloElements', 'HelloElemVersionBitmap') +__all__ = ('Hello', 'HelloElemType', + 'HelloElemVersionBitmap', 'ListOfHelloElements', 'OPFHelloElemHeader') # Enums @@ -129,10 +130,10 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(OPFHelloElemHeader): - """ Version bitmap Hello Element - The bitmaps field indicates the set of versions of the OpenFlow - switch protocol a device supports, and may be used during version negotiation. - + """ Version bitmap Hello Element. + The bitmaps field indicates the set of versions + of the OpenFlow switch protocol a device supports, + and may be used during version negotiation. """ bitmaps = BinaryData() @@ -148,10 +149,10 @@ def __init__(self, length=None, bitmaps=None): - Exactly (length + 7) / 8 * 8 - (length) (Between 0 and 7) bytes of all-zero bytes. - bitmaps(binary): List of bitmaps - supported versions + bitmaps(binary): List of bitmaps - supported versions. """ - super().__init__(HelloElemType.OFPHET_VERSIONBITMAP,length) + super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) self.bitmaps = bitmaps From 9627614b5360498ab344169a4612b7753d4e99ac Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:05:15 -0400 Subject: [PATCH 28/81] Fix indentation --- pyof/v0x05/symmetric/hello.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 259976054..d86bd3e47 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -132,8 +132,8 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(OPFHelloElemHeader): """ Version bitmap Hello Element. The bitmaps field indicates the set of versions - of the OpenFlow switch protocol a device supports, - and may be used during version negotiation. + of the OpenFlow switch protocol a device supports, + and may be used during version negotiation. """ bitmaps = BinaryData() From 6609355e448116fa8be0f15fb5cec29c88d8495c Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:08:06 -0400 Subject: [PATCH 29/81] Add a blank line to the definition in HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index d86bd3e47..7e0dd656d 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -134,6 +134,7 @@ class HelloElemVersionBitmap(OPFHelloElemHeader): The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. + """ bitmaps = BinaryData() From c3718ac4182135516e7c1bc815314b3b5f083ac2 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:10:41 -0400 Subject: [PATCH 30/81] Add a blank line to the definition in HelloElemVersionBitmap --- pyof/v0x05/symmetric/hello.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 7e0dd656d..528586e46 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -131,6 +131,7 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(OPFHelloElemHeader): """ Version bitmap Hello Element. + The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. From 33ecf234767cbe6c4445dac3e966c69136ac1228 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:14:41 -0400 Subject: [PATCH 31/81] Add a blank line to the definition in HelloElemVersionBitmap to fix the indentation --- pyof/v0x05/symmetric/hello.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 528586e46..9ae0e9a7a 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -132,10 +132,9 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(OPFHelloElemHeader): """ Version bitmap Hello Element. - The bitmaps field indicates the set of versions + The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, and may be used during version negotiation. - """ bitmaps = BinaryData() @@ -152,7 +151,6 @@ def __init__(self, length=None, bitmaps=None): bytes of all-zero bytes. bitmaps(binary): List of bitmaps - supported versions. - """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) self.bitmaps = bitmaps From 40ff5de75af13467ce522f68b91c6f07f650c21d Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:22:18 -0400 Subject: [PATCH 32/81] Add a newlines, spaces to fix the indentation --- pyof/v0x05/__init__.py | 1 + pyof/v0x05/symmetric/__init__.py | 2 +- pyof/v0x05/symmetric/hello.py | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/__init__.py b/pyof/v0x05/__init__.py index e69de29bb..f29833e00 100644 --- a/pyof/v0x05/__init__.py +++ b/pyof/v0x05/__init__.py @@ -0,0 +1 @@ +"""The ofx parser package - spec version 0x05 (1.4.1).""" diff --git a/pyof/v0x05/symmetric/__init__.py b/pyof/v0x05/symmetric/__init__.py index ecf70ed4a..6b4d142c0 100644 --- a/pyof/v0x05/symmetric/__init__.py +++ b/pyof/v0x05/symmetric/__init__.py @@ -1 +1 @@ -"""Symmetric Messages.""" \ No newline at end of file +"""Symmetric Messages.""" diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 9ae0e9a7a..a207a051b 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -10,7 +10,8 @@ # Third-party imports __all__ = ('Hello', 'HelloElemType', - 'HelloElemVersionBitmap', 'ListOfHelloElements', 'OPFHelloElemHeader') + 'HelloElemVersionBitmap', 'ListOfHelloElements', + 'OPFHelloElemHeader') # Enums @@ -142,7 +143,7 @@ class HelloElemVersionBitmap(OPFHelloElemHeader): def __init__(self, length=None, bitmaps=None): """ - It will initialize the class with the needed values. + Initialize the class with the needed values. Args: length(int): Followed by: @@ -156,4 +157,3 @@ def __init__(self, length=None, bitmaps=None): self.bitmaps = bitmaps - From 843bd3fa8c6b0f3e8e31af5ca56891af5aa5c812 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:26:59 -0400 Subject: [PATCH 33/81] Add a newlines, spaces to fix the indentation --- pyof/v0x05/symmetric/hello.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index a207a051b..08a1521c0 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -141,7 +141,6 @@ class HelloElemVersionBitmap(OPFHelloElemHeader): bitmaps = BinaryData() def __init__(self, length=None, bitmaps=None): - """ Initialize the class with the needed values. From e742e9deb7e694819cd4ca135732b418e1e1e3ce Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:30:54 -0400 Subject: [PATCH 34/81] Add a newlines, spaces to fix the indentation --- pyof/v0x05/symmetric/hello.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 08a1521c0..88b85d1be 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -154,5 +154,3 @@ def __init__(self, length=None, bitmaps=None): """ super().__init__(HelloElemType.OFPHET_VERSIONBITMAP, length) self.bitmaps = bitmaps - - From 692b4fb120547f2c22fb9cd3da444cbde7e3a4e5 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:35:14 -0400 Subject: [PATCH 35/81] Add a newlines, spaces to fix the indentation --- pyof/v0x05/symmetric/hello.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index 88b85d1be..f5201cadd 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -2,7 +2,7 @@ # System imports -from pyof.foundation.base import GenericMessage, GenericStruct, Enum +from pyof.foundation.base import Enum, GenericMessage, GenericStruct from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16 from pyof.foundation.exceptions import PackException from pyof.v0x05.common.header import Header, Type @@ -131,7 +131,7 @@ def __init__(self, xid=None, elements=None): class HelloElemVersionBitmap(OPFHelloElemHeader): - """ Version bitmap Hello Element. + """Version bitmap Hello Element. The bitmaps field indicates the set of versions of the OpenFlow switch protocol a device supports, @@ -141,8 +141,7 @@ class HelloElemVersionBitmap(OPFHelloElemHeader): bitmaps = BinaryData() def __init__(self, length=None, bitmaps=None): - """ - Initialize the class with the needed values. + """Initialize the class with the needed values. Args: length(int): Followed by: From ccf33aa052f836e80cd70582f0525abd62d3fc1d Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 15:38:48 -0400 Subject: [PATCH 36/81] Fixing some indentations --- pyof/v0x05/symmetric/hello.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/hello.py b/pyof/v0x05/symmetric/hello.py index f5201cadd..90372aac7 100644 --- a/pyof/v0x05/symmetric/hello.py +++ b/pyof/v0x05/symmetric/hello.py @@ -143,7 +143,7 @@ class HelloElemVersionBitmap(OPFHelloElemHeader): def __init__(self, length=None, bitmaps=None): """Initialize the class with the needed values. - Args: + Args: length(int): Followed by: - Exactly (length - 4) bytes containing the bitmaps, then - Exactly (length + 7) / 8 * 8 - (length) (Between 0 and 7) From 8c66a0be11db9e2beeef95ae61743526181e96c4 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 16:09:52 -0400 Subject: [PATCH 37/81] Created two new files the action and the flow_match the action file uses a flow_match class. --- pyof/v0x05/common/action.py | 477 ++++++++++++++++++++++++++++++++ pyof/v0x05/common/flow_match.py | 462 +++++++++++++++++++++++++++++++ 2 files changed, 939 insertions(+) create mode 100644 pyof/v0x05/common/action.py create mode 100644 pyof/v0x05/common/flow_match.py diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py new file mode 100644 index 000000000..727924f67 --- /dev/null +++ b/pyof/v0x05/common/action.py @@ -0,0 +1,477 @@ +"""Defines actions that may be associated with flows packets.""" +# System imports +from enum import IntEnum +from math import ceil + +# Local source tree imports +from pyof.foundation.base import GenericStruct +from pyof.foundation.basic_types import ( + FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) +from pyof.v0x05.common.flow_match import OxmTLV + +# Third-party imports + +__all__ = ('ActionExperimenterHeader', 'ActionGroup', 'ActionHeader', + 'ActionCopyTTLIn', 'ActionCopyTTLOut', 'ActionDecMPLSTTL', + 'ActionSetMPLSTTL', 'ActionDecNWTTL', 'ActionSetNWTTL', + 'ActionOutput', 'ActionPopMPLS', 'ActionPopPBB', 'ActionPopVLAN', + 'ActionPush', 'ActionSetField', 'ActionSetQueue', 'ActionType', + 'ControllerMaxLen', 'ListOfActions') + +# Enums + + +class ActionType(IntEnum): + """Actions associated with flows and packets.""" + + #: Output to switch port. + OFPAT_OUTPUT = 0 + #: Copy TTL "outwards" -- from next-to-outermost to outermost + OFPAT_COPY_TTL_OUT = 11 + #: Copy TTL "inwards" -- from outermost to next-to-outermost + OFPAT_COPY_TTL_IN = 12 + #: MPLS TTL + OFPAT_SET_MPLS_TTL = 15 + #: Decrement MPLS TTL + OFPAT_DEC_MPLS_TTL = 16 + #: Push a new VLAN tag + OFPAT_PUSH_VLAN = 17 + #: Pop the outer VLAN tag + OFPAT_POP_VLAN = 18 + #: Push a new MPLS tag + OFPAT_PUSH_MPLS = 19 + #: Pop the outer MPLS tag + OFPAT_POP_MPLS = 20 + #: Set queue id when outputting to a port + OFPAT_SET_QUEUE = 21 + #: Apply group. + OFPAT_GROUP = 22 + #: IP TTL. + OFPAT_SET_NW_TTL = 23 + #: Decrement IP TTL. + OFPAT_DEC_NW_TTL = 24 + #: Set a header field using OXM TLV format. + OFPAT_SET_FIELD = 25 + #: Push a new PBB service tag (I-TAG) + OFPAT_PUSH_PBB = 26 + #: Pop the outer PBB service tag (I-TAG) + OFPAT_POP_PBB = 27 + #: Experimenter type + OFPAT_EXPERIMENTER = 0xffff + + +class ControllerMaxLen(IntEnum): + """A max_len of OFPCML_NO_BUFFER means not to buffer. + + The packet should be sent. + """ + + #: maximum max_len value which can be used to request a specific byte + #: length. + OFPCML_MAX = 0xffe5 + #: indicates that no buffering should be applied and the whole packet is to + #: be sent to the controller. + OFPCML_NO_BUFFER = 0xffff + + +# Classes + + +class ActionHeader(GenericStruct): + """Action header that is common to all actions. + + The length includes the header and any padding used to make the action + 64-bit aligned. + NB: The length of an action *must* always be a multiple of eight. + """ + + #: One of OFPAT_*. + + action_type = UBInt16(enum_ref=ActionType) + #: Length of action, including this header. This is the length of actions, + #: including any padding to make it 64-bit aligned. + length = UBInt16() + + _allowed_types = () + + def __init__(self, action_type=None, length=None): + """Create an ActionHeader with the optional parameters below. + + Args: + action_type (~pyof.v0x05.common.action.ActionType): + The type of the action. + length (int): Length of action, including this header. + """ + super().__init__() + self.action_type = action_type + self.length = length + + def get_size(self, value=None): + """Return the action length including the padding (multiple of 8).""" + if isinstance(value, ActionHeader): + return value.get_size() + elif value is None: + current_size = super().get_size() + return ceil(current_size / 8) * 8 + raise ValueError(f'Invalid value "{value}" for Action*.get_size()') + + def unpack(self, buff, offset=0): + """Unpack a binary message into this object's attributes. + + Unpack the binary value *buff* and update this object attributes based + on the results. + + Args: + buff (bytes): Binary data package to be unpacked. + offset (int): Where to begin unpacking. + + Raises: + Exception: If there is a struct unpacking error. + + """ + self.action_type = UBInt16(enum_ref=ActionType) + self.action_type.unpack(buff, offset) + + for cls in ActionHeader.__subclasses__(): + if self.action_type.value in cls.get_allowed_types(): + self.__class__ = cls + break + + super().unpack(buff, offset) + + @classmethod + def get_allowed_types(cls): + """Return allowed types for the class.""" + return cls._allowed_types + + +class ActionExperimenterHeader(ActionHeader): + """Action structure for OFPAT_EXPERIMENTER.""" + + # Experimenter ID + experimenter = UBInt32() + + _allowed_types = (ActionType.OFPAT_EXPERIMENTER, ) + + def __init__(self, length=None, experimenter=None): + """Create ActionExperimenterHeader with the optional parameters below. + + Args: + experimenter (int): The experimenter field is the Experimenter ID, + which takes the same form as in struct ofp_experimenter. + """ + super().__init__(action_type=ActionType.OFPAT_EXPERIMENTER) + self.length = length + self.experimenter = experimenter + + +class ExperimenterStruct(GenericStruct): + """ Typical Experimenter structure. """ + + # Experimenter ID: + # - MSB 0: low-order bytes are IEEE OUI + # - MSB != 0: defined by ONF + experimenter = UBInt32() + # Experimenter defined + exp_type = UBInt32() + + experimenter_data = UBInt8() + + +class ActionGroup(ActionHeader): + """Action structure for OFPAT_GROUP.""" + + # Group identifier. + + group_id = UBInt32() + + _allowed_types = (ActionType.OFPAT_GROUP, ) + + def __init__(self, group_id=None): + """Create an ActionGroup with the optional parameters below. + + Args: + group_id (int): The group_id indicates the group used to process + this packet. The set of buckets to apply depends on the group + type. + """ + super().__init__(action_type=ActionType.OFPAT_GROUP, length=8) + self.group_id = group_id + + +class ActionDecMPLSTTL(ActionHeader): + """Action structure for OFPAT_DEC_MPLS_TTL.""" + + # Pad to 64 bits + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_DEC_MPLS_TTL, ) + + def __init__(self): + """Create an ActionDecMPLSTTL.""" + super().__init__(action_type=ActionType.OFPAT_DEC_MPLS_TTL, length=8) + + +class ActionSetMPLSTTL(ActionHeader): + """Action structure for OFPAT_SET_MPLS_TTL.""" + + # MPLS TTL + mpls_ttl = UBInt8() + # + + pad = Pad(3) + + _allowed_types = (ActionType.OFPAT_SET_MPLS_TTL, ) + + def __init__(self, mpls_ttl=None): + """Create an ActionSetMPLSTTL with the optional parameters below. + + Args: + mpls_ttl (int): The mpls_ttl field is the MPLS TTL to set. + """ + super().__init__(action_type=ActionType.OFPAT_SET_MPLS_TTL, length=8) + self.mpls_ttl = mpls_ttl + + +class ActionCopyTTLIn(ActionHeader): + """Action structure for OFPAT_COPY_TTL_IN.""" + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_COPY_TTL_IN, ) + + def __init__(self): + """Create an ActionCopyTTLIn.""" + super().__init__(action_type=ActionType.OFPAT_COPY_TTL_IN, length=8) + + +class ActionCopyTTLOut(ActionHeader): + """Action structure for OFPAT_COPY_TTL_OUT.""" + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_COPY_TTL_OUT, ) + + def __init__(self): + """Create an ActionCopyTTLOut.""" + super().__init__(action_type=ActionType.OFPAT_COPY_TTL_OUT, length=8) + + +class ActionPopVLAN(ActionHeader): + """Action structure for OFPAT_POP_VLAN.""" + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_POP_VLAN, ) + + def __init__(self): + """Create an ActionPopVLAN.""" + super().__init__(action_type=ActionType.OFPAT_POP_VLAN, length=8) + + +class ActionPopPBB(ActionHeader): + """Action structure for OFPAT_POP_PBB.""" + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_POP_PBB, ) + + def __init__(self): + """Create an ActionPopPBB.""" + super().__init__(action_type=ActionType.OFPAT_POP_PBB, length=8) + + +class ActionDecNWTTL(ActionHeader): + """Action structure for OFPAT_DEC_NW_TTL.""" + + pad = Pad(4) + + _allowed_types = (ActionType.OFPAT_DEC_NW_TTL, ) + + def __init__(self): + """Create a ActionDecNWTTL.""" + super().__init__(action_type=ActionType.OFPAT_DEC_NW_TTL, length=8) + + +class ActionSetNWTTL(ActionHeader): + """Action structure for OFPAT_SET_NW_TTL.""" + + # IP TTL + nw_ttl = UBInt8() + # + + pad = Pad(3) + + _allowed_types = (ActionType.OFPAT_SET_NW_TTL, ) + + def __init__(self, nw_ttl=None): + """Create an ActionSetNWTTL with the optional parameters below. + + Args: + nw_ttl (int): the TTL address to set in the IP header. + """ + super().__init__(action_type=ActionType.OFPAT_SET_NW_TTL, length=8) + self.nw_ttl = nw_ttl + + +class ActionOutput(ActionHeader): + + """ + + Action structure for OFPAT_OUTPUT, which sends packets out ’port’. + When the ’port’ is the OFPP_CONTROLLER, ’max_len’ indicates the max + number of bytes to send. A ’max_len’ of zero means no bytes of the + packet should be sent. A ’max_len’ of OFPCML_NO_BUFFER means that + the packet is not buffered and the complete packet is to be sent to + the controller. + """ + # Extend the ActionHeader. + # Output port. + port = UBInt32() + # Max length to send to controller. + max_length = UBInt16() + # Pad to 64 bits. + + pad = Pad(6) + + _allowed_types = (ActionType.OFPAT_OUTPUT, ) + + def __init__(self, port=None, + max_length=ControllerMaxLen.OFPCML_NO_BUFFER): + """Create a ActionOutput with the optional parameters below. + + Args: + port (:class:`Port` or :class:`int`): Output port. + max_length (int): Max length to send to controller. + """ + super().__init__(action_type=ActionType.OFPAT_OUTPUT, length=16) + self.port = port + self.max_length = max_length + + +class ActionPopMPLS(ActionHeader): + """Action structure for OFPAT_POP_MPLS.""" + + # Ethertype + ethertype = UBInt16() + + pad = Pad(2) + + _allowed_types = (ActionType.OFPAT_POP_MPLS, ) + + def __init__(self, ethertype=None): + """Create an ActionPopMPLS with the optional parameters below. + + Args: + ethertype (int): indicates the Ethertype of the payload. + """ + super().__init__(action_type=ActionType.OFPAT_POP_MPLS) + self.ethertype = ethertype + + +class ActionPush(ActionHeader): + """Action structure for OFPAT_PUSH_[VLAN/MPLS/PBB].""" + + # Ethertype + ethertype = UBInt16() + # + + pad = Pad(2) + + _allowed_types = (ActionType. OFPAT_PUSH_VLAN, ActionType.OFPAT_PUSH_MPLS, + ActionType.OFPAT_PUSH_PBB, ) + + def __init__(self, action_type=None, ethertype=None): + """Create a ActionPush with the optional parameters below. + + Args: + action_type (:class:`ActionType`): indicates which tag will be + pushed (VLAN, MPLS, PBB). + ethertype (int): indicates the Ethertype of the new tag. + """ + super().__init__(action_type, length=8) + self.ethertype = ethertype + + +class ActionSetField(ActionHeader): + """Action structure for OFPAT_SET_FIELD.""" + + # + # + + # OXM TLV - Make compiler happy + + field = OxmTLV() + + _allowed_types = (ActionType.OFPAT_SET_FIELD, ) + + def __init__(self,length=None, field=None): + """Create a ActionSetField with the optional parameters below. + + Args: + length (int): length padded to 64 bits, followed by exactly + oxm_len bytes containing a single OXM TLV, then + exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4) + (between 0 and 7) bytes of all-zero bytes + field (:class:`OxmTLV`): OXM field and value. + """ + super().__init__(action_type=ActionType.OFPAT_SET_FIELD, length=length) + self.field = OxmTLV() if field is None else field + + def pack(self, value=None): + """Pack this structure updating the length and padding it.""" + self._update_length() + packet = super().pack() + return self._complete_last_byte(packet) + + def _update_length(self): + """Update the length field of the struct.""" + action_length = 4 + len(self.field.pack()) + overflow = action_length % 8 + self.length = action_length + if overflow: + self.length = action_length + 8 - overflow + + def _complete_last_byte(self, packet): + """Pad until the packet length is a multiple of 8 (bytes).""" + padded_size = self.length + padding_bytes = padded_size - len(packet) + if padding_bytes > 0: + packet += Pad(padding_bytes).pack() + return packet + + +class ActionSetQueue(ActionHeader): + """Action structure for OFPAT_SET_QUEUE.""" + + # Queue id for packets. + + queue_id = UBInt32() + + _allowed_types = (ActionType.OFPAT_SET_QUEUE, ) + + def __init__(self, queue_id=None): + """Create an ActionSetQueue with the optional parameters below. + + Args: + queue_id (int): The queue_id send packets to given queue on port. + """ + super().__init__(action_type=ActionType.OFPAT_SET_QUEUE, length=8) + self.queue_id = queue_id + + +class ListOfActions(FixedTypeList): + """List of actions. + + Represented by instances of ActionHeader and used on ActionHeader objects. + """ + + def __init__(self, items=None): + """Create a ListOfActions with the optional parameters below. + + Args: + items (~pyof.v0x05.common.action.ActionHeader): + Instance or a list of instances. + """ + super().__init__(pyof_class=ActionHeader, items=items) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py new file mode 100644 index 000000000..a8ae8fb98 --- /dev/null +++ b/pyof/v0x05/common/flow_match.py @@ -0,0 +1,462 @@ +"""Match strucutre and related enums. + +An OpenFlow match is composed of a flow match header and a sequence of zero or +more flow match fields. +""" +# System imports +from enum import IntEnum +from math import ceil + +# Local source tree imports +from pyof.foundation.base import GenericStruct, GenericBitMask +from pyof.foundation.basic_types import ( + BinaryData, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) +from pyof.foundation.exceptions import PackException, UnpackException + +__all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'Match', 'MatchType', + 'OxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', + 'OxmOfbMatchField', 'OxmTLV', 'VlanId') + + +class Ipv6ExtHdrFlags(GenericBitMask): + """Bit definitions for IPv6 Extension Header pseudo-field.""" + + #: "No next header" encountered. + OFPIEH_NONEXT = 1 << 0 + #: Encrypted Sec Payload header present. + OFPIEH_ESP = 1 << 1 + #: Authentication header present. + OFPIEH_AUTH = 1 << 2 + #: 1 or 2 dest headers present. + OFPIEH_DEST = 1 << 3 + #: Fragment header present. + OFPIEH_FRAG = 1 << 4 + #: Router header present. + OFPIEH_ROUTER = 1 << 5 + #: Hop-by-hop header present. + OFPIEH_HOP = 1 << 6 + #: Unexpected repeats encountered. + OFPIEH_UNREP = 1 << 7 + #: Unexpected sequencing encountered. + OFPIEH_UNSEQ = 1 << 8 + + +class OxmOfbMatchField(IntEnum): + """OXM Flow match field types for OpenFlow basic class. + + A switch is not required to support all match field types, just those + listed in the Table 10. Those required match fields don’t need to be + implemented in the same table lookup. The controller can query the switch + about which other fields it supports. + """ + + #: Switch input port. + OFPXMT_OFB_IN_PORT = 0 + #: Switch physical input port. + OFPXMT_OFB_IN_PHY_PORT = 1 + #: Metadata passed between tables. + OFPXMT_OFB_METADATA = 2 + #: Ethernet destination address. + OFPXMT_OFB_ETH_DST = 3 + #: Ethernet source address. + OFPXMT_OFB_ETH_SRC = 4 + #: Ethernet frame type. + OFPXMT_OFB_ETH_TYPE = 5 + #: VLAN id. + OFPXMT_OFB_VLAN_VID = 6 + #: VLAN priority. + OFPXMT_OFB_VLAN_PCP = 7 + #: IP DSCP (6 bits in ToS field). + OFPXMT_OFB_IP_DSCP = 8 + #: IP ECN (2 bits in ToS field). + OFPXMT_OFB_IP_ECN = 9 + #: IP protocol. + OFPXMT_OFB_IP_PROTO = 10 + #: IPv4 source address. + OFPXMT_OFB_IPV4_SRC = 11 + #: IPv4 destination address. + OFPXMT_OFB_IPV4_DST = 12 + #: TCP source port. + OFPXMT_OFB_TCP_SRC = 13 + #: TCP destination port. + OFPXMT_OFB_TCP_DST = 14 + #: UDP source port. + OFPXMT_OFB_UDP_SRC = 15 + #: UDP destination port. + OFPXMT_OFB_UDP_DST = 16 + #: SCTP source port. + OFPXMT_OFB_SCTP_SRC = 17 + #: SCTP destination port. + OFPXMT_OFB_SCTP_DST = 18 + #: ICMP type. + OFPXMT_OFB_ICMPV4_TYPE = 19 + #: ICMP code. + OFPXMT_OFB_ICMPV4_CODE = 20 + #: ARP opcode. + OFPXMT_OFB_ARP_OP = 21 + #: ARP source IPv4 address. + OFPXMT_OFB_ARP_SPA = 22 + #: ARP target IPv4 address. + OFPXMT_OFB_ARP_TPA = 23 + #: ARP source hardware address. + OFPXMT_OFB_ARP_SHA = 24 + #: ARP target hardware address. + OFPXMT_OFB_ARP_THA = 25 + #: IPv6 source address. + OFPXMT_OFB_IPV6_SRC = 26 + #: IPv6 destination address. + OFPXMT_OFB_IPV6_DST = 27 + #: IPv6 Flow Label + OFPXMT_OFB_IPV6_FLABEL = 28 + #: ICMPv6 type. + OFPXMT_OFB_ICMPV6_TYPE = 29 + #: ICMPv6 code. + OFPXMT_OFB_ICMPV6_CODE = 30 + #: Target address for ND. + OFPXMT_OFB_IPV6_ND_TARGET = 31 + #: Source link-layer for ND. + OFPXMT_OFB_IPV6_ND_SLL = 32 + #: Target link-layer for ND. + OFPXMT_OFB_IPV6_ND_TLL = 33 + #: MPLS label. + OFPXMT_OFB_MPLS_LABEL = 34 + #: MPLS TC. + OFPXMT_OFB_MPLS_TC = 35 + #: MPLS BoS bit. + OFPXMT_OFP_MPLS_BOS = 36 + #: PBB I-SID. + OFPXMT_OFB_PBB_ISID = 37 + #: Logical Port Metadata. + OFPXMT_OFB_TUNNEL_ID = 38 + #: IPv6 Extension Header pseudo-field + OFPXMT_OFB_IPV6_EXTHDR = 39 + + #: PBB UCA header field. + OFPXMT_OFB_PBB_UCA = 41 + + +class MatchType(IntEnum): + """Indicates the match structure in use. + + The match type is placed in the type field at the beginning of all match + structures. The "OpenFlow Extensible Match" type corresponds to OXM TLV + format described below and must be supported by all OpenFlow switches. + Extensions that define other match types may be published on the ONF wiki. + Support for extensions is optional + """ + + #: Deprecated + OFPMT_STANDARD = 0 + #: OpenFlow Extensible Match + OFPMT_OXM = 1 + + +class OxmClass(IntEnum): + """OpenFlow Extensible Match (OXM) Class IDs. + + The high order bit differentiate reserved classes from member classes. + Classes 0x0000 to 0x7FFF are member classes, allocated by ONF. + Classes 0x8000 to 0xFFFE are reserved classes, reserved for + standardisation. + """ + + #: Backward compatibility with NXM + OFPXMC_NXM_0 = 0x0000 + #: Backward compatibility with NXM + OFPXMC_NXM_1 = 0x0001 + #: Basic class for OpenFlow + OFPXMC_OPENFLOW_BASIC = 0x8000 + #: Experimenter class + OFPXMC_EXPERIMENTER = 0xFFFF + + +class VlanId(IntEnum): + """Indicates conditions of the Vlan. + + The VLAN id is 12-bits, so we can use the entire 16 bits to indicate + special conditions. + """ + + #: Bit that indicate that a VLAN id is set. + OFPVID_PRESENT = 0x1000 + #: No VLAN id was set + OFPVID_NONE = 0x0000 + + +# Classes + +class OxmTLV(GenericStruct): + """Oxm (OpenFlow Extensible Match) TLV.""" + + oxm_class = UBInt16(enum_ref=OxmClass) + oxm_field_and_mask = UBInt8() + oxm_length = UBInt8() + oxm_value = BinaryData() + + def __init__(self, oxm_class=OxmClass.OFPXMC_OPENFLOW_BASIC, + oxm_field=None, oxm_hasmask=False, oxm_value=None): + """Create an OXM TLV struct with the optional parameters below. + + Args: + oxm_class (OxmClass): Match class: member class or reserved class + oxm_field (OxmMatchFields, OxmOfbMatchField): Match field within + the class + oxm_hasmask (bool): Set if OXM include a bitmask in payload + oxm_value (bytes): OXM Payload + + """ + super().__init__() + self.oxm_class = oxm_class + self.oxm_field_and_mask = None + self.oxm_length = None + self.oxm_value = oxm_value + # Attributes that are not packed + self.oxm_field = oxm_field + self.oxm_hasmask = oxm_hasmask + + def unpack(self, buff, offset=0): + """Unpack the buffer into a OxmTLV. + + Args: + buff (bytes): The binary data to be unpacked. + offset (int): If we need to shift the beginning of the data. + + """ + super().unpack(buff, offset) + # Recover field from field_and_hasmask. + try: + self.oxm_field = self._unpack_oxm_field() + except ValueError as exception: + raise UnpackException(exception) + + # The last bit of field_and_mask is oxm_hasmask + self.oxm_hasmask = (self.oxm_field_and_mask & 1) == 1 # as boolean + + # Unpack oxm_value that has oxm_length bytes + start = offset + 4 # 4 bytes: class, field_and_mask and length + end = start + self.oxm_length + self.oxm_value = buff[start:end] + + def _unpack_oxm_field(self): + """Unpack oxm_field from oxm_field_and_mask. + + Returns: + :class:`OxmOfbMatchField`, int: oxm_field from oxm_field_and_mask. + + Raises: + ValueError: If oxm_class is OFPXMC_OPENFLOW_BASIC but + :class:`OxmOfbMatchField` has no such integer value. + + """ + field_int = self.oxm_field_and_mask >> 1 + # We know that the class below requires a subset of the ofb enum + if self.oxm_class == OxmClass.OFPXMC_OPENFLOW_BASIC: + return OxmOfbMatchField(field_int) + return field_int + + def _update_length(self): + """Update length field. + + Update the oxm_length field with the packed payload length. + + """ + payload = type(self).oxm_value.pack(self.oxm_value) + self.oxm_length = len(payload) + + def pack(self, value=None): + """Join oxm_hasmask bit and 7-bit oxm_field.""" + if value is not None: + return value.pack() + + # Set oxm_field_and_mask instance attribute + # 1. Move field integer one bit to the left + try: + field_int = self._get_oxm_field_int() + except ValueError as exception: + raise PackException(exception) + field_bits = field_int << 1 + # 2. hasmask bit + hasmask_bit = self.oxm_hasmask & 1 + # 3. Add hasmask bit to field value + self.oxm_field_and_mask = field_bits + hasmask_bit + + self._update_length() + return super().pack(value) + + def _get_oxm_field_int(self): + """Return a valid integer value for oxm_field. + + Used while packing. + + Returns: + int: valid oxm_field value. + + Raises: + ValueError: If :attribute:`oxm_field` is bigger than 7 bits or + should be :class:`OxmOfbMatchField` and the enum has no such + value. + + """ + if self.oxm_class == OxmClass.OFPXMC_OPENFLOW_BASIC: + return OxmOfbMatchField(self.oxm_field).value + elif not isinstance(self.oxm_field, int) or self.oxm_field > 127: + raise ValueError('oxm_field above 127: "{self.oxm_field}".') + return self.oxm_field + + +class OxmMatchFields(FixedTypeList): + """Generic Openflow EXtensible Match header. + + Abstract class that can be instantiated as Match or OxmExperimenterHeader. + + """ + + def __init__(self, items=None): + """Initialize ``items`` attribute. + + Args: + items (OxmHeader): Instance or a list of instances. + """ + super().__init__(pyof_class=OxmTLV, items=items) + + +class Match(GenericStruct): + """Describes the flow match header structure. + + These are the fields to match against flows. + + The :attr:`~type` field is set to :attr:`~MatchType.OFPMT_OXM` and + + :attr:`length` field is set to the actual length of match structure + including all match fields. The payload of the OpenFlow match is a set of + OXM Flow match fields. + + """ + + # One of OFPMT_* + match_type = UBInt16(enum_ref=MatchType) + # Length of Match (excluding padding) + length = UBInt16() + # 0 or more OXM match fields. + oxm_match_fields = OxmMatchFields() + # Zero bytes - see above for sizing + pad = Pad(4) + + def __init__(self, match_type=MatchType.OFPMT_OXM, length=None, oxm_match_fields=None): + """Describe the flow match header structure. + + Args: + match_type (MatchType): One of OFPMT_* (MatchType) items. + length (int): Length of Match (excluding padding) followed by + Exactly (length - 4) (possibly 0) bytes containing + OXM TLVs, then exactly ((length + 7)/8*8 - length) + (between 0 and 7) bytes of all-zero bytes. + oxm_match_fields (OxmMatchFields): Sample description. + + """ + super().__init__() + self.match_type = match_type + self.length = length + self.oxm_match_fields = oxm_match_fields or OxmMatchFields() + self._update_match_length() + + def _update_match_length(self): + """Update the match length field.""" + self.length = super().get_size() + + def pack(self, value=None): + """Pack and complete the last byte by padding.""" + if isinstance(value, Match): + return value.pack() + elif value is None: + self._update_match_length() + packet = super().pack() + return self._complete_last_byte(packet) + raise PackException(f'Match can\'t unpack "{value}".') + + def _complete_last_byte(self, packet): + """Pad until the packet length is a multiple of 8 (bytes).""" + padded_size = self.get_size() + padding_bytes = padded_size - len(packet) + if padding_bytes > 0: + packet += Pad(padding_bytes).pack() + return packet + + def get_size(self, value=None): + """Return the packet length including the padding (multiple of 8).""" + if isinstance(value, Match): + return value.get_size() + elif value is None: + current_size = super().get_size() + return ceil(current_size / 8) * 8 + raise ValueError(f'Invalid value "{value}" for Match.get_size()') + + def unpack(self, buff, offset=0): + """Discard padding bytes using the unpacked length attribute.""" + begin = offset + size = 0 + for name, value in list(self.get_class_attributes())[:-1]: + size = self._unpack_attribute(name, value, buff, begin) + begin += size + self._unpack_attribute('oxm_match_fields', type(self).oxm_match_fields, + buff[:offset+self.length - len(Pad(4))], begin - size) + + def get_field(self, field_type): + """Return the value for the 'field_type' field in oxm_match_fields. + + Args: + + field_type (~pyof.v0x05.common.flow_match.OxmOfbMatchField, + ~pyof.v0x05.common.flow_match.OxmMatchFields): + + The type of the OXM field you want the value. + + Returns: + The integer number of the 'field_type' if it exists. Otherwise + return None. + + """ + for field in self.oxm_match_fields: + if field.oxm_field == field_type: + return field.oxm_value + + return None + + +class OxmExperimenterHeader(GenericStruct): + """Header for OXM experimenter match fields.""" + + #: oxm_class = OFPXMC_EXPERIMENTER + oxm_header = UBInt32(OxmClass.OFPXMC_EXPERIMENTER, + enum_ref=OxmClass) + #: Experimenter ID which takes the same form as in struct + #: ofp_experimenter_header + experimenter = UBInt32() + + def __init__(self, experimenter=None): + """Initialize ``experimenter`` attribute. + + Args: + experimenter (int): Experimenter ID which takes the same form as + in struct ofp_experimenter_header + + """ + super().__init__() + self.experimenter = experimenter + + +class ListOfOxmHeader(FixedTypeList): + """List of Openflow Extensible Match header instances. + + Represented by instances of OxmHeader. + + """ + + def __init__(self, items=None): + """Initialize ``items`` attribute. + + Args: + items (OxmHeader): Instance or a list of instances. + + """ + super().__init__(pyof_class=OxmTLV, items=items) From 5f3e3bc1683432aa43d6ef4401d8a20cfb2d1f87 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Wed, 8 May 2019 16:15:17 -0400 Subject: [PATCH 38/81] Fixing some spaces and indentations to the action file. --- pyof/v0x05/common/action.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py index 727924f67..4a611e5c6 100644 --- a/pyof/v0x05/common/action.py +++ b/pyof/v0x05/common/action.py @@ -406,7 +406,7 @@ class ActionSetField(ActionHeader): _allowed_types = (ActionType.OFPAT_SET_FIELD, ) - def __init__(self,length=None, field=None): + def __init__(self, length=None, field=None): """Create a ActionSetField with the optional parameters below. Args: From 6ed2851a0b4bc7c16533e668d1a5d230b4c3ddb8 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:25:10 -0400 Subject: [PATCH 39/81] Delete a file to submit only one file to Kytos. --- pyof/v0x05/common/action.py | 477 ------------------------------------ 1 file changed, 477 deletions(-) delete mode 100644 pyof/v0x05/common/action.py diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py deleted file mode 100644 index 4a611e5c6..000000000 --- a/pyof/v0x05/common/action.py +++ /dev/null @@ -1,477 +0,0 @@ -"""Defines actions that may be associated with flows packets.""" -# System imports -from enum import IntEnum -from math import ceil - -# Local source tree imports -from pyof.foundation.base import GenericStruct -from pyof.foundation.basic_types import ( - FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) -from pyof.v0x05.common.flow_match import OxmTLV - -# Third-party imports - -__all__ = ('ActionExperimenterHeader', 'ActionGroup', 'ActionHeader', - 'ActionCopyTTLIn', 'ActionCopyTTLOut', 'ActionDecMPLSTTL', - 'ActionSetMPLSTTL', 'ActionDecNWTTL', 'ActionSetNWTTL', - 'ActionOutput', 'ActionPopMPLS', 'ActionPopPBB', 'ActionPopVLAN', - 'ActionPush', 'ActionSetField', 'ActionSetQueue', 'ActionType', - 'ControllerMaxLen', 'ListOfActions') - -# Enums - - -class ActionType(IntEnum): - """Actions associated with flows and packets.""" - - #: Output to switch port. - OFPAT_OUTPUT = 0 - #: Copy TTL "outwards" -- from next-to-outermost to outermost - OFPAT_COPY_TTL_OUT = 11 - #: Copy TTL "inwards" -- from outermost to next-to-outermost - OFPAT_COPY_TTL_IN = 12 - #: MPLS TTL - OFPAT_SET_MPLS_TTL = 15 - #: Decrement MPLS TTL - OFPAT_DEC_MPLS_TTL = 16 - #: Push a new VLAN tag - OFPAT_PUSH_VLAN = 17 - #: Pop the outer VLAN tag - OFPAT_POP_VLAN = 18 - #: Push a new MPLS tag - OFPAT_PUSH_MPLS = 19 - #: Pop the outer MPLS tag - OFPAT_POP_MPLS = 20 - #: Set queue id when outputting to a port - OFPAT_SET_QUEUE = 21 - #: Apply group. - OFPAT_GROUP = 22 - #: IP TTL. - OFPAT_SET_NW_TTL = 23 - #: Decrement IP TTL. - OFPAT_DEC_NW_TTL = 24 - #: Set a header field using OXM TLV format. - OFPAT_SET_FIELD = 25 - #: Push a new PBB service tag (I-TAG) - OFPAT_PUSH_PBB = 26 - #: Pop the outer PBB service tag (I-TAG) - OFPAT_POP_PBB = 27 - #: Experimenter type - OFPAT_EXPERIMENTER = 0xffff - - -class ControllerMaxLen(IntEnum): - """A max_len of OFPCML_NO_BUFFER means not to buffer. - - The packet should be sent. - """ - - #: maximum max_len value which can be used to request a specific byte - #: length. - OFPCML_MAX = 0xffe5 - #: indicates that no buffering should be applied and the whole packet is to - #: be sent to the controller. - OFPCML_NO_BUFFER = 0xffff - - -# Classes - - -class ActionHeader(GenericStruct): - """Action header that is common to all actions. - - The length includes the header and any padding used to make the action - 64-bit aligned. - NB: The length of an action *must* always be a multiple of eight. - """ - - #: One of OFPAT_*. - - action_type = UBInt16(enum_ref=ActionType) - #: Length of action, including this header. This is the length of actions, - #: including any padding to make it 64-bit aligned. - length = UBInt16() - - _allowed_types = () - - def __init__(self, action_type=None, length=None): - """Create an ActionHeader with the optional parameters below. - - Args: - action_type (~pyof.v0x05.common.action.ActionType): - The type of the action. - length (int): Length of action, including this header. - """ - super().__init__() - self.action_type = action_type - self.length = length - - def get_size(self, value=None): - """Return the action length including the padding (multiple of 8).""" - if isinstance(value, ActionHeader): - return value.get_size() - elif value is None: - current_size = super().get_size() - return ceil(current_size / 8) * 8 - raise ValueError(f'Invalid value "{value}" for Action*.get_size()') - - def unpack(self, buff, offset=0): - """Unpack a binary message into this object's attributes. - - Unpack the binary value *buff* and update this object attributes based - on the results. - - Args: - buff (bytes): Binary data package to be unpacked. - offset (int): Where to begin unpacking. - - Raises: - Exception: If there is a struct unpacking error. - - """ - self.action_type = UBInt16(enum_ref=ActionType) - self.action_type.unpack(buff, offset) - - for cls in ActionHeader.__subclasses__(): - if self.action_type.value in cls.get_allowed_types(): - self.__class__ = cls - break - - super().unpack(buff, offset) - - @classmethod - def get_allowed_types(cls): - """Return allowed types for the class.""" - return cls._allowed_types - - -class ActionExperimenterHeader(ActionHeader): - """Action structure for OFPAT_EXPERIMENTER.""" - - # Experimenter ID - experimenter = UBInt32() - - _allowed_types = (ActionType.OFPAT_EXPERIMENTER, ) - - def __init__(self, length=None, experimenter=None): - """Create ActionExperimenterHeader with the optional parameters below. - - Args: - experimenter (int): The experimenter field is the Experimenter ID, - which takes the same form as in struct ofp_experimenter. - """ - super().__init__(action_type=ActionType.OFPAT_EXPERIMENTER) - self.length = length - self.experimenter = experimenter - - -class ExperimenterStruct(GenericStruct): - """ Typical Experimenter structure. """ - - # Experimenter ID: - # - MSB 0: low-order bytes are IEEE OUI - # - MSB != 0: defined by ONF - experimenter = UBInt32() - # Experimenter defined - exp_type = UBInt32() - - experimenter_data = UBInt8() - - -class ActionGroup(ActionHeader): - """Action structure for OFPAT_GROUP.""" - - # Group identifier. - - group_id = UBInt32() - - _allowed_types = (ActionType.OFPAT_GROUP, ) - - def __init__(self, group_id=None): - """Create an ActionGroup with the optional parameters below. - - Args: - group_id (int): The group_id indicates the group used to process - this packet. The set of buckets to apply depends on the group - type. - """ - super().__init__(action_type=ActionType.OFPAT_GROUP, length=8) - self.group_id = group_id - - -class ActionDecMPLSTTL(ActionHeader): - """Action structure for OFPAT_DEC_MPLS_TTL.""" - - # Pad to 64 bits - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_DEC_MPLS_TTL, ) - - def __init__(self): - """Create an ActionDecMPLSTTL.""" - super().__init__(action_type=ActionType.OFPAT_DEC_MPLS_TTL, length=8) - - -class ActionSetMPLSTTL(ActionHeader): - """Action structure for OFPAT_SET_MPLS_TTL.""" - - # MPLS TTL - mpls_ttl = UBInt8() - # - - pad = Pad(3) - - _allowed_types = (ActionType.OFPAT_SET_MPLS_TTL, ) - - def __init__(self, mpls_ttl=None): - """Create an ActionSetMPLSTTL with the optional parameters below. - - Args: - mpls_ttl (int): The mpls_ttl field is the MPLS TTL to set. - """ - super().__init__(action_type=ActionType.OFPAT_SET_MPLS_TTL, length=8) - self.mpls_ttl = mpls_ttl - - -class ActionCopyTTLIn(ActionHeader): - """Action structure for OFPAT_COPY_TTL_IN.""" - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_COPY_TTL_IN, ) - - def __init__(self): - """Create an ActionCopyTTLIn.""" - super().__init__(action_type=ActionType.OFPAT_COPY_TTL_IN, length=8) - - -class ActionCopyTTLOut(ActionHeader): - """Action structure for OFPAT_COPY_TTL_OUT.""" - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_COPY_TTL_OUT, ) - - def __init__(self): - """Create an ActionCopyTTLOut.""" - super().__init__(action_type=ActionType.OFPAT_COPY_TTL_OUT, length=8) - - -class ActionPopVLAN(ActionHeader): - """Action structure for OFPAT_POP_VLAN.""" - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_POP_VLAN, ) - - def __init__(self): - """Create an ActionPopVLAN.""" - super().__init__(action_type=ActionType.OFPAT_POP_VLAN, length=8) - - -class ActionPopPBB(ActionHeader): - """Action structure for OFPAT_POP_PBB.""" - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_POP_PBB, ) - - def __init__(self): - """Create an ActionPopPBB.""" - super().__init__(action_type=ActionType.OFPAT_POP_PBB, length=8) - - -class ActionDecNWTTL(ActionHeader): - """Action structure for OFPAT_DEC_NW_TTL.""" - - pad = Pad(4) - - _allowed_types = (ActionType.OFPAT_DEC_NW_TTL, ) - - def __init__(self): - """Create a ActionDecNWTTL.""" - super().__init__(action_type=ActionType.OFPAT_DEC_NW_TTL, length=8) - - -class ActionSetNWTTL(ActionHeader): - """Action structure for OFPAT_SET_NW_TTL.""" - - # IP TTL - nw_ttl = UBInt8() - # - - pad = Pad(3) - - _allowed_types = (ActionType.OFPAT_SET_NW_TTL, ) - - def __init__(self, nw_ttl=None): - """Create an ActionSetNWTTL with the optional parameters below. - - Args: - nw_ttl (int): the TTL address to set in the IP header. - """ - super().__init__(action_type=ActionType.OFPAT_SET_NW_TTL, length=8) - self.nw_ttl = nw_ttl - - -class ActionOutput(ActionHeader): - - """ - - Action structure for OFPAT_OUTPUT, which sends packets out ’port’. - When the ’port’ is the OFPP_CONTROLLER, ’max_len’ indicates the max - number of bytes to send. A ’max_len’ of zero means no bytes of the - packet should be sent. A ’max_len’ of OFPCML_NO_BUFFER means that - the packet is not buffered and the complete packet is to be sent to - the controller. - """ - # Extend the ActionHeader. - # Output port. - port = UBInt32() - # Max length to send to controller. - max_length = UBInt16() - # Pad to 64 bits. - - pad = Pad(6) - - _allowed_types = (ActionType.OFPAT_OUTPUT, ) - - def __init__(self, port=None, - max_length=ControllerMaxLen.OFPCML_NO_BUFFER): - """Create a ActionOutput with the optional parameters below. - - Args: - port (:class:`Port` or :class:`int`): Output port. - max_length (int): Max length to send to controller. - """ - super().__init__(action_type=ActionType.OFPAT_OUTPUT, length=16) - self.port = port - self.max_length = max_length - - -class ActionPopMPLS(ActionHeader): - """Action structure for OFPAT_POP_MPLS.""" - - # Ethertype - ethertype = UBInt16() - - pad = Pad(2) - - _allowed_types = (ActionType.OFPAT_POP_MPLS, ) - - def __init__(self, ethertype=None): - """Create an ActionPopMPLS with the optional parameters below. - - Args: - ethertype (int): indicates the Ethertype of the payload. - """ - super().__init__(action_type=ActionType.OFPAT_POP_MPLS) - self.ethertype = ethertype - - -class ActionPush(ActionHeader): - """Action structure for OFPAT_PUSH_[VLAN/MPLS/PBB].""" - - # Ethertype - ethertype = UBInt16() - # - - pad = Pad(2) - - _allowed_types = (ActionType. OFPAT_PUSH_VLAN, ActionType.OFPAT_PUSH_MPLS, - ActionType.OFPAT_PUSH_PBB, ) - - def __init__(self, action_type=None, ethertype=None): - """Create a ActionPush with the optional parameters below. - - Args: - action_type (:class:`ActionType`): indicates which tag will be - pushed (VLAN, MPLS, PBB). - ethertype (int): indicates the Ethertype of the new tag. - """ - super().__init__(action_type, length=8) - self.ethertype = ethertype - - -class ActionSetField(ActionHeader): - """Action structure for OFPAT_SET_FIELD.""" - - # - # - - # OXM TLV - Make compiler happy - - field = OxmTLV() - - _allowed_types = (ActionType.OFPAT_SET_FIELD, ) - - def __init__(self, length=None, field=None): - """Create a ActionSetField with the optional parameters below. - - Args: - length (int): length padded to 64 bits, followed by exactly - oxm_len bytes containing a single OXM TLV, then - exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4) - (between 0 and 7) bytes of all-zero bytes - field (:class:`OxmTLV`): OXM field and value. - """ - super().__init__(action_type=ActionType.OFPAT_SET_FIELD, length=length) - self.field = OxmTLV() if field is None else field - - def pack(self, value=None): - """Pack this structure updating the length and padding it.""" - self._update_length() - packet = super().pack() - return self._complete_last_byte(packet) - - def _update_length(self): - """Update the length field of the struct.""" - action_length = 4 + len(self.field.pack()) - overflow = action_length % 8 - self.length = action_length - if overflow: - self.length = action_length + 8 - overflow - - def _complete_last_byte(self, packet): - """Pad until the packet length is a multiple of 8 (bytes).""" - padded_size = self.length - padding_bytes = padded_size - len(packet) - if padding_bytes > 0: - packet += Pad(padding_bytes).pack() - return packet - - -class ActionSetQueue(ActionHeader): - """Action structure for OFPAT_SET_QUEUE.""" - - # Queue id for packets. - - queue_id = UBInt32() - - _allowed_types = (ActionType.OFPAT_SET_QUEUE, ) - - def __init__(self, queue_id=None): - """Create an ActionSetQueue with the optional parameters below. - - Args: - queue_id (int): The queue_id send packets to given queue on port. - """ - super().__init__(action_type=ActionType.OFPAT_SET_QUEUE, length=8) - self.queue_id = queue_id - - -class ListOfActions(FixedTypeList): - """List of actions. - - Represented by instances of ActionHeader and used on ActionHeader objects. - """ - - def __init__(self, items=None): - """Create a ListOfActions with the optional parameters below. - - Args: - items (~pyof.v0x05.common.action.ActionHeader): - Instance or a list of instances. - """ - super().__init__(pyof_class=ActionHeader, items=items) From c9c2f23a4fe2d7d85ffc06ae1a115fbe183abf0b Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:40:18 -0400 Subject: [PATCH 40/81] Change the name of the class to eliminate the cross-reference error from the scrutinizer. Added OPF at the beginning of the class name. --- pyof/v0x05/common/flow_match.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index a8ae8fb98..0d4bf91ad 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -13,7 +13,7 @@ BinaryData, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) from pyof.foundation.exceptions import PackException, UnpackException -__all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'Match', 'MatchType', +__all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'OPFMatch', 'MatchType', 'OxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', 'OxmOfbMatchField', 'OxmTLV', 'VlanId') @@ -320,7 +320,7 @@ def __init__(self, items=None): super().__init__(pyof_class=OxmTLV, items=items) -class Match(GenericStruct): +class OPFMatch(GenericStruct): """Describes the flow match header structure. These are the fields to match against flows. @@ -366,7 +366,7 @@ def _update_match_length(self): def pack(self, value=None): """Pack and complete the last byte by padding.""" - if isinstance(value, Match): + if isinstance(value, OPFMatch): return value.pack() elif value is None: self._update_match_length() @@ -384,7 +384,7 @@ def _complete_last_byte(self, packet): def get_size(self, value=None): """Return the packet length including the padding (multiple of 8).""" - if isinstance(value, Match): + if isinstance(value, OPFMatch): return value.get_size() elif value is None: current_size = super().get_size() From 636d3cfc588e0295cf6dc27c7847a800a1e0ca20 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:42:39 -0400 Subject: [PATCH 41/81] Change the name of the class to eliminate the cross-reference error from the scrutinizer. Added OPF at the beginning of the class name. --- pyof/v0x05/common/flow_match.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index 0d4bf91ad..09565dda2 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -13,7 +13,7 @@ BinaryData, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) from pyof.foundation.exceptions import PackException, UnpackException -__all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'OPFMatch', 'MatchType', +__all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'OPFMatch', 'OPFMatchType', 'OxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', 'OxmOfbMatchField', 'OxmTLV', 'VlanId') @@ -135,7 +135,7 @@ class OxmOfbMatchField(IntEnum): OFPXMT_OFB_PBB_UCA = 41 -class MatchType(IntEnum): +class OPFMatchType(IntEnum): """Indicates the match structure in use. The match type is placed in the type field at the beginning of all match @@ -334,7 +334,7 @@ class OPFMatch(GenericStruct): """ # One of OFPMT_* - match_type = UBInt16(enum_ref=MatchType) + match_type = UBInt16(enum_ref=OPFMatchType) # Length of Match (excluding padding) length = UBInt16() # 0 or more OXM match fields. @@ -342,7 +342,7 @@ class OPFMatch(GenericStruct): # Zero bytes - see above for sizing pad = Pad(4) - def __init__(self, match_type=MatchType.OFPMT_OXM, length=None, oxm_match_fields=None): + def __init__(self, match_type=OPFMatchType.OFPMT_OXM, length=None, oxm_match_fields=None): """Describe the flow match header structure. Args: From 80f1294e38543bd2867fbd39d141f2b8aa1972e4 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:50:23 -0400 Subject: [PATCH 42/81] Change the name of the class to eliminate the cross-reference error from the scrutinizer. Added OPF at the beginning of the class name. --- pyof/v0x05/common/flow_match.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index 09565dda2..df8a7161d 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -14,8 +14,8 @@ from pyof.foundation.exceptions import PackException, UnpackException __all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'OPFMatch', 'OPFMatchType', - 'OxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', - 'OxmOfbMatchField', 'OxmTLV', 'VlanId') + 'OPFOxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', + 'OPFOxmOfbMatchField', 'OxmTLV', 'VlanId') class Ipv6ExtHdrFlags(GenericBitMask): @@ -41,7 +41,7 @@ class Ipv6ExtHdrFlags(GenericBitMask): OFPIEH_UNSEQ = 1 << 8 -class OxmOfbMatchField(IntEnum): +class OPFOxmOfbMatchField(IntEnum): """OXM Flow match field types for OpenFlow basic class. A switch is not required to support all match field types, just those @@ -151,7 +151,7 @@ class OPFMatchType(IntEnum): OFPMT_OXM = 1 -class OxmClass(IntEnum): +class OPFOxmClass(IntEnum): """OpenFlow Extensible Match (OXM) Class IDs. The high order bit differentiate reserved classes from member classes. @@ -188,12 +188,12 @@ class VlanId(IntEnum): class OxmTLV(GenericStruct): """Oxm (OpenFlow Extensible Match) TLV.""" - oxm_class = UBInt16(enum_ref=OxmClass) + oxm_class = UBInt16(enum_ref=OPFOxmClass) oxm_field_and_mask = UBInt8() oxm_length = UBInt8() oxm_value = BinaryData() - def __init__(self, oxm_class=OxmClass.OFPXMC_OPENFLOW_BASIC, + def __init__(self, oxm_class=OPFOxmClass.OFPXMC_OPENFLOW_BASIC, oxm_field=None, oxm_hasmask=False, oxm_value=None): """Create an OXM TLV struct with the optional parameters below. @@ -250,8 +250,8 @@ def _unpack_oxm_field(self): """ field_int = self.oxm_field_and_mask >> 1 # We know that the class below requires a subset of the ofb enum - if self.oxm_class == OxmClass.OFPXMC_OPENFLOW_BASIC: - return OxmOfbMatchField(field_int) + if self.oxm_class == OPFOxmClass.OFPXMC_OPENFLOW_BASIC: + return OPFOxmOfbMatchField(field_int) return field_int def _update_length(self): @@ -297,8 +297,8 @@ def _get_oxm_field_int(self): value. """ - if self.oxm_class == OxmClass.OFPXMC_OPENFLOW_BASIC: - return OxmOfbMatchField(self.oxm_field).value + if self.oxm_class == OPFOxmClass.OFPXMC_OPENFLOW_BASIC: + return OPFOxmOfbMatchField(self.oxm_field).value elif not isinstance(self.oxm_field, int) or self.oxm_field > 127: raise ValueError('oxm_field above 127: "{self.oxm_field}".') return self.oxm_field @@ -427,8 +427,8 @@ class OxmExperimenterHeader(GenericStruct): """Header for OXM experimenter match fields.""" #: oxm_class = OFPXMC_EXPERIMENTER - oxm_header = UBInt32(OxmClass.OFPXMC_EXPERIMENTER, - enum_ref=OxmClass) + oxm_header = UBInt32(OPFOxmClass.OFPXMC_EXPERIMENTER, + enum_ref=OPFOxmClass) #: Experimenter ID which takes the same form as in struct #: ofp_experimenter_header experimenter = UBInt32() From 78f0043ad23ec409168deb1f51a6646568f4b95c Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:53:20 -0400 Subject: [PATCH 43/81] Change the name of the class to eliminate the cross-reference error from the scrutinizer. Added OPF at the beginning of the class name. --- pyof/v0x05/common/flow_match.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index df8a7161d..4b4c789d9 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -14,8 +14,8 @@ from pyof.foundation.exceptions import PackException, UnpackException __all__ = ('Ipv6ExtHdrFlags', 'ListOfOxmHeader', 'OPFMatch', 'OPFMatchType', - 'OPFOxmClass', 'OxmExperimenterHeader', 'OxmMatchFields', - 'OPFOxmOfbMatchField', 'OxmTLV', 'VlanId') + 'OPFOxmClass', 'OxmExperimenterHeader', 'OPFOxmMatchFields', + 'OPFOxmOfbMatchField', 'OPFOxmTLV', 'VlanId') class Ipv6ExtHdrFlags(GenericBitMask): @@ -185,7 +185,7 @@ class VlanId(IntEnum): # Classes -class OxmTLV(GenericStruct): +class OPFOxmTLV(GenericStruct): """Oxm (OpenFlow Extensible Match) TLV.""" oxm_class = UBInt16(enum_ref=OPFOxmClass) @@ -304,7 +304,7 @@ def _get_oxm_field_int(self): return self.oxm_field -class OxmMatchFields(FixedTypeList): +class OPFOxmMatchFields(FixedTypeList): """Generic Openflow EXtensible Match header. Abstract class that can be instantiated as Match or OxmExperimenterHeader. @@ -317,7 +317,7 @@ def __init__(self, items=None): Args: items (OxmHeader): Instance or a list of instances. """ - super().__init__(pyof_class=OxmTLV, items=items) + super().__init__(pyof_class=OPFOxmTLV, items=items) class OPFMatch(GenericStruct): @@ -338,7 +338,7 @@ class OPFMatch(GenericStruct): # Length of Match (excluding padding) length = UBInt16() # 0 or more OXM match fields. - oxm_match_fields = OxmMatchFields() + oxm_match_fields = OPFOxmMatchFields() # Zero bytes - see above for sizing pad = Pad(4) @@ -357,7 +357,7 @@ def __init__(self, match_type=OPFMatchType.OFPMT_OXM, length=None, oxm_match_fie super().__init__() self.match_type = match_type self.length = length - self.oxm_match_fields = oxm_match_fields or OxmMatchFields() + self.oxm_match_fields = oxm_match_fields or OPFOxmMatchFields() self._update_match_length() def _update_match_length(self): @@ -459,4 +459,4 @@ def __init__(self, items=None): items (OxmHeader): Instance or a list of instances. """ - super().__init__(pyof_class=OxmTLV, items=items) + super().__init__(pyof_class=OPFOxmTLV, items=items) From 9536b2a63bde92b35c6cd15d6840400b81df66e2 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:56:59 -0400 Subject: [PATCH 44/81] Create a new line for the parameter list that violate the length of the line. --- pyof/v0x05/common/flow_match.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index 4b4c789d9..b8c3c0bb8 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -342,7 +342,8 @@ class OPFMatch(GenericStruct): # Zero bytes - see above for sizing pad = Pad(4) - def __init__(self, match_type=OPFMatchType.OFPMT_OXM, length=None, oxm_match_fields=None): + def __init__(self, match_type=OPFMatchType.OFPMT_OXM, + length=None, oxm_match_fields=None): """Describe the flow match header structure. Args: @@ -398,8 +399,10 @@ def unpack(self, buff, offset=0): for name, value in list(self.get_class_attributes())[:-1]: size = self._unpack_attribute(name, value, buff, begin) begin += size - self._unpack_attribute('oxm_match_fields', type(self).oxm_match_fields, - buff[:offset+self.length - len(Pad(4))], begin - size) + self._unpack_attribute('oxm_match_fields', + type(self).oxm_match_fields, + buff[:offset+self.length - len(Pad(4))], + begin - size) def get_field(self, field_type): """Return the value for the 'field_type' field in oxm_match_fields. From 339b8a857ea037602ac1c5fa57b027621799993e Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 14:58:11 -0400 Subject: [PATCH 45/81] Fix the import sorted issue. --- pyof/v0x05/common/flow_match.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyof/v0x05/common/flow_match.py b/pyof/v0x05/common/flow_match.py index b8c3c0bb8..36472b5bc 100644 --- a/pyof/v0x05/common/flow_match.py +++ b/pyof/v0x05/common/flow_match.py @@ -8,7 +8,7 @@ from math import ceil # Local source tree imports -from pyof.foundation.base import GenericStruct, GenericBitMask +from pyof.foundation.base import GenericBitMask, GenericStruct from pyof.foundation.basic_types import ( BinaryData, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) from pyof.foundation.exceptions import PackException, UnpackException From 3fc0d15f2a9e0d2f24d62d7a7b152e422e4f73a6 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 15:23:20 -0400 Subject: [PATCH 46/81] Change the name of the classes to prevent the error cross reference with the previos version and fix some indentation and documentation and line length limits. --- pyof/v0x05/common/action.py | 474 ++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) create mode 100644 pyof/v0x05/common/action.py diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py new file mode 100644 index 000000000..98ab98c99 --- /dev/null +++ b/pyof/v0x05/common/action.py @@ -0,0 +1,474 @@ +"""Defines actions that may be associated with flows packets.""" +# System imports +from enum import IntEnum +from math import ceil + +# Local source tree imports +from pyof.foundation.base import GenericStruct +from pyof.foundation.basic_types import ( + FixedTypeList, Pad, UBInt8, UBInt16, UBInt32) +from pyof.v0x05.common.flow_match import OPFOxmTLV + +# Third-party imports + +__all__ = ('OPFActionExperimenterHeader', 'OPFActionGroup', 'OPFActionHeader', + 'OPFActionCopyTTLIn', 'OPFActionCopyTTLOut', 'OPFActionDecMPLSTTL', + 'OPFActionSetMPLSTTL', 'OPFActionDecNWTTL', 'OPFActionSetNWTTL', + 'OPFActionOutput', 'OPFActionPopMPLS', 'OPFActionPopPBB', + 'OPFActionPopVLAN', 'OPFActionPush', 'OPFActionSetField', + 'OPFActionSetQueue', 'OPFActionType', 'ControllerMaxLen', + 'ListOfActions') + +# Enums + + +class OPFActionType(IntEnum): + """Actions associated with flows and packets.""" + + #: Output to switch port. + OFPAT_OUTPUT = 0 + #: Copy TTL "outwards" -- from next-to-outermost to outermost + OFPAT_COPY_TTL_OUT = 11 + #: Copy TTL "inwards" -- from outermost to next-to-outermost + OFPAT_COPY_TTL_IN = 12 + #: MPLS TTL + OFPAT_SET_MPLS_TTL = 15 + #: Decrement MPLS TTL + OFPAT_DEC_MPLS_TTL = 16 + #: Push a new VLAN tag + OFPAT_PUSH_VLAN = 17 + #: Pop the outer VLAN tag + OFPAT_POP_VLAN = 18 + #: Push a new MPLS tag + OFPAT_PUSH_MPLS = 19 + #: Pop the outer MPLS tag + OFPAT_POP_MPLS = 20 + #: Set queue id when outputting to a port + OFPAT_SET_QUEUE = 21 + #: Apply group. + OFPAT_GROUP = 22 + #: IP TTL. + OFPAT_SET_NW_TTL = 23 + #: Decrement IP TTL. + OFPAT_DEC_NW_TTL = 24 + #: Set a header field using OXM TLV format. + OFPAT_SET_FIELD = 25 + #: Push a new PBB service tag (I-TAG) + OFPAT_PUSH_PBB = 26 + #: Pop the outer PBB service tag (I-TAG) + OFPAT_POP_PBB = 27 + #: Experimenter type + OFPAT_EXPERIMENTER = 0xffff + + +class ControllerMaxLen(IntEnum): + """A max_len of OFPCML_NO_BUFFER means not to buffer. + + The packet should be sent. + """ + + #: maximum max_len value which can be used to request a specific byte + #: length. + OFPCML_MAX = 0xffe5 + #: indicates that no buffering should be applied and the whole packet is to + #: be sent to the controller. + OFPCML_NO_BUFFER = 0xffff + + +# Classes + + +class OPFActionHeader(GenericStruct): + """Action header that is common to all actions. + + The length includes the header and any padding used to make the action + 64-bit aligned. + NB: The length of an action *must* always be a multiple of eight. + """ + + #: One of OFPAT_*. + + action_type = UBInt16(enum_ref=OPFActionType) + #: Length of action, including this header. This is the length of actions, + #: including any padding to make it 64-bit aligned. + length = UBInt16() + + _allowed_types = () + + def __init__(self, action_type=None, length=None): + """Create an ActionHeader with the optional parameters below. + + Args: + action_type (~pyof.v0x05.common.action.ActionType): + The type of the action. + length (int): Length of action, including this header. + """ + super().__init__() + self.action_type = action_type + self.length = length + + def get_size(self, value=None): + """Return the action length including the padding (multiple of 8).""" + if isinstance(value, OPFActionHeader): + return value.get_size() + elif value is None: + current_size = super().get_size() + return ceil(current_size / 8) * 8 + raise ValueError(f'Invalid value "{value}" for Action*.get_size()') + + def unpack(self, buff, offset=0): + """Unpack a binary message into this object's attributes. + + Unpack the binary value *buff* and update this object attributes based + on the results. + + Args: + buff (bytes): Binary data package to be unpacked. + offset (int): Where to begin unpacking. + + Raises: + Exception: If there is a struct unpacking error. + + """ + self.action_type = UBInt16(enum_ref=OPFActionType) + self.action_type.unpack(buff, offset) + + for cls in OPFActionHeader.__subclasses__(): + if self.action_type.value in cls.get_allowed_types(): + self.__class__ = cls + break + + super().unpack(buff, offset) + + @classmethod + def get_allowed_types(cls): + """Return allowed types for the class.""" + return cls._allowed_types + + +class OPFActionExperimenterHeader(OPFActionHeader): + """Action structure for OFPAT_EXPERIMENTER.""" + + # Experimenter ID + experimenter = UBInt32() + + _allowed_types = (OPFActionType.OFPAT_EXPERIMENTER, ) + + def __init__(self, length=None, experimenter=None): + """Create ActionExperimenterHeader with the optional parameters below. + + Args: + experimenter (int): The experimenter field is the Experimenter ID, + which takes the same form as in struct ofp_experimenter. + """ + super().__init__(action_type=OPFActionType.OFPAT_EXPERIMENTER) + self.length = length + self.experimenter = experimenter + + +class OPFExperimenterStruct(GenericStruct): + """ Typical Experimenter structure. """ + + # Experimenter ID: + # - MSB 0: low-order bytes are IEEE OUI + # - MSB != 0: defined by ONF + experimenter = UBInt32() + # Experimenter defined + exp_type = UBInt32() + + experimenter_data = UBInt8() + + +class OPFActionGroup(OPFActionHeader): + """Action structure for OFPAT_GROUP.""" + + # Group identifier. + + group_id = UBInt32() + + _allowed_types = (OPFActionType.OFPAT_GROUP, ) + + def __init__(self, group_id=None): + """Create an ActionGroup with the optional parameters below. + + Args: + group_id (int): The group_id indicates the group used to process + this packet. The set of buckets to apply depends on the group + type. + """ + super().__init__(action_type=OPFActionType.OFPAT_GROUP, length=8) + self.group_id = group_id + + +class OPFActionDecMPLSTTL(OPFActionHeader): + """Action structure for OFPAT_DEC_MPLS_TTL.""" + + # Pad to 64 bits + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_DEC_MPLS_TTL, ) + + def __init__(self): + """Create an ActionDecMPLSTTL.""" + super().__init__(action_type=OPFActionType.OFPAT_DEC_MPLS_TTL, length=8) + + +class OPFActionSetMPLSTTL(OPFActionHeader): + """Action structure for OFPAT_SET_MPLS_TTL.""" + + # MPLS TTL + mpls_ttl = UBInt8() + + pad = Pad(3) + + _allowed_types = (OPFActionType.OFPAT_SET_MPLS_TTL, ) + + def __init__(self, mpls_ttl=None): + """Create an ActionSetMPLSTTL with the optional parameters below. + + Args: + mpls_ttl (int): The mpls_ttl field is the MPLS TTL to set. + """ + super().__init__(action_type=OPFActionType.OFPAT_SET_MPLS_TTL, length=8) + self.mpls_ttl = mpls_ttl + + +class OPFActionCopyTTLIn(OPFActionHeader): + """Action structure for OFPAT_COPY_TTL_IN.""" + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_COPY_TTL_IN, ) + + def __init__(self): + """Create an ActionCopyTTLIn.""" + super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_IN, length=8) + + +class OPFActionCopyTTLOut(OPFActionHeader): + """Action structure for OFPAT_COPY_TTL_OUT.""" + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_COPY_TTL_OUT, ) + + def __init__(self): + """Create an ActionCopyTTLOut.""" + super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_OUT, length=8) + + +class OPFActionPopVLAN(OPFActionHeader): + """Action structure for OFPAT_POP_VLAN.""" + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_POP_VLAN, ) + + def __init__(self): + """Create an ActionPopVLAN.""" + super().__init__(action_type=OPFActionType.OFPAT_POP_VLAN, length=8) + + +class OPFActionPopPBB(OPFActionHeader): + """Action structure for OFPAT_POP_PBB.""" + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_POP_PBB, ) + + def __init__(self): + """Create an ActionPopPBB.""" + super().__init__(action_type=OPFActionType.OFPAT_POP_PBB, length=8) + + +class OPFActionDecNWTTL(OPFActionHeader): + """Action structure for OFPAT_DEC_NW_TTL.""" + + pad = Pad(4) + + _allowed_types = (OPFActionType.OFPAT_DEC_NW_TTL, ) + + def __init__(self): + """Create a ActionDecNWTTL.""" + super().__init__(action_type=OPFActionType.OFPAT_DEC_NW_TTL, length=8) + + +class OPFActionSetNWTTL(OPFActionHeader): + """Action structure for OFPAT_SET_NW_TTL.""" + + # IP TTL + nw_ttl = UBInt8() + + pad = Pad(3) + + _allowed_types = (OPFActionType.OFPAT_SET_NW_TTL, ) + + def __init__(self, nw_ttl=None): + """Create an ActionSetNWTTL with the optional parameters below. + + Args: + nw_ttl (int): the TTL address to set in the IP header. + """ + super().__init__(action_type=OPFActionType.OFPAT_SET_NW_TTL, length=8) + self.nw_ttl = nw_ttl + + +class OPFActionOutput(OPFActionHeader): + """Action structure for OFPAT_OUTPUT. + + When the ’port’ is the OFPP_CONTROLLER, ’max_len’ indicates the max + number of bytes to send. A ’max_len’ of zero means no bytes of the + packet should be sent. A ’max_len’ of OFPCML_NO_BUFFER means that + the packet is not buffered and the complete packet is to be sent to + the controller. + """ + # Extend the ActionHeader. + # Output port. + port = UBInt32() + # Max length to send to controller. + max_length = UBInt16() + # Pad to 64 bits. + + pad = Pad(6) + + _allowed_types = (OPFActionType.OFPAT_OUTPUT, ) + + def __init__(self, port=None, + max_length=ControllerMaxLen.OFPCML_NO_BUFFER): + """Create a ActionOutput with the optional parameters below. + + Args: + port (:class:`Port` or :class:`int`): Output port. + max_length (int): Max length to send to controller. + """ + super().__init__(action_type=OPFActionType.OFPAT_OUTPUT, length=16) + self.port = port + self.max_length = max_length + + +class OPFActionPopMPLS(OPFActionHeader): + """Action structure for OFPAT_POP_MPLS.""" + + # Ethertype + ethertype = UBInt16() + + pad = Pad(2) + + _allowed_types = (OPFActionType.OFPAT_POP_MPLS, ) + + def __init__(self, ethertype=None): + """Create an ActionPopMPLS with the optional parameters below. + + Args: + ethertype (int): indicates the Ethertype of the payload. + """ + super().__init__(action_type=OPFActionType.OFPAT_POP_MPLS) + self.ethertype = ethertype + + +class OPFActionPush(OPFActionHeader): + """Action structure for OFPAT_PUSH_[VLAN/MPLS/PBB].""" + + # Ethertype + ethertype = UBInt16() + # + + pad = Pad(2) + + _allowed_types = (OPFActionType. OFPAT_PUSH_VLAN, OPFActionType.OFPAT_PUSH_MPLS, + OPFActionType.OFPAT_PUSH_PBB, ) + + def __init__(self, action_type=None, ethertype=None): + """Create a ActionPush with the optional parameters below. + + Args: + action_type (:class:`ActionType`): indicates which tag will be + pushed (VLAN, MPLS, PBB). + ethertype (int): indicates the Ethertype of the new tag. + """ + super().__init__(action_type, length=8) + self.ethertype = ethertype + + +class OPFActionSetField(OPFActionHeader): + """Action structure for OFPAT_SET_FIELD.""" + + # + # + + # OXM TLV - Make compiler happy + + field = OPFOxmTLV() + + _allowed_types = (OPFActionType.OFPAT_SET_FIELD, ) + + def __init__(self, length=None, field=None): + """Create a ActionSetField with the optional parameters below. + + Args: + length (int): length padded to 64 bits, followed by exactly + oxm_len bytes containing a single OXM TLV, then + exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4) + (between 0 and 7) bytes of all-zero bytes + field (:class:`OxmTLV`): OXM field and value. + """ + super().__init__(action_type=OPFActionType.OFPAT_SET_FIELD, length=length) + self.field = OPFOxmTLV() if field is None else field + + def pack(self, value=None): + """Pack this structure updating the length and padding it.""" + self._update_length() + packet = super().pack() + return self._complete_last_byte(packet) + + def _update_length(self): + """Update the length field of the struct.""" + action_length = 4 + len(self.field.pack()) + overflow = action_length % 8 + self.length = action_length + if overflow: + self.length = action_length + 8 - overflow + + def _complete_last_byte(self, packet): + """Pad until the packet length is a multiple of 8 (bytes).""" + padded_size = self.length + padding_bytes = padded_size - len(packet) + if padding_bytes > 0: + packet += Pad(padding_bytes).pack() + return packet + + +class OPFActionSetQueue(OPFActionHeader): + """Action structure for OFPAT_SET_QUEUE.""" + + # Queue id for packets. + + queue_id = UBInt32() + + _allowed_types = (OPFActionType.OFPAT_SET_QUEUE, ) + + def __init__(self, queue_id=None): + """Create an ActionSetQueue with the optional parameters below. + + Args: + queue_id (int): The queue_id send packets to given queue on port. + """ + super().__init__(action_type=OPFActionType.OFPAT_SET_QUEUE, length=8) + self.queue_id = queue_id + + +class ListOfActions(FixedTypeList): + """List of actions. + + Represented by instances of ActionHeader and used on ActionHeader objects. + """ + + def __init__(self, items=None): + """Create a ListOfActions with the optional parameters below. + + Args: + items (~pyof.v0x05.common.action.ActionHeader): + Instance or a list of instances. + """ + super().__init__(pyof_class=OPFActionHeader, items=items) From 7c5e2ec27a1780cca95fe7e74bd4798fea780fa1 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 15:33:43 -0400 Subject: [PATCH 47/81] Change some spaces in the comments to fix the indentation of the comments. --- pyof/v0x05/common/action.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py index 98ab98c99..a99d90682 100644 --- a/pyof/v0x05/common/action.py +++ b/pyof/v0x05/common/action.py @@ -67,11 +67,11 @@ class ControllerMaxLen(IntEnum): The packet should be sent. """ - #: maximum max_len value which can be used to request a specific byte - #: length. + #: Maximum max_len value which can be used to request a specific byte + #: length. OFPCML_MAX = 0xffe5 - #: indicates that no buffering should be applied and the whole packet is to - #: be sent to the controller. + #: indicates that no buffering should be applied and the whole packet is + #: to be sent to the controller. OFPCML_NO_BUFFER = 0xffff @@ -90,7 +90,7 @@ class OPFActionHeader(GenericStruct): action_type = UBInt16(enum_ref=OPFActionType) #: Length of action, including this header. This is the length of actions, - #: including any padding to make it 64-bit aligned. + #: including any padding to make it 64-bit aligned. length = UBInt16() _allowed_types = () @@ -159,7 +159,7 @@ def __init__(self, length=None, experimenter=None): Args: experimenter (int): The experimenter field is the Experimenter ID, - which takes the same form as in struct ofp_experimenter. + which takes the same form as in struct ofp_experimenter. """ super().__init__(action_type=OPFActionType.OFPAT_EXPERIMENTER) self.length = length @@ -372,11 +372,11 @@ class OPFActionPush(OPFActionHeader): # Ethertype ethertype = UBInt16() - # pad = Pad(2) - _allowed_types = (OPFActionType. OFPAT_PUSH_VLAN, OPFActionType.OFPAT_PUSH_MPLS, + _allowed_types = (OPFActionType. OFPAT_PUSH_VLAN, + OPFActionType.OFPAT_PUSH_MPLS, OPFActionType.OFPAT_PUSH_PBB, ) def __init__(self, action_type=None, ethertype=None): From 052c28ce6376318e68f0d14ffb156f8f28b6c6a9 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 15:45:41 -0400 Subject: [PATCH 48/81] Fix the spaces, indentation problems encounter by the Scrutinizer. --- pyof/v0x05/common/action.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py index a99d90682..664c691ef 100644 --- a/pyof/v0x05/common/action.py +++ b/pyof/v0x05/common/action.py @@ -167,7 +167,7 @@ def __init__(self, length=None, experimenter=None): class OPFExperimenterStruct(GenericStruct): - """ Typical Experimenter structure. """ + """Typical Experimenter structure. """ # Experimenter ID: # - MSB 0: low-order bytes are IEEE OUI @@ -211,7 +211,8 @@ class OPFActionDecMPLSTTL(OPFActionHeader): def __init__(self): """Create an ActionDecMPLSTTL.""" - super().__init__(action_type=OPFActionType.OFPAT_DEC_MPLS_TTL, length=8) + super().__init__(action_type=OPFActionType.OFPAT_DEC_MPLS_TTL, + length=8) class OPFActionSetMPLSTTL(OPFActionHeader): @@ -230,7 +231,8 @@ def __init__(self, mpls_ttl=None): Args: mpls_ttl (int): The mpls_ttl field is the MPLS TTL to set. """ - super().__init__(action_type=OPFActionType.OFPAT_SET_MPLS_TTL, length=8) + super().__init__(action_type=OPFActionType.OFPAT_SET_MPLS_TTL, + length=8) self.mpls_ttl = mpls_ttl @@ -243,7 +245,8 @@ class OPFActionCopyTTLIn(OPFActionHeader): def __init__(self): """Create an ActionCopyTTLIn.""" - super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_IN, length=8) + super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_IN, + length=8) class OPFActionCopyTTLOut(OPFActionHeader): @@ -255,7 +258,8 @@ class OPFActionCopyTTLOut(OPFActionHeader): def __init__(self): """Create an ActionCopyTTLOut.""" - super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_OUT, length=8) + super().__init__(action_type=OPFActionType.OFPAT_COPY_TTL_OUT, + length=8) class OPFActionPopVLAN(OPFActionHeader): @@ -309,6 +313,7 @@ def __init__(self, nw_ttl=None): Args: nw_ttl (int): the TTL address to set in the IP header. + """ super().__init__(action_type=OPFActionType.OFPAT_SET_NW_TTL, length=8) self.nw_ttl = nw_ttl @@ -413,7 +418,8 @@ def __init__(self, length=None, field=None): (between 0 and 7) bytes of all-zero bytes field (:class:`OxmTLV`): OXM field and value. """ - super().__init__(action_type=OPFActionType.OFPAT_SET_FIELD, length=length) + super().__init__(action_type=OPFActionType.OFPAT_SET_FIELD, + length=length) self.field = OPFOxmTLV() if field is None else field def pack(self, value=None): From dfee85cac30277378c6424a7c52fb977c6d3a3b3 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 15:50:02 -0400 Subject: [PATCH 49/81] Fix the spaces problems encounter by the Scrutinizer. --- pyof/v0x05/common/action.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py index 664c691ef..3d641f15e 100644 --- a/pyof/v0x05/common/action.py +++ b/pyof/v0x05/common/action.py @@ -167,7 +167,8 @@ def __init__(self, length=None, experimenter=None): class OPFExperimenterStruct(GenericStruct): - """Typical Experimenter structure. """ + """Typical Experimenter structure. + """ # Experimenter ID: # - MSB 0: low-order bytes are IEEE OUI From 693b970caf7eec056e93cd2df0e4c81f45052118 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 15:53:25 -0400 Subject: [PATCH 50/81] Fix the spaces problems encounter by the Scrutinizer. --- pyof/v0x05/common/action.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/common/action.py b/pyof/v0x05/common/action.py index 3d641f15e..83fc34f03 100644 --- a/pyof/v0x05/common/action.py +++ b/pyof/v0x05/common/action.py @@ -167,8 +167,7 @@ def __init__(self, length=None, experimenter=None): class OPFExperimenterStruct(GenericStruct): - """Typical Experimenter structure. - """ + """Typical Experimenter structure.""" # Experimenter ID: # - MSB 0: low-order bytes are IEEE OUI @@ -328,7 +327,9 @@ class OPFActionOutput(OPFActionHeader): packet should be sent. A ’max_len’ of OFPCML_NO_BUFFER means that the packet is not buffered and the complete packet is to be sent to the controller. + """ + # Extend the ActionHeader. # Output port. port = UBInt32() From 7e7d4a705ab924ca0327c612707f1d72f7e35e93 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 16:33:55 -0400 Subject: [PATCH 51/81] Submitting the port feature from Open Flow Version 1.4.1 Specification under the common port section. --- pyof/v0x05/common/port.py | 426 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 426 insertions(+) create mode 100644 pyof/v0x05/common/port.py diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py new file mode 100644 index 000000000..480cf7689 --- /dev/null +++ b/pyof/v0x05/common/port.py @@ -0,0 +1,426 @@ +"""Defines physical port classes and related items.""" + +# System imports +from enum import IntEnum + +# Local source tree imports +from pyof.foundation.base import GenericBitMask, GenericStruct +from pyof.foundation.basic_types import (Char, FixedTypeList, HWAddress, + Pad, UBInt16, UBInt32) +from pyof.foundation.constants import OFP_MAX_PORT_NAME_LEN + + +# Third-party imports + +__all__ = ('ListOfPorts', 'ListOfPortDescProperties', 'Port', 'PortConfig', + 'PortFeatures', 'PortNo', 'PortState') + + +class PortNo(IntEnum): + """Port numbering. + + Ports are numbered starting from 1. + """ + + #: Maximum number of physical and logical switch ports. + OFPP_MAX = 0xffffff00 + # Reserved OpenFlow port (fake output "ports") + #: Send the packet out the input port. This reserved port must be + #: explicitly used in order to send back out of the input port. + OFPP_IN_PORT = 0xfffffff8 + #: Submit the packet to the first flow table + #: NB: This destination port can only be used in packet-out messages. + OFPP_TABLE = 0xfffffff9 + #: Process with normal L2/L3 switching. + OFPP_NORMAL = 0xfffffffa + #: All physical ports in VLAN, except input port and thos blocked or link + #: down. + OFPP_FLOOD = 0xfffffffb + #: All physical ports except input port + OFPP_ALL = 0xfffffffc + #: Send to controller + OFPP_CONTROLLER = 0xfffffffd + #: Local openflow "port" + OFPP_LOCAL = 0xfffffffe + #: Wildcard port used only for flow mod (delete) and flow stats requests. + #: Selects all flows regardless of output port (including flows with no + #: output port). + OFPP_ANY = 0xffffffff + + +class PortDescPropType(IntEnum): + """Port description property types.""" + + # Ethernet property + OFPPDPT_ETHERNET = 0 + # Optical property + OFPPDPT_OPTICAL = 1 + # Experimenter property + OFPPDPT_EXPERIMENTER = 0xfff + + +class OpticalPortFeatures(GenericBitMask): + """Features of optical ports available in switch.""" + + # Receiver is tunable. + OFPOPF_RX_TUNE = 1 << 0 + # Transmit is tunable. + OFPOPF_TX_TUNE = 1 << 1 + # Power is configurable. + OFPOPF_TX_PWR = 1 << 2 + # Use Frequency, not wavelength + OFPOPF_USE_FREQ = 1 << 3 + + +class PortConfig(GenericBitMask): + """Flags to indicate behavior of the physical port. + + These flags are used in :class:`Port` to describe the current + configuration. They are used in the + :class:`~pyof.v0x05.controller2switch.port_mod.PortMod` + message to configure the port's behavior. + + The :attr:`OFPPC_PORT_DOWN` bit indicates that the port has been + administratively brought down and should not be used by OpenFlow. The + :attr:`~OFPPC_NO_RECV` bit indicates that packets received on that port + should be ignored. The :attr:`OFPPC_NO_FWD` bit indicates that OpenFlow + should not send packets to that port. The :attr:`OFPPC_NO_PACKET_IN` bit + indicates that packets on that port that generate a table miss should never + trigger a packet-in message to the controller. + + In general, the port config bits are set by the controller and not changed + by the switch. Those bits may be useful for the controller to implement + protocols such as STP or BFD. If the port config bits are changed by the + switch through another administrative interface, the switch sends an + :attr:`OFPT_PORT_STATUS` message to notify the controller of the change. + """ + + #: Port is administratively down. + OFPPC_PORT_DOWN = 1 << 0 + #: Drop all packets received by port. + OFPPC_NO_RECV = 1 << 2 + #: Drop packets forwarded to port. + OFPPC_NO_FWD = 1 << 5 + #: Do not send packet-in msgs for port. + OFPPC_NO_PACKET_IN = 1 << 6 + + +class PortFeatures(GenericBitMask): + """Physical ports features. + + The curr, advertised, supported, and peer fields indicate link modes + (speed and duplexity), link type (copper/fiber) and link features + (autonegotiation and pause). + + Multiple of these flags may be set simultaneously. If none of the port + speed flags are set, the max_speed or curr_speed are used. + + The curr_speed and max_speed fields indicate the current and maximum bit + rate (raw transmission speed) of the link in kbps. The number should be + rounded to match common usage. For example, an optical 10 Gb Ethernet port + should have this field set to 10000000 (instead of 10312500), and an OC-192 + port should have this field set to 10000000 (instead of 9953280). + + The max_speed fields indicate the maximum configured capacity of the link, + whereas the curr_speed indicates the current capacity. If the port is a LAG + with 3 links of 1Gb/s capacity, with one of the ports of the LAG being + down, one port auto-negotiated at 1Gb/s and 1 port auto-negotiated at + 100Mb/s, the max_speed is 3 Gb/s and the curr_speed is 1.1 Gb/s. + """ + + #: 10 Mb half-duplex rate support. + OFPPF_10MB_HD = 1 << 0 + #: 10 Mb full-duplex rate support. + OFPPF_10MB_FD = 1 << 1 + #: 100 Mb half-duplex rate support. + OFPPF_100MB_HD = 1 << 2 + #: 100 Mb full-duplex rate support. + OFPPF_100MB_FD = 1 << 3 + #: 1 Gb half-duplex rate support. + OFPPF_1GB_HD = 1 << 4 + #: 1 Gb full-duplex rate support. + OFPPF_1GB_FD = 1 << 5 + #: 10 Gb full-duplex rate support. + OFPPF_10GB_FD = 1 << 6 + #: 40 Gb full-duplex rate support. + OFPPF_40GB_FD = 1 << 7 + #: 100 Gb full-duplex rate support. + OFPPF_100GB_FD = 1 << 8 + #: 1 Tb full-duplex rate support. + OFPPF_1TB_FD = 1 << 9 + #: Other rate, not in the list + OFPPF_OTHER = 1 << 10 + + #: Copper medium. + OFPPF_COPPER = 1 << 11 + #: Fiber medium. + OFPPF_FIBER = 1 << 12 + #: Auto-negotiation. + OFPPF_AUTONEG = 1 << 13 + #: Pause. + OFPPF_PAUSE = 1 << 14 + #: Asymmetric pause. + OFPPF_PAUSE_ASYM = 1 << 15 + + +class PortState(GenericBitMask): + """Current state of the physical port. + + These are not configurable from the controller. + + The port state bits represent the state of the physical link or switch + protocols outside of OpenFlow. The :attr:`~PortConfig.OFPPS_LINK_DOWN` bit + indicates the the physical link is not present. The + :attr:`~PortConfig.OFPPS_BLOCKED` bit indicates that a switch protocol + outside of OpenFlow, such as 802.1D Spanning Tree, is preventing the use of + that port with :attr:`~PortConfig.OFPP_FLOOD`. + + All port state bits are read-only and cannot be changed by the controller. + When the port flags are changed, the switch sends an + :attr:`v0x05.common.header.Type.OFPT_PORT_STATUS` message to notify the + controller of the change. + """ + + #: Not physical link present. + OFPPS_LINK_DOWN = 1 << 0 + #: Port is blocked. + OFPPS_BLOCKED = 1 << 1 + #: Live for Fast Failover Group. + OFPPS_LIVE = 1 << 2 + + +# Classes +class PortDescPropHeader(GenericStruct): + """Common header for all port description properties.""" + + # One of OFPPDPT_* + port_desc_type = UBInt16() + # Length in bytes of this property + length = UBInt16() + + def __init__(self, port_desc_type=None, length=None): + """Create the Header for Port Description properties. + + Args: + port_desc_type (int): The Port Description property. + length (int): The length of the message. + """ + super().__init__() + self.port_desc_type = port_desc_type + self.length = length + + +class ListOfPortDescProperties(FixedTypeList): + """List of Port Description Properties. + + Represented by instances of PortDescPropHeader objects. + """ + + def __init__(self, items=None): + """Create a ListOfActions with the optional parameters below. + + Args: + items (~pyof.v0x05.common.action.ActionHeader): + Instance or a list of instances. + """ + super().__init__(pyof_class=PortDescPropHeader, items=items) + + +class Port(GenericStruct): + """Description of a port. + + The port_no field uniquely identifies a port within a switch. The hw_addr + field typically is the MAC address for the port; + :data:`.OFP_MAX_ETH_ALEN` is 6. The name field is a null-terminated string + containing a human-readable name for the interface. + The value of :data:`.OFP_MAX_PORT_NAME_LEN` is 16. + + :attr:`curr`, :attr:`advertised`, :attr:`supported` and :attr:`peer` fields + indicate link modes (speed and duplexity), link type (copper/fiber) and + link features (autonegotiation and pause). They are bitmaps of + :class:`PortFeatures` enum values that describe features. + Multiple of these flags may be set simultaneously. If none of the port + speed flags are set, the :attr:`max_speed` or :attr:`curr_speed` are used. + """ + + port_no = UBInt32() + + length = UBInt16() + pad = Pad(2) + hw_addr = HWAddress() + pad2 = Pad(2) # Align to 64 bits + name = Char(length=OFP_MAX_PORT_NAME_LEN) # Null terminated + config = UBInt32(enum_ref=PortConfig) # Bitmap of OFPPC_* flags + state = UBInt32(enum_ref=PortState) # Bitmap of OFPPS_* flags + + properties = ListOfPortDescProperties() + + def __init__(self, port_no=None, hw_addr=None, name=None, config=None, + state=None, properties=ListOfPortDescProperties): + """Create a Port with the optional parameters below. + + Args: + port_no (int): Port number. + hw_addr (HWAddress): Hardware address. + name (str): Null-terminated name. + + config (~pyof.v0x05.common.port.PortConfig): + Bitmap of OFPPC* flags. + state (~pyof.v0x05.common.port.PortState): Bitmap of OFPPS* flags. + properties (ListOfPortDescProperties): Port description property list + - 0 or more properties. + + """ + super().__init__() + self.port_no = port_no + self.hw_addr = hw_addr + self.name = name + self.config = config + self.state = state + self.properties = properties + self.length = self.__sizeof__() + + +class PortDescPropEthernet(PortDescPropHeader): + """Ethernet port description property""" + + # Align to 64 bits + pad4 = Pad(4) + # Current features. + curr = UBInt32(enum_ref=PortFeatures) + # Feature being advertised by port. + advertised = UBInt32(enum_ref=PortFeatures) + # Features supported by the port. + supported = UBInt32(enum_ref=PortFeatures) + # Features advertised by peer. + peer = UBInt32(enum_ref=PortFeatures) + # Current port bitrate in kbps. + curr_speed = UBInt32() + # Max port bitrate in kbps. + max_speed = UBInt32() + + def __init__(self, curr=PortFeatures, advertised=PortFeatures, + supported=PortFeatures, peer=PortFeatures, curr_speed=None, + max_speed=None): + """Create the Port Description Property for Ethernet. + + Args: + curr (int): Current features. + advertised (int): Feature being advertised by port. + supported (int): Features supported by the port. + peer (int): Features advertised by peer. + curr_speed (int): Current port bitrate in kbps. + max_speed (int): Max port bitrate in kbps. + """ + super().__init__(port_desc_type=PortDescPropType.OFPPDPT_ETHERNET) + self.curr = curr + self.advertised = advertised + self.supported = supported + self.peer = peer + self.curr_speed = curr_speed + self.max_speed = max_speed + self.length = self.__sizeof__() + + +class PortDescPropOptical(PortDescPropHeader): + """Optical port description property.""" + + # Align to 64 bits. + pad4 = Pad(4) + + # Features supported by the port. + supported = UBInt32() + # Minimum TX Frequency/Wavelength. + tx_min_freq_lmda = UBInt32() + # Maximum TX Frequency/Wavelength. + tx_max_freq_lmda = UBInt32() + # TX Grid Spacing Frequency/Wavelength. + tx_grid_freq_lmda = UBInt32() + # Minimum RX Frequency/Wavelength. + rx_min_freq_lmda = UBInt32() + # Maximum RX Frequency/Wavelength. + rx_max_freq_lmda = UBInt32() + # RX Grid Spacing Frequency/Wavelength + rx_grid_freq_lmda = UBInt32() + # Minimum TX power + tx_pwr_min = UBInt16() + # Maximun TX power + tx_pwr_max = UBInt16() + + def __init__(self, supported=None, tx_min_freq_lmda=None, + tx_max_freq_lmda=None, tx_grid_freq_lmda=None, + rx_min_freq_lmda=None, rx_max_freq_lmda=None, + rx_grid_freq_lmda=None, tx_pwr_min=None, tx_pwr_max=None): + """Create the Port Description Property for Optical. + Args: + supported (int): Features supported by the port. + tx_min_freq_lmda (int): Minimum TX Frequency/Wavelength. + tx_max_freq_lmda (int): Maximum TX Frequency/Wavelength. + tx_grid_freq_lmda (int): TX Grid Spacing Frequency/Wavelength. + rx_min_freq_lmda (int): Minimum RX Frequency/Wavelength. + rx_max_freq_lmda (int): Maximum RX Frequency/Wavelength. + rx_grid_freq_lmda (int): RX Grid Spacing Frequency/Wavelength. + tx_pwr_min (int): Minimum TX power. + tx_pwr_max (int): Maximun TX power. + """ + super().__init__(port_desc_type=PortDescPropType.OFPPDPT_OPTICAL) + self.supported = supported + self.tx_min_freq_lmda = tx_min_freq_lmda + self.tx_max_freq_lmda = tx_max_freq_lmda + self.tx_grid_freq_lmda = tx_grid_freq_lmda + self.rx_grid_freq_lmda = rx_grid_freq_lmda + self.rx_min_freq_lmda = rx_min_freq_lmda + self.rx_max_freq_lmda = rx_max_freq_lmda + self.tx_pwr_min = tx_pwr_min + self.tx_pwr_max = tx_pwr_max + self.length = self.__sizeof__() + + +class PortDescPropExperimenter(PortDescPropHeader): + """Experimenter port description property.""" + + # Experimenter ID which takes the same form as in ExperimenterHeader. + experimenter = UBInt16() + # Experimenter defined. + exp_type = UBInt16() + experimenterData = UBInt32(0) + + def __init__(self, experimenter=None, exp_type=None, experimenter_data=None): + """Create the Port Description Property for Experimenter. + Args: + experimenter (int): Experimenter ID which takes the same form as + in ExperimenterHeader. + exp_type (int): Experimenter defined. + experimenter_data (int): Experimenter Data. + Followed by: + - Exactly (length - 12) bytes containing the experimenter data, then + - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) bytes + of all-zero bytes. + """ + super().__init__(port_desc_type=PortDescPropType.OFPPDPT_EXPERIMENTER) + self.experimenter = experimenter + self.exp_type = exp_type + self.experimenterData = experimenter_data + + +class ListOfPorts(FixedTypeList): + """List of Ports. + + Represented by instances of :class:`Port` and used on + + :class:`~pyof.v0x05.controller2switch.features_reply.FeaturesReply`/ + :class:`~pyof.v0x05.controller2switch.features_reply.SwitchFeatures` + objects. + """ + + def __init__(self, items=None): + """Create a ListOfPort with the optional parameters below. + + Args: + + items (:class:`list`, :class:`~pyof.v0x05.common.port.Port`): + One :class:`~pyof.v0x04.common.port.Port` instance or list. + + """ + super().__init__(pyof_class=Port, + items=items) From 04e998e1b70fb5f868432bb9a8b192bacc640d30 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 16:44:39 -0400 Subject: [PATCH 52/81] Fixing the cross reference and updating the length of some of the port properties classes. --- pyof/v0x05/common/port.py | 58 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index 480cf7689..f26ae897d 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -12,11 +12,11 @@ # Third-party imports -__all__ = ('ListOfPorts', 'ListOfPortDescProperties', 'Port', 'PortConfig', - 'PortFeatures', 'PortNo', 'PortState') +__all__ = ('ListOfPorts', 'ListOfPortDescProperties', 'OPFPort', 'OPFPortConfig', + 'OPFPortFeatures', 'OPFPortNo', 'OPFPortState') -class PortNo(IntEnum): +class OPFPortNo(IntEnum): """Port numbering. Ports are numbered starting from 1. @@ -48,7 +48,7 @@ class PortNo(IntEnum): OFPP_ANY = 0xffffffff -class PortDescPropType(IntEnum): +class OPFPortDescPropType(IntEnum): """Port description property types.""" # Ethernet property @@ -59,7 +59,7 @@ class PortDescPropType(IntEnum): OFPPDPT_EXPERIMENTER = 0xfff -class OpticalPortFeatures(GenericBitMask): +class OPFOpticalPortFeatures(GenericBitMask): """Features of optical ports available in switch.""" # Receiver is tunable. @@ -72,7 +72,7 @@ class OpticalPortFeatures(GenericBitMask): OFPOPF_USE_FREQ = 1 << 3 -class PortConfig(GenericBitMask): +class OPFPortConfig(GenericBitMask): """Flags to indicate behavior of the physical port. These flags are used in :class:`Port` to describe the current @@ -105,7 +105,7 @@ class PortConfig(GenericBitMask): OFPPC_NO_PACKET_IN = 1 << 6 -class PortFeatures(GenericBitMask): +class OPFPortFeatures(GenericBitMask): """Physical ports features. The curr, advertised, supported, and peer fields indicate link modes @@ -163,7 +163,7 @@ class PortFeatures(GenericBitMask): OFPPF_PAUSE_ASYM = 1 << 15 -class PortState(GenericBitMask): +class OPFPortState(GenericBitMask): """Current state of the physical port. These are not configurable from the controller. @@ -190,7 +190,7 @@ class PortState(GenericBitMask): # Classes -class PortDescPropHeader(GenericStruct): +class OPFPortDescPropHeader(GenericStruct): """Common header for all port description properties.""" # One of OFPPDPT_* @@ -223,10 +223,10 @@ def __init__(self, items=None): items (~pyof.v0x05.common.action.ActionHeader): Instance or a list of instances. """ - super().__init__(pyof_class=PortDescPropHeader, items=items) + super().__init__(pyof_class=OPFPortDescPropHeader, items=items) -class Port(GenericStruct): +class OPFPort(GenericStruct): """Description of a port. The port_no field uniquely identifies a port within a switch. The hw_addr @@ -250,8 +250,8 @@ class Port(GenericStruct): hw_addr = HWAddress() pad2 = Pad(2) # Align to 64 bits name = Char(length=OFP_MAX_PORT_NAME_LEN) # Null terminated - config = UBInt32(enum_ref=PortConfig) # Bitmap of OFPPC_* flags - state = UBInt32(enum_ref=PortState) # Bitmap of OFPPS_* flags + config = UBInt32(enum_ref=OPFPortConfig) # Bitmap of OFPPC_* flags + state = UBInt32(enum_ref=OPFPortState) # Bitmap of OFPPS_* flags properties = ListOfPortDescProperties() @@ -278,29 +278,29 @@ def __init__(self, port_no=None, hw_addr=None, name=None, config=None, self.config = config self.state = state self.properties = properties - self.length = self.__sizeof__() + self.length = UBInt16(self.__sizeof__()) -class PortDescPropEthernet(PortDescPropHeader): +class OPFPortDescPropEthernet(OPFPortDescPropHeader): """Ethernet port description property""" # Align to 64 bits pad4 = Pad(4) # Current features. - curr = UBInt32(enum_ref=PortFeatures) + curr = UBInt32(enum_ref=OPFPortFeatures) # Feature being advertised by port. - advertised = UBInt32(enum_ref=PortFeatures) + advertised = UBInt32(enum_ref=OPFPortFeatures) # Features supported by the port. - supported = UBInt32(enum_ref=PortFeatures) + supported = UBInt32(enum_ref=OPFPortFeatures) # Features advertised by peer. - peer = UBInt32(enum_ref=PortFeatures) + peer = UBInt32(enum_ref=OPFPortFeatures) # Current port bitrate in kbps. curr_speed = UBInt32() # Max port bitrate in kbps. max_speed = UBInt32() - def __init__(self, curr=PortFeatures, advertised=PortFeatures, - supported=PortFeatures, peer=PortFeatures, curr_speed=None, + def __init__(self, curr=OPFPortFeatures, advertised=OPFPortFeatures, + supported=OPFPortFeatures, peer=OPFPortFeatures, curr_speed=None, max_speed=None): """Create the Port Description Property for Ethernet. @@ -312,17 +312,17 @@ def __init__(self, curr=PortFeatures, advertised=PortFeatures, curr_speed (int): Current port bitrate in kbps. max_speed (int): Max port bitrate in kbps. """ - super().__init__(port_desc_type=PortDescPropType.OFPPDPT_ETHERNET) + super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_ETHERNET) self.curr = curr self.advertised = advertised self.supported = supported self.peer = peer self.curr_speed = curr_speed self.max_speed = max_speed - self.length = self.__sizeof__() + self.length = UBInt16(self.__sizeof__()) -class PortDescPropOptical(PortDescPropHeader): +class PortDescPropOptical(OPFPortDescPropHeader): """Optical port description property.""" # Align to 64 bits. @@ -363,7 +363,7 @@ def __init__(self, supported=None, tx_min_freq_lmda=None, tx_pwr_min (int): Minimum TX power. tx_pwr_max (int): Maximun TX power. """ - super().__init__(port_desc_type=PortDescPropType.OFPPDPT_OPTICAL) + super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_OPTICAL) self.supported = supported self.tx_min_freq_lmda = tx_min_freq_lmda self.tx_max_freq_lmda = tx_max_freq_lmda @@ -373,10 +373,10 @@ def __init__(self, supported=None, tx_min_freq_lmda=None, self.rx_max_freq_lmda = rx_max_freq_lmda self.tx_pwr_min = tx_pwr_min self.tx_pwr_max = tx_pwr_max - self.length = self.__sizeof__() + self.length = UBInt16(self.__sizeof__()) -class PortDescPropExperimenter(PortDescPropHeader): +class PortDescPropExperimenter(OPFPortDescPropHeader): """Experimenter port description property.""" # Experimenter ID which takes the same form as in ExperimenterHeader. @@ -397,7 +397,7 @@ def __init__(self, experimenter=None, exp_type=None, experimenter_data=None): - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) bytes of all-zero bytes. """ - super().__init__(port_desc_type=PortDescPropType.OFPPDPT_EXPERIMENTER) + super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_EXPERIMENTER) self.experimenter = experimenter self.exp_type = exp_type self.experimenterData = experimenter_data @@ -422,5 +422,5 @@ def __init__(self, items=None): One :class:`~pyof.v0x04.common.port.Port` instance or list. """ - super().__init__(pyof_class=Port, + super().__init__(pyof_class=OPFPort, items=items) From 3dbc3bb028386f9e93ba09bb9ddb5608a8bf8011 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 16:58:26 -0400 Subject: [PATCH 53/81] Fixed the limited lines problems and the sorted imports --- pyof/v0x05/common/port.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index f26ae897d..ee6e7832b 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -12,8 +12,9 @@ # Third-party imports -__all__ = ('ListOfPorts', 'ListOfPortDescProperties', 'OPFPort', 'OPFPortConfig', - 'OPFPortFeatures', 'OPFPortNo', 'OPFPortState') +__all__ = ('ListOfPortDescProperties', 'ListOfPorts', 'OPFPort', + 'OPFPortConfig', 'OPFPortFeatures', 'OPFPortNo', + 'OPFPortState') class OPFPortNo(IntEnum): @@ -267,8 +268,8 @@ def __init__(self, port_no=None, hw_addr=None, name=None, config=None, config (~pyof.v0x05.common.port.PortConfig): Bitmap of OFPPC* flags. state (~pyof.v0x05.common.port.PortState): Bitmap of OFPPS* flags. - properties (ListOfPortDescProperties): Port description property list - - 0 or more properties. + properties (ListOfPortDescProperties): Port description property + list - 0 or more properties. """ super().__init__() @@ -282,7 +283,7 @@ def __init__(self, port_no=None, hw_addr=None, name=None, config=None, class OPFPortDescPropEthernet(OPFPortDescPropHeader): - """Ethernet port description property""" + """Ethernet port description property.""" # Align to 64 bits pad4 = Pad(4) @@ -300,8 +301,8 @@ class OPFPortDescPropEthernet(OPFPortDescPropHeader): max_speed = UBInt32() def __init__(self, curr=OPFPortFeatures, advertised=OPFPortFeatures, - supported=OPFPortFeatures, peer=OPFPortFeatures, curr_speed=None, - max_speed=None): + supported=OPFPortFeatures, peer=OPFPortFeatures, + curr_speed=None, max_speed=None): """Create the Port Description Property for Ethernet. Args: @@ -352,6 +353,7 @@ def __init__(self, supported=None, tx_min_freq_lmda=None, rx_min_freq_lmda=None, rx_max_freq_lmda=None, rx_grid_freq_lmda=None, tx_pwr_min=None, tx_pwr_max=None): """Create the Port Description Property for Optical. + Args: supported (int): Features supported by the port. tx_min_freq_lmda (int): Minimum TX Frequency/Wavelength. @@ -383,19 +385,22 @@ class PortDescPropExperimenter(OPFPortDescPropHeader): experimenter = UBInt16() # Experimenter defined. exp_type = UBInt16() - experimenterData = UBInt32(0) + experimenterData = UBInt32() - def __init__(self, experimenter=None, exp_type=None, experimenter_data=None): + def __init__(self, experimenter=None, exp_type=None, + experimenter_data=None): """Create the Port Description Property for Experimenter. + Args: - experimenter (int): Experimenter ID which takes the same form as - in ExperimenterHeader. + experimenter (int): Experimenter ID which takes the same + form as in ExperimenterHeader. exp_type (int): Experimenter defined. experimenter_data (int): Experimenter Data. Followed by: - - Exactly (length - 12) bytes containing the experimenter data, then - - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) bytes - of all-zero bytes. + - Exactly (length - 12) bytes containing the experimenter + data, then + - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) + bytes of all-zero bytes. """ super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_EXPERIMENTER) self.experimenter = experimenter From 4d7d90ea487344832c4821ffb88ff6d787bad1f2 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 17:06:14 -0400 Subject: [PATCH 54/81] Fixed the indentation. --- pyof/v0x05/common/port.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index ee6e7832b..ef992e4e6 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -1,10 +1,9 @@ """Defines physical port classes and related items.""" # System imports -from enum import IntEnum # Local source tree imports -from pyof.foundation.base import GenericBitMask, GenericStruct +from pyof.foundation.base import Enum, GenericBitMask, GenericStruct from pyof.foundation.basic_types import (Char, FixedTypeList, HWAddress, Pad, UBInt16, UBInt32) from pyof.foundation.constants import OFP_MAX_PORT_NAME_LEN @@ -17,7 +16,7 @@ 'OPFPortState') -class OPFPortNo(IntEnum): +class OPFPortNo(Enum): """Port numbering. Ports are numbered starting from 1. @@ -49,7 +48,7 @@ class OPFPortNo(IntEnum): OFPP_ANY = 0xffffffff -class OPFPortDescPropType(IntEnum): +class OPFPortDescPropType(Enum): """Port description property types.""" # Ethernet property @@ -313,7 +312,7 @@ def __init__(self, curr=OPFPortFeatures, advertised=OPFPortFeatures, curr_speed (int): Current port bitrate in kbps. max_speed (int): Max port bitrate in kbps. """ - super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_ETHERNET) + super().__init__(OPFPortDescPropType.OFPPDPT_ETHERNET) self.curr = curr self.advertised = advertised self.supported = supported @@ -365,7 +364,7 @@ def __init__(self, supported=None, tx_min_freq_lmda=None, tx_pwr_min (int): Minimum TX power. tx_pwr_max (int): Maximun TX power. """ - super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_OPTICAL) + super().__init__(OPFPortDescPropType.OFPPDPT_OPTICAL) self.supported = supported self.tx_min_freq_lmda = tx_min_freq_lmda self.tx_max_freq_lmda = tx_max_freq_lmda @@ -385,7 +384,7 @@ class PortDescPropExperimenter(OPFPortDescPropHeader): experimenter = UBInt16() # Experimenter defined. exp_type = UBInt16() - experimenterData = UBInt32() + experimenter_data = UBInt32() def __init__(self, experimenter=None, exp_type=None, experimenter_data=None): @@ -402,10 +401,10 @@ def __init__(self, experimenter=None, exp_type=None, - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) bytes of all-zero bytes. """ - super().__init__(port_desc_type=OPFPortDescPropType.OFPPDPT_EXPERIMENTER) + super().__init__(OPFPortDescPropType.OFPPDPT_EXPERIMENTER) self.experimenter = experimenter self.exp_type = exp_type - self.experimenterData = experimenter_data + self.experimenter_data = experimenter_data class ListOfPorts(FixedTypeList): From 71fb3844690cbaedcf24c32003f1cc4fb7cef319 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 17:11:59 -0400 Subject: [PATCH 55/81] Rewrote the description under the OPFPortDescPropHeader --- pyof/v0x05/common/port.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index ef992e4e6..13b03c751 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -199,11 +199,11 @@ class OPFPortDescPropHeader(GenericStruct): length = UBInt16() def __init__(self, port_desc_type=None, length=None): - """Create the Header for Port Description properties. + """Create the Header for Port Description Properties. Args: - port_desc_type (int): The Port Description property. - length (int): The length of the message. + port_desc_type (int): The Port Description property type. + length (int): The property's length """ super().__init__() self.port_desc_type = port_desc_type From 15e4f50e6b7fc12a5d99cdd9d8566d5d5db3580c Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 17:36:17 -0400 Subject: [PATCH 56/81] Rewrote the description under the OPFPortDescPropHeader --- pyof/v0x05/common/port.py | 63 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index 13b03c751..03b3e489c 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -4,8 +4,7 @@ # Local source tree imports from pyof.foundation.base import Enum, GenericBitMask, GenericStruct -from pyof.foundation.basic_types import (Char, FixedTypeList, HWAddress, - Pad, UBInt16, UBInt32) +from pyof.foundation.basic_types import (Char, FixedTypeList, HWAddress, Pad, UBInt16, UBInt32) from pyof.foundation.constants import OFP_MAX_PORT_NAME_LEN @@ -201,9 +200,9 @@ class OPFPortDescPropHeader(GenericStruct): def __init__(self, port_desc_type=None, length=None): """Create the Header for Port Description Properties. - Args: - port_desc_type (int): The Port Description property type. - length (int): The property's length + Args: + port_desc_type (int): The Port Description property type. + length (int): The property's length. """ super().__init__() self.port_desc_type = port_desc_type @@ -304,13 +303,13 @@ def __init__(self, curr=OPFPortFeatures, advertised=OPFPortFeatures, curr_speed=None, max_speed=None): """Create the Port Description Property for Ethernet. - Args: - curr (int): Current features. - advertised (int): Feature being advertised by port. - supported (int): Features supported by the port. - peer (int): Features advertised by peer. - curr_speed (int): Current port bitrate in kbps. - max_speed (int): Max port bitrate in kbps. + Args: + curr (int): Current features. + advertised (int): Feature being advertised by port. + supported (int): Features supported by the port. + peer (int): Features advertised by peer. + curr_speed (int): Current port bitrate in kbps. + max_speed (int): Max port bitrate in kbps. """ super().__init__(OPFPortDescPropType.OFPPDPT_ETHERNET) self.curr = curr @@ -353,16 +352,16 @@ def __init__(self, supported=None, tx_min_freq_lmda=None, rx_grid_freq_lmda=None, tx_pwr_min=None, tx_pwr_max=None): """Create the Port Description Property for Optical. - Args: - supported (int): Features supported by the port. - tx_min_freq_lmda (int): Minimum TX Frequency/Wavelength. - tx_max_freq_lmda (int): Maximum TX Frequency/Wavelength. - tx_grid_freq_lmda (int): TX Grid Spacing Frequency/Wavelength. - rx_min_freq_lmda (int): Minimum RX Frequency/Wavelength. - rx_max_freq_lmda (int): Maximum RX Frequency/Wavelength. - rx_grid_freq_lmda (int): RX Grid Spacing Frequency/Wavelength. - tx_pwr_min (int): Minimum TX power. - tx_pwr_max (int): Maximun TX power. + Args: + supported (int): Features supported by the port. + tx_min_freq_lmda (int): Minimum TX Frequency/Wavelength. + tx_max_freq_lmda (int): Maximum TX Frequency/Wavelength. + tx_grid_freq_lmda (int): TX Grid Spacing Frequency/Wavelength. + rx_min_freq_lmda (int): Minimum RX Frequency/Wavelength. + rx_max_freq_lmda (int): Maximum RX Frequency/Wavelength. + rx_grid_freq_lmda (int): RX Grid Spacing Frequency/Wavelength. + tx_pwr_min (int): Minimum TX power. + tx_pwr_max (int): Maximun TX power. """ super().__init__(OPFPortDescPropType.OFPPDPT_OPTICAL) self.supported = supported @@ -390,16 +389,16 @@ def __init__(self, experimenter=None, exp_type=None, experimenter_data=None): """Create the Port Description Property for Experimenter. - Args: - experimenter (int): Experimenter ID which takes the same - form as in ExperimenterHeader. - exp_type (int): Experimenter defined. - experimenter_data (int): Experimenter Data. - Followed by: - - Exactly (length - 12) bytes containing the experimenter - data, then - - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) - bytes of all-zero bytes. + Args: + experimenter (int): Experimenter ID which takes the same + form as in ExperimenterHeader. + exp_type (int): Experimenter defined. + experimenter_data (int): Experimenter Data. + Followed by: + - Exactly (length - 12) bytes containing the experimenter + data, then + - Exactly (length + 7) / 8 * 8 - (length) (between 0 and 7) + bytes of all-zero bytes. """ super().__init__(OPFPortDescPropType.OFPPDPT_EXPERIMENTER) self.experimenter = experimenter From 792baaf3175f3e90ea38c95406385ca3fd20f9d0 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 17:42:40 -0400 Subject: [PATCH 57/81] Rewrote the description under the OPFPortDescPropHeader --- pyof/v0x05/common/port.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index 03b3e489c..7eed44060 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -4,12 +4,11 @@ # Local source tree imports from pyof.foundation.base import Enum, GenericBitMask, GenericStruct -from pyof.foundation.basic_types import (Char, FixedTypeList, HWAddress, Pad, UBInt16, UBInt32) +from pyof.foundation.basic_types import (Char, FixedTypeList, + HWAddress, Pad, UBInt16, UBInt32) from pyof.foundation.constants import OFP_MAX_PORT_NAME_LEN -# Third-party imports - __all__ = ('ListOfPortDescProperties', 'ListOfPorts', 'OPFPort', 'OPFPortConfig', 'OPFPortFeatures', 'OPFPortNo', 'OPFPortState') From 0897df5fbe9d642c5be89b5c149c8f5f3f928092 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 17:51:22 -0400 Subject: [PATCH 58/81] Fixing the sorted import error. --- pyof/v0x05/common/port.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/common/port.py b/pyof/v0x05/common/port.py index 7eed44060..fe47cf5e6 100644 --- a/pyof/v0x05/common/port.py +++ b/pyof/v0x05/common/port.py @@ -4,10 +4,11 @@ # Local source tree imports from pyof.foundation.base import Enum, GenericBitMask, GenericStruct -from pyof.foundation.basic_types import (Char, FixedTypeList, - HWAddress, Pad, UBInt16, UBInt32) +from pyof.foundation.basic_types import ( + Char, FixedTypeList, HWAddress, Pad, UBInt16, UBInt32) from pyof.foundation.constants import OFP_MAX_PORT_NAME_LEN +# Third-party imports __all__ = ('ListOfPortDescProperties', 'ListOfPorts', 'OPFPort', 'OPFPortConfig', 'OPFPortFeatures', 'OPFPortNo', From 92d7ad16e5e7c006c9a43594662a4398a314d657 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 20:52:40 -0400 Subject: [PATCH 59/81] Added the echo_reply file --- pyof/v0x05/symmetric/echo_reply.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 pyof/v0x05/symmetric/echo_reply.py diff --git a/pyof/v0x05/symmetric/echo_reply.py b/pyof/v0x05/symmetric/echo_reply.py new file mode 100644 index 000000000..3392770a3 --- /dev/null +++ b/pyof/v0x05/symmetric/echo_reply.py @@ -0,0 +1,34 @@ +"""Defines Echo Reply message during the handshake.""" + +# System imports + +# Third-party imports + +from pyof.foundation.base import GenericMessage +from pyof.foundation.basic_types import BinaryData +from pyof.v0x05.common.header import Header, Type + +__all__ = ('EchoReply',) + +# Classes + + +class EchoReply(GenericMessage): + """OpenFlow Reply message. + + This message does not contain a body beyond the OpenFlow Header. + """ + + header = Header(message_type=Type.OFPT_ECHO_REPLY, length=8) + + data = BinaryData() + + def __init__(self, xid=None, data=b''): + """Create a EchoReply with the optional parameters below. + + Args: + xid (int): xid to be used on the message header. + data (bytes): arbitrary-length data field. + """ + super().__init__(xid) + self.data = data From d62aaf26de62e813c0c4245d2a780600e0480a4a Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 21:01:00 -0400 Subject: [PATCH 60/81] Added the echo_request file --- pyof/v0x05/symmetric/echo_request.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 pyof/v0x05/symmetric/echo_request.py diff --git a/pyof/v0x05/symmetric/echo_request.py b/pyof/v0x05/symmetric/echo_request.py new file mode 100644 index 000000000..6ef1d5de4 --- /dev/null +++ b/pyof/v0x05/symmetric/echo_request.py @@ -0,0 +1,33 @@ +"""Defines Echo Request message during the handshake.""" + +# System imports + +# Third-party imports + +from pyof.foundation.base import GenericMessage +from pyof.foundation.basic_types import BinaryData +from pyof.v0x05.common.header import Header, Type + +__all__ = ('EchoRequest',) + +# Classes + + +class EchoRequest(GenericMessage): + """OpenFlow Reply message. + + This message does not contain a body after the OpenFlow Header. + """ + + header = Header(message_type=Type.OFPT_ECHO_REQUEST, length=8) + data = BinaryData() + + def __init__(self, xid=None, data=b''): + """Create a EchoRequest with the optional parameters below. + + Args: + xid (int): xid to be used on the message header. + data (bytes): arbitrary-length data field. + """ + super().__init__(xid) + self.data = data From 981c065a009b166cdbec8be40c041b8e3fff9a6b Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 21:25:12 -0400 Subject: [PATCH 61/81] Added the error_msg file --- pyof/v0x05/symmetric/error_msg.py | 646 ++++++++++++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 pyof/v0x05/symmetric/error_msg.py diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py new file mode 100644 index 000000000..168eca5c3 --- /dev/null +++ b/pyof/v0x05/symmetric/error_msg.py @@ -0,0 +1,646 @@ +"""Defines an Error Message.""" + +# System imports + +from pyof.foundation import exceptions +from pyof.foundation.base import Enum, GenericMessage +from pyof.foundation.basic_types import BinaryData, UBInt16, UBInt32 +from pyof.v0x05.common.header import Header, Type + +# Third-party imports + + +__all__ = ('BadActionCode', 'BadInstructionCode', 'BadMatchCode', 'ErrorType', + 'FlowModFailedCode', 'GroupModFailedCode', 'HelloFailedCode', + 'MeterModFailedCode', 'PortModFailedCode', 'QueueOpFailedCode', + 'RoleRequestFailedCode', 'SwitchConfigFailedCode', + 'TableFeaturesFailedCode', 'TableModFailedCode', + 'GenericFailedCode', 'BadPropertyCode', 'AsyncConfigFailedCode', + 'FlowMonitorFailedCode', 'BundleFailedCode') + +# Enums + + +class GenericFailedCode(Enum): + """Error_msg 'code' values for OFPET_BAD_ACTION. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unknown error + GENERIC_ERROR = 0 + + +class BadActionCode(Enum): + """Error_msg 'code' values for OFPET_BAD_ACTION. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unknown action type. + OFPBAC_BAD_TYPE = 0 + #: Length problem in actions. + OFPBAC_BAD_LEN = 1 + #: Unknown experimenter id specified. + OFPBAC_BAD_EXPERIMENTER = 2 + #: Unknown action for experimenter id. + OFPBAC_BAD_EXP_TYPE = 3 + #: Problem validating output port. + OFPBAC_BAD_OUT_PORT = 4 + #: Bad action argument. + OFPBAC_BAD_ARGUMENT = 5 + #: Permissions error. + OFPBAC_EPERM = 6 + #: Can’t handle this many actions. + OFPBAC_TOO_MANY = 7 + #: Problem validating output queue. + OFPBAC_BAD_QUEUE = 8 + #: Invalid group id in forward action. + OFPBAC_BAD_OUT_GROUP = 9 + #: Action can’t apply for this match, or Set-Field missing prerequisite. + OFPBAC_MATCH_INCONSISTENT = 10 + #: Action order is unsupported for the action list in an Apply-Actions + #: instruction. + OFPBAC_UNSUPPORTED_ORDER = 11 + #: Actions uses an unsupported tag/encap. + OFPBAC_BAD_TAG = 12 + #: Unsupported type in SET_FIELD action. + OFPBAC_BAD_SET_TYPE = 13 + #: Length problem in SET_FIELD action. + OFPBAC_BAD_SET_LEN = 14 + #: Bad argument in SET_FIELD action. + OFPBAC_BAD_SET_ARGUMENT = 15 + + +class BadInstructionCode(Enum): + """Error_msg 'code' values for OFPET_BAD_INSTRUCTION. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unknown instruction. + OFPBIC_UNKNOWN_INST = 0 + #: Switch or table does not support the instruction. + OFPBIC_UNSUP_INST = 1 + #: Invalid Table-ID specified. + OFPBIC_BAD_TABLE_ID = 2 + #: Metadata value unsupported by datapath. + OFPBIC_UNSUP_METADATA = 3 + #: Metadata mask value unsupported by datapath. + OFPBIC_UNSUP_METADATA_MASK = 4 + #: Unknown experimenter id specified. + OFPBIC_BAD_EXPERIMENTER = 5 + #: Unknown instruction for experimenter id. + OFPBIC_BAD_EXP_TYPE = 6 + #: Length problem in instructions. + OFPBIC_BAD_LEN = 7 + #: Permissions error. + OFPBIC_EPERM = 8 + #: Duplicate instruction. + OFPBIC_DUP_INST = 9 + + +class BadMatchCode(Enum): + """Error_msg 'code' values for OFPET_BAD_MATCH. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unsupported match type specified by the match + OFPBMC_BAD_TYPE = 0 + #: Length problem in match. + OFPBMC_BAD_LEN = 1 + #: Match uses an unsupported tag/encap. + OFPBMC_BAD_TAG = 2 + #: Unsupported datalink addr mask - switch does not support arbitrary + #: datalink address mask. + OFPBMC_BAD_DL_ADDR_MASK = 3 + #: Unsupported network addr mask - switch does not support arbitrary + #: network address mask. + OFPBMC_BAD_NW_ADDR_MASK = 4 + #: Unsupported combination of fields masked or omitted in the match. + OFPBMC_BAD_WILDCARDS = 5 + #: Unsupported field type in the match. + OFPBMC_BAD_FIELD = 6 + #: Unsupported value in a match field. + OFPBMC_BAD_VALUE = 7 + #: Unsupported mask specified in the match, field is not dl-address or + #: nw-address. + OFPBMC_BAD_MASK = 8 + #: A prerequisite was not met. + OFPBMC_BAD_PREREQ = 9 + #: A field type was duplicated. + OFPBMC_DUP_FIELD = 10 + #: Permissions error. + OFPBMC_EPERM = 11 + + +class BadRequestCode(Enum): + """Error_msg 'code' values for OFPET_BAD_REQUEST. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: ofp_header.version not supported. + OFPBRC_BAD_VERSION = 0 + #: ofp_header.type not supported. + OFPBRC_BAD_TYPE = 1 + #: ofp_multipart_request.type not supported. + OFPBRC_BAD_MULTIPART = 2 + #: Experimenter id not supported (in ofp_experimenter_header or + #: ofp_multipart_request or * ofp_multipart_reply). + OFPBRC_BAD_EXPERIMENTER = 3 + #: Experimenter type not supported. + OFPBRC_BAD_EXP_TYPE = 4 + #: Permissions error. + OFPBRC_EPERM = 5 + #: Wrong request length for type. + OFPBRC_BAD_LEN = 6 + #: Specified buffer has already been used. + OFPBRC_BUFFER_EMPTY = 7 + #: Specified buffer does not exist. + OFPBRC_BUFFER_UNKNOWN = 8 + #: Specified table-id invalid or does not * exist. + OFPBRC_BAD_TABLE_ID = 9 + #: Denied because controller is slave. + OFPBRC_IS_SLAVE = 10 + #: Invalid port. + OFPBRC_BAD_PORT = 11 + #: Invalid packet in packet-out. + OFPBRC_BAD_PACKET = 12 + #: ofp_multipart_request overflowed the assigned buffer. + OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13 + #: Timeout during multipart request. + OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14 + #: Timeout during multipart reply + OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 + + +class ErrorType(Enum): + """Values for ’type’ in ofp_error_message. + + These values are immutable: they will not change in future versions of the + protocol (although new values may be added). + """ + + #: Hello protocol failed + OFPET_HELLO_FAILED = 0 + #: Request was not understood + OFPET_BAD_REQUEST = 1 + #: Error in action description + OFPET_BAD_ACTION = 2 + #: Error in instruction list. + OFPET_BAD_INSTRUCTION = 3 + #: Error in match. + OFPET_BAD_MATCH = 4 + #: Problem modifying flow entry. + OFPET_FLOW_MOD_FAILED = 5 + #: Problem modifying group entry. + OFPET_GROUP_MOD_FAILED = 6 + #: Port mod request failed. + OFPET_PORT_MOD_FAILED = 7 + #: Table mod request failed. + OFPET_TABLE_MOD_FAILED = 8 + #: Queue operation failed. + OFPET_QUEUE_OP_FAILED = 9 + #: Switch config request failed. + OFPET_SWITCH_CONFIG_FAILED = 10 + #: Controller Role request failed. + OFPET_ROLE_REQUEST_FAILED = 11 + #: Error in meter. + OFPET_METER_MOD_FAILED = 12 + #: Setting table features failed. + OFPET_TABLE_FEATURES_FAILED = 13 + #: Some property is invalid. + OFPET_BAD_PROPERTY = 14 + #: Asynchronous config request failed + OFPET_ASYNC_CONFIG_FAILED = 15 + #: Setting flow monitor failed. + OFPET_FLOW_MONITOR_FAILED = 16 + #: Bundle operation failed + OFPET_BUNDLE_FAILED = 17 + #: Experimenter error messages. + OFPET_EXPERIMENTER = 0xffff + + def get_class(self): + """Return a Code class based on current ErrorType value. + + Returns: + enum.IntEnum: class referenced by current error type. + + """ + classes = {'OFPET_HELLO_FAILED': HelloFailedCode, + 'OFPET_BAD_REQUEST': BadRequestCode, + 'OFPET_BAD_ACTION': BadActionCode, + 'OFPET_BAD_INSTRUCTION': BadInstructionCode, + 'OFPET_BAD_MATCH': BadMatchCode, + 'OFPET_FLOW_MOD_FAILED': FlowModFailedCode, + 'OFPET_GROUP_MOD_FAILED': GroupModFailedCode, + 'OFPET_PORT_MOD_FAILED': PortModFailedCode, + 'OFPET_QUEUE_OP_FAILED': QueueOpFailedCode, + 'OFPET_SWITCH_CONFIG_FAILED': SwitchConfigFailedCode, + 'OFPET_ROLE_REQUEST_FAILED': RoleRequestFailedCode, + 'OFPET_METER_MOD_FAILED': MeterModFailedCode, + 'OFPET_TABLE_MOD_FAILED': TableModFailedCode, + 'OFPET_TABLE_FEATURES_FAILED': TableFeaturesFailedCode, + 'OFPET_BAD_PROPERTY': BadPropertyCode, + 'OFPET_ASYNC_CONFIG_FAILED': AsyncConfigFailedCode, + 'OFPET_FLOW_MONITOR_FAILED': FlowMonitorFailedCode, + 'OFPET_BUNDLE_FAILED': BundleFailedCode} + return classes.get(self.name, GenericFailedCode) + + +class FlowModFailedCode(Enum): + """Error_msg 'code' values for OFPET_FLOW_MOD_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unspecified error. + OFPFMFC_UNKNOWN = 0 + #: Flow not added because table was full. + OFPFMFC_TABLE_FULL = 1 + #: Table does not exist + OFPFMFC_BAD_TABLE_ID = 2 + #: Attempted to add overlapping flow with CHECK_OVERLAP flag set. + OFPFMFC_OVERLAP = 3 + #: Permissions error. + OFPFMFC_EPERM = 4 + #: Flow not added because of unsupported idle/hard timeout. + OFPFMFC_BAD_TIMEOUT = 5 + #: Unsupported or unknown command. + OFPFMFC_BAD_COMMAND = 6 + #: Unsupported or unknown flags. + OFPFMFC_BAD_FLAGS = 7 + #: Problem in table synchronisation + OFPFMFC_CANT_SYNC = 8 + #: Unsupported priority value + OFPFMFC_BAD_PRIORITY = 9 + #: Synchronised flow entry is read only. + OFPFMFC_IS_SYNC = 10 + + +class GroupModFailedCode(Enum): + """Error_msg 'code' values for OFPET_GROUP_MOD_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Group not added because a group ADD attempted to replace an + #: already-present group. + FPGMFC_GROUP_EXISTS = 0 + #: Group not added because Group specified is invalid. + OFPGMFC_INVALID_GROUP = 1 + #: Switch does not support unequal load sharing with select groups. + OFPGMFC_WEIGHT_UNSUPPORTED = 2 + #: The group table is full. + OFPGMFC_OUT_OF_GROUPS = 3 + #: The maximum number of action buckets for a group has been exceeded. + OFPGMFC_OUT_OF_BUCKETS = 4 + #: Switch does not support groups that forward to groups. + OFPGMFC_CHAINING_UNSUPPORTED = 5 + #: This group cannot watch the watch_port or watch_group specified. + OFPGMFC_WATCH_UNSUPPORTED = 6 + #: Group entry would cause a loop. + OFPGMFC_LOOP = 7 + #: Group not modified because a group MODIFY attempted to modify a + #: non-existent group. + OFPGMFC_UNKNOWN_GROUP = 8 + #: Group not deleted because another group is forwarding to it. + OFPGMFC_CHAINED_GROUP = 9 + #: Unsupported or unknown group type. + OFPGMFC_BAD_TYPE = 10 + #: Unsupported or unknown command. + OFPGMFC_BAD_COMMAND = 11 + #: Error in bucket. + OFPGMFC_BAD_BUCKET = 12 + #: Error in watch port/group. + OFPGMFC_BAD_WATCH = 13 + #: Permissions error. + OFPGMFC_EPERM = 14 + + +class HelloFailedCode(Enum): + """Error_msg 'code' values for OFPET_HELLO_FAILED. + + 'data' contains an ASCII text string that may give failure details. + """ + + #: No compatible version + OFPHFC_INCOMPATIBLE = 0 + #: Permissions error + OFPHFC_EPERM = 1 + + +class MeterModFailedCode(Enum): + """Error msg 'code' values for OFPET_METER_MOD_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unspecified error. + OFPMMFC_UNKNOWN = 0 + #: Meter not added because a Meter ADD * attempted to replace an existing + #: Meter. + OFPMMFC_METER_EXISTS = 1 + #: Meter not added because Meter specified * is invalid. + OFPMMFC_INVALID_METER = 2 + #: Meter not modified because a Meter MODIFY attempted to modify a + #: non-existent Meter. + OFPMMFC_UNKNOWN_METER = 3 + #: Unsupported or unknown command. + OFPMMFC_BAD_COMMAND = 4 + #: Flag configuration unsupported. + OFPMMFC_BAD_FLAGS = 5 + #: Rate unsupported. + OFPMMFC_BAD_RATE = 6 + #: Burst size unsupported. + OFPMMFC_BAD_BURST = 7 + #: Band unsupported. + OFPMMFC_BAD_BAND = 8 + #: Band value unsupported. + OFPMMFC_BAD_BAND_VALUE = 9 + #: No more meters available. + OFPMMFC_OUT_OF_METERS = 10 + #: The maximum number of properties * for a meter has been exceeded. + OFPMMFC_OUT_OF_BANDS = 11 + + +class PortModFailedCode(Enum): + """Error_msg 'code' values for OFPET_PORT_MOD_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Specified port number does not exist. + OFPPMFC_BAD_PORT = 0 + #: Specified hardware address does not * match the port number. + OFPPMFC_BAD_HW_ADDR = 1 + #: Specified config is invalid. + OFPPMFC_BAD_CONFIG = 2 + #: Specified advertise is invalid. + OFPPMFC_BAD_ADVERTISE = 3 + #: Permissions error. + OFPPMFC_EPERM = 4 + + +class QueueOpFailedCode(Enum): + """Error msg 'code' values for OFPET_QUEUE_OP_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Invalid port (or port does not exist) + OFPQOFC_BAD_PORT = 0 + #: Queue does not exist + OFPQOFC_BAD_QUEUE = 1 + #: Permissions error + OFPQOFC_EPERM = 2 + + +class RoleRequestFailedCode(Enum): + """Error msg 'code' values for OFPET_ROLE_REQUEST_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Stale Message: old generation_id. + OFPRRFC_STALE = 0 + #: Controller role change unsupported. + OFPRRFC_UNSUP = 1 + #: Invalid role. + OFPRRFC_BAD_ROLE = 2 + + +class SwitchConfigFailedCode(Enum): + """Error msg 'code' values for OFPET_SWITCH_CONFIG_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Specified flags is invalid. + OFPSCFC_BAD_FLAGS = 0 + #: Specified len is invalid. + OFPSCFC_BAD_LEN = 1 + #: Permissions error. + OFPQCFC_EPERM = 2 + + +class TableFeaturesFailedCode(Enum): + """Error msg 'code' values for OFPET_TABLE_FEATURES_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Specified table does not exist. + OFPTFFC_BAD_TABLE = 0 + #: Invalid metadata mask. + OFPTFFC_BAD_METADATA = 1 + #: Permissions error. + OFPTFFC_EPERM = 5 + + +class TableModFailedCode(Enum): + """Error_msg 'code' values for OFPET_TABLE_MOD_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Specified table does not exist. + OFPTMFC_BAD_TABLE = 0 + #: Specified config is invalid. + OFPTMFC_BAD_CONFIG = 1 + #: Permissions error. + OFPTMFC_EPERM = 2 + + +class BadPropertyCode(Enum): + """Error_msg 'code' values for OFPET_BAD_PROPERTY. + + 'data' contains at least the first 64 bytes of the failed request. + """ + #: Unknown property type. + OFPBPC_BAD_TYPE = 0 + #: Length problem in property. + OFPBPC_BAD_LEN = 1 + #: Unsupported property value. + OFPBPC_BAD_VALUE = 2 + #: Can't handle this many properties. + OFPBPC_TOO_MANY = 3 + #: A property type was duplicated. + OFPBPC_DUP_TYPE = 4 + #: Unknown experimenter id specified. + OFPBPC_BAD_EXPERIMENTER = 5 + #: Unknown exp_type for experimenter id. + OFPBPC_BAD_EXP_TYPE = 6 + #: Unknown value for experimenter id. + OFPBPC_BAD_EXP_VALUE = 7 + #: Permissions error + OFPBPC_EPERM = 8 + + +class AsyncConfigFailedCode(Enum): + """Error_msg 'code' values for OFPET_ASYNC_CONFIG_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: One mask is invalid. + OFPACFC_INVALID = 0 + #: Requested configuration not supported. + OFPACFC_UNSUPPORTED = 1 + #: Permissions error. + OFPACFC_EPERM = 2 + + +class FlowMonitorFailedCode(Enum): + """Error_msg 'code' values for OFPET_FLOW_MONITOR_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unspecified error. + OFPMOFC_UNKNOWN = 0 + #: Monitor not added because a Monitor ADD attempted to replace + #: and existing Monitor. + OFPMOFC_MONITOR_EXISTS = 1 + #: Monitor not added because Monitor specified is invalid. + OFPMOFC_INVALID_MONITOR = 2 + #: Monitor not modified because a Monitor MODIFY attempted to modify + # a non-existent Monitor. + OFPMOFC_UNKNOWN_MONITOR = 3 + #: Unsupported or unknown command. + OFPMOFC_BAD_COMMAND = 4 + #: Flag configuration unsupported. + OFPMOFC_BAD_FLAGS = 5 + #: Specified table does not exist. + OFPMOFC_BAD_TABLE_ID = 6 + #: Error in output port/group. + OFPMOFC_BAD_OUT = 7 + + +class BundleFailedCode(Enum): + """Error_msg 'code' values for OFPET_BUNDLE_FAILED. + + 'data' contains at least the first 64 bytes of the failed request. + """ + + #: Unspecified error. + OFPBFC_UNKNOWN = 0 + #: Permissions error. + OFPBFC_EPERM = 1 + #: Bundle ID doesn't exist. + OFPBFC_BAD_ID = 2 + #: Bundle ID already exist. + OFPBFC_BUNDLE_EXIST = 3 + #: Bundle ID is closed. + OFPBFC_BUNDLE_CLOSED = 4 + #: Too many bundles IDs. + OFPBFC_OUT_OF_BUNDLES = 5 + #: Unsupported or unknown message control type + OFPBFC_BAD_TYPE = 6 + #: Unsupported, unknown, or inconsistent flags. + OFPBFC_BAD_FLAGS = 7 + #: Length problem in included message. + OFPBFC_MSG_BAD_LEN = 8 + #: Inconsistent or duplicate XID. + OFPBFC_MSG_BAD_XID = 9 + #: Unsupported message in this bundle. + OFPBFC_MSG_UNSUP = 10 + #: Unsupported message combination in this bundle. + OFPBFC_MSG_CONFLICT = 11 + #: Can't handle this many messages in bundle. + OFPBFC__MSG_TOO_MANY = 12 + #: One message in bundle failed. + OFPBFC_MSG_FAILED = 13 + #: Bundle is taking too long. + OFPBFC_TIMEOUT = 14 + #: Bundle is locking the resources. + OFPBFC_BUNDLE_IN_PROGRESS = 15 + + +# Classes + +class ErrorMsg(GenericMessage): + """OpenFlow Error Message. + + This message does not contain a body in addition to the OpenFlow Header. + """ + + #: :class:`~.header.Header`: OpenFlow Header + header = Header(message_type=Type.OFPT_ERROR) + #: ErrorType enum item + error_type = UBInt16(enum_ref=ErrorType) + #: Error code associated with ErrorType + code = UBInt16() + #: Variable-length data interpreted based on the type and code. + # No padding. + data = BinaryData() + + def __init__(self, xid=None, error_type=None, code=None, data=b''): + """Assign parameters to object attributes. + + Args: + xid (int): To be included in the message header. + error_type (ErrorType): Error type. + code (Enum): Error code. + data: Its content is specified in the error code documentation. + Unless specified otherwise, the data field contains at least + 64 bytes of the failed request that caused the error message + to be generated, if the failed request is shorter than 64 + bytes it should be the full request without any padding. + """ + super().__init__(xid) + self.error_type = error_type + self.code = code + self.data = data + + def unpack(self, buff, offset=0): + """Unpack binary data into python object.""" + super().unpack(buff, offset) + code_class = ErrorType(self.error_type).get_class() + self.code = code_class(self.code) + + +class ErrorExperimenterMsg(GenericMessage): + """OFPET_EXPERIMENTER: Error message (datapath -> controller). + + The experimenter field is the Experimenter ID, which takes the same form + as in :class:`~.symmetric.experimenter.ExperimenterHeader + """ + + # :class:`~.header.Header`: OpenFlow Header + header = Header(message_type=Type.OFPT_ERROR) + #: OFPET_EXPERIMENTER. + error_type = UBInt16(ErrorType.OFPET_EXPERIMENTER, enum_ref=ErrorType) + #: Experimenter Defined + exp_type = UBInt16() + #: Experimenter ID which takes the same form as in + #: :class:`~.symmetric.experimenter.ExperimenterHeader`. + experimenter = UBInt32() + #: Variable-length data interpreted based on the type and code. + # No padding. + data = BinaryData() + + def __init__(self, xid=None, exp_type=None, experimenter=None, data=b''): + """Assign parameters to object attributes. + + Args: + xid (int): To be included in the message header. + exp_type (int): Experimenter defined. + experimenter (int): Experimenter ID which takes the same form as + in :class:`~.symmetric.experimenter.ExperimenterHeader`. + data: Variable-length data interpreted based on the type and code. + No padding. + """ + super().__init__(xid) + self.exp_type = exp_type + self.experimenter = experimenter + self.data = data + + def unpack(self, buff, offset=0): + """Unpack binary data into python object.""" + raise exceptions.MethodNotImplemented("'Unpack' method not " + "implemented on ErrorMsg class") + + From 65e32c5084e6a2db3df9703101ac74eee6085316 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 21:39:59 -0400 Subject: [PATCH 62/81] Fixing the sorted import and spaces. --- pyof/v0x05/symmetric/error_msg.py | 105 +++++++++++++++--------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py index 168eca5c3..45db061bc 100644 --- a/pyof/v0x05/symmetric/error_msg.py +++ b/pyof/v0x05/symmetric/error_msg.py @@ -10,18 +10,20 @@ # Third-party imports -__all__ = ('BadActionCode', 'BadInstructionCode', 'BadMatchCode', 'ErrorType', - 'FlowModFailedCode', 'GroupModFailedCode', 'HelloFailedCode', - 'MeterModFailedCode', 'PortModFailedCode', 'QueueOpFailedCode', - 'RoleRequestFailedCode', 'SwitchConfigFailedCode', - 'TableFeaturesFailedCode', 'TableModFailedCode', - 'GenericFailedCode', 'BadPropertyCode', 'AsyncConfigFailedCode', - 'FlowMonitorFailedCode', 'BundleFailedCode') +__all__ = ('OPFBadActionCode', 'OPFBadInstructionCode', 'OPFBadMatchCode', + 'OPFErrorType', 'OPFFlowModFailedCode', 'OPFGroupModFailedCode', + 'OPFHelloFailedCode', 'OPFMeterModFailedCode', + 'OPFPortModFailedCode', 'OPFQueueOpFailedCode', + 'OPFRoleRequestFailedCode', 'OPFSwitchConfigFailedCode', + 'OPFTableFeaturesFailedCode', 'OPFTableModFailedCode', + 'OPFGenericFailedCode', 'OPFBadPropertyCode', + 'OPFAsyncConfigFailedCode', 'OPFFlowMonitorFailedCode', + 'OPFBundleFailedCode') # Enums -class GenericFailedCode(Enum): +class OPFGenericFailedCode(Enum): """Error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least the first 64 bytes of the failed request. @@ -31,7 +33,7 @@ class GenericFailedCode(Enum): GENERIC_ERROR = 0 -class BadActionCode(Enum): +class OPFBadActionCode(Enum): """Error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least the first 64 bytes of the failed request. @@ -72,7 +74,7 @@ class BadActionCode(Enum): OFPBAC_BAD_SET_ARGUMENT = 15 -class BadInstructionCode(Enum): +class OPFBadInstructionCode(Enum): """Error_msg 'code' values for OFPET_BAD_INSTRUCTION. 'data' contains at least the first 64 bytes of the failed request. @@ -100,7 +102,7 @@ class BadInstructionCode(Enum): OFPBIC_DUP_INST = 9 -class BadMatchCode(Enum): +class OPFBadMatchCode(Enum): """Error_msg 'code' values for OFPET_BAD_MATCH. 'data' contains at least the first 64 bytes of the failed request. @@ -135,7 +137,7 @@ class BadMatchCode(Enum): OFPBMC_EPERM = 11 -class BadRequestCode(Enum): +class OPFBadRequestCode(Enum): """Error_msg 'code' values for OFPET_BAD_REQUEST. 'data' contains at least the first 64 bytes of the failed request. @@ -176,7 +178,7 @@ class BadRequestCode(Enum): OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 -class ErrorType(Enum): +class OPFErrorType(Enum): """Values for ’type’ in ofp_error_message. These values are immutable: they will not change in future versions of the @@ -229,28 +231,28 @@ def get_class(self): enum.IntEnum: class referenced by current error type. """ - classes = {'OFPET_HELLO_FAILED': HelloFailedCode, - 'OFPET_BAD_REQUEST': BadRequestCode, - 'OFPET_BAD_ACTION': BadActionCode, - 'OFPET_BAD_INSTRUCTION': BadInstructionCode, - 'OFPET_BAD_MATCH': BadMatchCode, - 'OFPET_FLOW_MOD_FAILED': FlowModFailedCode, - 'OFPET_GROUP_MOD_FAILED': GroupModFailedCode, - 'OFPET_PORT_MOD_FAILED': PortModFailedCode, - 'OFPET_QUEUE_OP_FAILED': QueueOpFailedCode, - 'OFPET_SWITCH_CONFIG_FAILED': SwitchConfigFailedCode, - 'OFPET_ROLE_REQUEST_FAILED': RoleRequestFailedCode, - 'OFPET_METER_MOD_FAILED': MeterModFailedCode, - 'OFPET_TABLE_MOD_FAILED': TableModFailedCode, - 'OFPET_TABLE_FEATURES_FAILED': TableFeaturesFailedCode, - 'OFPET_BAD_PROPERTY': BadPropertyCode, - 'OFPET_ASYNC_CONFIG_FAILED': AsyncConfigFailedCode, - 'OFPET_FLOW_MONITOR_FAILED': FlowMonitorFailedCode, - 'OFPET_BUNDLE_FAILED': BundleFailedCode} - return classes.get(self.name, GenericFailedCode) - - -class FlowModFailedCode(Enum): + classes = {'OFPET_HELLO_FAILED': OPFHelloFailedCode, + 'OFPET_BAD_REQUEST': OPFBadRequestCode, + 'OFPET_BAD_ACTION': OPFBadActionCode, + 'OFPET_BAD_INSTRUCTION': OPFBadInstructionCode, + 'OFPET_BAD_MATCH': OPFBadMatchCode, + 'OFPET_FLOW_MOD_FAILED': OPFFlowModFailedCode, + 'OFPET_GROUP_MOD_FAILED': OPFGroupModFailedCode, + 'OFPET_PORT_MOD_FAILED': OPFPortModFailedCode, + 'OFPET_QUEUE_OP_FAILED': OPFQueueOpFailedCode, + 'OFPET_SWITCH_CONFIG_FAILED': OPFSwitchConfigFailedCode, + 'OFPET_ROLE_REQUEST_FAILED': OPFRoleRequestFailedCode, + 'OFPET_METER_MOD_FAILED': OPFMeterModFailedCode, + 'OFPET_TABLE_MOD_FAILED': OPFTableModFailedCode, + 'OFPET_TABLE_FEATURES_FAILED': OPFTableFeaturesFailedCode, + 'OFPET_BAD_PROPERTY': OPFBadPropertyCode, + 'OFPET_ASYNC_CONFIG_FAILED': OPFAsyncConfigFailedCode, + 'OFPET_FLOW_MONITOR_FAILED': OPFFlowMonitorFailedCode, + 'OFPET_BUNDLE_FAILED': OPFBundleFailedCode} + return classes.get(self.name, OPFGenericFailedCode) + + +class OPFFlowModFailedCode(Enum): """Error_msg 'code' values for OFPET_FLOW_MOD_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -280,7 +282,7 @@ class FlowModFailedCode(Enum): OFPFMFC_IS_SYNC = 10 -class GroupModFailedCode(Enum): +class OPFGroupModFailedCode(Enum): """Error_msg 'code' values for OFPET_GROUP_MOD_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -320,7 +322,7 @@ class GroupModFailedCode(Enum): OFPGMFC_EPERM = 14 -class HelloFailedCode(Enum): +class OPFHelloFailedCode(Enum): """Error_msg 'code' values for OFPET_HELLO_FAILED. 'data' contains an ASCII text string that may give failure details. @@ -332,7 +334,7 @@ class HelloFailedCode(Enum): OFPHFC_EPERM = 1 -class MeterModFailedCode(Enum): +class OPFMeterModFailedCode(Enum): """Error msg 'code' values for OFPET_METER_MOD_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -366,7 +368,7 @@ class MeterModFailedCode(Enum): OFPMMFC_OUT_OF_BANDS = 11 -class PortModFailedCode(Enum): +class OPFPortModFailedCode(Enum): """Error_msg 'code' values for OFPET_PORT_MOD_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -384,7 +386,7 @@ class PortModFailedCode(Enum): OFPPMFC_EPERM = 4 -class QueueOpFailedCode(Enum): +class OPFQueueOpFailedCode(Enum): """Error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -398,7 +400,7 @@ class QueueOpFailedCode(Enum): OFPQOFC_EPERM = 2 -class RoleRequestFailedCode(Enum): +class OPFRoleRequestFailedCode(Enum): """Error msg 'code' values for OFPET_ROLE_REQUEST_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -412,7 +414,7 @@ class RoleRequestFailedCode(Enum): OFPRRFC_BAD_ROLE = 2 -class SwitchConfigFailedCode(Enum): +class OPFSwitchConfigFailedCode(Enum): """Error msg 'code' values for OFPET_SWITCH_CONFIG_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -426,7 +428,7 @@ class SwitchConfigFailedCode(Enum): OFPQCFC_EPERM = 2 -class TableFeaturesFailedCode(Enum): +class OPFTableFeaturesFailedCode(Enum): """Error msg 'code' values for OFPET_TABLE_FEATURES_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -440,7 +442,7 @@ class TableFeaturesFailedCode(Enum): OFPTFFC_EPERM = 5 -class TableModFailedCode(Enum): +class OPFTableModFailedCode(Enum): """Error_msg 'code' values for OFPET_TABLE_MOD_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -454,11 +456,12 @@ class TableModFailedCode(Enum): OFPTMFC_EPERM = 2 -class BadPropertyCode(Enum): +class OPFBadPropertyCode(Enum): """Error_msg 'code' values for OFPET_BAD_PROPERTY. 'data' contains at least the first 64 bytes of the failed request. """ + #: Unknown property type. OFPBPC_BAD_TYPE = 0 #: Length problem in property. @@ -479,7 +482,7 @@ class BadPropertyCode(Enum): OFPBPC_EPERM = 8 -class AsyncConfigFailedCode(Enum): +class OPFAsyncConfigFailedCode(Enum): """Error_msg 'code' values for OFPET_ASYNC_CONFIG_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -493,7 +496,7 @@ class AsyncConfigFailedCode(Enum): OFPACFC_EPERM = 2 -class FlowMonitorFailedCode(Enum): +class OPFFlowMonitorFailedCode(Enum): """Error_msg 'code' values for OFPET_FLOW_MONITOR_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -519,7 +522,7 @@ class FlowMonitorFailedCode(Enum): OFPMOFC_BAD_OUT = 7 -class BundleFailedCode(Enum): +class OPFBundleFailedCode(Enum): """Error_msg 'code' values for OFPET_BUNDLE_FAILED. 'data' contains at least the first 64 bytes of the failed request. @@ -561,7 +564,7 @@ class BundleFailedCode(Enum): # Classes -class ErrorMsg(GenericMessage): +class OPFErrorMsg(GenericMessage): """OpenFlow Error Message. This message does not contain a body in addition to the OpenFlow Header. @@ -602,7 +605,7 @@ def unpack(self, buff, offset=0): self.code = code_class(self.code) -class ErrorExperimenterMsg(GenericMessage): +class OPFErrorExperimenterMsg(GenericMessage): """OFPET_EXPERIMENTER: Error message (datapath -> controller). The experimenter field is the Experimenter ID, which takes the same form @@ -642,5 +645,3 @@ def unpack(self, buff, offset=0): """Unpack binary data into python object.""" raise exceptions.MethodNotImplemented("'Unpack' method not " "implemented on ErrorMsg class") - - From 65d00ae2b4f4cd59de382de418e8977359436793 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 21:44:32 -0400 Subject: [PATCH 63/81] Fixed the Errors. --- pyof/v0x05/symmetric/error_msg.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py index 45db061bc..9b69e1da9 100644 --- a/pyof/v0x05/symmetric/error_msg.py +++ b/pyof/v0x05/symmetric/error_msg.py @@ -573,7 +573,7 @@ class OPFErrorMsg(GenericMessage): #: :class:`~.header.Header`: OpenFlow Header header = Header(message_type=Type.OFPT_ERROR) #: ErrorType enum item - error_type = UBInt16(enum_ref=ErrorType) + error_type = UBInt16(enum_ref=OPFErrorType) #: Error code associated with ErrorType code = UBInt16() #: Variable-length data interpreted based on the type and code. @@ -601,7 +601,7 @@ def __init__(self, xid=None, error_type=None, code=None, data=b''): def unpack(self, buff, offset=0): """Unpack binary data into python object.""" super().unpack(buff, offset) - code_class = ErrorType(self.error_type).get_class() + code_class = OPFErrorType(self.error_type).get_class() self.code = code_class(self.code) @@ -615,7 +615,7 @@ class OPFErrorExperimenterMsg(GenericMessage): # :class:`~.header.Header`: OpenFlow Header header = Header(message_type=Type.OFPT_ERROR) #: OFPET_EXPERIMENTER. - error_type = UBInt16(ErrorType.OFPET_EXPERIMENTER, enum_ref=ErrorType) + error_type = UBInt16(OPFErrorType.OFPET_EXPERIMENTER, enum_ref=OPFErrorType) #: Experimenter Defined exp_type = UBInt16() #: Experimenter ID which takes the same form as in From 7a3956e7b002f17f97c00cd0f3c8168f388f1e4c Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Thu, 9 May 2019 21:46:59 -0400 Subject: [PATCH 64/81] Fixed the limited line. --- pyof/v0x05/symmetric/error_msg.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py index 9b69e1da9..3ba24439c 100644 --- a/pyof/v0x05/symmetric/error_msg.py +++ b/pyof/v0x05/symmetric/error_msg.py @@ -615,7 +615,8 @@ class OPFErrorExperimenterMsg(GenericMessage): # :class:`~.header.Header`: OpenFlow Header header = Header(message_type=Type.OFPT_ERROR) #: OFPET_EXPERIMENTER. - error_type = UBInt16(OPFErrorType.OFPET_EXPERIMENTER, enum_ref=OPFErrorType) + error_type = UBInt16(OPFErrorType.OFPET_EXPERIMENTER, + enum_ref=OPFErrorType) #: Experimenter Defined exp_type = UBInt16() #: Experimenter ID which takes the same form as in From e034b93d748afbbc337fda306ed45d9351c93504 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 09:41:09 -0400 Subject: [PATCH 65/81] Fixing the Invalid Name. --- pyof/v0x05/symmetric/error_msg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py index 3ba24439c..27d40cfad 100644 --- a/pyof/v0x05/symmetric/error_msg.py +++ b/pyof/v0x05/symmetric/error_msg.py @@ -173,9 +173,9 @@ class OPFBadRequestCode(Enum): #: ofp_multipart_request overflowed the assigned buffer. OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13 #: Timeout during multipart request. - OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14 + OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14 # pylint: disable=invalid-name #: Timeout during multipart reply - OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 + OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 # pylint: disable=invalid-name class OPFErrorType(Enum): From 9f90db36216586cab64accc6230189490e1091a6 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 09:44:55 -0400 Subject: [PATCH 66/81] Fixing the Invalid Name. --- pyof/v0x05/symmetric/error_msg.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/symmetric/error_msg.py b/pyof/v0x05/symmetric/error_msg.py index 27d40cfad..c36450cfe 100644 --- a/pyof/v0x05/symmetric/error_msg.py +++ b/pyof/v0x05/symmetric/error_msg.py @@ -171,11 +171,11 @@ class OPFBadRequestCode(Enum): #: Invalid packet in packet-out. OFPBRC_BAD_PACKET = 12 #: ofp_multipart_request overflowed the assigned buffer. - OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13 + OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13 # pylint: disable=invalid-name #: Timeout during multipart request. - OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14 # pylint: disable=invalid-name + OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14 # pylint: disable=invalid-name #: Timeout during multipart reply - OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 # pylint: disable=invalid-name + OFPBRC_MULTIPART_REPLY_TIMEOUT = 15 # pylint: disable=invalid-name class OPFErrorType(Enum): From 780f6e5f878970fadcd1a4c1d8172923bd49fa6d Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 10:35:05 -0400 Subject: [PATCH 67/81] Add the experimenter feature for v0x05 --- pyof/v0x05/symmetric/experimenter.py | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 pyof/v0x05/symmetric/experimenter.py diff --git a/pyof/v0x05/symmetric/experimenter.py b/pyof/v0x05/symmetric/experimenter.py new file mode 100644 index 000000000..7a6ee55db --- /dev/null +++ b/pyof/v0x05/symmetric/experimenter.py @@ -0,0 +1,53 @@ +"""Defines Experimenter message.""" + +# System imports + +# Third-party imports + +from pyof.foundation.base import GenericMessage +from pyof.foundation.basic_types import BinaryData, UBInt32 +from pyof.v0x05.common.header import Header, Type + +__all__ = ('ExperimenterHeader',) + +# Classes + + +class ExperimenterHeader(GenericMessage): + """OpenFlow Experimenter message. + + The experimenter field is a 32-bit value that uniquely identifies the + experimenter. If the most significant byte is zero, the next three bytes + are the experimenter’s IEEE OUI. If the most significant byte is not zero, + it is a value allocated by the Open Networking Foundation. If experimenter + does not have (or wish to use) their OUI, they should contact the Open + Networking Foundation to obtain an unique experimenter ID. + + The rest of the body is uninterpreted by standard OpenFlow processing and + is arbitrarily defined by the corresponding experimenter. + + If a switch does not understand an experimenter extension, it must send an + OFPT_ERROR message with a OFPBRC_BAD_EXPERIMENTER error code and + OFPET_BAD_REQUEST error type. + """ + + header = Header(message_type=Type.OFPT_EXPERIMENTER) + experimenter = UBInt32() + exp_type = UBInt32() + experimenter_data = BinaryData() + + def __init__(self, xid=None, experimenter=None, exp_type=None, experimenter_data=b''): + """Create a ExperimenterHeader with the optional parameters below. + + Args: + xid (int): xid to be used on the message header. + experimenter (int): Vendor ID: + MSB 0: low-order bytes are IEEE OUI. + MSB != 0: defined by ONF. + exp_type (int): Experimenter defined. + experimenter_data (Binary): Experimenter-defined arbitrary additional data. + """ + super().__init__(xid) + self.experimenter = experimenter + self.exp_type = exp_type + self.experimenter_data = experimenter_data From 3891f659bdca115821b0fc227c2e9190fa912fb4 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 10:37:25 -0400 Subject: [PATCH 68/81] Fixing some line limits --- pyof/v0x05/symmetric/experimenter.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/experimenter.py b/pyof/v0x05/symmetric/experimenter.py index 7a6ee55db..65da7c373 100644 --- a/pyof/v0x05/symmetric/experimenter.py +++ b/pyof/v0x05/symmetric/experimenter.py @@ -36,7 +36,8 @@ class ExperimenterHeader(GenericMessage): exp_type = UBInt32() experimenter_data = BinaryData() - def __init__(self, xid=None, experimenter=None, exp_type=None, experimenter_data=b''): + def __init__(self, xid=None, experimenter=None, exp_type=None, + experimenter_data=b''): """Create a ExperimenterHeader with the optional parameters below. Args: @@ -45,7 +46,8 @@ def __init__(self, xid=None, experimenter=None, exp_type=None, experimenter_data MSB 0: low-order bytes are IEEE OUI. MSB != 0: defined by ONF. exp_type (int): Experimenter defined. - experimenter_data (Binary): Experimenter-defined arbitrary additional data. + experimenter_data (Binary): Experimenter-defined arbitrary + additional data. """ super().__init__(xid) self.experimenter = experimenter From 0736281b00d3cfb789e66455d9fbfb41143f363d Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 10:39:54 -0400 Subject: [PATCH 69/81] Fixed the cross reference. --- pyof/v0x05/symmetric/experimenter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/symmetric/experimenter.py b/pyof/v0x05/symmetric/experimenter.py index 65da7c373..b45d531d5 100644 --- a/pyof/v0x05/symmetric/experimenter.py +++ b/pyof/v0x05/symmetric/experimenter.py @@ -8,12 +8,12 @@ from pyof.foundation.basic_types import BinaryData, UBInt32 from pyof.v0x05.common.header import Header, Type -__all__ = ('ExperimenterHeader',) +__all__ = ('OPFExperimenterHeader',) # Classes -class ExperimenterHeader(GenericMessage): +class OPFExperimenterHeader(GenericMessage): """OpenFlow Experimenter message. The experimenter field is a 32-bit value that uniquely identifies the From a73cefba288094e0f66b8796640daad886bbbd5e Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 10:58:53 -0400 Subject: [PATCH 70/81] Add the Packet In feature from V0x05 --- pyof/v0x05/asynchronous/__init__.py | 1 + pyof/v0x05/asynchronous/packet_in.py | 107 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 pyof/v0x05/asynchronous/__init__.py create mode 100644 pyof/v0x05/asynchronous/packet_in.py diff --git a/pyof/v0x05/asynchronous/__init__.py b/pyof/v0x05/asynchronous/__init__.py new file mode 100644 index 000000000..9a2270440 --- /dev/null +++ b/pyof/v0x05/asynchronous/__init__.py @@ -0,0 +1 @@ +"""Asynchronous messages.""" diff --git a/pyof/v0x05/asynchronous/packet_in.py b/pyof/v0x05/asynchronous/packet_in.py new file mode 100644 index 000000000..2300f3edc --- /dev/null +++ b/pyof/v0x05/asynchronous/packet_in.py @@ -0,0 +1,107 @@ +"""For packets received by the datapath and sent to the controller.""" + +# System imports + +from pyof.foundation.base import Enum, GenericMessage +from pyof.foundation.basic_types import ( + BinaryData, UBInt8, UBInt16, UBInt32, UBInt64) +from pyof.v0x05.common.flow_match import OPFMatch, OPFOxmOfbMatchField +from pyof.v0x05.common.header import Header, Type + +# Third-party imports + + +__all__ = ('OPFPacketIn', 'OPFPacketInReason') + +# Enums + + +class OPFPacketInReason(Enum): + """Reason why this packet is being sent to the controller.""" + + #: No matching flow (table- miss flow entry). + OFPR_TABLE_MISS = 0 + #: Output to controller in apply-actions. + OFPR_APPLY_ACTION = 1 + #: Packet has invalid TTL. + OFPR_INVALID_TTL = 2 + #: Output to controller in action set. + OFPR_ACTION_SET = 3 + #: Output to controller in group bucket. + OFPR_GROUP = 4 + #: Output to controller in packet-out. + OFPR_PACKET_OUT = 5 + + +# Classes + + +class OPFPacketIn(GenericMessage): + """Packet received on port (datapath -> controller).""" + + #: :class:`~pyof.v0x05.common.header.Header`: OpenFlow Header + header = Header(message_type=Type.OFPT_PACKET_IN) + #: ID assigned by datapath. + buffer_id = UBInt32() + #: Full length of frame. + total_len = UBInt16() + #: Reason packet is being sent (one of OFPR_*), + reason = UBInt8(enum_ref=OPFPacketInReason) + #: ID of the table that was looked up. + table_id = UBInt8() + #: Cookie of the flow entry that was looked up. + cookie = UBInt64() + #: Packet metadata. Variable size. + match = OPFMatch() + + #: Align to 64 bit + 16 bit + #: pad = Pad(2) + #: Ethernet frame whose length is inferred from header.length. + #: The padding bytes preceding the Ethernet frame ensure that the IP + #: header (if any) following the Ethernet header is 32-bit aligned. + data = BinaryData() + + def __init__(self, xid=None, buffer_id=None, total_len=None, reason=None, + table_id=None, cookie=None, match=None, data=b''): + """Assign parameters to object attributes. + + Args: + xid (int): Header's xid. + buffer_id (int): ID assigned by datapath. + total_len (int): Full length of frame. + reason (~pyof.v0x05.asynchronous.packet_in.PacketInReason): + The reason why the packet is being sent + table_id (int): ID of the table that was looked up + cookie (int): Cookie of the flow entry that was looked up + match (:class:`~pyof.v0x05.common.flow_match.Match`): + Packet metadata with variable size. + data (bytes): Ethernet frame, halfway through 32-bit word, so the + IP header is 32-bit aligned. The amount of data is inferred + from the length field in the header. Because of padding, + offsetof(struct ofp_packet_in, data) == + sizeof(struct ofp_packet_in) - 2. + """ + super().__init__(xid) + self.buffer_id = buffer_id + self.total_len = total_len + self.reason = reason + self.table_id = table_id + self.cookie = cookie + self.match = match + self.data = data + + @property + def in_port(self): + """Retrieve the 'in_port' that generated the PacketIn. + + This method will look for the OXM_TLV with type OFPXMT_OFB_IN_PORT on + the `oxm_match_fields` field from `match` field and return its value, + if the OXM exists. + + Returns: + The integer number of the 'in_port' that generated the PacketIn if + it exists. Otherwise return None. + + """ + in_port = self.match.get_field(OPFOxmOfbMatchField.OFPXMT_OFB_IN_PORT) + return int.from_bytes(in_port, 'big') From bbb2f28c5dbd88137ee08ff9c2ab45118f0950b0 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 11:31:50 -0400 Subject: [PATCH 71/81] Add the Request Forward feature from V0x05 --- pyof/v0x05/asynchronous/request_forward.py | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pyof/v0x05/asynchronous/request_forward.py diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py new file mode 100644 index 000000000..1756fe4c7 --- /dev/null +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -0,0 +1,41 @@ +"""Defines a Request Forward Message.""" + +# System imports + +# Local source tree imports +from pyof.foundation.base import Enum, GenericStruct +from pyof.v0x05.common.header import Header, Type + +# Third-party imports + +__all__ = ('RequestForwardHeader', 'RequestForwardReason') + + +# Enums + +class RequestForwardReason(Enum): + """Request forward reason.""" + + #: Forward group mod requests. + OFPRFR_GROUP_MOD = 0 + #: Forward meter mod requests. + OFPRFR_METER_MOD = 1 + + +class RequestForwardHeader(GenericStruct): + """Group/Meter request forwarding.""" + + header = Header(Type.OFPT_REQUESTFORWARD) + request = Header() + + def __init__(self, header=Header(Type.OFPT_REQUESTFORWARD), + request=Header): + """Create an instance of the header. + + Args: + header (Header): Type OFPT_REQUESTFORWARD. + request (Header): Request being forwarded. + """ + super().__init__() + self.header = header + self.request = request From 50aa4e994bfc24d6a1da581ade8ac2c8966bb8dc Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:02:28 -0400 Subject: [PATCH 72/81] Fixing the cross reference --- pyof/v0x05/asynchronous/request_forward.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 1756fe4c7..ce3c5233e 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -25,7 +25,9 @@ class RequestForwardReason(Enum): class RequestForwardHeader(GenericStruct): """Group/Meter request forwarding.""" + # :class:`~.header.Header`: OpenFlow Header header = Header(Type.OFPT_REQUESTFORWARD) + # :class:`~.header.Header`: OpenFlow Header request = Header() def __init__(self, header=Header(Type.OFPT_REQUESTFORWARD), @@ -33,8 +35,10 @@ def __init__(self, header=Header(Type.OFPT_REQUESTFORWARD), """Create an instance of the header. Args: - header (Header): Type OFPT_REQUESTFORWARD. - request (Header): Request being forwarded. + header (:class: `~pyof.v0x05.common.header.Header`): + Type OFPT_REQUESTFORWARD. + request (:class: `~pyof.v0x05.common.header.Header`): + Request being forwarded. """ super().__init__() self.header = header From 23edb9432e22959959d00763cdba24692ef9db6f Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:07:38 -0400 Subject: [PATCH 73/81] Fixing the cross reference --- pyof/v0x05/asynchronous/request_forward.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index ce3c5233e..89d4e80de 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -26,6 +26,7 @@ class RequestForwardHeader(GenericStruct): """Group/Meter request forwarding.""" # :class:`~.header.Header`: OpenFlow Header + # :class:`~.header.Type`: OpenFlow Type header = Header(Type.OFPT_REQUESTFORWARD) # :class:`~.header.Header`: OpenFlow Header request = Header() @@ -36,7 +37,7 @@ def __init__(self, header=Header(Type.OFPT_REQUESTFORWARD), Args: header (:class: `~pyof.v0x05.common.header.Header`): - Type OFPT_REQUESTFORWARD. + :class: `~pyof.v0x05.common.header.Type` OFPT_REQUESTFORWARD. request (:class: `~pyof.v0x05.common.header.Header`): Request being forwarded. """ From 86c1c2d647bb197684ae822e9ceac5f38fb15794 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:10:28 -0400 Subject: [PATCH 74/81] Fixing a space line after the imports --- pyof/v0x05/asynchronous/request_forward.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 89d4e80de..2ff637468 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -3,6 +3,7 @@ # System imports # Local source tree imports + from pyof.foundation.base import Enum, GenericStruct from pyof.v0x05.common.header import Header, Type From 96cdfcf3f43035ae3e95b19a478ed35b20f8a22a Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:16:31 -0400 Subject: [PATCH 75/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 2ff637468..be351e9c7 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -2,8 +2,6 @@ # System imports -# Local source tree imports - from pyof.foundation.base import Enum, GenericStruct from pyof.v0x05.common.header import Header, Type From d5b39b636d4a31fed257ddb4c689e5591150419a Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:21:52 -0400 Subject: [PATCH 76/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index be351e9c7..58479130b 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -7,6 +7,7 @@ # Third-party imports + __all__ = ('RequestForwardHeader', 'RequestForwardReason') From 551459d01d0a6b39516c23cf5a7c443e42787991 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:51:15 -0400 Subject: [PATCH 77/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 58479130b..47d93a7fb 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -2,7 +2,9 @@ # System imports + from pyof.foundation.base import Enum, GenericStruct + from pyof.v0x05.common.header import Header, Type # Third-party imports From affab2570a04ea3ec853a95d916166e4ab03124a Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:54:32 -0400 Subject: [PATCH 78/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 47d93a7fb..58479130b 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -2,9 +2,7 @@ # System imports - from pyof.foundation.base import Enum, GenericStruct - from pyof.v0x05.common.header import Header, Type # Third-party imports From 3136ea6a1fec48bf2483b9ec2ea87e6f3cddbd7f Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 12:57:12 -0400 Subject: [PATCH 79/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index 58479130b..e40e46eb8 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -5,6 +5,7 @@ from pyof.foundation.base import Enum, GenericStruct from pyof.v0x05.common.header import Header, Type + # Third-party imports From 8166d050947e10890771759ebab22447334fdb88 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 13:02:54 -0400 Subject: [PATCH 80/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index e40e46eb8..f5ca7f0f7 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -5,7 +5,6 @@ from pyof.foundation.base import Enum, GenericStruct from pyof.v0x05.common.header import Header, Type - # Third-party imports @@ -36,11 +35,11 @@ def __init__(self, header=Header(Type.OFPT_REQUESTFORWARD), request=Header): """Create an instance of the header. - Args: - header (:class: `~pyof.v0x05.common.header.Header`): - :class: `~pyof.v0x05.common.header.Type` OFPT_REQUESTFORWARD. - request (:class: `~pyof.v0x05.common.header.Header`): - Request being forwarded. + Args: + header (:class: `~pyof.v0x05.common.header.Header`): + :class: `~pyof.v0x05.common.header.Type` OFPT_REQUESTFORWARD. + request (:class: `~pyof.v0x05.common.header.Header`): + Request being forwarded. """ super().__init__() self.header = header From e28687456e7b220bdf16d578dd828ada0c7a8271 Mon Sep 17 00:00:00 2001 From: Roicxy Alonso Gonzalez Date: Fri, 10 May 2019 13:21:14 -0400 Subject: [PATCH 81/81] Fixing the spaces error --- pyof/v0x05/asynchronous/request_forward.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyof/v0x05/asynchronous/request_forward.py b/pyof/v0x05/asynchronous/request_forward.py index f5ca7f0f7..c7fdad323 100644 --- a/pyof/v0x05/asynchronous/request_forward.py +++ b/pyof/v0x05/asynchronous/request_forward.py @@ -1,11 +1,11 @@ -"""Defines a Request Forward Message.""" +"""Defines a Request Forward Header.""" -# System imports +#: System imports. from pyof.foundation.base import Enum, GenericStruct from pyof.v0x05.common.header import Header, Type -# Third-party imports +#: Third-party imports. __all__ = ('RequestForwardHeader', 'RequestForwardReason')