Test Failed
Pull Request — master (#505)
by macartur
01:31
created

GroupFeatures.__init__()   A

Complexity

Conditions 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 12
cp 0
c 0
b 0
f 0
rs 9.0856
cc 1
crap 2
1
"""Controller replying state from datapath."""
2
3
# System imports
4
from enum import Enum
5
6
# Local source tree imports
7
from pyof.foundation.base import GenericBitMask, GenericMessage, GenericStruct
8
from pyof.foundation.basic_types import (
9
    BinaryData, Char, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32, UBInt64)
10
from pyof.foundation.constants import DESC_STR_LEN, SERIAL_NUM_LEN
11
from pyof.v0x04.common.flow_instructions import ListOfInstruction
12
from pyof.v0x04.common.flow_match import Match
13
from pyof.v0x04.common.header import Header, Type
14
from pyof.v0x04.common.port import Port
15
from pyof.v0x04.controller2switch.common import (
16
    Bucket, BucketCounter, ExperimenterMultipartHeader, MultipartTypes,
17
    TableFeatures)
18
from pyof.v0x04.controller2switch.meter_mod import (
19
    ListOfMeterBandHeader, MeterBandType, MeterFlags)
20
21
# Third-party imports
22
23
24
__all__ = ('MultipartReply', 'MultipartReplyFlags', 'AggregateStatsReply',
25
           'Desc', 'FlowStats', 'PortStats', 'QueueStats', 'GroupDescStats',
26
           'GroupFeatures', 'GroupStats', 'MeterConfig', 'MeterFeatures',
27
           'BandStats', 'ListOfBandStats', 'MeterStats', 'GroupCapabilities',
28
           'TableStats')
29
30
# Enum
31
32
33
class MultipartReplyFlags(Enum):
34
    """Flags for MultipartReply."""
35
36
    #: More replies to follow.
37
    OFPMPF_REPLY_MORE = 1 << 0
38
39
40
class GroupCapabilities(GenericBitMask):
41
    """Group configuration flags."""
42
43
    #: Support weight for select groups.
44
    OFPGFC_SELECT_WEIGHT = 1 << 0
45
    #: Support liveness for select groups.
46
    OFPGFC_SELECT_LIVENESS = 1 << 1
47
    #: Support chaining groups.
48
    OFPGFC_CHAINING = 1 << 2
49
    #: Chack chaining for loops and delete.
50
    OFPGFC_CHAINING_CHECKS = 1 << 3
51
52
# Classes
53
54
55
class MultipartReply(GenericMessage):
56
    """Reply datapath state.
57
58
    While the system is running, the controller may reply state from the
59
    datapath using the OFPT_MULTIPART_REPLY message.
60
    """
61
62
    #: Openflow :class:`~pyof.v0x04.common.header.Header`
63
    header = Header(message_type=Type.OFPT_MULTIPART_REPLY)
64
    #: One of the OFPMP_* constants.
65
    multipart_type = UBInt16(enum_ref=MultipartTypes)
66
    #: OFPMPF_REPLY_* flags.
67
    flags = UBInt16()
68
    #: Padding
69
    pad = Pad(4)
70
    #: Body of the reply
71
    body = BinaryData()
72
73
    def __init__(self, xid=None, multipart_type=None, flags=None, body=b''):
74
        """Create a MultipartReply with the optional parameters below.
75
76
        Args:
77
            xid (int): xid to the header.
78
            multipart_type (int): One of the OFPMP_* constants.
79
            flags (int): OFPMPF_REPLY_* flags.
80
            body (bytes): Body of the reply.
81
        """
82
        super().__init__(xid)
83
        self.multipart_type = multipart_type
84
        self.flags = flags
85
        self.body = body
86
87 View Code Duplication
    def pack(self, value=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
88
        """Pack a StatsReply using the object's attributes.
89
90
        This method will pack the attribute body and multipart_type before pack
91
        the StatsReply object, then will return this struct as a binary data.
92
93
        Returns:
94
            stats_reply_packed (bytes): Binary data with StatsReply packed.
95
96
        """
97
        buff = self.body
98
        if not value:
99
            value = self.body
100
101
        if value:
102
            if isinstance(value, (list, FixedTypeList)):
103
                obj = self._get_body_instance()
104
                obj.extend(value)
105
            elif hasattr(value, 'pack'):
106
                obj = value
107
108
            self.body = obj.pack()
109
110
        multipart_packed = super().pack()
111
        self.body = buff
112
113
        return multipart_packed
114
115
    def unpack(self, buff, offset=0):
116
        """Unpack a binary message into this object's attributes.
117
118
        Unpack the binary value *buff* and update this object attributes based
119
        on the results. It is an inplace method and it receives the binary data
120
        of the message **without the header**.
121
122
        This class' unpack method is like the :meth:`.GenericMessage.unpack`
123
        one, except for the ``body`` attribute which has its type determined
124
        by the ``multipart_type`` attribute.
125
126
        Args:
127
            buff (bytes): Binary data package to be unpacked, without the
128
                header.
129
        """
130
        super().unpack(buff[offset:])
131
        self._unpack_body()
132
133
    def _unpack_body(self):
134
        """Unpack `body` replace it by the result."""
135
        obj = self._get_body_instance()
136
        obj.unpack(self.body.value)
137
        self.body = obj
138
139
    def _get_body_instance(self):
140
        """Return the body instance."""
141
        exp_header = ExperimenterMultipartHeader
142
        simple_body = {MultipartTypes.OFPMP_DESC: Desc,
143
                       MultipartTypes.OFPMP_GROUP_FEATURES: GroupFeatures,
144
                       MultipartTypes.OFPMP_METER_FEATURES: MeterFeatures,
145
                       MultipartTypes.OFPMP_EXPERIMENTER: exp_header}
146
147
        array_of_bodies = {MultipartTypes.OFPMP_FLOW: FlowStats,
148
                           MultipartTypes.OFPMP_AGGREGATE: AggregateStatsReply,
149
                           MultipartTypes.OFPMP_TABLE: TableStats,
150
                           MultipartTypes.OFPMP_PORT_STATS: PortStats,
151
                           MultipartTypes.OFPMP_QUEUE: QueueStats,
152
                           MultipartTypes.OFPMP_GROUP: GroupStats,
153
                           MultipartTypes.OFPMP_GROUP_DESC: GroupDescStats,
154
                           MultipartTypes.OFPMP_METER: MeterStats,
155
                           MultipartTypes.OFPMP_METER_CONFIG: MeterConfig,
156
                           MultipartTypes.OFPMP_TABLE_FEATURES: TableFeatures,
157
                           MultipartTypes.OFPMP_PORT_DESC: Port}
158
159
        if isinstance(self.multipart_type, (int, UBInt16)):
160
            self.multipart_type = self.multipart_type.enum_ref(
161
                self.multipart_type.value)
162
163
        pyof_class = simple_body.get(self.multipart_type, None)
164
        if pyof_class:
165
            return pyof_class()
166
167
        array_of_class = array_of_bodies.get(self.multipart_type, None)
168
        if array_of_class:
169
            return FixedTypeList(pyof_class=array_of_class)
170
171
        return BinaryData(b'')
172
173
174
# MultipartReply Body
175
176
class AggregateStatsReply(GenericStruct):
177
    """Body of reply to OFPMP_AGGREGATE request."""
178
179
    #: Number of packets in flows.
180
    packet_count = UBInt64()
181
    #: Number of bytes in flows.
182
    byte_count = UBInt64()
183
    #: Number of flows.
184
    flow_count = UBInt32()
185
    #: Align to 64 bits
186
    pad = Pad(4)
187
188
    def __init__(self, packet_count=None, byte_count=None, flow_count=None):
189
        """Create a AggregateStatsReply with the optional parameters below.
190
191
        Args:
192
            packet_count (int): Number of packets in flows
193
            byte_count (int):   Number of bytes in flows
194
            flow_count (int):   Number of flows
195
        """
196
        super().__init__()
197
        self.packet_count = packet_count
198
        self.byte_count = byte_count
199
        self.flow_count = flow_count
200
201
202 View Code Duplication
class Desc(GenericStruct):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
203
    """Information available from the OFPST_DESC stats request.
204
205
    Information about the switch manufacturer, hardware revision, software
206
    revision, serial number and a description field.
207
    """
208
209
    #: Manufacturer description
210
    mfr_desc = Char(length=DESC_STR_LEN)
211
    #: Hardware description
212
    hw_desc = Char(length=DESC_STR_LEN)
213
    #: Software description
214
    sw_desc = Char(length=DESC_STR_LEN)
215
    #: Serial number
216
    serial_num = Char(length=SERIAL_NUM_LEN)
217
    #: Datapath description
218
    dp_desc = Char(length=DESC_STR_LEN)
219
220
    def __init__(self, mfr_desc=None, hw_desc=None, sw_desc=None,
221
                 serial_num=None, dp_desc=None):
222
        """Create a Desc with the optional parameters below.
223
224
        Args:
225
            mfr_desc (str): Manufacturer description
226
            hw_desc (str): Hardware description
227
            sw_desc (str): Software description
228
            serial_num (str): Serial number
229
            dp_desc (str): Datapath description
230
        """
231
        super().__init__()
232
        self.mfr_desc = mfr_desc
233
        self.hw_desc = hw_desc
234
        self.sw_desc = sw_desc
235
        self.serial_num = serial_num
236
        self.dp_desc = dp_desc
237
238
239 View Code Duplication
class FlowStats(GenericStruct):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
240
    """Body of reply to OFPST_FLOW request."""
241
242
    length = UBInt16()
243
    table_id = UBInt8()
244
    #: Align to 32 bits.
245
    pad = Pad(1)
246
    duration_sec = UBInt32()
247
    duration_nsec = UBInt32()
248
    priority = UBInt16()
249
    idle_timeout = UBInt16()
250
    hard_timeout = UBInt16()
251
    flags = UBInt16()
252
    #: Align to 64-bits
253
    pad2 = Pad(4)
254
    cookie = UBInt64()
255
    packet_count = UBInt64()
256
    byte_count = UBInt64()
257
    match = Match()
258
    instructions = ListOfInstruction()
259
260
    def __init__(self, length=None, table_id=None, duration_sec=None,
261
                 duration_nsec=None, priority=None, idle_timeout=None,
262
                 hard_timeout=None, flags=None, cookie=None, packet_count=None,
263
                 byte_count=None, match=None, instructions=None):
264
        """Create a FlowStats with the optional parameters below.
265
266
        Args:
267
            length (int): Length of this entry.
268
            table_id (int): ID of table flow came from.
269
            duration_sec (int): Time flow has been alive in seconds.
270
            duration_nsec (int): Time flow has been alive in nanoseconds in
271
                addition to duration_sec.
272
            priority (int): Priority of the entry. Only meaningful when this
273
                is not an exact-match entry.
274
            idle_timeout (int): Number of seconds idle before expiration.
275
            hard_timeout (int): Number of seconds before expiration.
276
            cookie (int): Opaque controller-issued identifier.
277
            packet_count (int): Number of packets in flow.
278
            byte_count (int): Number of bytes in flow.
279
            match (~pyof.v0x04.common.flow_match.Match): Description of fields.
280
        """
281
        super().__init__()
282
        self.length = length
283
        self.table_id = table_id
284
        self.duration_sec = duration_sec
285
        self.duration_nsec = duration_nsec
286
        self.priority = priority
287
        self.idle_timeout = idle_timeout
288
        self.hard_timeout = hard_timeout
289
        self.flags = flags
290
        self.cookie = cookie
291
        self.packet_count = packet_count
292
        self.byte_count = byte_count
293
        self.match = match
294
        self.instructions = instructions or []
295
296
    def unpack(self, buff, offset=0):
297
        """Unpack a binary message into this object's attributes.
298
299
        Pass the correct length for list unpacking.
300
301
        Args:
302
            buff (bytes): Binary data package to be unpacked.
303
            offset (int): Where to begin unpacking.
304
        """
305
        unpack_length = UBInt16()
306
        unpack_length.unpack(buff, offset)
307
        super().unpack(buff[:offset+unpack_length], offset)
308
309
310
class PortStats(GenericStruct):
311
    """Body of reply to OFPST_PORT request.
312
313
    If a counter is unsupported, set the field to all ones.
314
    """
315
316
    port_no = UBInt32()
317
    #: Align to 64-bits.
318
    pad = Pad(4)
319
    rx_packets = UBInt64()
320
    tx_packets = UBInt64()
321
    rx_bytes = UBInt64()
322
    tx_bytes = UBInt64()
323
    rx_dropped = UBInt64()
324
    tx_dropped = UBInt64()
325
    rx_errors = UBInt64()
326
    tx_errors = UBInt64()
327
    rx_frame_err = UBInt64()
328
    rx_over_err = UBInt64()
329
    rx_crc_err = UBInt64()
330
    collisions = UBInt64()
331
    duration_sec = UBInt32()
332
    duration_nsec = UBInt32()
333
334 View Code Duplication
    def __init__(self, port_no=None, rx_packets=None,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
335
                 tx_packets=None, rx_bytes=None, tx_bytes=None,
336
                 rx_dropped=None, tx_dropped=None, rx_errors=None,
337
                 tx_errors=None, rx_frame_err=None, rx_over_err=None,
338
                 rx_crc_err=None, collisions=None, duration_sec=None,
339
                 duration_nsec=None):
340
        """Create a PortStats with the optional parameters below.
341
342
        Args:
343
            port_no (:class:`int`, :class:`~pyof.v0x04.common.port.Port`):
344
                Port number.
345
            rx_packets (int): Number of received packets.
346
            tx_packets (int): Number of transmitted packets.
347
            rx_bytes (int): Number of received bytes.
348
            tx_bytes (int): Number of transmitted bytes.
349
            rx_dropped (int): Number of packets dropped by RX.
350
            tx_dropped (int): Number of packets dropped by TX.
351
            rx_errors (int): Number of receive errors. This is a super-set of
352
                more specific receive errors and should be greater than or
353
                equal to the sum of all rx_*_err values.
354
            tx_errors (int): Number of transmit errors.  This is a super-set of
355
                more specific transmit errors and should be greater than or
356
                equal to the sum of all tx_*_err values (none currently
357
                defined).
358
            rx_frame_err (int): Number of frame alignment errors.
359
            rx_over_err (int): Number of packets with RX overrun.
360
            rx_crc_err (int): Number of CRC errors.
361
            collisions (int): Number of collisions.
362
            duration_sec (int): Time port has been alive in seconds
363
            duration_nsec (int): Time port has been alive in nanoseconds beyond
364
                duration_sec
365
        """
366
        super().__init__()
367
        self.port_no = port_no
368
        self.rx_packets = rx_packets
369
        self.tx_packets = tx_packets
370
        self.rx_bytes = rx_bytes
371
        self.tx_bytes = tx_bytes
372
        self.rx_dropped = rx_dropped
373
        self.tx_dropped = tx_dropped
374
        self.rx_errors = rx_errors
375
        self.tx_errors = tx_errors
376
        self.rx_frame_err = rx_frame_err
377
        self.rx_over_err = rx_over_err
378
        self.rx_crc_err = rx_crc_err
379
        self.collisions = collisions
380
        self.duration_sec = duration_sec
381
        self.duration_nsec = duration_nsec
382
383
384
class QueueStats(GenericStruct):
385
    """Implements the reply body of a port_no."""
386
387
    port_no = UBInt32()
388
    queue_id = UBInt32()
389
    tx_bytes = UBInt64()
390
    tx_packets = UBInt64()
391
    tx_errors = UBInt64()
392
    duration_sec = UBInt32()
393
    duration_nsec = UBInt32()
394
395
    def __init__(self, port_no=None, queue_id=None, tx_bytes=None,
396
                 tx_packets=None, tx_errors=None, duration_sec=None,
397
                 duration_nsec=None):
398
        """Create a QueueStats with the optional parameters below.
399
400
        Args:
401
            port_no (:class:`int`, :class:`~pyof.v0x04.common.port.Port`):
402
                Port Number.
403
            queue_id (int): Queue ID.
404
            tx_bytes (int): Number of transmitted bytes.
405
            tx_packets (int): Number of transmitted packets.
406
            tx_errors (int): Number of packets dropped due to overrun.
407
            duration_sec (int): Time queue has been alive in seconds.
408
            duration_nsec (int): Time queue has been alive in nanoseconds
409
                beyond duration_sec.
410
        """
411
        super().__init__()
412
        self.port_no = port_no
413
        self.queue_id = queue_id
414
        self.tx_bytes = tx_bytes
415
        self.tx_packets = tx_packets
416
        self.tx_errors = tx_errors
417
        self.duration_sec = duration_sec
418
        self.duration_nsec = duration_nsec
419
420
421 View Code Duplication
class GroupDescStats(GenericStruct):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
422
    """Body of reply to OFPMP_GROUP_DESC request."""
423
424
    length = UBInt16()
425
    group_type = UBInt8()
426
    #: Pad to 64 bits.
427
    pad = Pad(1)
428
    group_id = UBInt32()
429
    buckets = FixedTypeList(Bucket)
430
431
    def __init__(self, length=None, group_type=None, group_id=None,
432
                 buckets=None):
433
        """Create a GroupDescStats with the optional parameters below.
434
435
        Args:
436
            length (int): Length of this entry.
437
            group_type (|GroupType_v0x04|): One of OFPGT_*.
438
            group_id (int): Group identifier.
439
            buckets (|ListOfBuckets_v0x04|): List of buckets in group.
440
        """
441
        super().__init__()
442
        self.length = length
443
        self.group_type = group_type
444
        self.group_id = group_id
445
        self.buckets = buckets
446
447
448
class GroupFeatures(GenericStruct):
449
    """Body of reply to OFPMP_GROUP_FEATURES request.Group features."""
450
451
    types = UBInt32()
452
    capabilities = UBInt32(enum_ref=GroupCapabilities)
453
    max_groups1 = UBInt32()
454
    max_groups2 = UBInt32()
455
    max_groups3 = UBInt32()
456
    max_groups4 = UBInt32()
457
    actions1 = UBInt32()
458
    actions2 = UBInt32()
459
    actions3 = UBInt32()
460
    actions4 = UBInt32()
461
462
    def __init__(self, types=None, capabilities=None, max_groups1=None,
463
                 max_groups2=None, max_groups3=None, max_groups4=None,
464
                 actions1=None, actions2=None, actions3=None, actions4=None):
465
        """Create a GroupFeatures with the optional parameters below.
466
467
        Args:
468
            types: Bitmap of OFPGT_* values supported.
469
            capabilities: Bitmap of OFPGFC_* capability supported.
470
            max_groups: 4-position array; Maximum number of groups for each
471
                type.
472
            actions: 4-position array; Bitmaps of OFPAT_* that are supported.
473
        """
474
        super().__init__()
475
        self.types = types
476
        self.capabilities = capabilities
477
        self.max_groups1 = max_groups1
478
        self.max_groups2 = max_groups2
479
        self.max_groups3 = max_groups3
480
        self.max_groups4 = max_groups4
481
        self.actions1 = actions1
482
        self.actions2 = actions2
483
        self.actions3 = actions3
484
        self.actions4 = actions4
485
486
487
class GroupStats(GenericStruct):
488
    """Body of reply to OFPMP_GROUP request."""
489
490
    length = UBInt16()
491
    #: Align to 64 bits.
492
    pad = Pad(2)
493
    group_id = UBInt32()
494
    ref_count = UBInt32()
495
    #: Align to 64 bits.
496
    pad2 = Pad(4)
497
    packet_count = UBInt64()
498
    byte_count = UBInt64()
499
    duration_sec = UBInt32()
500
    duration_nsec = UBInt32()
501
    bucket_stats = FixedTypeList(BucketCounter)
502
503
    def __init__(self, length=None, group_id=None, ref_count=None,
504
                 packet_count=None, byte_count=None, duration_sec=None,
505
                 duration_nsec=None, bucket_stats=None):
506
        """Create a GroupStats with the optional parameters below.
507
508
        Args:
509
            length: Length of this entry
510
            group_id: Group identifier
511
            ref_count: Number of flows or groups that directly forward
512
                to this group.
513
            packet_count: Number of packets processed by group
514
            byte_count: Number of bytes processed by group
515
            duration_sec: Time group has been alive in seconds
516
            duration_nsec: Time group has been alive in nanoseconds
517
            bucket_stats: List of stats of group buckets
518
        """
519
        super().__init__()
520
        self.length = length
521
        self.group_id = group_id
522
        self.ref_count = ref_count
523
        self.packet_count = packet_count
524
        self.byte_count = byte_count
525
        self.duration_sec = duration_sec
526
        self.duration_nsec = duration_nsec
527
        self.bucket_stats = bucket_stats
528
529
530
class MeterConfig(GenericStruct):
531
    """MeterConfig is a class to represent ofp_meter_config structure.
532
533
    Body of reply to OFPMP_METER_CONFIG request.
534
    """
535
536
    # Length of this entry.
537
    length = UBInt16()
538
    # All OFPMC_* that apply.
539
    flags = UBInt16(enum_ref=MeterFlags)
540
    # Meter instance or OFPM_ALL .
541
    meter_id = UBInt32()
542
    # The bands length is inferred from the length field.
543
    bands = ListOfMeterBandHeader()
544
545
    def __init__(self, flags=MeterFlags.OFPMF_STATS, meter_id=None,
546
                 bands=None):
547
        """Create a MeterConfig with the optional parameters below.
548
549
        Args:
550
            flags (|MeterFlags_v0x04|):
551
                Meter configuration flags.The default value is
552
                MeterFlags.OFPMF_STATS
553
            meter_id (|Meter_v0x04|):
554
                Meter Indentify.The value Meter.OFPM_ALL is used to
555
                refer to all Meters on the switch.
556
            bands(list): List of MeterBandHeader instances.
557
        """
558
        super().__init__()
559
        self.flags = flags
560
        self.meter_id = meter_id
561
        self.bands = bands if bands else []
562
563
564
class MeterFeatures(GenericStruct):
565
    """Body of reply to OFPMP_METER_FEATURES request. Meter features."""
566
567
    max_meter = UBInt32()
568
    band_types = UBInt32(enum_ref=MeterBandType)
569
    capabilities = UBInt32(enum_ref=MeterFlags)
570
    max_bands = UBInt8()
571
    max_color = UBInt8()
572
    pad = Pad(2)
573
574
    def __init__(self, max_meter=None, band_types=None, capabilities=None,
575
                 max_bands=None, max_color=None):
576
        """Create a MeterFeatures with the optional parameters below.
577
578
        Args:
579
            max_meter(int): Maximum number of meters.
580
            band_types (|MeterBandType_v0x04|):
581
                Bitmaps of OFPMBT_* values supported.
582
            capabilities (|MeterFlags_v0x04|): Bitmaps of "ofp_meter_flags".
583
            max_bands(int): Maximum bands per meters
584
            max_color(int): Maximum color value
585
        """
586
        super().__init__()
587
        self.max_meter = max_meter
588
        self.band_types = band_types
589
        self.capabilities = capabilities
590
        self.max_bands = max_bands
591
        self.max_color = max_color
592
593
594
class BandStats(GenericStruct):
595
    """Band  Statistics.
596
597
    Statistics for each meter band.
598
    """
599
600
    packet_band_count = UBInt64()
601
    byte_band_count = UBInt64()
602
603
    def __init__(self, packet_band_count=None, byte_band_count=None):
604
        """Create a BandStats with the optional parameters below.
605
606
        Args:
607
            packet_band_count(int): Number of packets in band.
608
            byte_band_count(int):   Number of bytes in band.
609
        """
610
        super().__init__()
611
        self.packet_band_count = packet_band_count
612
        self.byte_band_count = byte_band_count
613
614
615
class ListOfBandStats(FixedTypeList):
616
    """List of BandStats.
617
618
    Represented by instances of BandStats.
619
    """
620
621
    def __init__(self, items=None):
622
        """Create a ListOfBandStats with the optional parameters below.
623
624
        Args:
625
            items (|BandStats_v0x04|): Instance or a list of instances.
626
        """
627
        super().__init__(pyof_class=BandStats, items=items)
628
629
630
class MeterStats(GenericStruct):
631
    """Meter Statistics.
632
633
    Body of reply to OFPMP_METER request.
634
    """
635
636
    meter_id = UBInt32()
637
    length = UBInt16()
638
    pad = Pad(6)
639
    flow_count = UBInt32()
640
    packet_in_count = UBInt64()
641
    byte_in_count = UBInt64()
642
    duration_sec = UBInt32()
643
    duration_nsec = UBInt32()
644
    band_stats = ListOfBandStats()
645
646
    def __init__(self, meter_id=None, flow_count=None,
647
                 packet_in_count=None, byte_in_count=None, duration_sec=None,
648
                 duration_nsec=None, band_stats=None):
649
        """Create a MeterStats with the optional parameters below.
650
651
        Args:
652
            meter_id (|Meter_v0x04|):  Meter instance.
653
            flow_count(int):      Number of flows bound to meter.
654
            packet_in_count(int): Number of packets in input.
655
            byte_in_count(int):   Number of bytes in input.
656
            duration_sec(int):    Time meter has been alive in seconds.
657
            duration_nsec(int):   Time meter has been alive in
658
                                  nanoseconds beyond duration_sec.
659
            band_stats(list):     Instances of BandStats
660
        """
661
        super().__init__()
662
        self.meter_id = meter_id
663
        self.flow_count = flow_count
664
        self.packet_in_count = packet_in_count
665
        self.byte_in_count = byte_in_count
666
        self.duration_sec = duration_sec
667
        self.duration_nsec = duration_nsec
668
        self.band_stats = band_stats if band_stats else []
669
        self.update_length()
670
671
    def update_length(self):
672
        """Update length attribute with current struct length."""
673
        self.length = self.get_size()
674
675
    def pack(self, value=None):
676
        """Pack method used to update the length of instance and packing.
677
678
        Args:
679
            value: Structure to be packed.
680
        """
681
        self.update_length()
682
        return super().pack(value)
683
684
    def unpack(self, buff=None, offset=0):
685
        """Unpack *buff* into this object.
686
687
        This method will convert a binary data into a readable value according
688
        to the attribute format.
689
690
        Args:
691
            buff (bytes): Binary buffer.
692
            offset (int): Where to begin unpacking.
693
694
        Raises:
695
            :exc:`~.exceptions.UnpackException`: If unpack fails.
696
697
        """
698
        length = UBInt16()
699
        length.unpack(buff, offset)
700
701
        length.unpack(buff, offset=offset+MeterStats.meter_id.get_size())
702
        super().unpack(buff[:offset+length.value], offset=offset)
703
704
705
class TableStats(GenericStruct):
706
    """Body of reply to OFPST_TABLE request."""
707
708
    table_id = UBInt8()
709
    #: Align to 32-bits.
710
    pad = Pad(3)
711
    active_count = UBInt32()
712
    lookup_count = UBInt64()
713
    matched_count = UBInt64()
714
715
    def __init__(self, table_id=None, active_count=None, lookup_count=None,
716
                 matched_count=None):
717
        """Create a TableStats with the optional parameters below.
718
719
        Args:
720
            table_id (int): Identifier of table.  Lower numbered tables are
721
                consulted first.
722
            active_count (int): Number of active entries.
723
            lookup_count (int): Number of packets looked up in table.
724
            matched_count (int): Number of packets that hit table.
725
        """
726
        super().__init__()
727
        self.table_id = table_id
728
        self.active_count = active_count
729
        self.lookup_count = lookup_count
730
        self.matched_count = matched_count
731