FlowStats.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 36
Code Lines 18

Duplication

Lines 36
Ratio 100 %

Code Coverage

Tests 15
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 18
dl 36
loc 36
ccs 15
cts 15
cp 1
rs 9.5
c 0
b 0
f 0
cc 1
nop 14
crap 1

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