Passed
Push — master ( b085fb...082312 )
by Humberto
03:44
created

GroupStats.__init__()   A

Complexity

Conditions 1

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.729

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 25
ccs 1
cts 10
cp 0.1
rs 9.8
c 0
b 0
f 0
cc 1
nop 9
crap 1.729

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
"""Controller replying state from datapath."""
2
3
# System imports
4 1
from enum import Enum
5
6
# Local source tree imports
7 1
from pyof.foundation.base import GenericBitMask, GenericMessage, GenericStruct
8 1
from pyof.foundation.basic_types import (
9
    BinaryData, Char, FixedTypeList, Pad, UBInt8, UBInt16, UBInt32, UBInt64)
10 1
from pyof.foundation.constants import DESC_STR_LEN, SERIAL_NUM_LEN
11 1
from pyof.v0x04.common.flow_instructions import ListOfInstruction
12 1
from pyof.v0x04.common.flow_match import Match
13 1
from pyof.v0x04.common.header import Header, Type
14 1
from pyof.v0x04.common.port import Port
15 1
from pyof.v0x04.controller2switch.common import (
16
    Bucket, BucketCounter, ExperimenterMultipartHeader, MultipartType,
17
    TableFeatures)
18 1
from pyof.v0x04.controller2switch.meter_mod import (
19
    ListOfMeterBandHeader, MeterBandType, MeterFlags)
20
21
# Third-party imports
22
23
24 1
__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 1
class MultipartReplyFlags(Enum):
34
    """Flags for MultipartReply."""
35
36
    #: More replies to follow.
37 1
    OFPMPF_REPLY_MORE = 1 << 0
38
39
40 1
class GroupCapabilities(GenericBitMask):
41
    """Group configuration flags."""
42
43
    #: Support weight for select groups.
44 1
    OFPGFC_SELECT_WEIGHT = 1 << 0
45
    #: Support liveness for select groups.
46 1
    OFPGFC_SELECT_LIVENESS = 1 << 1
47
    #: Support chaining groups.
48 1
    OFPGFC_CHAINING = 1 << 2
49
    #: Chack chaining for loops and delete.
50 1
    OFPGFC_CHAINING_CHECKS = 1 << 3
51
52
# Classes
53
54
55 1
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 1
    header = Header(message_type=Type.OFPT_MULTIPART_REPLY)
64
    #: One of the OFPMP_* constants.
65 1
    multipart_type = UBInt16(enum_ref=MultipartType)
66
    #: OFPMPF_REPLY_* flags.
67 1
    flags = UBInt16()
68
    #: Padding
69 1
    pad = Pad(4)
70
    #: Body of the reply
71 1
    body = BinaryData()
72
73 1
    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 1
        super().__init__(xid)
83 1
        self.multipart_type = multipart_type
84 1
        self.flags = flags
85 1
        self.body = body
86
87 1 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 1
        buff = self.body
98 1
        if not value:
99 1
            value = self.body
100
101 1
        if value:
102 1
            if isinstance(value, (list, FixedTypeList)):
103
                obj = self._get_body_instance()
104
                obj.extend(value)
105 1
            elif hasattr(value, 'pack'):
106 1
                obj = value
107
108 1
            self.body = obj.pack()
0 ignored issues
show
introduced by
The variable obj does not seem to be defined for all execution paths.
Loading history...
109
110 1
        multipart_packed = super().pack()
111 1
        self.body = buff
112
113 1
        return multipart_packed
114
115 1
    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 1
        super().unpack(buff[offset:])
131 1
        self._unpack_body()
132
133 1
    def _unpack_body(self):
134
        """Unpack `body` replace it by the result."""
135 1
        obj = self._get_body_instance()
136 1
        obj.unpack(self.body.value)
137 1
        self.body = obj
138
139 1
    def _get_body_instance(self):
140
        """Return the body instance."""
141 1
        exp_header = ExperimenterMultipartHeader
142 1
        simple_body = {MultipartType.OFPMP_DESC: Desc,
143
                       MultipartType.OFPMP_GROUP_FEATURES: GroupFeatures,
144
                       MultipartType.OFPMP_METER_FEATURES: MeterFeatures,
145
                       MultipartType.OFPMP_EXPERIMENTER: exp_header}
146
147 1
        array_of_bodies = {MultipartType.OFPMP_FLOW: FlowStats,
148
                           MultipartType.OFPMP_AGGREGATE: AggregateStatsReply,
149
                           MultipartType.OFPMP_TABLE: TableStats,
150
                           MultipartType.OFPMP_PORT_STATS: PortStats,
151
                           MultipartType.OFPMP_QUEUE: QueueStats,
152
                           MultipartType.OFPMP_GROUP: GroupStats,
153
                           MultipartType.OFPMP_GROUP_DESC: GroupDescStats,
154
                           MultipartType.OFPMP_METER: MeterStats,
155
                           MultipartType.OFPMP_METER_CONFIG: MeterConfig,
156
                           MultipartType.OFPMP_TABLE_FEATURES: TableFeatures,
157
                           MultipartType.OFPMP_PORT_DESC: Port}
158
159 1
        if isinstance(self.multipart_type, (int, UBInt16)):
160 1
            self.multipart_type = self.multipart_type.enum_ref(
161
                self.multipart_type.value)
162
163 1
        pyof_class = simple_body.get(self.multipart_type, None)
164 1
        if pyof_class:
165 1
            return pyof_class()
166
167 1
        array_of_class = array_of_bodies.get(self.multipart_type, None)
168 1
        if array_of_class:
169 1
            return FixedTypeList(pyof_class=array_of_class)
170
171
        return BinaryData(b'')
172
173
174
# MultipartReply Body
175
176 1
class AggregateStatsReply(GenericStruct):
177
    """Body of reply to OFPMP_AGGREGATE request."""
178
179
    #: Number of packets in flows.
180 1
    packet_count = UBInt64()
181
    #: Number of bytes in flows.
182 1
    byte_count = UBInt64()
183
    #: Number of flows.
184 1
    flow_count = UBInt32()
185
    #: Align to 64 bits
186 1
    pad = Pad(4)
187
188 1
    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 1 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 1
    mfr_desc = Char(length=DESC_STR_LEN)
211
    #: Hardware description
212 1
    hw_desc = Char(length=DESC_STR_LEN)
213
    #: Software description
214 1
    sw_desc = Char(length=DESC_STR_LEN)
215
    #: Serial number
216 1
    serial_num = Char(length=SERIAL_NUM_LEN)
217
    #: Datapath description
218 1
    dp_desc = Char(length=DESC_STR_LEN)
219
220 1
    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 1
        super().__init__()
232 1
        self.mfr_desc = mfr_desc
233 1
        self.hw_desc = hw_desc
234 1
        self.sw_desc = sw_desc
235 1
        self.serial_num = serial_num
236 1
        self.dp_desc = dp_desc
237
238
239 1 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 1
    length = UBInt16()
243 1
    table_id = UBInt8()
244
    #: Align to 32 bits.
245 1
    pad = Pad(1)
246 1
    duration_sec = UBInt32()
247 1
    duration_nsec = UBInt32()
248 1
    priority = UBInt16()
249 1
    idle_timeout = UBInt16()
250 1
    hard_timeout = UBInt16()
251 1
    flags = UBInt16()
252
    #: Align to 64-bits
253 1
    pad2 = Pad(4)
254 1
    cookie = UBInt64()
255 1
    packet_count = UBInt64()
256 1
    byte_count = UBInt64()
257 1
    match = Match()
258 1
    instructions = ListOfInstruction()
259
260 1
    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 1
        super().__init__()
282 1
        self.length = length
283 1
        self.table_id = table_id
284 1
        self.duration_sec = duration_sec
285 1
        self.duration_nsec = duration_nsec
286 1
        self.priority = priority
287 1
        self.idle_timeout = idle_timeout
288 1
        self.hard_timeout = hard_timeout
289 1
        self.flags = flags
290 1
        self.cookie = cookie
291 1
        self.packet_count = packet_count
292 1
        self.byte_count = byte_count
293 1
        self.match = match
294 1
        self.instructions = instructions or []
295
296 1
    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 1
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 1
    port_no = UBInt32()
317
    #: Align to 64-bits.
318 1
    pad = Pad(4)
319 1
    rx_packets = UBInt64()
320 1
    tx_packets = UBInt64()
321 1
    rx_bytes = UBInt64()
322 1
    tx_bytes = UBInt64()
323 1
    rx_dropped = UBInt64()
324 1
    tx_dropped = UBInt64()
325 1
    rx_errors = UBInt64()
326 1
    tx_errors = UBInt64()
327 1
    rx_frame_err = UBInt64()
328 1
    rx_over_err = UBInt64()
329 1
    rx_crc_err = UBInt64()
330 1
    collisions = UBInt64()
331 1
    duration_sec = UBInt32()
332 1
    duration_nsec = UBInt32()
333
334 1
    def __init__(self, port_no=None, rx_packets=None,
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 1
        super().__init__()
367 1
        self.port_no = port_no
368 1
        self.rx_packets = rx_packets
369 1
        self.tx_packets = tx_packets
370 1
        self.rx_bytes = rx_bytes
371 1
        self.tx_bytes = tx_bytes
372 1
        self.rx_dropped = rx_dropped
373 1
        self.tx_dropped = tx_dropped
374 1
        self.rx_errors = rx_errors
375 1
        self.tx_errors = tx_errors
376 1
        self.rx_frame_err = rx_frame_err
377 1
        self.rx_over_err = rx_over_err
378 1
        self.rx_crc_err = rx_crc_err
379 1
        self.collisions = collisions
380 1
        self.duration_sec = duration_sec
381 1
        self.duration_nsec = duration_nsec
382
383
384 1
class QueueStats(GenericStruct):
385
    """Implements the reply body of a port_no."""
386
387 1
    port_no = UBInt32()
388 1
    queue_id = UBInt32()
389 1
    tx_bytes = UBInt64()
390 1
    tx_packets = UBInt64()
391 1
    tx_errors = UBInt64()
392 1
    duration_sec = UBInt32()
393 1
    duration_nsec = UBInt32()
394
395 1
    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 1
        super().__init__()
412 1
        self.port_no = port_no
413 1
        self.queue_id = queue_id
414 1
        self.tx_bytes = tx_bytes
415 1
        self.tx_packets = tx_packets
416 1
        self.tx_errors = tx_errors
417 1
        self.duration_sec = duration_sec
418 1
        self.duration_nsec = duration_nsec
419
420
421 1
class GroupDescStats(GenericStruct):
422
    """Body of reply to OFPMP_GROUP_DESC request."""
423
424 1
    length = UBInt16()
425 1
    group_type = UBInt8()
426
    #: Pad to 64 bits.
427 1
    pad = Pad(1)
428 1
    group_id = UBInt32()
429 1
    buckets = FixedTypeList(Bucket)
430
431 1
    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 1
class GroupFeatures(GenericStruct):
449
    """Body of reply to OFPMP_GROUP_FEATURES request.Group features."""
450
451 1
    types = UBInt32()
452 1
    capabilities = UBInt32(enum_ref=GroupCapabilities)
453 1
    max_groups1 = UBInt32()
454 1
    max_groups2 = UBInt32()
455 1
    max_groups3 = UBInt32()
456 1
    max_groups4 = UBInt32()
457 1
    actions1 = UBInt32()
458 1
    actions2 = UBInt32()
459 1
    actions3 = UBInt32()
460 1
    actions4 = UBInt32()
461
462 1
    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 1
class GroupStats(GenericStruct):
488
    """Body of reply to OFPMP_GROUP request."""
489
490 1
    length = UBInt16()
491
    #: Align to 64 bits.
492 1
    pad = Pad(2)
493 1
    group_id = UBInt32()
494 1
    ref_count = UBInt32()
495
    #: Align to 64 bits.
496 1
    pad2 = Pad(4)
497 1
    packet_count = UBInt64()
498 1
    byte_count = UBInt64()
499 1
    duration_sec = UBInt32()
500 1
    duration_nsec = UBInt32()
501 1
    bucket_stats = FixedTypeList(BucketCounter)
502
503 1
    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 1
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 1
    length = UBInt16()
538
    # All OFPMC_* that apply.
539 1
    flags = UBInt16(enum_ref=MeterFlags)
540
    # Meter instance or OFPM_ALL .
541 1
    meter_id = UBInt32()
542
    # The bands length is inferred from the length field.
543 1
    bands = ListOfMeterBandHeader()
544
545 1
    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 1
class MeterFeatures(GenericStruct):
565
    """Body of reply to OFPMP_METER_FEATURES request. Meter features."""
566
567 1
    max_meter = UBInt32()
568 1
    band_types = UBInt32(enum_ref=MeterBandType)
569 1
    capabilities = UBInt32(enum_ref=MeterFlags)
570 1
    max_bands = UBInt8()
571 1
    max_color = UBInt8()
572 1
    pad = Pad(2)
573
574 1
    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 1
class BandStats(GenericStruct):
595
    """Band  Statistics.
596
597
    Statistics for each meter band.
598
    """
599
600 1
    packet_band_count = UBInt64()
601 1
    byte_band_count = UBInt64()
602
603 1
    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 1
class ListOfBandStats(FixedTypeList):
616
    """List of BandStats.
617
618
    Represented by instances of BandStats.
619
    """
620
621 1
    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 1
        super().__init__(pyof_class=BandStats, items=items)
628
629
630 1
class MeterStats(GenericStruct):
631
    """Meter Statistics.
632
633
    Body of reply to OFPMP_METER request.
634
    """
635
636 1
    meter_id = UBInt32()
637 1
    length = UBInt16()
638 1
    pad = Pad(6)
639 1
    flow_count = UBInt32()
640 1
    packet_in_count = UBInt64()
641 1
    byte_in_count = UBInt64()
642 1
    duration_sec = UBInt32()
643 1
    duration_nsec = UBInt32()
644 1
    band_stats = ListOfBandStats()
645
646 1
    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 1
    def update_length(self):
672
        """Update length attribute with current struct length."""
673
        self.length = self.get_size()
674
675 1
    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 1
    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 1
class TableStats(GenericStruct):
706
    """Body of reply to OFPST_TABLE request."""
707
708 1
    table_id = UBInt8()
709
    #: Align to 32-bits.
710 1
    pad = Pad(3)
711 1
    active_count = UBInt32()
712 1
    lookup_count = UBInt64()
713 1
    matched_count = UBInt64()
714
715 1
    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 1
        super().__init__()
727 1
        self.table_id = table_id
728 1
        self.active_count = active_count
729 1
        self.lookup_count = lookup_count
730
        self.matched_count = matched_count
731