Test Failed
Pull Request — master (#573)
by Gleyberson
01:50
created

TableFeatures.__init__()   A

Complexity

Conditions 2

Size

Total Lines 36
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 36
ccs 10
cts 10
cp 1
rs 9.6
c 0
b 0
f 0
cc 2
nop 8
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
"""Defines common structures and enums for controller2switch."""
2
3
# System imports
4 1
from enum import IntEnum
5
6 1
from pyof.foundation.base import GenericMessage, GenericStruct
7 1
from pyof.foundation.basic_types import (
8
    Char, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32, UBInt64)
9 1
from pyof.foundation.constants import OFP_MAX_TABLE_NAME_LEN
10 1
from pyof.v0x04.asynchronous.flow_removed import FlowRemovedReason
11 1
from pyof.v0x04.asynchronous.packet_in import PacketInReason
12 1
from pyof.v0x04.asynchronous.port_status import PortReason
13
# Local source tree imports
14 1
from pyof.v0x04.common.action import (
15
    ActionHeader, ControllerMaxLen, ListOfActions)
16 1
from pyof.v0x04.common.flow_instructions import ListOfInstruction
17 1
from pyof.v0x04.common.flow_match import ListOfOxmHeader
18 1
from pyof.v0x04.common.header import Header
19 1
from pyof.v0x04.controller2switch.table_mod import Table
20
21 1
__all__ = ('ConfigFlag', 'ControllerRole', 'TableFeaturePropType',
22
           'MultipartType', 'Bucket', 'BucketCounter', 'ListOfBucketCounter',
23
           'ExperimenterMultipartHeader', 'Property', 'InstructionsProperty',
24
           'NextTablesProperty', 'ActionsProperty', 'OxmProperty',
25
           'ListOfProperty', 'TableFeatures')
26
27
# Enum
28
29
30 1
class ConfigFlag(IntEnum):
31
    """Handling of IP fragments."""
32
33
    #: No special handling for fragments.
34 1
    OFPC_FRAG_NORMAL = 0
35
    #: Drop fragments.
36 1
    OFPC_FRAG_DROP = 1
37
    #: Reassemble (only if OFPC_IP_REASM set).
38 1
    OFPC_FRAG_REASM = 2
39 1
    OFPC_FRAG_MASK = 3
40
41
42 1
class ControllerRole(IntEnum):
43
    """Controller roles."""
44
45
    #: Don’t change current role.
46 1
    OFPCR_ROLE_NOCHANGE = 0
47
    #: Default role, full access.
48 1
    OFPCR_ROLE_EQUAL = 1
49
    #: Full access, at most one master.
50 1
    OFPCR_ROLE_MASTER = 2
51
    #: Read-only access.
52 1
    OFPCR_ROLE_SLAVE = 3
53
54
55 1
class TableFeaturePropType(IntEnum):
56
    """Table Property Types.
57
58
    Low order bit cleared indicates a property for a regular Flow Entry.
59
    Low order bit set indicates a property for the Table-Miss Flow Entry.
60
    """
61
62
    # Instructions property.
63 1
    OFPTFPT_INSTRUCTIONS = 0
64
    # Instructions for table-miss.
65 1
    OFPTFPT_INSTRUCTIONS_MISS = 1
66
    # Next Table property.
67 1
    OFPTFPT_NEXT_TABLES = 2
68
    # Next Table for table-miss.
69 1
    OFPTFPT_NEXT_TABLES_MISS = 3
70
    # Write Actions property.
71 1
    OFPTFPT_WRITE_ACTIONS = 4
72
    # Write Actions for table-miss.
73 1
    OFPTFPT_WRITE_ACTIONS_MISS = 5
74
    # Apply Actions property.
75 1
    OFPTFPT_APPLY_ACTIONS = 6
76
    # Apply Actions for table-miss.
77 1
    OFPTFPT_APPLY_ACTIONS_MISS = 7
78
    # Match property.
79 1
    OFPTFPT_MATCH = 8
80
    # Wildcards property.
81 1
    OFPTFPT_WILDCARDS = 10
82
    # Write Set-Field property.
83 1
    OFPTFPT_WRITE_SETFIELD = 12
84
    # Write Set-Field for table-miss.
85 1
    OFPTFPT_WRITE_SETFIELD_MISS = 13
86
    # Apply Set-Field property.
87 1
    OFPTFPT_APPLY_SETFIELD = 14
88
    # Apply Set-Field for table-miss.
89 1
    OFPTFPT_APPLY_SETFIELD_MISS = 15
90
    # Experimenter property.
91 1
    OFPTFPT_EXPERIMENTER = 0xFFFE
92
    # Experimenter for table-miss.
93 1
    OFPTFPT_EXPERIMENTER_MISS = 0xFFFF
94
95 1
    def find_class(self):
96
        """Return a class related with this type."""
97
        if self.value <= 1:
98
            return InstructionsProperty
99
        elif self.value <= 3:
100
            return NextTablesProperty
101
        elif self.value <= 7:
102
            return ActionsProperty
103
104
        return OxmProperty
105
106
107 1
class MultipartType(IntEnum):
108
    """Types of Multipart Messages, both Request and Reply."""
109
110
    #: Description of this OpenFlow switch.
111
    #: The request body is empty.
112
    #: The reply body is struct ofp_desc.
113 1
    OFPMP_DESC = 0
114
115
    #: Individual flow statistics.
116
    #: The request body is struct ofp_flow_stats_request.
117
    #: The reply body is an array of struct ofp_flow_stats.
118 1
    OFPMP_FLOW = 1
119
120
    #: Aggregate flow statistics.
121
    #: The request body is struct ofp_aggregate_stats_request.
122
    #: The reply body is struct ofp_aggregate_stats_reply.
123 1
    OFPMP_AGGREGATE = 2
124
125
    #: Flow table statistics.
126
    #: The request body is empty.
127
    #: The reply body is an array of struct ofp_table_stats.
128 1
    OFPMP_TABLE = 3
129
130
    #: Port statistics.
131
    #: The request body is struct ofp_port_stats_request.
132
    #: The reply body is an array of struct ofp_port_stats.
133 1
    OFPMP_PORT_STATS = 4
134
135
    #: Queue statistics for a port.
136
    #: The request body is struct ofp_queue_stats_request.
137
    #: The reply body is an array of struct ofp_queue_stats.
138 1
    OFPMP_QUEUE = 5
139
140
    #: Group counter statistics.
141
    #: The request body is struct ofp_group_stats_request.
142
    #: The reply is an array of struct ofp_group_stats.
143 1
    OFPMP_GROUP = 6
144
145
    #: Group description.
146
    #: The request body is empty.
147
    #: The reply body is an array of struct ofp_group_desc_stats.
148 1
    OFPMP_GROUP_DESC = 7
149
150
    #: Group features.
151
    #: The request body is empty.
152
    #: The reply body is struct ofp_group_features.
153 1
    OFPMP_GROUP_FEATURES = 8
154
155
    #: Meter statistics.
156
    #: The request body is struct ofp_meter_multipart_requests.
157
    #: The reply body is an array of struct ofp_meter_stats.
158 1
    OFPMP_METER = 9
159
160
    #: Meter configuration.
161
    #: The request body is struct ofp_meter_multipart_requests.
162
    #: The reply body is an array of struct ofp_meter_config.
163 1
    OFPMP_METER_CONFIG = 10
164
165
    #: Meter features.
166
    #: The request body is empty.
167
    #: The reply body is struct ofp_meter_features.
168 1
    OFPMP_METER_FEATURES = 11
169
170
    #: Table features.
171
    #: The request body is either empty or contains an array of
172
    #: struct ofp_table_features containing the controller’s desired view of
173
    #: the switch. If the switch is unable to set the specified view an error
174
    #: is returned.
175
    #: The reply body is an array of struct ofp_table_features.
176 1
    OFPMP_TABLE_FEATURES = 12
177
178
    #: Port description.
179
    #: The request body is empty.
180
    #: The reply body is an array of struct ofp_port.
181 1
    OFPMP_PORT_DESC = 13
182
183
    #: Experimenter extension.
184
    #: The request and reply bodies begin with
185
    #: struct ofp_experimenter_multipart_header.
186
    #: The request and reply bodies are otherwise experimenter-defined.
187 1
    OFPMP_EXPERIMENTER = 0xffff
188
189
190
# Classes
191
192 1
class Bucket(GenericStruct):
193
    """Bucket for use in groups."""
194
195 1
    length = UBInt16()
196 1
    weight = UBInt16()
197 1
    watch_port = UBInt32()
198 1
    watch_group = UBInt32()
199 1
    pad = Pad(4)
200 1
    actions = FixedTypeList(ActionHeader)
201
202 1
    def __init__(self, length=None, weight=None, watch_port=None,
203
                 watch_group=None, actions=None):
204
        """Initialize all instance variables.
205
206
        Args:
207
            length (int): Length the bucket in bytes, including this header and
208
                any padding to make it 64-bit aligned.
209
            weight (int): Relative weight of bucket. Only defined for select
210
                groups.
211
            watch_port (int): Port whose state affects whether this bucket is
212
                live. Only required for fast failover groups.
213
            watch_group (int): Group whose state affects whether this bucket is
214
                live. Only required for fast failover groups.
215
            actions (~pyof.v0x04.common.action.ListOfActions): The action
216
                length is inferred from the length field in the header.
217
        """
218 1
        super().__init__()
219 1
        self.length = length
220 1
        self.weight = weight
221 1
        self.watch_port = watch_port
222 1
        self.watch_group = watch_group
223 1
        self.actions = actions
224
225
226 1
class BucketCounter(GenericStruct):
227
    """Used in group stats replies."""
228
229
    #: Number of packets processed by bucket.
230 1
    packet_count = UBInt64()
231
    #: Number of bytes processed by bucket.
232 1
    byte_count = UBInt64()
233
234 1
    def __init__(self, packet_count=None, byte_count=None):
235
        """Create BucketCounter with the optional parameters below.
236
237
        Args:
238
            packet_count (int): Number of packets processed by bucket.
239
            byte_count (int): Number of bytes processed by bucket.
240
        """
241
        super().__init__()
242
        self.packet_count = packet_count
243
        self.byte_count = byte_count
244
245
246 1
class ListOfBucketCounter(FixedTypeList):
247
    """List of BucketCounter.
248
249
    Represented by instances of BucketCounter.
250
    """
251
252 1
    def __init__(self, items=None):
253
        """Create a ListOfBucketCounter with the optional parameters below.
254
255
        Args:
256
            items (|BucketCounter_v0x04|): Instance or a list of instances.
257
        """
258 1
        super().__init__(pyof_class=BucketCounter, items=items)
259
260
261
# Base Classes for other messages - not meant to be directly used, so, because
262
# of that, they will not be inserted on the __all__ attribute.
263
264
265 1
class AsyncConfig(GenericMessage):
266
    """Asynchronous message configuration base class.
267
268
    Common structure for SetAsync and GetAsyncReply messages.
269
270
    AsyncConfig contains three 2-element arrays. Each array controls whether
271
    the controller receives asynchronous messages with a specific
272
    :class:`~pyof.v0x04.common.header.Type`. Within each array, element
273
    0 specifies messages of interest when the controller has a OFPCR_ROLE_EQUAL
274
    or OFPCR_ROLE_MASTER role; element 1, when the controller has a
275
    OFPCR_ROLE_SLAVE role. Each array element is a bit-mask in which a 0-bit
276
    disables receiving a message sent with the reason code corresponding to the
277
    bit index and a 1-bit enables receiving it.
278
    """
279
280
    #: OpenFlow :class:`~pyof.v0x04.common.header.Header`
281
    #: OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC.
282 1
    header = Header()
283 1
    packet_in_mask1 = UBInt32(enum_ref=PacketInReason)
284 1
    packet_in_mask2 = UBInt32(enum_ref=PacketInReason)
285 1
    port_status_mask1 = UBInt32(enum_ref=PortReason)
286 1
    port_status_mask2 = UBInt32(enum_ref=PortReason)
287 1
    flow_removed_mask1 = UBInt32(enum_ref=FlowRemovedReason)
288 1
    flow_removed_mask2 = UBInt32(enum_ref=FlowRemovedReason)
289
290 1
    def __init__(self, xid=None, packet_in_mask1=None, packet_in_mask2=None,
291
                 port_status_mask1=None, port_status_mask2=None,
292
                 flow_removed_mask1=None, flow_removed_mask2=None):
293
        """Create a AsyncConfig with the optional parameters below.
294
295
        Args:
296
            xid (int): xid to be used on the message header.
297
            packet_in_mask1
298
                (~pyof.v0x04.asynchronous.packet_in.PacketInReason):
299
                    A instance of PacketInReason
300
            packet_in_mask2
301
                (~pyof.v0x04.asynchronous.packet_in.PacketInReason):
302
                    A instance of PacketInReason
303
            port_status_mask1
304
                (~pyof.v0x04.asynchronous.port_status.PortReason):
305
                    A instance of PortReason
306
            port_status_mask2
307
                (~pyof.v0x04.asynchronous.port_status.PortReason):
308
                    A instance of PortReason
309
            flow_removed_mask1
310
                (~pyof.v0x04.asynchronous.flow_removed.FlowRemoved):
311
                    A instance of FlowRemoved.
312
            flow_removed_mask2
313
                (~pyof.v0x04.asynchronous.flow_removed.FlowRemoved):
314
                    A instance of FlowRemoved.
315
        """
316 1
        super().__init__(xid)
317 1
        self.packet_in_mask1 = packet_in_mask1
318 1
        self.packet_in_mask2 = packet_in_mask2
319 1
        self.port_status_mask1 = port_status_mask1
320 1
        self.port_status_mask2 = port_status_mask2
321 1
        self.flow_removed_mask1 = flow_removed_mask1
322 1
        self.flow_removed_mask2 = flow_removed_mask2
323
324
325 1
class RoleBaseMessage(GenericMessage):
326
    """Role basic structure for RoleRequest and RoleReply messages."""
327
328
    #: :class:`~pyof.v0x04.common.header.Header`
329
    #: Type OFPT_ROLE_REQUEST/OFPT_ROLE_REPLY.
330 1
    header = Header()
331
    #: One of NX_ROLE_*. (:class:`~.controller2switch.common.ControllerRole`)
332 1
    role = UBInt32(enum_ref=ControllerRole)
333
    #: Align to 64 bits.
334 1
    pad = Pad(4)
335
    #: Master Election Generation Id.
336 1
    generation_id = UBInt64()
337
338 1
    def __init__(self, xid=None, role=None, generation_id=None):
339
        """Create a RoleBaseMessage with the optional parameters below.
340
341
        Args:
342
            xid (int): OpenFlow xid to the header.
343
            role (:class:`~.controller2switch.common.ControllerRole`): .
344
            generation_id (int): Master Election Generation Id.
345
        """
346 1
        super().__init__(xid)
347 1
        self.role = role
348 1
        self.generation_id = generation_id
349
350
351 1
class SwitchConfig(GenericMessage):
352
    """Used as base class for SET_CONFIG and GET_CONFIG_REPLY messages."""
353
354
    #: OpenFlow :class:`~pyof.v0x04.common.header.Header`
355 1
    header = Header()
356 1
    flags = UBInt16(enum_ref=ConfigFlag)
357 1
    miss_send_len = UBInt16()
358
359 1
    def __init__(self, xid=None, flags=ConfigFlag.OFPC_FRAG_NORMAL,
360
                 miss_send_len=ControllerMaxLen.OFPCML_NO_BUFFER):
361
        """Create a SwitchConfig with the optional parameters below.
362
363
        Args:
364
            xid (int): xid to be used on the message header.
365
            flags (ConfigFlag): OFPC_* flags.
366
            miss_send_len (int): UBInt16 max bytes of new flow that the
367
                datapath should send to the controller.
368
        """
369 1
        super().__init__(xid)
370 1
        self.flags = flags
371 1
        self.miss_send_len = miss_send_len
372
373
374
# Multipart body
375
376 1
class ExperimenterMultipartHeader(GenericStruct):
377
    """Body for ofp_multipart_request/reply of type OFPMP_EXPERIMENTER."""
378
379 1
    experimenter = UBInt32()
380 1
    exp_type = UBInt32()
381
    #: Followed by experimenter-defined arbitrary data.
382
383 1
    def __init__(self, experimenter=None, exp_type=None):
384
        """Create a ExperimenterMultipartHeader with the parameters below.
385
386
        Args:
387
            experimenter: Experimenter ID which takes the same form as in
388
                struct ofp_experimenter_header (
389
                :class:`~pyof.v0x04.symmetric.experimenter.ExperimenterHeader`)
390
            exp_type: Experimenter defined.
391
        """
392
        super().__init__()
393
        self.experimenter = experimenter
394
        self.exp_type = exp_type
395
396
397 1
class Property(GenericStruct):
398
    """Table Property class.
399
400
    This class represents a Table Property generic structure.
401
    """
402
403 1
    property_type = UBInt16(enum_ref=TableFeaturePropType)
404 1
    length = UBInt16(4)
405
406 1
    def __init__(self, property_type=None):
407
        """Create a Property with the optional parameters below.
408
409
        Args:
410
            type(|TableFeaturePropType_v0x04|):
411
                Property Type value of this instance.
412
        """
413
        super().__init__()
414
        self.property_type = property_type
415
416 1
    def pack(self, value=None):
417
        """Pack method used to update the length of instance and  packing.
418
419
        Args:
420
            value: Structure to be packed.
421
        """
422
        self.update_length()
423
        return super().pack(value)
424
425 1
    def unpack(self, buff=None, offset=0):
426
        """Unpack *buff* into this object.
427
428
        This method will convert a binary data into a readable value according
429
        to the attribute format.
430
431
        Args:
432
            buff (bytes): Binary buffer.
433
            offset (int): Where to begin unpacking.
434
435
        Raises:
436
            :exc:`~.exceptions.UnpackException`: If unpack fails.
437
438
        """
439
        property_type = UBInt16(enum_ref=TableFeaturePropType)
440
        property_type.unpack(buff, offset)
441
        self.__class__ = TableFeaturePropType(property_type.value).find_class()
442
443
        length = UBInt16()
444
        length.unpack(buff, offset=offset+2)
445
        super().unpack(buff[:offset+length.value], offset=offset)
446
447 1
    def update_length(self):
448
        """Update the length of current instance."""
449
        self.length = self.get_size()
450
451
452 1
class InstructionsProperty(Property):
453
    """Instructions property.
454
455
    This class represents Property with the following types:
456
        OFPTFPT_INSTRUCTIONS
457
        OFPTFPT_INSTRUCTIONS_MISS
458
    """
459
460 1
    instruction_ids = ListOfInstruction()
461
462 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_INSTRUCTIONS,
463
                 instruction_ids=None):
464
        """Create a InstructionsProperty with the optional parameters below.
465
466
        Args:
467
            type(|TableFeaturePropType_v0x04|):
468
                Property Type value of this instance.
469
            next_table_ids(|ListOfInstruction_v0x04|):
470
                List of InstructionGotoTable instances.
471
        """
472
        super().__init__(property_type=property_type)
473
        self.instruction_ids = instruction_ids if instruction_ids else []
474
        self.update_length()
475
476
477 1
class NextTablesProperty(Property):
478
    """Next Tables Property.
479
480
    This class represents Property with the following types:
481
        OFPTFPT_NEXT_TABLES
482
        OFPTFPT_NEXT_TABLES_MISS
483
    """
484
485 1
    next_table_ids = ListOfInstruction()
486
487 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_NEXT_TABLES,
488
                 next_table_ids=None):
489
        """Create a NextTablesProperty with the optional parameters below.
490
491
        Args:
492
            type(|TableFeaturePropType_v0x04|):
493
                Property Type value of this instance.
494
            next_table_ids (|ListOfInstruction_v0x04|):
495
                List of InstructionGotoTable instances.
496
        """
497
        super().__init__(property_type)
498
        self.next_table_ids = (ListOfInstruction() if next_table_ids is None
499
                               else next_table_ids)
500
        self.update_length()
501
502
503 1
class ActionsProperty(Property):
504
    """Actions Property.
505
506
    This class represents Property with the following type:
507
        OFPTFPT_WRITE_ACTIONS
508
        OFPTFPT_WRITE_ACTIONS_MISS
509
        OFPTFPT_APPLY_ACTIONS
510
        OFPTFPT_APPLY_ACTIONS_MISS
511
    """
512
513 1
    action_ids = ListOfActions()
514
515 1
    def __init__(self,
516
                 property_type=TableFeaturePropType.OFPTFPT_WRITE_ACTIONS,
517
                 action_ids=None):
518
        """Create a ActionsProperty with the optional parameters below.
519
520
        Args:
521
            type(|TableFeaturePropType_v0x04|):
522
                Property Type value of this instance.
523
            action_ids(|ListOfActions_v0x04|):
524
                List of Action instances.
525
        """
526
        super().__init__(property_type)
527
        self.action_ids = action_ids if action_ids else ListOfActions()
528
        self.update_length()
529
530
531 1
class OxmProperty(Property):
532
    """Match, Wildcard or Set-Field property.
533
534
    This class represents Property with the following types:
535
        OFPTFPT_MATCH
536
        OFPTFPT_WILDCARDS
537
        OFPTFPT_WRITE_SETFIELD
538
        OFPTFPT_WRITE_SETFIELD_MISS
539
        OFPTFPT_APPLY_SETFIELD
540
        OFPTFPT_APPLY_SETFIELD_MISS
541
    """
542
543 1
    oxm_ids = ListOfOxmHeader()
544
545 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_MATCH,
546
                 oxm_ids=None):
547
        """Create an OxmProperty with the optional parameters below.
548
549
        Args:
550
            type(|TableFeaturePropType_v0x04|):
551
                Property Type value of this instance.
552
            oxm_ids(|ListOfOxmHeader_v0x04|):
553
                List of OxmHeader instances.
554
        """
555
        super().__init__(property_type)
556
        self.oxm_ids = ListOfOxmHeader() if oxm_ids is None else oxm_ids
557
        self.update_length()
558
559
560 1
class ListOfProperty(FixedTypeList):
561
    """List of Table Property.
562
563
    Represented by instances of Property.
564
    """
565
566 1
    def __init__(self, items=None):
567
        """Create a ListOfProperty with the optional parameters below.
568
569
        Args:
570
            items (|Property_v0x04|): Instance or a list of instances.
571
        """
572 1
        super().__init__(pyof_class=Property, items=items)
573
574
575 1
class TableFeatures(GenericStruct):
576
    """Abstration of common class Table Features.
577
578
    Body for MultipartRequest of type OFPMP_TABLE_FEATURES.
579
    Body of reply to OFPMP_TABLE_FEATURES request.
580
    """
581
582 1
    length = UBInt16()
583
    # /* Identifier of table.  Lower numbered tables are consulted first. */
584 1
    table_id = UBInt8()
585
    # /* Align to 64-bits. */
586 1
    pad = Pad(5)
587 1
    name = Char(length=OFP_MAX_TABLE_NAME_LEN)
588
    # /* Bits of metadata table can match. */
589 1
    metadata_match = UBInt64()
590
    # /* Bits of metadata table can write. */
591 1
    metadata_write = UBInt64()
592
    # /* Bitmap of OFPTC_* values */
593 1
    config = UBInt32()
594
    # /* Max number of entries supported. */
595 1
    max_entries = UBInt32()
596
    # /* Table Feature Property list */
597 1
    properties = ListOfProperty()
598
599 1
    def __init__(self, table_id=Table.OFPTT_ALL, name="",
600
                 metadata_match=0xFFFFFFFFFFFFFFFF,
601
                 metadata_write=0xFFFFFFFFFFFFFFFF,
602
                 config=0,
603
                 max_entries=0,
604
                 properties=None):
605
        """Create a TableFeatures with the optional parameters below.
606
607
        Args:
608
            table_id(int): Indetifier of table.The default value
609
                OFPTT_ALL(``0xff``) will apply the configuration to all tables
610
                in the switch.
611
            name(Char): Characters representing the table name.
612
            metadata_match(int): Indicate the bits of the metadata field that
613
               the table can match on.The default value ``0xFFFFFFFFFFFFFFFF``
614
               indicates that the table can match the full metadata field.
615
            metadata_write(int): Indicates the bits of the metadata field that
616
               the table can write using the OFPIT_WRITE_METADATA instruction.
617
               The default value ``0xFFFFFFFFFFFFFFFF`` indicates that the
618
               table can write the full metadata field.
619
            config(int): Field reseved for future use.
620
            max_entries(int): Describe the maximum number of flow entries that
621
                can be inserted into that table.
622
            properties(~pyof.v0x04.controller2switch.common.ListOfProperty):
623
                List of Property intances.
624
        """
625 1
        super().__init__()
626 1
        self.table_id = table_id
627 1
        self.name = name
628 1
        self.metadata_match = metadata_match
629 1
        self.metadata_write = metadata_write
630 1
        self.config = config
631 1
        self.max_entries = max_entries
632 1
        self.properties = (ListOfProperty() if properties is None else
633
                           properties)
634 1
        self.update_length()
635
636 1
    def pack(self, value=None):
637
        """Pack method used to update the length of instance and packing.
638
639
        Args:
640
            value: Structure to be packed.
641
        """
642 1
        self.update_length()
643 1
        return super().pack(value)
644
645 1
    def update_length(self):
646
        """Update the length of current instance."""
647 1
        self.length = self.get_size()
648
649 1
    def unpack(self, buff=None, offset=0):
650
        """Unpack *buff* into this object.
651
652
        This method will convert a binary data into a readable value according
653
        to the attribute format.
654
655
        Args:
656
            buff (bytes): Binary buffer.
657
            offset (int): Where to begin unpacking.
658
659
        Raises:
660
            :exc:`~.exceptions.UnpackException`: If unpack fails.
661
662
        """
663 1
        length = UBInt16()
664 1
        length.unpack(buff, offset)
665
        super().unpack(buff[:offset+length.value], offset)
666