Passed
Pull Request — master (#576)
by Rogerio
01:59
created

TableFeatures.__init__()   A

Complexity

Conditions 2

Size

Total Lines 37
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 37
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
        """
219 1
        super().__init__()
220 1
        self.length = length
221 1
        self.weight = weight
222 1
        self.watch_port = watch_port
223 1
        self.watch_group = watch_group
224 1
        self.actions = actions
225
226 1
    def unpack(self, buff, offset=0):
227
        """Unpack bucket.
228
229
        Bucket has a dynamic content with length as first field.
230
        The length is needed to compute the total buffer offset.
231
        """
232 1
        length = UBInt16()
233 1
        length.unpack(buff, offset=offset)
234 1
        super().unpack(buff[:offset + length.value], offset=offset)
235
236 1
    def get_size(self, value=None):
237
        """
238
        Return the Bucket length.
239
240
        If the object length is None, returns the minimum size.
241
        """
242 1
        if self.length is None:
243 1
            return super().get_size()
244
245 1
        return self.length
246
247
248 1
class BucketCounter(GenericStruct):
249
    """Used in group stats replies."""
250
251
    #: Number of packets processed by bucket.
252 1
    packet_count = UBInt64()
253
    #: Number of bytes processed by bucket.
254 1
    byte_count = UBInt64()
255
256 1
    def __init__(self, packet_count=None, byte_count=None):
257
        """Create BucketCounter with the optional parameters below.
258
259
        Args:
260
            packet_count (int): Number of packets processed by bucket.
261
            byte_count (int): Number of bytes processed by bucket.
262
263
        """
264
        super().__init__()
265
        self.packet_count = packet_count
266
        self.byte_count = byte_count
267
268
269 1
class ListOfBucketCounter(FixedTypeList):
270
    """List of BucketCounter.
271
272
    Represented by instances of BucketCounter.
273
    """
274
275 1
    def __init__(self, items=None):
276
        """Create a ListOfBucketCounter with the optional parameters below.
277
278
        Args:
279
            items (|BucketCounter_v0x04|): Instance or a list of instances.
280
281
        """
282 1
        super().__init__(pyof_class=BucketCounter, items=items)
283
284
285
# Base Classes for other messages - not meant to be directly used, so, because
286
# of that, they will not be inserted on the __all__ attribute.
287
288
289 1
class AsyncConfig(GenericMessage):
290
    """Asynchronous message configuration base class.
291
292
    Common structure for SetAsync and GetAsyncReply messages.
293
294
    AsyncConfig contains three 2-element arrays. Each array controls whether
295
    the controller receives asynchronous messages with a specific
296
    :class:`~pyof.v0x04.common.header.Type`. Within each array, element
297
    0 specifies messages of interest when the controller has a OFPCR_ROLE_EQUAL
298
    or OFPCR_ROLE_MASTER role; element 1, when the controller has a
299
    OFPCR_ROLE_SLAVE role. Each array element is a bit-mask in which a 0-bit
300
    disables receiving a message sent with the reason code corresponding to the
301
    bit index and a 1-bit enables receiving it.
302
    """
303
304
    #: OpenFlow :class:`~pyof.v0x04.common.header.Header`
305
    #: OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC.
306 1
    header = Header()
307 1
    packet_in_mask1 = UBInt32(enum_ref=PacketInReason)
308 1
    packet_in_mask2 = UBInt32(enum_ref=PacketInReason)
309 1
    port_status_mask1 = UBInt32(enum_ref=PortReason)
310 1
    port_status_mask2 = UBInt32(enum_ref=PortReason)
311 1
    flow_removed_mask1 = UBInt32(enum_ref=FlowRemovedReason)
312 1
    flow_removed_mask2 = UBInt32(enum_ref=FlowRemovedReason)
313
314 1
    def __init__(self, xid=None, packet_in_mask1=None, packet_in_mask2=None,
315
                 port_status_mask1=None, port_status_mask2=None,
316
                 flow_removed_mask1=None, flow_removed_mask2=None):
317
        """Create a AsyncConfig with the optional parameters below.
318
319
        Args:
320
            xid (int): xid to be used on the message header.
321
            packet_in_mask1
322
                (~pyof.v0x04.asynchronous.packet_in.PacketInReason):
323
                    A instance of PacketInReason
324
            packet_in_mask2
325
                (~pyof.v0x04.asynchronous.packet_in.PacketInReason):
326
                    A instance of PacketInReason
327
            port_status_mask1
328
                (~pyof.v0x04.asynchronous.port_status.PortReason):
329
                    A instance of PortReason
330
            port_status_mask2
331
                (~pyof.v0x04.asynchronous.port_status.PortReason):
332
                    A instance of PortReason
333
            flow_removed_mask1
334
                (~pyof.v0x04.asynchronous.flow_removed.FlowRemoved):
335
                    A instance of FlowRemoved.
336
            flow_removed_mask2
337
                (~pyof.v0x04.asynchronous.flow_removed.FlowRemoved):
338
                    A instance of FlowRemoved.
339
340
        """
341 1
        super().__init__(xid)
342 1
        self.packet_in_mask1 = packet_in_mask1
343 1
        self.packet_in_mask2 = packet_in_mask2
344 1
        self.port_status_mask1 = port_status_mask1
345 1
        self.port_status_mask2 = port_status_mask2
346 1
        self.flow_removed_mask1 = flow_removed_mask1
347 1
        self.flow_removed_mask2 = flow_removed_mask2
348
349
350 1
class RoleBaseMessage(GenericMessage):
351
    """Role basic structure for RoleRequest and RoleReply messages."""
352
353
    #: :class:`~pyof.v0x04.common.header.Header`
354
    #: Type OFPT_ROLE_REQUEST/OFPT_ROLE_REPLY.
355 1
    header = Header()
356
    #: One of NX_ROLE_*. (:class:`~.controller2switch.common.ControllerRole`)
357 1
    role = UBInt32(enum_ref=ControllerRole)
358
    #: Align to 64 bits.
359 1
    pad = Pad(4)
360
    #: Master Election Generation Id.
361 1
    generation_id = UBInt64()
362
363 1
    def __init__(self, xid=None, role=None, generation_id=None):
364
        """Create a RoleBaseMessage with the optional parameters below.
365
366
        Args:
367
            xid (int): OpenFlow xid to the header.
368
            role (:class:`~.controller2switch.common.ControllerRole`): .
369
            generation_id (int): Master Election Generation Id.
370
371
        """
372 1
        super().__init__(xid)
373 1
        self.role = role
374 1
        self.generation_id = generation_id
375
376
377 1
class SwitchConfig(GenericMessage):
378
    """Used as base class for SET_CONFIG and GET_CONFIG_REPLY messages."""
379
380
    #: OpenFlow :class:`~pyof.v0x04.common.header.Header`
381 1
    header = Header()
382 1
    flags = UBInt16(enum_ref=ConfigFlag)
383 1
    miss_send_len = UBInt16()
384
385 1
    def __init__(self, xid=None, flags=ConfigFlag.OFPC_FRAG_NORMAL,
386
                 miss_send_len=ControllerMaxLen.OFPCML_NO_BUFFER):
387
        """Create a SwitchConfig with the optional parameters below.
388
389
        Args:
390
            xid (int): xid to be used on the message header.
391
            flags (ConfigFlag): OFPC_* flags.
392
            miss_send_len (int): UBInt16 max bytes of new flow that the
393
                datapath should send to the controller.
394
395
        """
396 1
        super().__init__(xid)
397 1
        self.flags = flags
398 1
        self.miss_send_len = miss_send_len
399
400
401
# Multipart body
402
403 1
class ExperimenterMultipartHeader(GenericStruct):
404
    """Body for ofp_multipart_request/reply of type OFPMP_EXPERIMENTER."""
405
406 1
    experimenter = UBInt32()
407 1
    exp_type = UBInt32()
408
    #: Followed by experimenter-defined arbitrary data.
409
410 1
    def __init__(self, experimenter=None, exp_type=None):
411
        """Create a ExperimenterMultipartHeader with the parameters below.
412
413
        Args:
414
            experimenter: Experimenter ID which takes the same form as in
415
                struct ofp_experimenter_header (
416
                :class:`~pyof.v0x04.symmetric.experimenter.ExperimenterHeader`)
417
            exp_type: Experimenter defined.
418
419
        """
420
        super().__init__()
421
        self.experimenter = experimenter
422
        self.exp_type = exp_type
423
424
425 1
class Property(GenericStruct):
426
    """Table Property class.
427
428
    This class represents a Table Property generic structure.
429
    """
430
431 1
    property_type = UBInt16(enum_ref=TableFeaturePropType)
432 1
    length = UBInt16(4)
433
434 1
    def __init__(self, property_type=None):
435
        """Create a Property with the optional parameters below.
436
437
        Args:
438
            type(|TableFeaturePropType_v0x04|):
439
                Property Type value of this instance.
440
441
        """
442
        super().__init__()
443
        self.property_type = property_type
444
445 1
    def pack(self, value=None):
446
        """Pack method used to update the length of instance and  packing.
447
448
        Args:
449
            value: Structure to be packed.
450
451
        """
452
        self.update_length()
453
        return super().pack(value)
454
455 1
    def unpack(self, buff=None, offset=0):
456
        """Unpack *buff* into this object.
457
458
        This method will convert a binary data into a readable value according
459
        to the attribute format.
460
461
        Args:
462
            buff (bytes): Binary buffer.
463
            offset (int): Where to begin unpacking.
464
465
        Raises:
466
            :exc:`~.exceptions.UnpackException`: If unpack fails.
467
468
        """
469
        property_type = UBInt16(enum_ref=TableFeaturePropType)
470
        property_type.unpack(buff, offset)
471
        self.__class__ = TableFeaturePropType(property_type.value).find_class()
472
473
        length = UBInt16()
474
        length.unpack(buff, offset=offset+2)
475
        super().unpack(buff[:offset+length.value], offset=offset)
476
477 1
    def update_length(self):
478
        """Update the length of current instance."""
479
        self.length = self.get_size()
480
481
482 1
class InstructionsProperty(Property):
483
    """Instructions property.
484
485
    This class represents Property with the following types:
486
        OFPTFPT_INSTRUCTIONS
487
        OFPTFPT_INSTRUCTIONS_MISS
488
    """
489
490 1
    instruction_ids = ListOfInstruction()
491
492 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_INSTRUCTIONS,
493
                 instruction_ids=None):
494
        """Create a InstructionsProperty with the optional parameters below.
495
496
        Args:
497
            type(|TableFeaturePropType_v0x04|):
498
                Property Type value of this instance.
499
            next_table_ids(|ListOfInstruction_v0x04|):
500
                List of InstructionGotoTable instances.
501
502
        """
503
        super().__init__(property_type=property_type)
504
        self.instruction_ids = instruction_ids if instruction_ids else []
505
        self.update_length()
506
507
508 1
class NextTablesProperty(Property):
509
    """Next Tables Property.
510
511
    This class represents Property with the following types:
512
        OFPTFPT_NEXT_TABLES
513
        OFPTFPT_NEXT_TABLES_MISS
514
    """
515
516 1
    next_table_ids = ListOfInstruction()
517
518 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_NEXT_TABLES,
519
                 next_table_ids=None):
520
        """Create a NextTablesProperty with the optional parameters below.
521
522
        Args:
523
            type(|TableFeaturePropType_v0x04|):
524
                Property Type value of this instance.
525
            next_table_ids (|ListOfInstruction_v0x04|):
526
                List of InstructionGotoTable instances.
527
528
        """
529
        super().__init__(property_type)
530
        self.next_table_ids = (ListOfInstruction() if next_table_ids is None
531
                               else next_table_ids)
532
        self.update_length()
533
534
535 1
class ActionsProperty(Property):
536
    """Actions Property.
537
538
    This class represents Property with the following type:
539
        OFPTFPT_WRITE_ACTIONS
540
        OFPTFPT_WRITE_ACTIONS_MISS
541
        OFPTFPT_APPLY_ACTIONS
542
        OFPTFPT_APPLY_ACTIONS_MISS
543
    """
544
545 1
    action_ids = ListOfActions()
546
547 1
    def __init__(self,
548
                 property_type=TableFeaturePropType.OFPTFPT_WRITE_ACTIONS,
549
                 action_ids=None):
550
        """Create a ActionsProperty with the optional parameters below.
551
552
        Args:
553
            type(|TableFeaturePropType_v0x04|):
554
                Property Type value of this instance.
555
            action_ids(|ListOfActions_v0x04|):
556
                List of Action instances.
557
558
        """
559
        super().__init__(property_type)
560
        self.action_ids = action_ids if action_ids else ListOfActions()
561
        self.update_length()
562
563
564 1
class OxmProperty(Property):
565
    """Match, Wildcard or Set-Field property.
566
567
    This class represents Property with the following types:
568
        OFPTFPT_MATCH
569
        OFPTFPT_WILDCARDS
570
        OFPTFPT_WRITE_SETFIELD
571
        OFPTFPT_WRITE_SETFIELD_MISS
572
        OFPTFPT_APPLY_SETFIELD
573
        OFPTFPT_APPLY_SETFIELD_MISS
574
    """
575
576 1
    oxm_ids = ListOfOxmHeader()
577
578 1
    def __init__(self, property_type=TableFeaturePropType.OFPTFPT_MATCH,
579
                 oxm_ids=None):
580
        """Create an OxmProperty with the optional parameters below.
581
582
        Args:
583
            type(|TableFeaturePropType_v0x04|):
584
                Property Type value of this instance.
585
            oxm_ids(|ListOfOxmHeader_v0x04|):
586
                List of OxmHeader instances.
587
588
        """
589
        super().__init__(property_type)
590
        self.oxm_ids = ListOfOxmHeader() if oxm_ids is None else oxm_ids
591
        self.update_length()
592
593
594 1
class ListOfProperty(FixedTypeList):
595
    """List of Table Property.
596
597
    Represented by instances of Property.
598
    """
599
600 1
    def __init__(self, items=None):
601
        """Create a ListOfProperty with the optional parameters below.
602
603
        Args:
604
            items (|Property_v0x04|): Instance or a list of instances.
605
606
        """
607 1
        super().__init__(pyof_class=Property, items=items)
608
609
610 1
class TableFeatures(GenericStruct):
611
    """Abstration of common class Table Features.
612
613
    Body for MultipartRequest of type OFPMP_TABLE_FEATURES.
614
    Body of reply to OFPMP_TABLE_FEATURES request.
615
    """
616
617 1
    length = UBInt16()
618
    # /* Identifier of table.  Lower numbered tables are consulted first. */
619 1
    table_id = UBInt8()
620
    # /* Align to 64-bits. */
621 1
    pad = Pad(5)
622 1
    name = Char(length=OFP_MAX_TABLE_NAME_LEN)
623
    # /* Bits of metadata table can match. */
624 1
    metadata_match = UBInt64()
625
    # /* Bits of metadata table can write. */
626 1
    metadata_write = UBInt64()
627
    # /* Bitmap of OFPTC_* values */
628 1
    config = UBInt32()
629
    # /* Max number of entries supported. */
630 1
    max_entries = UBInt32()
631
    # /* Table Feature Property list */
632 1
    properties = ListOfProperty()
633
634 1
    def __init__(self, table_id=Table.OFPTT_ALL, name="",
635
                 metadata_match=0xFFFFFFFFFFFFFFFF,
636
                 metadata_write=0xFFFFFFFFFFFFFFFF,
637
                 config=0,
638
                 max_entries=0,
639
                 properties=None):
640
        """Create a TableFeatures with the optional parameters below.
641
642
        Args:
643
            table_id(int): Indetifier of table.The default value
644
                OFPTT_ALL(``0xff``) will apply the configuration to all tables
645
                in the switch.
646
            name(Char): Characters representing the table name.
647
            metadata_match(int): Indicate the bits of the metadata field that
648
               the table can match on.The default value ``0xFFFFFFFFFFFFFFFF``
649
               indicates that the table can match the full metadata field.
650
            metadata_write(int): Indicates the bits of the metadata field that
651
               the table can write using the OFPIT_WRITE_METADATA instruction.
652
               The default value ``0xFFFFFFFFFFFFFFFF`` indicates that the
653
               table can write the full metadata field.
654
            config(int): Field reseved for future use.
655
            max_entries(int): Describe the maximum number of flow entries that
656
                can be inserted into that table.
657
            properties(~pyof.v0x04.controller2switch.common.ListOfProperty):
658
                List of Property intances.
659
660
        """
661 1
        super().__init__()
662 1
        self.table_id = table_id
663 1
        self.name = name
664 1
        self.metadata_match = metadata_match
665 1
        self.metadata_write = metadata_write
666 1
        self.config = config
667 1
        self.max_entries = max_entries
668 1
        self.properties = (ListOfProperty() if properties is None else
669
                           properties)
670 1
        self.update_length()
671
672 1
    def pack(self, value=None):
673
        """Pack method used to update the length of instance and packing.
674
675
        Args:
676
            value: Structure to be packed.
677
678
        """
679 1
        self.update_length()
680 1
        return super().pack(value)
681
682 1
    def update_length(self):
683
        """Update the length of current instance."""
684 1
        self.length = self.get_size()
685
686 1
    def unpack(self, buff=None, offset=0):
687
        """Unpack *buff* into this object.
688
689
        This method will convert a binary data into a readable value according
690
        to the attribute format.
691
692
        Args:
693
            buff (bytes): Binary buffer.
694
            offset (int): Where to begin unpacking.
695
696
        Raises:
697
            :exc:`~.exceptions.UnpackException`: If unpack fails.
698
699
        """
700 1
        length = UBInt16()
701 1
        length.unpack(buff, offset)
702
        super().unpack(buff[:offset+length.value], offset)
703