Passed
Push — master ( ebaa29...24e02e )
by Humberto
01:58
created

Bucket.get_size()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 10
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nop 2
crap 2
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