Issues (31)

pyof/v0x01/controller2switch/common.py (2 issues)

1
"""Defines common structures and enums for controller2switch."""
2
3
# System imports
4
from enum import IntEnum
5
6
from pyof.foundation.base import GenericMessage, GenericStruct
7
from pyof.foundation.basic_types import (
8
    BinaryData, Char, Pad, UBInt8, UBInt16, UBInt32, UBInt64)
9
from pyof.foundation.constants import (
10
    DESC_STR_LEN, OFP_MAX_TABLE_NAME_LEN, SERIAL_NUM_LEN)
11
# Local source tree imports
12
from pyof.v0x01.common.action import ListOfActions
13
from pyof.v0x01.common.flow_match import FlowWildCards, Match
14
from pyof.v0x01.common.header import Header
15
from pyof.v0x01.common.phy_port import Port
16
17
# Third-party imports
18
19
__all__ = ('ConfigFlag', 'StatsType', 'AggregateStatsReply',
20
           'AggregateStatsRequest', 'DescStats', 'FlowStats',
21
           'FlowStatsRequest', 'PortStats', 'PortStatsRequest', 'QueueStats',
22
           'QueueStatsRequest', 'TableStats', 'VendorStats',
23
           'VendorStatsRequest')
24
25
# Enums
26
27
28
class ConfigFlag(IntEnum):
29
    """Configuration Flags. Handling of IP Fragments."""
30
31
    #: No special handling for fragments
32
    OFPC_FRAG_NORMAL = 0
33
    #: Drop fragments
34
    OFPC_FRAG_DROP = 1
35
    #: Reassemble (only if OFPC_IP_REASM set)
36
    OFPC_FRAG_REASM = 2
37
    OFPC_FRAG_MASK = 3
38
39
40
class StatsType(IntEnum):
41
    """Type field to be used both in both request and reply.
42
43
    It specifies the kind of information being passed and determines how the
44
    body field is interpreted.
45
    """
46
47
    #: Description of this OpenFlow switch. The request body is empty.
48
    OFPST_DESC = 0
49
    #: Individual flow statistics. The request body is struct
50
    #: ofp_flow_stats_request.
51
    OFPST_FLOW = 1
52
    #: Aggregate flow statistics. The request body is struct
53
    #: ofp_aggregate_stats_request.
54
    OFPST_AGGREGATE = 2
55
    #: Flow table statistics. The request body is empty.
56
    OFPST_TABLE = 3
57
    #: Physical port statistics. The request body is empty.
58
    OFPST_PORT = 4
59
    #: Queue statistics for a port. The request body defines the port
60
    OFPST_QUEUE = 5
61
    #: Vendor extension. The request and reply bodies begin with a 32-bit
62
    #: vendor ID
63
    OFPST_VENDOR = 0xffff
64
65
66
# Classes
67
68
69
class SwitchConfig(GenericMessage):
70
    """Used as base class for SET_CONFIG and GET_CONFIG_REPLY messages."""
71
72
    header = Header()
73
    flags = UBInt16(enum_ref=ConfigFlag)
74
    miss_send_len = UBInt16()
75
76
    def __init__(self, xid=None, flags=None, miss_send_len=None):
77
        """Create a SwitchConfig with the optional parameters below.
78
79
        Args:
80
            xid (int): xid to be used on the message header.
81
            flags (ConfigFlag): OFPC_* flags.
82
            miss_send_len (int): UBInt16 max bytes of new flow that the
83
                datapath should send to the controller.
84
        """
85
        super().__init__(xid)
86
        self.flags = flags
87
        self.miss_send_len = miss_send_len
88
89
    def __repr__(self):
90
        """Show a full representation of the object."""
91
        return "%s(xid=%r, flags=%s, miss_send_len=%r)" \
92
               % (self.__class__.__name__, self.header.xid, self.flags,
93
                  self.miss_send_len)
94
95
96
class AggregateStatsReply(GenericStruct):
97
    """Body of reply to OFPST_AGGREGATE request."""
98
99
    packet_count = UBInt64()
100
    byte_count = UBInt64()
101
    flow_count = UBInt32()
102
    #: Align to 64 bits
103
    pad = Pad(4)
104
105
    def __init__(self, packet_count=None, byte_count=None, flow_count=None):
106
        """Create a AggregateStatsReply with the optional parameters below.
107
108
        Args:
109
            packet_count (int): Number of packets in flows
110
            byte_count (int):   Number of bytes in flows
111
            flow_count (int):   Number of flows
112
        """
113
        super().__init__()
114
        self.packet_count = packet_count
115
        self.byte_count = byte_count
116
        self.flow_count = flow_count
117
118
119
class AggregateStatsRequest(GenericStruct):
120
    """Body for ofp_stats_request of type OFPST_AGGREGATE."""
121
122
    match = Match()
123
    table_id = UBInt8()
124
    #: Align to 32 bits
125
    pad = Pad(1)
126
    out_port = UBInt16()
127
128
    def __init__(self, match=Match(), table_id=0xff, out_port=Port.OFPP_NONE):
129
        """Create a AggregateStatsRequest with the optional parameters below.
130
131
        Args:
132
            match (~pyof.v0x01.common.flow_match.Match): Fields to match.
133
            table_id (int): ID of table to read (from pyof_table_stats) 0xff
134
                for all tables or 0xfe for emergency.
135
            out_port (int): Require matching entries to include this as an
136
                output port. A value of OFPP_NONE indicates no restriction.
137
        """
138
        super().__init__()
139
        self.match = match
140
        self.table_id = table_id
141
        self.out_port = out_port
142
143
144 View Code Duplication
class DescStats(GenericStruct):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
145
    """Information available from the OFPST_DESC stats request.
146
147
    Information about the switch manufacturer, hardware revision, software
148
    revision, serial number and a description field.
149
    """
150
151
    mfr_desc = Char(length=DESC_STR_LEN)
152
    hw_desc = Char(length=DESC_STR_LEN)
153
    sw_desc = Char(length=DESC_STR_LEN)
154
    serial_num = Char(length=SERIAL_NUM_LEN)
155
    dp_desc = Char(length=DESC_STR_LEN)
156
157
    def __init__(self, mfr_desc=None, hw_desc=None, sw_desc=None,
158
                 serial_num=None, dp_desc=None):
159
        """Create a DescStats with the optional parameters below.
160
161
        Args:
162
            mfr_desc (str): Manufacturer description
163
            hw_desc (str): Hardware description
164
            sw_desc (str): Software description
165
            serial_num (str): Serial number
166
            dp_desc (str): Human readable description of datapath
167
        """
168
        super().__init__()
169
        self.mfr_desc = mfr_desc
170
        self.hw_desc = hw_desc
171
        self.sw_desc = sw_desc
172
        self.serial_num = serial_num
173
        self.dp_desc = dp_desc
174
175
176 View Code Duplication
class FlowStats(GenericStruct):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
177
    """Body of reply to OFPST_FLOW request."""
178
179
    length = UBInt16()
180
    table_id = UBInt8()
181
    #: Align to 32 bits.
182
    pad = Pad(1)
183
    match = Match()
184
    duration_sec = UBInt32()
185
    duration_nsec = UBInt32()
186
    priority = UBInt16()
187
    idle_timeout = UBInt16()
188
    hard_timeout = UBInt16()
189
    #: Align to 64-bits
190
    pad2 = Pad(6)
191
    cookie = UBInt64()
192
    packet_count = UBInt64()
193
    byte_count = UBInt64()
194
    actions = ListOfActions()
195
196
    def __init__(self, length=None, table_id=None, match=None,
197
                 duration_sec=None, duration_nsec=None, priority=None,
198
                 idle_timeout=None, hard_timeout=None, cookie=None,
199
                 packet_count=None, byte_count=None, actions=None):
200
        """Create a FlowStats with the optional parameters below.
201
202
        Args:
203
            length (int): Length of this entry.
204
            table_id (int): ID of table flow came from.
205
            match (~pyof.v0x01.common.flow_match.Match): Description of fields.
206
            duration_sec (int): Time flow has been alive in seconds.
207
            duration_nsec (int): Time flow has been alive in nanoseconds in
208
                addition to duration_sec.
209
            priority (int): Priority of the entry. Only meaningful when this
210
                is not an exact-match entry.
211
            idle_timeout (int): Number of seconds idle before expiration.
212
            hard_timeout (int): Number of seconds before expiration.
213
            cookie (int): Opaque controller-issued identifier.
214
            packet_count (int): Number of packets in flow.
215
            byte_count (int): Number of bytes in flow.
216
            actions (:class:`~pyof.v0x01.common.actions.ListOfActions`):
217
                List of Actions.
218
        """
219
        super().__init__()
220
        self.length = length
221
        self.table_id = table_id
222
        self.match = match
223
        self.duration_sec = duration_sec
224
        self.duration_nsec = duration_nsec
225
        self.priority = priority
226
        self.idle_timeout = idle_timeout
227
        self.hard_timeout = hard_timeout
228
        self.cookie = cookie
229
        self.packet_count = packet_count
230
        self.byte_count = byte_count
231
        self.actions = [] if actions is None else actions
232
233
    def unpack(self, buff, offset=0):
234
        """Unpack *buff* into this object.
235
236
        Do nothing, since the _length is already defined and it is just a Pad.
237
        Keep buff and offset just for compability with other unpack methods.
238
239
        Args:
240
            buff (bytes): Buffer where data is located.
241
            offset (int): Where data stream begins.
242
        """
243
        self.length = UBInt16()
244
        self.length.unpack(buff, offset)
245
        max_length = offset + self.length.value
246
        super().unpack(buff[:max_length], offset)
247
248
249
class FlowStatsRequest(GenericStruct):
250
    """Body for ofp_stats_request of type OFPST_FLOW."""
251
252
    match = Match()
253
    table_id = UBInt8()
254
    #: Align to 32 bits.
255
    pad = Pad(1)
256
    out_port = UBInt16()
257
258
    def __init__(self, match=None, table_id=0xff, out_port=Port.OFPP_NONE):
259
        """Create a FlowStatsRequest with the optional parameters below.
260
261
        Args:
262
            match (:class:`~pyof.v0x01.common.flow_match.Match`):
263
                Fields to match.
264
            table_id (int): ID of table to read (from pyof_table_stats)
265
                0xff for all tables or 0xfe for emergency.
266
            out_port (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`):
267
                Require matching entries to include this as an output port.
268
                A value of :attr:`.Port.OFPP_NONE` indicates no restriction.
269
        """
270
        super().__init__()
271
        self.match = Match() if match is None else match
272
        self.table_id = table_id
273
        self.out_port = out_port
274
275
276
class PortStats(GenericStruct):
277
    """Body of reply to OFPST_PORT request.
278
279
    If a counter is unsupported, set the field to all ones.
280
    """
281
282
    port_no = UBInt16()
283
    #: Align to 64-bits.
284
    pad = Pad(6)
285
    rx_packets = UBInt64()
286
    tx_packets = UBInt64()
287
    rx_bytes = UBInt64()
288
    tx_bytes = UBInt64()
289
    rx_dropped = UBInt64()
290
    tx_dropped = UBInt64()
291
    rx_errors = UBInt64()
292
    tx_errors = UBInt64()
293
    rx_frame_err = UBInt64()
294
    rx_over_err = UBInt64()
295
    rx_crc_err = UBInt64()
296
    collisions = UBInt64()
297
298
    def __init__(self, port_no=None, rx_packets=None,
299
                 tx_packets=None, rx_bytes=None, tx_bytes=None,
300
                 rx_dropped=None, tx_dropped=None, rx_errors=None,
301
                 tx_errors=None, rx_frame_err=None, rx_over_err=None,
302
                 rx_crc_err=None, collisions=None):
303
        """Create a PortStats with the optional parameters below.
304
305
        Args:
306
            port_no (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`):
307
                Port number.
308
            rx_packets (int): Number of received packets.
309
            tx_packets (int): Number of transmitted packets.
310
            rx_bytes (int): Number of received bytes.
311
            tx_bytes (int): Number of transmitted bytes.
312
            rx_dropped (int): Number of packets dropped by RX.
313
            tx_dropped (int): Number of packets dropped by TX.
314
            rx_errors (int): Number of receive errors. This is a super-set of
315
                more specific receive errors and should be greater than or
316
                equal to the sum of all rx_*_err values.
317
            tx_errors (int): Number of transmit errors.  This is a super-set of
318
                more specific transmit errors and should be greater than or
319
                equal to the sum of all tx_*_err values (none currently
320
                defined).
321
            rx_frame_err (int): Number of frame alignment errors.
322
            rx_over_err (int): Number of packets with RX overrun.
323
            rx_crc_err (int): Number of CRC errors.
324
            collisions (int): Number of collisions.
325
        """
326
        super().__init__()
327
        self.port_no = port_no
328
        self.rx_packets = rx_packets
329
        self.tx_packets = tx_packets
330
        self.rx_bytes = rx_bytes
331
        self.tx_bytes = tx_bytes
332
        self.rx_dropped = rx_dropped
333
        self.tx_dropped = tx_dropped
334
        self.rx_errors = rx_errors
335
        self.tx_errors = tx_errors
336
        self.rx_frame_err = rx_frame_err
337
        self.rx_over_err = rx_over_err
338
        self.rx_crc_err = rx_crc_err
339
        self.collisions = collisions
340
341
342
class PortStatsRequest(GenericStruct):
343
    """Body for ofp_stats_request of type OFPST_PORT."""
344
345
    port_no = UBInt16()
346
    #: Align to 64-bits.
347
    pad = Pad(6)
348
349
    def __init__(self, port_no=Port.OFPP_NONE):
350
        """Create a PortStatsRequest with the optional parameters below.
351
352
        Args:
353
            port_no (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`):
354
                OFPST_PORT message must request statistics either for a single
355
                port (specified in ``port_no``) or for all ports
356
                (if ``port_no`` == :attr:`.Port.OFPP_NONE`).
357
        """
358
        super().__init__()
359
        self.port_no = port_no
360
361
362
class QueueStats(GenericStruct):
363
    """Implements the reply body of a port_no."""
364
365
    port_no = UBInt16()
366
    #: Align to 32-bits.
367
    pad = Pad(2)
368
    queue_id = UBInt32()
369
    tx_bytes = UBInt64()
370
    tx_packets = UBInt64()
371
    tx_errors = UBInt64()
372
373
    def __init__(self, port_no=None, queue_id=None, tx_bytes=None,
374
                 tx_packets=None, tx_errors=None):
375
        """Create a QueueStats with the optional parameters below.
376
377
        Args:
378
            port_no (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`):
379
                Port Number.
380
            queue_id (int): Queue ID.
381
            tx_bytes (int): Number of transmitted bytes.
382
            tx_packets (int): Number of transmitted packets.
383
            tx_errors (int): Number of packets dropped due to overrun.
384
        """
385
        super().__init__()
386
        self.port_no = port_no
387
        self.queue_id = queue_id
388
        self.tx_bytes = tx_bytes
389
        self.tx_packets = tx_packets
390
        self.tx_errors = tx_errors
391
392
393
class QueueStatsRequest(GenericStruct):
394
    """Implements the request body of a ``port_no``."""
395
396
    port_no = UBInt16()
397
    #: Align to 32-bits
398
    pad = Pad(2)
399
    queue_id = UBInt32()
400
401
    def __init__(self, port_no=None, queue_id=None):
402
        """Create a QueueStatsRequest with the optional parameters below.
403
404
        Args:
405
            port_no (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`):
406
                 All ports if :attr:`.Port.OFPP_ALL`.
407
            queue_id (int): All queues if OFPQ_ALL (``0xfffffff``).
408
        """
409
        super().__init__()
410
        self.port_no = port_no
411
        self.queue_id = queue_id
412
413
414
class TableStats(GenericStruct):
415
    """Body of reply to OFPST_TABLE request."""
416
417
    table_id = UBInt8()
418
    #: Align to 32-bits.
419
    pad = Pad(3)
420
    name = Char(length=OFP_MAX_TABLE_NAME_LEN)
421
    wildcards = UBInt32(enum_ref=FlowWildCards)
422
    max_entries = UBInt32()
423
    active_count = UBInt32()
424
    count_lookup = UBInt64()
425
    count_matched = UBInt64()
426
427
    def __init__(self, table_id=None, name=None, wildcards=None,
428
                 max_entries=None, active_count=None, count_lookup=None,
429
                 count_matched=None):
430
        """Create a TableStats with the optional parameters below.
431
432
        Args:
433
            table_id (int): Identifier of table.  Lower numbered tables are
434
                consulted first.
435
            name (str): Table name.
436
            wildcards (:class:`~pyof.v0x01.common.flow_match.FlowWildCards`):
437
                Bitmap of OFPFW_* wildcards that are supported by the table.
438
            max_entries (int): Max number of entries supported.
439
            active_count (int): Number of active entries.
440
            count_lookup (int): Number of packets looked up in table.
441
            count_matched (int): Number of packets that hit table.
442
        """
443
        super().__init__()
444
        self.table_id = table_id
445
        self.name = name
446
        self.wildcards = wildcards
447
        self.max_entries = max_entries
448
        self.active_count = active_count
449
        self.count_lookup = count_lookup
450
        self.count_matched = count_matched
451
452
453
class VendorStats(GenericStruct):
454
    """Vendor extension."""
455
456
    vendor = UBInt32()
457
    body = BinaryData()
458
459
    def __init__(self, vendor=None, body=b''):
460
        """Create instance attributes.
461
462
        Args:
463
            vendor (int): 32-bit vendor ID.
464
            body (bytes): Vendor-defined body
465
        """
466
        super().__init__()
467
        self.vendor = vendor
468
        self.body = body
469
470
471
VendorStatsRequest = VendorStats
472