Passed
Push — master ( 259507...dfca6c )
by Humberto
01:30 queued 12s
created

Bucket.__repr__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

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