pyof.v0x01.asynchronous.error_msg   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Test Coverage

Coverage 95.18%

Importance

Changes 0
Metric Value
wmc 9
eloc 91
dl 0
loc 248
ccs 79
cts 83
cp 0.9518
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A ErrorMsg.__init__() 0 13 1
A ErrorType.get_class() 0 14 1
A ErrorMsg.unpack() 0 17 1
B ErrorMsg.pack() 0 26 6
1
"""Defines an Error Message."""
2
3
# System imports
4 1
from enum import IntEnum
5
6 1
from pyof.foundation.base import GenericMessage
7 1
from pyof.foundation.basic_types import BinaryData, UBInt16
8 1
from pyof.foundation.exceptions import PackException
9
# Do not import new_message_from_header directly to avoid cyclic import.
10 1
from pyof.v0x01.common.header import Header, Type
11
12 1
__all__ = ('ErrorMsg', 'ErrorType', 'BadActionCode', 'BadRequestCode',
13
           'FlowModFailedCode', 'HelloFailedCode', 'PortModFailedCode',
14
           'QueueOpFailedCode', 'GenericFailedCode')
15
16
17
# Enums
18
19 1
class ErrorType(IntEnum):
20
    """Values for ’type’ in ofp_error_message.
21
22
    These values are immutable: they will not change in future versions of the
23
    protocol (although new values may be added).
24
    """
25
26
    #: Hello protocol failed
27 1
    OFPET_HELLO_FAILED = 0
28
    #: Request was not understood
29 1
    OFPET_BAD_REQUEST = 1
30
    #: Error in action description
31 1
    OFPET_BAD_ACTION = 2
32
    #: Problem in modifying Flow entry
33 1
    OFPET_FLOW_MOD_FAILED = 3
34
    #: Problem in modifying Port entry
35 1
    OFPET_PORT_MOD_FAILED = 4
36
    #: Problem in modifying Queue entry
37 1
    OFPET_QUEUE_OP_FAILED = 5
38
39 1
    def get_class(self):
40
        """Return a Code class based on current ErrorType value.
41
42
        Returns:
43
            enum.IntEnum: class referenced by current error type.
44
45
        """
46 1
        classes = {'OFPET_HELLO_FAILED': HelloFailedCode,
47
                   'OFPET_BAD_REQUEST': BadRequestCode,
48
                   'OFPET_BAD_ACTION': BadActionCode,
49
                   'OFPET_FLOW_MOD_FAILED': FlowModFailedCode,
50
                   'OFPET_PORT_MOD_FAILED': PortModFailedCode,
51
                   'OFPET_QUEUE_OP_FAILED': QueueOpFailedCode}
52 1
        return classes.get(self.name, GenericFailedCode)
53
54
55 1
class GenericFailedCode(IntEnum):
56
    """Error_msg 'code' values for OFPET_BAD_ACTION.
57
58
    'data' contains at least the first 64 bytes of the failed request.
59
    """
60
61
    #: Unknown error
62 1
    GENERIC_ERROR = 0
63
64
65 1
class HelloFailedCode(IntEnum):
66
    """Error_msg 'code' values for OFPET_HELLO_FAILED.
67
68
    'data' contains an ASCII text string that may give failure details.
69
    """
70
71
    #: No compatible version
72 1
    OFPHFC_INCOMPATIBLE = 0
73
    #: Permissions error
74 1
    OFPHFC_EPERM = 1
75
76
77 1
class BadRequestCode(IntEnum):
78
    """Error_msg 'code' values for OFPET_BAD_REQUEST.
79
80
    'data' contains at least the first 64 bytes of the failed request.
81
    """
82
83
    #: ofp_header.version not supported.
84 1
    OFPBRC_BAD_VERSION = 0
85
    #: ofp_header.type not supported.
86 1
    OFPBRC_BAD_TYPE = 1
87
    #: ofp_stats_request.type not supported.
88 1
    OFPBRC_BAD_STAT = 2
89
    #: Vendor not supported (in ofp_vendor_header or ofp_stats_request or
90
    #: ofp_stats_reply).
91 1
    OFPBRC_BAD_VENDOR = 3
92
    #: Vendor subtype not supported.
93 1
    OFPBRC_BAD_SUBTYPE = 4
94
    #: Permissions error.
95 1
    OFPBRC_EPERM = 5
96
    #: Wrong request length for type.
97 1
    OFPBRC_BAD_LEN = 6
98
    #: Specified buffer has already been used.
99 1
    OFPBRC_BUFFER_EMPTY = 7
100
    #: Specified buffer does not exist.
101 1
    OFPBRC_BUFFER_UNKNOWN = 8
102
103
104 1
class BadActionCode(IntEnum):
105
    """Error_msg 'code' values for OFPET_BAD_ACTION.
106
107
    'data' contains at least the first 64 bytes of the failed request.
108
    """
109
110
    #: Unknown action type
111 1
    OFPBAC_BAD_TYPE = 0
112
    #: Length problem in actions
113 1
    OFPBAC_BAD_LEN = 1
114
    #: Unknown vendor id specified
115 1
    OFPBAC_BAD_VENDOR = 2
116
    #: Unknown action type for vendor id
117 1
    OFPBAC_BAD_VENDOR_TYPE = 3
118
    #: Problem validating output action
119 1
    OFPBAC_BAD_OUT_PORT = 4
120
    #: Bad action argument
121 1
    OFPBAC_BAD_ARGUMENT = 5
122
    #: Permissions error
123 1
    OFPBAC_EPERM = 6
124
    #: Can’t handle this many actions
125 1
    OFPBAC_TOO_MANY = 7
126
    #: Problem validating output queue
127 1
    OFPBAC_BAD_QUEUE = 8
128
129
130 1
class FlowModFailedCode(IntEnum):
131
    """Error_msg 'code' values for OFPET_FLOW_MOD_FAILED.
132
133
    'data' contains at least the first 64 bytes of the failed request.
134
    """
135
136
    #: Flow not added because of full tables
137 1
    OFPFMFC_ALL_TABLES_FULL = 0
138
    #: Attempted to add overlapping flow with CHECK_OVERLAP flag set
139 1
    OFPFMFC_OVERLAP = 1
140
    #: Permissions error
141 1
    OFPFMFC_EPERM = 2
142
    #: Flow not added because of non-zero idle/hard timeout
143 1
    OFPFMFC_BAD_EMERG_TIMEOUT = 3
144
    #: Unknown command
145 1
    OFPFMFC_BAD_COMMAND = 4
146
    #: Unsupported action list - cannot process in the order specified
147 1
    OFPFMFC_UNSUPPORTED = 5
148
149
150 1
class PortModFailedCode(IntEnum):
151
    """Error_msg 'code' values for OFPET_PORT_MOD_FAILED.
152
153
    'data' contains at least the first 64 bytes of the failed request.
154
    """
155
156
    #: Specified port does not exist
157 1
    OFPPMFC_BAD_PORT = 0
158
    #: Specified hardware address is wrong
159 1
    OFPPMFC_BAD_HW_ADDR = 1
160
161
162 1
class QueueOpFailedCode(IntEnum):
163
    """Error msg 'code' values for OFPET_QUEUE_OP_FAILED.
164
165
    'data' contains at least the first 64 bytes of the failed request.
166
    """
167
168
    #: Invalid port (or port does not exist)
169 1
    OFPQOFC_BAD_PORT = 0
170
    #: Queue does not exist
171 1
    OFPQOFC_BAD_QUEUE = 1
172
    #: Permissions error
173 1
    OFPQOFC_EPERM = 2
174
175
176
# Classes
177
178 1
class ErrorMsg(GenericMessage):
179
    """OpenFlow Error Message.
180
181
    This message does not contain a body in addition to the OpenFlow Header.
182
    """
183
184
    #: :class:`~pyof.v0x01.common.header.Header`: OpenFlow Header
185 1
    header = Header(message_type=Type.OFPT_ERROR)
186 1
    error_type = UBInt16(enum_ref=ErrorType)
187 1
    code = UBInt16()
188 1
    data = BinaryData()
189
190 1
    def __init__(self, xid=None, error_type=None, code=None, data=b''):
191
        """Assign parameters to object attributes.
192
193
        Args:
194
            xid (int): To be included in the message header.
195
            error_type (:class:`ErrorType`): Error type.
196
            code (enum.IntEnum): Error code.
197
            data (bytes): Its content is based on the error type and code.
198
        """
199 1
        super().__init__(xid)
200 1
        self.error_type = error_type
201 1
        self.code = code
202 1
        self.data = data
203
204 1
    def pack(self, value=None):
205
        """Pack the value as a binary representation.
206
207
        :attr:`data` is packed before the calling :meth:`.GenericMessage.pack`.
208
        After that, :attr:`data`'s value is restored.
209
210
        Returns:
211
            bytes: The binary representation.
212
213
        Raises:
214
            :exc:`~.exceptions.PackException`: If pack fails.
215
216
        """
217 1
        if value is None:
218 1
            data_backup = None
219 1
            if self.data is not None and not isinstance(self.data, bytes):
220 1
                data_backup = self.data
221 1
                self.data = self.data.pack()
222 1
            packed = super().pack()
223 1
            if data_backup is not None:
224 1
                self.data = data_backup
225 1
            return packed
226
        if isinstance(value, type(self)):
227
            return value.pack()
228
        msg = "{} is not an instance of {}".format(value, type(self).__name__)
229
        raise PackException(msg)
230
231 1
    def unpack(self, buff, offset=0):
232
        """Unpack *buff* into this object.
233
234
        This method will convert a binary data into a readable value according
235
        to the attribute format.
236
237
        Args:
238
            buff (bytes): Binary buffer.
239
            offset (int): Where to begin unpacking.
240
241
        Raises:
242
            :exc:`~.exceptions.UnpackException`: If unpack fails.
243
244
        """
245 1
        super().unpack(buff, offset)
246 1
        code_class = ErrorType(self.error_type).get_class()
247
        self.code = code_class(self.code)
248