1# Copyright (C) 2011, 2012 Nippon Telegraph and Telephone Corporation.
2# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""
18Decoder/Encoder implementations of OpenFlow 1.0.
19"""
20
21import struct
22import base64
23
24import six
25import netaddr
26
27from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
28from ryu.lib import addrconv
29from ryu.lib import ip
30from ryu.lib import mac
31from ryu.lib.packet import packet
32from ryu.lib.pack_utils import msg_pack_into
33from ryu.ofproto import nx_match
34from ryu.ofproto import ofproto_common
35from ryu.ofproto import ofproto_parser
36from ryu.ofproto import ofproto_v1_0 as ofproto
37from ryu.ofproto import nx_actions
38from ryu import utils
39
40import logging
41LOG = logging.getLogger('ryu.ofproto.ofproto_v1_0_parser')
42
43_MSG_PARSERS = {}
44
45
46def _set_msg_type(msg_type):
47    '''Annotate corresponding OFP message type'''
48    def _set_cls_msg_type(cls):
49        cls.cls_msg_type = msg_type
50        return cls
51    return _set_cls_msg_type
52
53
54def _register_parser(cls):
55    '''class decorator to register msg parser'''
56    assert cls.cls_msg_type is not None
57    assert cls.cls_msg_type not in _MSG_PARSERS
58    _MSG_PARSERS[cls.cls_msg_type] = cls.parser
59    return cls
60
61
62@ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
63def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
64    parser = _MSG_PARSERS.get(msg_type)
65    return parser(datapath, version, msg_type, msg_len, xid, buf)
66
67
68# OFP_MSG_REPLY = {
69#     OFPFeaturesRequest: OFPSwitchFeatures,
70#     OFPBarrierRequest: OFPBarrierReply,
71#     OFPQueueGetConfigRequest: OFPQueueGetConfigReply,
72#
73#     # ofp_stats_request -> ofp_stats_reply
74#     OFPDescStatsRequest: OFPDescStatsReply,
75#     OFPFlowStatsRequest: OFPFlowStatsReply,
76#     OFPAggregateStatsRequest: OFPAggregateStatsReply,
77#     OFPTableStatsRequest: OFPTableStatsReply,
78#     OFPPortStatsRequest: OFPPortStatsReply,
79#     OFPQueueStatsRequest: OFPQueueStatsReply,
80#     OFPVendorStatsRequest: OFPVendorStatsReply,
81#     }
82def _set_msg_reply(msg_reply):
83    '''Annotate OFP reply message class'''
84    def _set_cls_msg_reply(cls):
85        cls.cls_msg_reply = msg_reply
86        return cls
87    return _set_cls_msg_reply
88
89
90#
91# common structures
92#
93
94class OFPPhyPort(ofproto_parser.namedtuple('OFPPhyPort', (
95        'port_no', 'hw_addr', 'name', 'config', 'state', 'curr', 'advertised',
96        'supported', 'peer'))):
97    """
98    Description of a port
99
100    ========== =========================================================
101    Attribute  Description
102    ========== =========================================================
103    port_no    Port number and it uniquely identifies a port within
104               a switch.
105    hw_addr    MAC address for the port.
106    name       Null-terminated string containing a human-readable name
107               for the interface.
108    config     Bitmap of port configration flags.
109
110               | OFPPC_PORT_DOWN
111               | OFPPC_NO_STP
112               | OFPPC_NO_RECV
113               | OFPPC_NO_RECV_STP
114               | OFPPC_NO_FLOOD
115               | OFPPC_NO_FWD
116               | OFPPC_NO_PACKET_IN
117    state      Bitmap of port state flags.
118
119               | OFPPS_LINK_DOWN
120               | OFPPS_STP_LISTEN
121               | OFPPS_STP_LEARN
122               | OFPPS_STP_FORWARD
123               | OFPPS_STP_BLOCK
124               | OFPPS_STP_MASK
125    curr       Current features.
126    advertised Features being advertised by the port.
127    supported  Features supported by the port.
128    peer       Features advertised by peer.
129    ========== =========================================================
130    """
131    _TYPE = {
132        'ascii': [
133            'hw_addr',
134        ],
135        'utf-8': [
136            # OF spec is unclear about the encoding of name.
137            # we assumes UTF-8, which is used by OVS.
138            'name',
139        ]
140    }
141
142    @classmethod
143    def parser(cls, buf, offset):
144        port = struct.unpack_from(ofproto.OFP_PHY_PORT_PACK_STR,
145                                  buf, offset)
146        port = list(port)
147        i = cls._fields.index('hw_addr')
148        port[i] = addrconv.mac.bin_to_text(port[i])
149        i = cls._fields.index('name')
150        port[i] = port[i].rstrip(b'\0')
151        return cls(*port)
152
153
154class OFPMatch(StringifyMixin):
155    """
156    Flow Match Structure
157
158    This class is implementation of the flow match structure having
159    compose/query API.
160
161    ================ ==================================================
162    Attribute        Description
163    ================ ==================================================
164    wildcards        Wildcard fields.
165    (match fields)   For the available match fields,
166                     please refer to the following.
167    ================ ==================================================
168
169    ================ =============== ==================================
170    Argument         Value           Description
171    ================ =============== ==================================
172    in_port          Integer 16bit   Switch input port.
173    dl_src           MAC address     Ethernet source address.
174    dl_dst           MAC address     Ethernet destination address.
175    dl_vlan          Integer 16bit   Input VLAN id.
176    dl_vlan_pcp      Integer 8bit    Input VLAN priority.
177    dl_type          Integer 16bit   Ethernet frame type.
178    nw_tos           Integer 8bit    IP ToS (actually DSCP field, 6 bits).
179    nw_proto         Integer 8bit    IP protocol or lower 8 bits of
180                                     ARP opcode.
181    nw_src           IPv4 address    IP source address.
182    nw_dst           IPv4 address    IP destination address.
183    tp_src           Integer 16bit   TCP/UDP source port.
184    tp_dst           Integer 16bit   TCP/UDP destination port.
185    nw_src_mask      Integer 8bit    IP source address mask
186                                     specified as IPv4 address prefix.
187    nw_dst_mask      Integer 8bit    IP destination address mask
188                                     specified as IPv4 address prefix.
189    ================ =============== ==================================
190
191    Example::
192
193        >>> # compose
194        >>> match = parser.OFPMatch(
195        ...     in_port=1,
196        ...     dl_type=0x0800,
197        ...     dl_src='aa:bb:cc:dd:ee:ff',
198        ...     nw_src='192.168.0.1')
199        >>> # query
200        >>> if 'nw_src' in match:
201        ...     print match['nw_src']
202        ...
203        '192.168.0.1'
204    """
205
206    def __init__(self, wildcards=None, in_port=None, dl_src=None, dl_dst=None,
207                 dl_vlan=None, dl_vlan_pcp=None, dl_type=None, nw_tos=None,
208                 nw_proto=None, nw_src=None, nw_dst=None,
209                 tp_src=None, tp_dst=None, nw_src_mask=32, nw_dst_mask=32):
210        super(OFPMatch, self).__init__()
211        wc = ofproto.OFPFW_ALL
212        if in_port is None:
213            self.in_port = 0
214        else:
215            wc &= ~ofproto.OFPFW_IN_PORT
216            self.in_port = in_port
217
218        if dl_src is None:
219            self.dl_src = mac.DONTCARE
220        else:
221            wc &= ~ofproto.OFPFW_DL_SRC
222            if (isinstance(dl_src, (six.text_type, str)) and
223                    netaddr.valid_mac(dl_src)):
224                dl_src = addrconv.mac.text_to_bin(dl_src)
225            if dl_src == 0:
226                self.dl_src = mac.DONTCARE
227            else:
228                self.dl_src = dl_src
229
230        if dl_dst is None:
231            self.dl_dst = mac.DONTCARE
232        else:
233            wc &= ~ofproto.OFPFW_DL_DST
234            if (isinstance(dl_dst, (six.text_type, str)) and
235                    netaddr.valid_mac(dl_dst)):
236                dl_dst = addrconv.mac.text_to_bin(dl_dst)
237            if dl_dst == 0:
238                self.dl_dst = mac.DONTCARE
239            else:
240                self.dl_dst = dl_dst
241
242        if dl_vlan is None:
243            self.dl_vlan = 0
244        else:
245            wc &= ~ofproto.OFPFW_DL_VLAN
246            self.dl_vlan = dl_vlan
247
248        if dl_vlan_pcp is None:
249            self.dl_vlan_pcp = 0
250        else:
251            wc &= ~ofproto.OFPFW_DL_VLAN_PCP
252            self.dl_vlan_pcp = dl_vlan_pcp
253
254        if dl_type is None:
255            self.dl_type = 0
256        else:
257            wc &= ~ofproto.OFPFW_DL_TYPE
258            self.dl_type = dl_type
259
260        if nw_tos is None:
261            self.nw_tos = 0
262        else:
263            wc &= ~ofproto.OFPFW_NW_TOS
264            self.nw_tos = nw_tos
265
266        if nw_proto is None:
267            self.nw_proto = 0
268        else:
269            wc &= ~ofproto.OFPFW_NW_PROTO
270            self.nw_proto = nw_proto
271
272        if nw_src is None:
273            self.nw_src = 0
274        else:
275            wc &= (32 - nw_src_mask) << ofproto.OFPFW_NW_SRC_SHIFT \
276                | ~ofproto.OFPFW_NW_SRC_MASK
277            if not isinstance(nw_src, int):
278                nw_src = ip.ipv4_to_int(nw_src)
279            self.nw_src = nw_src
280
281        if nw_dst is None:
282            self.nw_dst = 0
283        else:
284            wc &= (32 - nw_dst_mask) << ofproto.OFPFW_NW_DST_SHIFT \
285                | ~ofproto.OFPFW_NW_DST_MASK
286            if not isinstance(nw_dst, int):
287                nw_dst = ip.ipv4_to_int(nw_dst)
288            self.nw_dst = nw_dst
289
290        if tp_src is None:
291            self.tp_src = 0
292        else:
293            wc &= ~ofproto.OFPFW_TP_SRC
294            self.tp_src = tp_src
295
296        if tp_dst is None:
297            self.tp_dst = 0
298        else:
299            wc &= ~ofproto.OFPFW_TP_DST
300            self.tp_dst = tp_dst
301
302        if wildcards is None:
303            self.wildcards = wc
304        else:
305            self.wildcards = wildcards
306
307    def __getitem__(self, name):
308        if not isinstance(name, str):
309            raise KeyError(name)
310        elif name == 'nw_src_mask':
311            _m = 32 - ((self.wildcards & ofproto.OFPFW_NW_SRC_MASK) >>
312                       ofproto.OFPFW_NW_SRC_SHIFT)
313            return 0 if _m < 0 else _m
314        elif name == 'nw_dst_mask':
315            _m = 32 - ((self.wildcards & ofproto.OFPFW_NW_DST_MASK) >>
316                       ofproto.OFPFW_NW_DST_SHIFT)
317            return 0 if _m < 0 else _m
318        elif name == 'wildcards':
319            return self.wildcards
320
321        wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0)
322        if ~self.wildcards & wc:
323            value = getattr(self, name)
324            if name in ['dl_src', 'dl_dst']:
325                value = addrconv.mac.bin_to_text(value)
326            elif name in ['nw_src', 'nw_dst']:
327                value = ip.ipv4_to_str(value)
328            return value
329        else:
330            raise KeyError(name)
331
332    def __contains__(self, name):
333        wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0)
334        return ~self.wildcards & wc
335
336    def serialize(self, buf, offset):
337        msg_pack_into(ofproto.OFP_MATCH_PACK_STR, buf, offset,
338                      self.wildcards, self.in_port, self.dl_src,
339                      self.dl_dst, self.dl_vlan, self.dl_vlan_pcp,
340                      self.dl_type, self.nw_tos, self.nw_proto,
341                      self.nw_src, self.nw_dst, self.tp_src, self.tp_dst)
342
343    @classmethod
344    def parse(cls, buf, offset):
345        match = struct.unpack_from(ofproto.OFP_MATCH_PACK_STR,
346                                   buf, offset)
347        return cls(*match)
348
349    def to_jsondict(self):
350        fields = {}
351        # copy values to avoid original values conversion
352        for k, v in self.__dict__.items():
353            if k in ['dl_src', 'dl_dst']:
354                fields[k] = addrconv.mac.bin_to_text(v)
355            elif k in ['nw_src', 'nw_dst']:
356                fields[k] = ip.ipv4_to_str(v)
357            else:
358                fields[k] = v
359        return {self.__class__.__name__: fields}
360
361    @classmethod
362    def from_jsondict(cls, dict_):
363        return cls(**dict_)
364
365
366class OFPActionHeader(StringifyMixin):
367    _base_attributes = ['type', 'len']
368
369    def __init__(self, type_, len_):
370        self.type = type_
371        self.len = len_
372
373    def serialize(self, buf, offset):
374        msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
375                      buf, offset, self.type, self.len)
376
377
378class OFPAction(OFPActionHeader):
379    _ACTION_TYPES = {}
380
381    @staticmethod
382    def register_action_type(type_, len_):
383        def _register_action_type(cls):
384            cls.cls_action_type = type_
385            cls.cls_action_len = len_
386            OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
387            return cls
388        return _register_action_type
389
390    def __init__(self):
391        cls = self.__class__
392        super(OFPAction, self).__init__(cls.cls_action_type,
393                                        cls.cls_action_len)
394
395    @classmethod
396    def parser(cls, buf, offset):
397        type_, len_ = struct.unpack_from(
398            ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
399        cls_ = cls._ACTION_TYPES.get(type_)
400        assert cls_ is not None
401        return cls_.parser(buf, offset)
402
403
404@OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
405                                ofproto.OFP_ACTION_OUTPUT_SIZE)
406class OFPActionOutput(OFPAction):
407    """
408    Output action
409
410    This action indicates output a packet to the switch port.
411
412    ================ ======================================================
413    Attribute        Description
414    ================ ======================================================
415    port             Output port.
416    max_len          Max length to send to controller.
417    ================ ======================================================
418
419    Note::
420        The reason of this magic number (0xffe5)
421        is because there is no good constant in of1.0.
422        The same value as OFPCML_MAX of of1.2 and of1.3 is used.
423    """
424
425    def __init__(self, port, max_len=0xffe5):
426        super(OFPActionOutput, self).__init__()
427        self.port = port
428        self.max_len = max_len
429
430    @classmethod
431    def parser(cls, buf, offset):
432        type_, len_, port, max_len = struct.unpack_from(
433            ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
434        assert type_ == ofproto.OFPAT_OUTPUT
435        assert len_ == ofproto.OFP_ACTION_OUTPUT_SIZE
436        return cls(port, max_len)
437
438    def serialize(self, buf, offset):
439        msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
440                      offset, self.type, self.len, self.port, self.max_len)
441
442
443@OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_VID,
444                                ofproto.OFP_ACTION_VLAN_VID_SIZE)
445class OFPActionVlanVid(OFPAction):
446    """
447    Set the 802.1q VLAN id action
448
449    This action indicates the 802.1q VLAN id to be set.
450
451    ================ ======================================================
452    Attribute        Description
453    ================ ======================================================
454    vlan_vid         VLAN id.
455    ================ ======================================================
456    """
457
458    def __init__(self, vlan_vid):
459        super(OFPActionVlanVid, self).__init__()
460        self.vlan_vid = vlan_vid
461
462    @classmethod
463    def parser(cls, buf, offset):
464        type_, len_, vlan_vid = struct.unpack_from(
465            ofproto.OFP_ACTION_VLAN_VID_PACK_STR, buf, offset)
466        assert type_ == ofproto.OFPAT_SET_VLAN_VID
467        assert len_ == ofproto.OFP_ACTION_VLAN_VID_SIZE
468        return cls(vlan_vid)
469
470    def serialize(self, buf, offset):
471        msg_pack_into(ofproto.OFP_ACTION_VLAN_VID_PACK_STR,
472                      buf, offset, self.type, self.len, self.vlan_vid)
473
474
475@OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_PCP,
476                                ofproto.OFP_ACTION_VLAN_PCP_SIZE)
477class OFPActionVlanPcp(OFPAction):
478    """
479    Set the 802.1q priority action
480
481    This action indicates the 802.1q priority to be set.
482
483    ================ ======================================================
484    Attribute        Description
485    ================ ======================================================
486    vlan_pcp         VLAN priority.
487    ================ ======================================================
488    """
489
490    def __init__(self, vlan_pcp):
491        super(OFPActionVlanPcp, self).__init__()
492        self.vlan_pcp = vlan_pcp
493
494    @classmethod
495    def parser(cls, buf, offset):
496        type_, len_, vlan_pcp = struct.unpack_from(
497            ofproto.OFP_ACTION_VLAN_PCP_PACK_STR, buf, offset)
498        assert type_ == ofproto.OFPAT_SET_VLAN_PCP
499        assert len_ == ofproto.OFP_ACTION_VLAN_PCP_SIZE
500        return cls(vlan_pcp)
501
502    def serialize(self, buf, offset):
503        msg_pack_into(ofproto.OFP_ACTION_VLAN_PCP_PACK_STR,
504                      buf, offset, self.type, self.len, self.vlan_pcp)
505
506
507@OFPAction.register_action_type(ofproto.OFPAT_STRIP_VLAN,
508                                ofproto.OFP_ACTION_HEADER_SIZE)
509class OFPActionStripVlan(OFPAction):
510    """
511    Strip the 802.1q header action
512
513    This action indicates the 802.1q priority to be striped.
514    """
515
516    def __init__(self):
517        super(OFPActionStripVlan, self).__init__()
518
519    @classmethod
520    def parser(cls, buf, offset):
521        type_, len_ = struct.unpack_from(
522            ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
523        assert type_ == ofproto.OFPAT_STRIP_VLAN
524        assert len_ == ofproto.OFP_ACTION_HEADER_SIZE
525        return cls()
526
527
528class OFPActionDlAddr(OFPAction):
529    def __init__(self, dl_addr):
530        super(OFPActionDlAddr, self).__init__()
531        if (isinstance(dl_addr, (six.text_type, str)) and
532                netaddr.valid_mac(dl_addr)):
533            dl_addr = addrconv.mac.text_to_bin(dl_addr)
534        self.dl_addr = dl_addr
535
536    @classmethod
537    def parser(cls, buf, offset):
538        type_, len_, dl_addr = struct.unpack_from(
539            ofproto.OFP_ACTION_DL_ADDR_PACK_STR, buf, offset)
540        assert type_ in (ofproto.OFPAT_SET_DL_SRC,
541                         ofproto.OFPAT_SET_DL_DST)
542        assert len_ == ofproto.OFP_ACTION_DL_ADDR_SIZE
543        return cls(dl_addr)
544
545    def serialize(self, buf, offset):
546        msg_pack_into(ofproto.OFP_ACTION_DL_ADDR_PACK_STR,
547                      buf, offset, self.type, self.len, self.dl_addr)
548
549    def to_jsondict(self):
550        body = {"dl_addr": addrconv.mac.bin_to_text(self.dl_addr)}
551        return {self.__class__.__name__: body}
552
553    @classmethod
554    def from_jsondict(cls, dict_):
555        return cls(**dict_)
556
557
558@OFPAction.register_action_type(ofproto.OFPAT_SET_DL_SRC,
559                                ofproto.OFP_ACTION_DL_ADDR_SIZE)
560class OFPActionSetDlSrc(OFPActionDlAddr):
561    """
562    Set the ethernet source address action
563
564    This action indicates the ethernet source address to be set.
565
566    ================ ======================================================
567    Attribute        Description
568    ================ ======================================================
569    dl_addr          Ethernet address.
570    ================ ======================================================
571    """
572
573    def __init__(self, dl_addr):
574        super(OFPActionSetDlSrc, self).__init__(dl_addr)
575
576
577@OFPAction.register_action_type(ofproto.OFPAT_SET_DL_DST,
578                                ofproto.OFP_ACTION_DL_ADDR_SIZE)
579class OFPActionSetDlDst(OFPActionDlAddr):
580    """
581    Set the ethernet destination address action
582
583    This action indicates the ethernet destination address to be set.
584
585    ================ ======================================================
586    Attribute        Description
587    ================ ======================================================
588    dl_addr          Ethernet address.
589    ================ ======================================================
590    """
591
592    def __init__(self, dl_addr):
593        super(OFPActionSetDlDst, self).__init__(dl_addr)
594
595
596class OFPActionNwAddr(OFPAction):
597    def __init__(self, nw_addr):
598        super(OFPActionNwAddr, self).__init__()
599        if not isinstance(nw_addr, int):
600            nw_addr = ip.ipv4_to_int(nw_addr)
601        self.nw_addr = nw_addr
602
603    @classmethod
604    def parser(cls, buf, offset):
605        type_, len_, nw_addr = struct.unpack_from(
606            ofproto.OFP_ACTION_NW_ADDR_PACK_STR, buf, offset)
607        assert type_ in (ofproto.OFPAT_SET_NW_SRC,
608                         ofproto.OFPAT_SET_NW_DST)
609        assert len_ == ofproto.OFP_ACTION_NW_ADDR_SIZE
610        return cls(nw_addr)
611
612    def serialize(self, buf, offset):
613        msg_pack_into(ofproto.OFP_ACTION_NW_ADDR_PACK_STR,
614                      buf, offset, self.type, self.len, self.nw_addr)
615
616    def to_jsondict(self):
617        body = {"nw_addr": ip.ipv4_to_str(self.nw_addr)}
618        return {self.__class__.__name__: body}
619
620    @classmethod
621    def from_jsondict(cls, dict_):
622        return cls(**dict_)
623
624
625@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_SRC,
626                                ofproto.OFP_ACTION_NW_ADDR_SIZE)
627class OFPActionSetNwSrc(OFPActionNwAddr):
628    """
629    Set the IP source address action
630
631    This action indicates the IP source address to be set.
632
633    ================ ======================================================
634    Attribute        Description
635    ================ ======================================================
636    nw_addr          IP address.
637    ================ ======================================================
638    """
639
640    def __init__(self, nw_addr):
641        super(OFPActionSetNwSrc, self).__init__(nw_addr)
642
643
644@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_DST,
645                                ofproto.OFP_ACTION_NW_ADDR_SIZE)
646class OFPActionSetNwDst(OFPActionNwAddr):
647    """
648    Set the IP destination address action
649
650    This action indicates the IP destination address to be set.
651
652    ================ ======================================================
653    Attribute        Description
654    ================ ======================================================
655    nw_addr          IP address.
656    ================ ======================================================
657    """
658
659    def __init__(self, nw_addr):
660        super(OFPActionSetNwDst, self).__init__(nw_addr)
661
662
663@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TOS,
664                                ofproto.OFP_ACTION_NW_TOS_SIZE)
665class OFPActionSetNwTos(OFPAction):
666    """
667    Set the IP ToS action
668
669    This action indicates the IP ToS (DSCP field, 6 bits) to be set.
670
671    ================ ======================================================
672    Attribute        Description
673    ================ ======================================================
674    tos              IP ToS (DSCP field, 6 bits).
675    ================ ======================================================
676    """
677
678    def __init__(self, tos):
679        super(OFPActionSetNwTos, self).__init__()
680        self.tos = tos
681
682    @classmethod
683    def parser(cls, buf, offset):
684        type_, len_, tos = struct.unpack_from(
685            ofproto.OFP_ACTION_NW_TOS_PACK_STR, buf, offset)
686        assert type_ == ofproto.OFPAT_SET_NW_TOS
687        assert len_ == ofproto.OFP_ACTION_NW_TOS_SIZE
688        return cls(tos)
689
690    def serialize(self, buf, offset):
691        msg_pack_into(ofproto.OFP_ACTION_NW_TOS_PACK_STR,
692                      buf, offset, self.type, self.len, self.tos)
693
694
695class OFPActionTpPort(OFPAction):
696    def __init__(self, tp):
697        super(OFPActionTpPort, self).__init__()
698        self.tp = tp
699
700    @classmethod
701    def parser(cls, buf, offset):
702        type_, len_, tp = struct.unpack_from(
703            ofproto.OFP_ACTION_TP_PORT_PACK_STR, buf, offset)
704        assert type_ in (ofproto.OFPAT_SET_TP_SRC,
705                         ofproto.OFPAT_SET_TP_DST)
706        assert len_ == ofproto.OFP_ACTION_TP_PORT_SIZE
707        return cls(tp)
708
709    def serialize(self, buf, offset):
710        msg_pack_into(ofproto.OFP_ACTION_TP_PORT_PACK_STR,
711                      buf, offset, self.type, self.len, self.tp)
712
713
714@OFPAction.register_action_type(ofproto.OFPAT_SET_TP_SRC,
715                                ofproto.OFP_ACTION_TP_PORT_SIZE)
716class OFPActionSetTpSrc(OFPActionTpPort):
717    """
718    Set the TCP/UDP source port action
719
720    This action indicates the TCP/UDP source port to be set.
721
722    ================ ======================================================
723    Attribute        Description
724    ================ ======================================================
725    tp               TCP/UDP port.
726    ================ ======================================================
727    """
728
729    def __init__(self, tp):
730        super(OFPActionSetTpSrc, self).__init__(tp)
731
732
733@OFPAction.register_action_type(ofproto.OFPAT_SET_TP_DST,
734                                ofproto.OFP_ACTION_TP_PORT_SIZE)
735class OFPActionSetTpDst(OFPActionTpPort):
736    """
737    Set the TCP/UDP destination port action
738
739    This action indicates the TCP/UDP destination port to be set.
740
741    ================ ======================================================
742    Attribute        Description
743    ================ ======================================================
744    tp               TCP/UDP port.
745    ================ ======================================================
746    """
747
748    def __init__(self, tp):
749        super(OFPActionSetTpDst, self).__init__(tp)
750
751
752@OFPAction.register_action_type(ofproto.OFPAT_ENQUEUE,
753                                ofproto.OFP_ACTION_ENQUEUE_SIZE)
754class OFPActionEnqueue(OFPAction):
755    """
756    Output to queue action
757
758    This action indicates send packets to given queue on port.
759
760    ================ ======================================================
761    Attribute        Description
762    ================ ======================================================
763    port             Port that queue belongs.
764    queue_id         Where to enqueue the packets.
765    ================ ======================================================
766    """
767
768    def __init__(self, port, queue_id):
769        super(OFPActionEnqueue, self).__init__()
770        self.port = port
771        self.queue_id = queue_id
772
773    @classmethod
774    def parser(cls, buf, offset):
775        type_, len_, port, queue_id = struct.unpack_from(
776            ofproto.OFP_ACTION_ENQUEUE_PACK_STR, buf, offset)
777        assert type_ == ofproto.OFPAT_ENQUEUE
778        assert len_ == ofproto.OFP_ACTION_ENQUEUE_SIZE
779        return cls(port, queue_id)
780
781    def serialize(self, buf, offset):
782        msg_pack_into(ofproto.OFP_ACTION_ENQUEUE_PACK_STR, buf, offset,
783                      self.type, self.len, self.port, self.queue_id)
784
785
786@OFPAction.register_action_type(ofproto.OFPAT_VENDOR, 0)
787class OFPActionVendor(OFPAction):
788    """
789    Vendor action
790
791    This action is an extensible action for the vendor.
792    """
793    _ACTION_VENDORS = {}
794
795    @staticmethod
796    def register_action_vendor(vendor):
797        def _register_action_vendor(cls):
798            cls.cls_vendor = vendor
799            OFPActionVendor._ACTION_VENDORS[cls.cls_vendor] = cls
800            return cls
801        return _register_action_vendor
802
803    def __init__(self, vendor=None):
804        super(OFPActionVendor, self).__init__()
805        self.type = ofproto.OFPAT_VENDOR
806        self.len = None
807
808        if vendor is None:
809            self.vendor = self.cls_vendor
810        else:
811            self.vendor = vendor
812
813    @classmethod
814    def parser(cls, buf, offset):
815        type_, len_, vendor = struct.unpack_from(
816            ofproto.OFP_ACTION_VENDOR_HEADER_PACK_STR, buf, offset)
817
818        data = buf[(offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE
819                    ): offset + len_]
820
821        if vendor == ofproto_common.NX_EXPERIMENTER_ID:
822            obj = NXAction.parse(data)  # noqa
823        else:
824            cls_ = cls._ACTION_VENDORS.get(vendor, None)
825
826            if cls_ is None:
827                obj = OFPActionVendorUnknown(vendor, data)
828            else:
829                obj = cls_.parser(buf, offset)
830
831        obj.len = len_
832        return obj
833
834    def serialize(self, buf, offset):
835        msg_pack_into(ofproto.OFP_ACTION_VENDOR_HEADER_PACK_STR,
836                      buf, offset, self.type, self.len, self.vendor)
837
838
839# OpenFlow1.2 or later compatible
840OFPActionExperimenter = OFPActionVendor
841
842
843class OFPActionVendorUnknown(OFPActionVendor):
844    def __init__(self, vendor, data=None, type_=None, len_=None):
845        super(OFPActionVendorUnknown,
846              self).__init__(vendor=vendor)
847        self.data = data
848
849    def serialize(self, buf, offset):
850        # fixup
851        data = self.data
852        if data is None:
853            data = bytearray()
854        self.len = (utils.round_up(len(data), 8) +
855                    ofproto.OFP_ACTION_VENDOR_HEADER_SIZE)
856        super(OFPActionVendorUnknown, self).serialize(buf, offset)
857        msg_pack_into('!%ds' % len(self.data),
858                      buf,
859                      offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE,
860                      self.data)
861
862
863@OFPActionVendor.register_action_vendor(ofproto_common.NX_EXPERIMENTER_ID)
864class NXActionHeader(OFPActionVendor):
865    _NX_ACTION_SUBTYPES = {}
866
867    @staticmethod
868    def register_nx_action_subtype(subtype, len_):
869        def _register_nx_action_subtype(cls):
870            cls.cls_action_len = len_
871            cls.cls_subtype = subtype
872            NXActionHeader._NX_ACTION_SUBTYPES[cls.cls_subtype] = cls
873            return cls
874        return _register_nx_action_subtype
875
876    def __init__(self):
877        super(NXActionHeader, self).__init__()
878        self.subtype = self.cls_subtype
879
880    def serialize(self, buf, offset):
881        msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
882                      buf, offset, self.type, self.len)
883
884    @classmethod
885    def parser(cls, buf, offset):
886        type_, len_, vendor, subtype = struct.unpack_from(
887            ofproto.NX_ACTION_HEADER_PACK_STR, buf, offset)
888        cls_ = cls._NX_ACTION_SUBTYPES.get(subtype)
889        return cls_.parser(buf, offset)
890
891
892class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
893        'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
894
895    _TYPE = {
896        'ascii': [
897            'mfr_desc',
898            'hw_desc',
899            'sw_desc',
900            'serial_num',
901            'dp_desc',
902        ]
903    }
904
905    @classmethod
906    def parser(cls, buf, offset):
907        desc = struct.unpack_from(ofproto.OFP_DESC_STATS_PACK_STR,
908                                  buf, offset)
909        desc = list(desc)
910        desc = [x.rstrip(b'\0') for x in desc]
911        stats = cls(*desc)
912        stats.length = ofproto.OFP_DESC_STATS_SIZE
913        return stats
914
915
916class OFPFlowStats(StringifyMixin):
917    def __init__(self):
918        super(OFPFlowStats, self).__init__()
919        self.length = None
920        self.table_id = None
921        self.match = None
922        self.duration_sec = None
923        self.duration_nsec = None
924        self.priority = None
925        self.idle_timeout = None
926        self.hard_timeout = None
927        self.cookie = None
928        self.packet_count = None
929        self.byte_count = None
930        self.actions = None
931
932    @classmethod
933    def parser(cls, buf, offset):
934        flow_stats = cls()
935
936        flow_stats.length, flow_stats.table_id = struct.unpack_from(
937            ofproto.OFP_FLOW_STATS_0_PACK_STR, buf, offset)
938        offset += ofproto.OFP_FLOW_STATS_0_SIZE
939
940        flow_stats.match = OFPMatch.parse(buf, offset)
941        offset += ofproto.OFP_MATCH_SIZE
942
943        (flow_stats.duration_sec,
944         flow_stats.duration_nsec,
945         flow_stats.priority,
946         flow_stats.idle_timeout,
947         flow_stats.hard_timeout,
948         flow_stats.cookie,
949         flow_stats.packet_count,
950         flow_stats.byte_count) = struct.unpack_from(
951            ofproto.OFP_FLOW_STATS_1_PACK_STR, buf, offset)
952        offset += ofproto.OFP_FLOW_STATS_1_SIZE
953
954        flow_stats.actions = []
955        length = ofproto.OFP_FLOW_STATS_SIZE
956        while length < flow_stats.length:
957            action = OFPAction.parser(buf, offset)
958            flow_stats.actions.append(action)
959
960            offset += action.len
961            length += action.len
962
963        return flow_stats
964
965
966class OFPAggregateStats(ofproto_parser.namedtuple('OFPAggregateStats', (
967        'packet_count', 'byte_count', 'flow_count'))):
968    @classmethod
969    def parser(cls, buf, offset):
970        agg = struct.unpack_from(
971            ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
972        stats = cls(*agg)
973        stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
974        return stats
975
976
977class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', (
978        'table_id', 'name', 'wildcards', 'max_entries', 'active_count',
979        'lookup_count', 'matched_count'))):
980
981    _TYPE = {
982        'utf-8': [
983            # OF spec is unclear about the encoding of name.
984            # we assumes UTF-8.
985            'name',
986        ]
987    }
988
989    @classmethod
990    def parser(cls, buf, offset):
991        tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR,
992                                 buf, offset)
993        tbl = list(tbl)
994        i = cls._fields.index('name')
995        tbl[i] = tbl[i].rstrip(b'\0')
996        stats = cls(*tbl)
997        stats.length = ofproto.OFP_TABLE_STATS_SIZE
998        return stats
999
1000
1001class OFPPortStats(ofproto_parser.namedtuple('OFPPortStats', (
1002        'port_no', 'rx_packets', 'tx_packets', 'rx_bytes', 'tx_bytes',
1003        'rx_dropped', 'tx_dropped', 'rx_errors', 'tx_errors',
1004        'rx_frame_err', 'rx_over_err', 'rx_crc_err', 'collisions'))):
1005    @classmethod
1006    def parser(cls, buf, offset):
1007        port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR,
1008                                  buf, offset)
1009        stats = cls(*port)
1010        stats.length = ofproto.OFP_PORT_STATS_SIZE
1011        return stats
1012
1013
1014class OFPQueueStats(ofproto_parser.namedtuple('OFPQueueStats', (
1015        'port_no', 'queue_id', 'tx_bytes', 'tx_packets', 'tx_errors'))):
1016    @classmethod
1017    def parser(cls, buf, offset):
1018        queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR,
1019                                   buf, offset)
1020        stats = cls(*queue)
1021        stats.length = ofproto.OFP_QUEUE_STATS_SIZE
1022        return stats
1023
1024
1025class OFPVendorStats(ofproto_parser.namedtuple('OFPVendorStats',
1026                                               ('specific_data'))):
1027    @classmethod
1028    def parser(cls, buf, offset):
1029        stats = cls(buf[offset:])
1030        stats.length = len(stats.specific_data)
1031        return stats
1032
1033
1034class NXFlowStats(StringifyMixin):
1035    def __init__(self):
1036        super(NXFlowStats, self).__init__()
1037        self.length = None
1038        self.table_id = None
1039        self.duration_sec = None
1040        self.duration_nsec = None
1041        self.priority = None
1042        self.idle_timeout = None
1043        self.hard_timeout = None
1044        self.match_len = None
1045        self.idle_age = None
1046        self.hard_age = None
1047        self.cookie = None
1048        self.packet_count = None
1049        self.byte_count = None
1050
1051    @classmethod
1052    def parser(cls, buf, offset):
1053        original_offset = offset
1054        nxflow_stats = cls()
1055        (nxflow_stats.length, nxflow_stats.table_id,
1056         nxflow_stats.duration_sec, nxflow_stats.duration_nsec,
1057         nxflow_stats.priority, nxflow_stats.idle_timeout,
1058         nxflow_stats.hard_timeout, nxflow_stats.match_len,
1059         nxflow_stats.idle_age, nxflow_stats.hard_age,
1060         nxflow_stats.cookie, nxflow_stats.packet_count,
1061         nxflow_stats.byte_count) = struct.unpack_from(
1062            ofproto.NX_FLOW_STATS_PACK_STR, buf, offset)
1063        offset += ofproto.NX_FLOW_STATS_SIZE
1064
1065        fields = []
1066        match_len = nxflow_stats.match_len
1067        match_len -= 4
1068        while match_len > 0:
1069            field = nx_match.MFField.parser(buf, offset)
1070            offset += field.length
1071            match_len -= field.length
1072            fields.append(field)
1073        nxflow_stats.fields = fields
1074
1075        actions = []
1076        total_len = original_offset + nxflow_stats.length
1077        match_len = nxflow_stats.match_len
1078        offset += utils.round_up(match_len, 8) - match_len
1079        while offset < total_len:
1080            action = OFPAction.parser(buf, offset)
1081            actions.append(action)
1082            offset += action.len
1083        nxflow_stats.actions = actions
1084
1085        return nxflow_stats
1086
1087
1088class NXAggregateStats(ofproto_parser.namedtuple('NXAggregateStats', (
1089        'packet_count', 'byte_count', 'flow_count'))):
1090    @classmethod
1091    def parser(cls, buf, offset):
1092        agg = struct.unpack_from(
1093            ofproto.NX_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
1094        stats = cls(*agg)
1095        stats.length = ofproto.NX_AGGREGATE_STATS_REPLY_SIZE
1096
1097        return stats
1098
1099
1100class OFPQueuePropHeader(StringifyMixin):
1101    _QUEUE_PROPERTIES = {}
1102
1103    @staticmethod
1104    def register_queue_property(prop_type, prop_len):
1105        def _register_queue_propery(cls):
1106            cls.cls_prop_type = prop_type
1107            cls.cls_prop_len = prop_len
1108            OFPQueuePropHeader._QUEUE_PROPERTIES[prop_type] = cls
1109            return cls
1110        return _register_queue_propery
1111
1112    def __init__(self):
1113        self.property = self.cls_prop_type
1114        self.len = self.cls_prop_len
1115
1116    @classmethod
1117    def parser(cls, buf, offset):
1118        property_, len_ = struct.unpack_from(
1119            ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR, buf, offset)
1120        prop_cls = cls._QUEUE_PROPERTIES[property_]
1121        assert property_ == prop_cls.cls_prop_type
1122        assert len_ == prop_cls.cls_prop_len
1123
1124        offset += ofproto.OFP_QUEUE_PROP_HEADER_SIZE
1125        return prop_cls.parser(buf, offset)
1126
1127
1128@OFPQueuePropHeader.register_queue_property(
1129    ofproto.OFPQT_NONE, ofproto.OFP_QUEUE_PROP_HEADER_SIZE)
1130class OFPQueuePropNone(OFPQueuePropHeader):
1131    def __init__(self):
1132        super(OFPQueuePropNone, self).__init__()
1133
1134    @classmethod
1135    def parser(cls, buf, offset):
1136        return cls()
1137
1138
1139@OFPQueuePropHeader.register_queue_property(
1140    ofproto.OFPQT_MIN_RATE, ofproto.OFP_QUEUE_PROP_MIN_RATE_SIZE)
1141class OFPQueuePropMinRate(OFPQueuePropHeader):
1142    def __init__(self, rate):
1143        super(OFPQueuePropMinRate, self).__init__()
1144        self.rate = rate
1145
1146    @classmethod
1147    def parser(cls, buf, offset):
1148        (rate,) = struct.unpack_from(
1149            ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR,
1150            buf, offset)
1151        return cls(rate)
1152
1153
1154class OFPPacketQueue(StringifyMixin):
1155    """
1156    Description of a queue
1157
1158    ========== =========================================================
1159    Attribute  Description
1160    ========== =========================================================
1161    queue_id   ID for the specific queue.
1162    len        Length in bytes of this queue desc.
1163    properties List of ``OFPQueueProp*`` instance.
1164    ========== =========================================================
1165    """
1166
1167    def __init__(self, queue_id, len_):
1168        self.queue_id = queue_id
1169        self.len = len_
1170        self.properties = None
1171
1172    @classmethod
1173    def parser(cls, buf, offset):
1174        queue_id, len_ = struct.unpack_from(
1175            ofproto.OFP_PACKET_QUEUE_PQCK_STR, buf, offset)
1176        packet_queue = cls(queue_id, len_)
1177
1178        packet_queue.properties = []
1179        cur_len = ofproto.OFP_PACKET_QUEUE_SIZE
1180        offset += ofproto.OFP_PACKET_QUEUE_SIZE
1181        while (cur_len + ofproto.OFP_QUEUE_PROP_HEADER_SIZE <=
1182               packet_queue.len):
1183            prop = OFPQueuePropHeader.parser(buf, offset)
1184            packet_queue.properties.append(prop)
1185
1186            cur_len += prop.len
1187            offset += prop.len
1188
1189        return packet_queue
1190
1191#
1192# Symmetric messages
1193# parser + serializer
1194#
1195
1196
1197@_register_parser
1198@_set_msg_type(ofproto.OFPT_HELLO)
1199class OFPHello(MsgBase):
1200    """
1201    Hello message
1202
1203    When connection is started, the hello message is exchanged between a
1204    switch and a controller.
1205
1206    This message is handled by the Ryu framework, so the Ryu application
1207    do not need to process this typically.
1208    """
1209
1210    def __init__(self, datapath):
1211        super(OFPHello, self).__init__(datapath)
1212
1213
1214@_register_parser
1215@_set_msg_type(ofproto.OFPT_ERROR)
1216class OFPErrorMsg(MsgBase):
1217    """
1218    Error message
1219
1220    The switch notifies controller of problems by this message.
1221
1222    ========== =========================================================
1223    Attribute  Description
1224    ========== =========================================================
1225    type       High level type of error
1226    code       Details depending on the type
1227    data       Variable length data depending on the type and code
1228    ========== =========================================================
1229
1230    ``type`` attribute corresponds to ``type_`` parameter of __init__.
1231
1232    Types and codes are defined in ``ryu.ofproto.ofproto``.
1233
1234    =========================== ===========
1235    Type                        Code
1236    =========================== ===========
1237    OFPET_HELLO_FAILED          OFPHFC_*
1238    OFPET_BAD_REQUEST           OFPBRC_*
1239    OFPET_BAD_ACTION            OFPBAC_*
1240    OFPET_FLOW_MOD_FAILED       OFPFMFC_*
1241    OFPET_PORT_MOD_FAILED       OFPPMFC_*
1242    OFPET_QUEUE_OP_FAILED       OFPQOFC_*
1243    =========================== ===========
1244
1245    Example::
1246
1247        @set_ev_cls(ofp_event.EventOFPErrorMsg,
1248                    [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
1249        def error_msg_handler(self, ev):
1250            msg = ev.msg
1251
1252            self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
1253                              'message=%s',
1254                              msg.type, msg.code, utils.hex_array(msg.data))
1255    """
1256
1257    def __init__(self, datapath, type_=None, code=None, data=None):
1258        super(OFPErrorMsg, self).__init__(datapath)
1259        self.type = type_
1260        self.code = code
1261        if isinstance(data, six.string_types):
1262            data = data.encode('ascii')
1263        self.data = data
1264
1265    @classmethod
1266    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1267        msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
1268                                             msg_len, xid, buf)
1269        msg.type, msg.code = struct.unpack_from(
1270            ofproto.OFP_ERROR_MSG_PACK_STR, msg.buf,
1271            ofproto.OFP_HEADER_SIZE)
1272        msg.data = msg.buf[ofproto.OFP_ERROR_MSG_SIZE:]
1273        return msg
1274
1275    def _serialize_body(self):
1276        assert self.data is not None
1277        msg_pack_into(ofproto.OFP_ERROR_MSG_PACK_STR, self.buf,
1278                      ofproto.OFP_HEADER_SIZE, self.type, self.code)
1279        self.buf += self.data
1280
1281
1282@_register_parser
1283@_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
1284class OFPEchoRequest(MsgBase):
1285    """
1286    Echo request message
1287
1288    This message is handled by the Ryu framework, so the Ryu application
1289    do not need to process this typically.
1290
1291    ========== =========================================================
1292    Attribute  Description
1293    ========== =========================================================
1294    data       An arbitrary length data.
1295    ========== =========================================================
1296
1297    Example::
1298
1299        def send_echo_request(self, datapath, data):
1300            ofp_parser = datapath.ofproto_parser
1301
1302            req = ofp_parser.OFPEchoRequest(datapath, data)
1303            datapath.send_msg(req)
1304    """
1305
1306    def __init__(self, datapath, data=None):
1307        super(OFPEchoRequest, self).__init__(datapath)
1308        self.data = data
1309
1310    @classmethod
1311    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1312        msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
1313                                                msg_len, xid, buf)
1314        msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
1315        return msg
1316
1317    def _serialize_body(self):
1318        if self.data is not None:
1319            self.buf += self.data
1320
1321
1322@_register_parser
1323@_set_msg_type(ofproto.OFPT_ECHO_REPLY)
1324class OFPEchoReply(MsgBase):
1325    """
1326    Echo reply message
1327
1328    This message is handled by the Ryu framework, so the Ryu application
1329    do not need to process this typically.
1330
1331    ========== =========================================================
1332    Attribute  Description
1333    ========== =========================================================
1334    data       An arbitrary length data.
1335    ========== =========================================================
1336
1337    Example::
1338
1339        @set_ev_cls(ofp_event.EventOFPEchoReply,
1340                    [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
1341        def echo_reply_handler(self, ev):
1342            self.logger.debug('OFPEchoReply received: data=%s',
1343                              utils.hex_array(ev.msg.data))
1344    """
1345
1346    def __init__(self, datapath, data=None):
1347        super(OFPEchoReply, self).__init__(datapath)
1348        self.data = data
1349
1350    @classmethod
1351    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1352        msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
1353                                              msg_len, xid, buf)
1354        msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
1355        return msg
1356
1357    def _serialize_body(self):
1358        assert self.data is not None
1359        self.buf += self.data
1360
1361
1362@_register_parser
1363@_set_msg_type(ofproto.OFPT_VENDOR)
1364class OFPVendor(MsgBase):
1365    """
1366    Vendor message
1367
1368    The controller send this message to send the vendor-specific
1369    information to a switch.
1370    """
1371    _VENDORS = {}
1372
1373    @staticmethod
1374    def register_vendor(id_):
1375        def _register_vendor(cls):
1376            OFPVendor._VENDORS[id_] = cls
1377            return cls
1378        return _register_vendor
1379
1380    def __init__(self, datapath):
1381        super(OFPVendor, self).__init__(datapath)
1382        self.data = None
1383        self.vendor = None
1384
1385    @classmethod
1386    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1387        msg = super(OFPVendor, cls).parser(datapath, version, msg_type,
1388                                           msg_len, xid, buf)
1389        (msg.vendor,) = struct.unpack_from(
1390            ofproto.OFP_VENDOR_HEADER_PACK_STR, msg.buf,
1391            ofproto.OFP_HEADER_SIZE)
1392
1393        cls_ = cls._VENDORS.get(msg.vendor)
1394        if cls_:
1395            msg.data = cls_.parser(datapath, msg.buf, 0)
1396        else:
1397            msg.data = msg.buf[ofproto.OFP_VENDOR_HEADER_SIZE:]
1398
1399        return msg
1400
1401    def serialize_header(self):
1402        msg_pack_into(ofproto.OFP_VENDOR_HEADER_PACK_STR,
1403                      self.buf, ofproto.OFP_HEADER_SIZE, self.vendor)
1404
1405    def _serialize_body(self):
1406        assert self.data is not None
1407        self.serialize_header()
1408        self.buf += self.data
1409
1410
1411@OFPVendor.register_vendor(ofproto_common.NX_EXPERIMENTER_ID)
1412class NiciraHeader(OFPVendor):
1413    _NX_SUBTYPES = {}
1414
1415    @staticmethod
1416    def register_nx_subtype(subtype):
1417        def _register_nx_subtype(cls):
1418            cls.cls_subtype = subtype
1419            NiciraHeader._NX_SUBTYPES[cls.cls_subtype] = cls
1420            return cls
1421        return _register_nx_subtype
1422
1423    def __init__(self, datapath, subtype):
1424        super(NiciraHeader, self).__init__(datapath)
1425        self.vendor = ofproto_common.NX_EXPERIMENTER_ID
1426        self.subtype = subtype
1427
1428    def serialize_header(self):
1429        super(NiciraHeader, self).serialize_header()
1430        msg_pack_into(ofproto.NICIRA_HEADER_PACK_STR,
1431                      self.buf, ofproto.OFP_HEADER_SIZE,
1432                      self.vendor, self.subtype)
1433
1434    @classmethod
1435    def parser(cls, datapath, buf, offset):
1436        vendor, subtype = struct.unpack_from(
1437            ofproto.NICIRA_HEADER_PACK_STR, buf,
1438            offset + ofproto.OFP_HEADER_SIZE)
1439        cls_ = cls._NX_SUBTYPES.get(subtype)
1440        return cls_.parser(datapath, buf,
1441                           offset + ofproto.NICIRA_HEADER_SIZE)
1442
1443
1444class NXTSetFlowFormat(NiciraHeader):
1445    def __init__(self, datapath, flow_format):
1446        super(NXTSetFlowFormat, self).__init__(
1447            datapath, ofproto.NXT_SET_FLOW_FORMAT)
1448        self.format = flow_format
1449
1450    def _serialize_body(self):
1451        self.serialize_header()
1452        msg_pack_into(ofproto.NX_SET_FLOW_FORMAT_PACK_STR,
1453                      self.buf, ofproto.NICIRA_HEADER_SIZE, self.format)
1454
1455
1456class NXTFlowMod(NiciraHeader):
1457    def __init__(self, datapath, cookie, command,
1458                 idle_timeout=0, hard_timeout=0,
1459                 priority=ofproto.OFP_DEFAULT_PRIORITY,
1460                 buffer_id=0xffffffff, out_port=ofproto.OFPP_NONE,
1461                 flags=0, rule=None, actions=None):
1462
1463        # the argument, rule, is positioned at the one before the last due
1464        # to the layout struct nxt_flow_mod.
1465        # Although rule must be given, default argument to rule, None,
1466        # is given to allow other default value of argument before rule.
1467        assert rule is not None
1468
1469        if actions is None:
1470            actions = []
1471        super(NXTFlowMod, self).__init__(datapath, ofproto.NXT_FLOW_MOD)
1472        self.cookie = cookie
1473        self.command = command
1474        self.idle_timeout = idle_timeout
1475        self.hard_timeout = hard_timeout
1476        self.priority = priority
1477        self.buffer_id = buffer_id
1478        self.out_port = out_port
1479        self.flags = flags
1480        self.rule = rule
1481        self.actions = actions
1482
1483    def _serialize_body(self):
1484        self.serialize_header()
1485
1486        offset = ofproto.NX_FLOW_MOD_SIZE
1487        match_len = nx_match.serialize_nxm_match(self.rule, self.buf, offset)
1488        offset += nx_match.round_up(match_len)
1489
1490        msg_pack_into(ofproto.NX_FLOW_MOD_PACK_STR,
1491                      self.buf, ofproto.NICIRA_HEADER_SIZE,
1492                      self.cookie, self.command, self.idle_timeout,
1493                      self.hard_timeout, self.priority, self.buffer_id,
1494                      self.out_port, self.flags, match_len)
1495
1496        if self.actions is not None:
1497            for a in self.actions:
1498                a.serialize(self.buf, offset)
1499                offset += a.len
1500
1501
1502class NXTRoleRequest(NiciraHeader):
1503    def __init__(self, datapath, role):
1504        super(NXTRoleRequest, self).__init__(
1505            datapath, ofproto.NXT_ROLE_REQUEST)
1506        self.role = role
1507
1508    def _serialize_body(self):
1509        self.serialize_header()
1510        msg_pack_into(ofproto.NX_ROLE_PACK_STR,
1511                      self.buf, ofproto.NICIRA_HEADER_SIZE, self.role)
1512
1513
1514@NiciraHeader.register_nx_subtype(ofproto.NXT_ROLE_REPLY)
1515class NXTRoleReply(NiciraHeader):
1516    def __init__(self, datapath, role):
1517        super(NXTRoleReply, self).__init__(
1518            datapath, ofproto.NXT_ROLE_REPLY)
1519        self.role = role
1520
1521    @classmethod
1522    def parser(cls, datapath, buf, offset):
1523        (role,) = struct.unpack_from(
1524            ofproto.NX_ROLE_PACK_STR, buf, offset)
1525        return cls(datapath, role)
1526
1527
1528class NXTFlowModTableId(NiciraHeader):
1529    def __init__(self, datapath, set_):
1530        super(NXTFlowModTableId, self).__init__(
1531            datapath, ofproto.NXT_FLOW_MOD_TABLE_ID)
1532        self.set = set_
1533
1534    def _serialize_body(self):
1535        self.serialize_header()
1536        msg_pack_into(ofproto.NX_FLOW_MOD_TABLE_ID_PACK_STR,
1537                      self.buf, ofproto.NICIRA_HEADER_SIZE,
1538                      self.set)
1539
1540
1541@NiciraHeader.register_nx_subtype(ofproto.NXT_FLOW_REMOVED)
1542class NXTFlowRemoved(NiciraHeader):
1543    def __init__(self, datapath, cookie, priority, reason,
1544                 duration_sec, duration_nsec, idle_timeout, match_len,
1545                 packet_count, byte_count, match):
1546        super(NXTFlowRemoved, self).__init__(
1547            datapath, ofproto.NXT_FLOW_REMOVED)
1548        self.cookie = cookie
1549        self.priority = priority
1550        self.reason = reason
1551        self.duration_sec = duration_sec
1552        self.duration_nsec = duration_nsec
1553        self.idle_timeout = idle_timeout
1554        self.match_len = match_len
1555        self.packet_count = packet_count
1556        self.byte_count = byte_count
1557        self.match = match
1558
1559    @classmethod
1560    def parser(cls, datapath, buf, offset):
1561        (cookie, priority, reason, duration_sec, duration_nsec,
1562         idle_timeout, match_len,
1563         packet_count, byte_count) = struct.unpack_from(
1564            ofproto.NX_FLOW_REMOVED_PACK_STR, buf, offset)
1565        offset += (ofproto.NX_FLOW_REMOVED_SIZE -
1566                   ofproto.NICIRA_HEADER_SIZE)
1567        match = nx_match.NXMatch.parser(buf, offset, match_len)
1568        return cls(datapath, cookie, priority, reason, duration_sec,
1569                   duration_nsec, idle_timeout, match_len, packet_count,
1570                   byte_count, match)
1571
1572
1573class NXTSetPacketInFormat(NiciraHeader):
1574    def __init__(self, datapath, packet_in_format):
1575        super(NXTSetPacketInFormat, self).__init__(
1576            datapath, ofproto.NXT_SET_PACKET_IN_FORMAT)
1577        self.format = packet_in_format
1578
1579    def _serialize_body(self):
1580        self.serialize_header()
1581        msg_pack_into(ofproto.NX_SET_PACKET_IN_FORMAT_PACK_STR,
1582                      self.buf, ofproto.NICIRA_HEADER_SIZE,
1583                      self.format)
1584
1585
1586@NiciraHeader.register_nx_subtype(ofproto.NXT_PACKET_IN)
1587class NXTPacketIn(NiciraHeader):
1588    def __init__(self, datapath, buffer_id, total_len, reason, table_id,
1589                 cookie, match_len, match, frame):
1590        super(NXTPacketIn, self).__init__(
1591            datapath, ofproto.NXT_PACKET_IN)
1592        self.buffer_id = buffer_id
1593        self.total_len = total_len
1594        self.reason = reason
1595        self.table_id = table_id
1596        self.cookie = cookie
1597        self.match_len = match_len
1598        self.match = match
1599        self.frame = frame
1600
1601    @classmethod
1602    def parser(cls, datapath, buf, offset):
1603        (buffer_id, total_len, reason, table_id,
1604         cookie, match_len) = struct.unpack_from(
1605            ofproto.NX_PACKET_IN_PACK_STR, buf, offset)
1606
1607        offset += (ofproto.NX_PACKET_IN_SIZE -
1608                   ofproto.NICIRA_HEADER_SIZE)
1609
1610        match = nx_match.NXMatch.parser(buf, offset, match_len)
1611        offset += (match_len + 7) // 8 * 8
1612        frame = buf[offset:]
1613        if total_len < len(frame):
1614            frame = frame[:total_len]
1615        return cls(datapath, buffer_id, total_len, reason, table_id,
1616                   cookie, match_len, match, frame)
1617
1618
1619class NXTFlowAge(NiciraHeader):
1620    def __init__(self, datapath):
1621        super(NXTFlowAge, self).__init__(
1622            datapath, ofproto.NXT_FLOW_AGE)
1623
1624    def _serialize_body(self):
1625        self.serialize_header()
1626
1627
1628class NXTSetAsyncConfig(NiciraHeader):
1629    def __init__(self, datapath, packet_in_mask, port_status_mask,
1630                 flow_removed_mask):
1631        super(NXTSetAsyncConfig, self).__init__(
1632            datapath, ofproto.NXT_SET_ASYNC_CONFIG)
1633        self.packet_in_mask = packet_in_mask
1634        self.port_status_mask = port_status_mask
1635        self.flow_removed_mask = flow_removed_mask
1636
1637    def _serialize_body(self):
1638        self.serialize_header()
1639        msg_pack_into(ofproto.NX_ASYNC_CONFIG_PACK_STR,
1640                      self.buf, ofproto.NICIRA_HEADER_SIZE,
1641                      self.packet_in_mask[0], self.packet_in_mask[1],
1642                      self.port_status_mask[0], self.port_status_mask[1],
1643                      self.flow_removed_mask[0], self.flow_removed_mask[1])
1644
1645
1646class NXTSetControllerId(NiciraHeader):
1647    def __init__(self, datapath, controller_id):
1648        super(NXTSetControllerId, self).__init__(
1649            datapath, ofproto.NXT_SET_CONTROLLER_ID)
1650        self.controller_id = controller_id
1651
1652    def _serialize_body(self):
1653        self.serialize_header()
1654        msg_pack_into(ofproto.NX_CONTROLLER_ID_PACK_STR,
1655                      self.buf, ofproto.NICIRA_HEADER_SIZE,
1656                      self.controller_id)
1657
1658
1659#
1660# asymmetric message (datapath -> controller)
1661# parser only
1662#
1663
1664
1665@_register_parser
1666@_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
1667class OFPSwitchFeatures(MsgBase):
1668    """
1669    Features reply message
1670
1671    The switch responds with a features reply message to a features
1672    request.
1673
1674    This message is handled by the Ryu framework, so the Ryu application
1675    do not need to process this typically.
1676
1677    ================ ======================================================
1678    Attribute        Description
1679    ================ ======================================================
1680    datapath_id      Datapath unique ID.
1681    n_buffers        Max packets buffered at once.
1682    n_tables         Number of tables supported by datapath.
1683    capabilities     Bitmap of capabilities flag.
1684
1685                     | OFPC_FLOW_STATS
1686                     | OFPC_TABLE_STATS
1687                     | OFPC_PORT_STATS
1688                     | OFPC_STP
1689                     | OFPC_RESERVED
1690                     | OFPC_IP_REASM
1691                     | OFPC_QUEUE_STATS
1692                     | OFPC_ARP_MATCH_IP
1693    actions          Bitmap of supported OFPAT_*.
1694    ports            List of ``OFPPhyPort`` instances.
1695    ================ ======================================================
1696
1697    Example::
1698
1699        @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
1700        def switch_features_handler(self, ev):
1701            msg = ev.msg
1702
1703            self.logger.debug('OFPSwitchFeatures received: '
1704                              'datapath_id=0x%016x n_buffers=%d '
1705                              'n_tables=%d capabilities=0x%08x ports=%s',
1706                              msg.datapath_id, msg.n_buffers, msg.n_tables,
1707                              msg.capabilities, msg.ports)
1708    """
1709
1710    def __init__(self, datapath, datapath_id=None, n_buffers=None,
1711                 n_tables=None, capabilities=None, actions=None, ports=None):
1712        super(OFPSwitchFeatures, self).__init__(datapath)
1713        self.datapath_id = datapath_id
1714        self.n_buffers = n_buffers
1715        self.n_tables = n_tables
1716        self.capabilities = capabilities
1717        self.actions = actions
1718        self.ports = ports
1719
1720    @classmethod
1721    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1722        msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
1723                                                   msg_len, xid, buf)
1724        (msg.datapath_id,
1725         msg.n_buffers,
1726         msg.n_tables,
1727         msg.capabilities,
1728         msg.actions) = struct.unpack_from(
1729            ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
1730            ofproto.OFP_HEADER_SIZE)
1731
1732        msg.ports = {}
1733        n_ports = ((msg_len - ofproto.OFP_SWITCH_FEATURES_SIZE) //
1734                   ofproto.OFP_PHY_PORT_SIZE)
1735        offset = ofproto.OFP_SWITCH_FEATURES_SIZE
1736        for _i in range(n_ports):
1737            port = OFPPhyPort.parser(msg.buf, offset)
1738            # print 'port = %s' % str(port)
1739            msg.ports[port.port_no] = port
1740            offset += ofproto.OFP_PHY_PORT_SIZE
1741
1742        return msg
1743
1744
1745@_register_parser
1746@_set_msg_type(ofproto.OFPT_PORT_STATUS)
1747class OFPPortStatus(MsgBase):
1748    """
1749    Port status message
1750
1751    The switch notifies controller of change of ports.
1752
1753    ================ ======================================================
1754    Attribute        Description
1755    ================ ======================================================
1756    reason           One of the following values.
1757
1758                     | OFPPR_ADD
1759                     | OFPPR_DELETE
1760                     | OFPPR_MODIFY
1761    desc             instance of ``OFPPhyPort``
1762    ================ ======================================================
1763
1764    Example::
1765
1766        @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
1767        def port_status_handler(self, ev):
1768            msg = ev.msg
1769            dp = msg.datapath
1770            ofp = dp.ofproto
1771
1772            if msg.reason == ofp.OFPPR_ADD:
1773                reason = 'ADD'
1774            elif msg.reason == ofp.OFPPR_DELETE:
1775                reason = 'DELETE'
1776            elif msg.reason == ofp.OFPPR_MODIFY:
1777                reason = 'MODIFY'
1778            else:
1779                reason = 'unknown'
1780
1781            self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
1782                              reason, msg.desc)
1783    """
1784
1785    def __init__(self, datapath, reason=None, desc=None):
1786        super(OFPPortStatus, self).__init__(datapath)
1787        self.reason = reason
1788        self.desc = desc
1789
1790    @classmethod
1791    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1792        msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
1793                                               msg_len, xid, buf)
1794        msg.reason = struct.unpack_from(
1795            ofproto.OFP_PORT_STATUS_PACK_STR,
1796            msg.buf, ofproto.OFP_HEADER_SIZE)[0]
1797        msg.desc = OFPPhyPort.parser(msg.buf,
1798                                     ofproto.OFP_PORT_STATUS_DESC_OFFSET)
1799        return msg
1800
1801
1802@_register_parser
1803@_set_msg_type(ofproto.OFPT_PACKET_IN)
1804class OFPPacketIn(MsgBase):
1805    """
1806    Packet-In message
1807
1808    The switch sends the packet that received to the controller by this
1809    message.
1810
1811    ============= =========================================================
1812    Attribute     Description
1813    ============= =========================================================
1814    buffer_id     ID assigned by datapath.
1815    total_len     Full length of frame.
1816    in_port       Port on which frame was received.
1817    reason        Reason packet is being sent.
1818
1819                  | OFPR_NO_MATCH
1820                  | OFPR_ACTION
1821                  | OFPR_INVALID_TTL
1822    data          Ethernet frame.
1823    ============= =========================================================
1824
1825    Example::
1826
1827        @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
1828        def packet_in_handler(self, ev):
1829            msg = ev.msg
1830            dp = msg.datapath
1831            ofp = dp.ofproto
1832
1833            if msg.reason == ofp.OFPR_NO_MATCH:
1834                reason = 'NO MATCH'
1835            elif msg.reason == ofp.OFPR_ACTION:
1836                reason = 'ACTION'
1837            elif msg.reason == ofp.OFPR_INVALID_TTL:
1838                reason = 'INVALID TTL'
1839            else:
1840                reason = 'unknown'
1841
1842            self.logger.debug('OFPPacketIn received: '
1843                              'buffer_id=%x total_len=%d in_port=%d, '
1844                              'reason=%s data=%s',
1845                              msg.buffer_id, msg.total_len, msg.in_port,
1846                              reason, utils.hex_array(msg.data))
1847    """
1848
1849    def __init__(self, datapath, buffer_id=None, total_len=None, in_port=None,
1850                 reason=None, data=None):
1851        super(OFPPacketIn, self).__init__(datapath)
1852        self.buffer_id = buffer_id
1853        self.total_len = total_len
1854        self.in_port = in_port
1855        self.reason = reason
1856        self.data = data
1857
1858    @classmethod
1859    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1860        msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
1861                                             msg_len, xid, buf)
1862        (msg.buffer_id,
1863         msg.total_len,
1864         msg.in_port,
1865         msg.reason) = struct.unpack_from(
1866            ofproto.OFP_PACKET_IN_PACK_STR,
1867            msg.buf, ofproto.OFP_HEADER_SIZE)
1868        msg.data = msg.buf[ofproto.OFP_PACKET_IN_SIZE:]
1869        if msg.total_len < len(msg.data):
1870            # discard padding for 8-byte alignment of OFP packet
1871            msg.data = msg.data[:msg.total_len]
1872        return msg
1873
1874
1875@_register_parser
1876@_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
1877class OFPGetConfigReply(MsgBase):
1878    """
1879    Get config reply message
1880
1881    The switch responds to a configuration request with a get config reply
1882    message.
1883
1884    ============= =========================================================
1885    Attribute     Description
1886    ============= =========================================================
1887    flags         One of the following configuration flags.
1888
1889                  | OFPC_FRAG_NORMAL
1890                  | OFPC_FRAG_DROP
1891                  | OFPC_FRAG_REASM
1892                  | OFPC_FRAG_MASK
1893    miss_send_len Max bytes of new flow that datapath should send to the
1894                  controller.
1895    ============= =========================================================
1896
1897    Example::
1898
1899        @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
1900        def get_config_reply_handler(self, ev):
1901            msg = ev.msg
1902            dp = msg.datapath
1903            ofp = dp.ofproto
1904
1905            if msg.flags == ofp.OFPC_FRAG_NORMAL:
1906                flags = 'NORMAL'
1907            elif msg.flags == ofp.OFPC_FRAG_DROP:
1908                flags = 'DROP'
1909            elif msg.flags == ofp.OFPC_FRAG_REASM:
1910                flags = 'REASM'
1911            elif msg.flags == ofp.OFPC_FRAG_MASK:
1912                flags = 'MASK'
1913            else:
1914                flags = 'unknown'
1915            self.logger.debug('OFPGetConfigReply received: '
1916                              'flags=%s miss_send_len=%d',
1917                              flags, msg.miss_send_len)
1918    """
1919
1920    def __init__(self, datapath):
1921        super(OFPGetConfigReply, self).__init__(datapath)
1922
1923    @classmethod
1924    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1925        msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
1926                                                   msg_len, xid, buf)
1927        (msg.flags, msg.miss_send_len) = struct.unpack_from(
1928            ofproto.OFP_SWITCH_CONFIG_PACK_STR,
1929            msg.buf, ofproto.OFP_HEADER_SIZE)
1930        return msg
1931
1932
1933@_register_parser
1934@_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
1935class OFPBarrierReply(MsgBase):
1936    """
1937    Barrier reply message
1938
1939    The switch responds with this message to a barrier request.
1940
1941    Example::
1942
1943        @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
1944        def barrier_reply_handler(self, ev):
1945            self.logger.debug('OFPBarrierReply received')
1946    """
1947
1948    def __init__(self, datapath):
1949        super(OFPBarrierReply, self).__init__(datapath)
1950
1951
1952@_register_parser
1953@_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
1954class OFPFlowRemoved(MsgBase):
1955    """
1956    Flow removed message
1957
1958    When flow entries time out or are deleted, the switch notifies controller
1959    with this message.
1960
1961    ================ ======================================================
1962    Attribute        Description
1963    ================ ======================================================
1964    match            Instance of ``OFPMatch``.
1965    cookie           Opaque controller-issued identifier.
1966    priority         Priority level of flow entry.
1967    reason           One of the following values.
1968
1969                     | OFPRR_IDLE_TIMEOUT
1970                     | OFPRR_HARD_TIMEOUT
1971                     | OFPRR_DELETE
1972    duration_sec     Time flow was alive in seconds.
1973    duration_nsec    Time flow was alive in nanoseconds
1974                     beyond duration_sec.
1975    idle_timeout     Idle timeout from original flow mod.
1976    packet_count     Number of packets that was associated with the flow.
1977    byte_count       Number of bytes that was associated with the flow.
1978    ================ ======================================================
1979
1980    Example::
1981
1982        @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
1983        def flow_removed_handler(self, ev):
1984            msg = ev.msg
1985            dp = msg.datapath
1986            ofp = dp.ofproto
1987
1988            if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
1989                reason = 'IDLE TIMEOUT'
1990            elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
1991                reason = 'HARD TIMEOUT'
1992            elif msg.reason == ofp.OFPRR_DELETE:
1993                reason = 'DELETE'
1994            elif msg.reason == ofp.OFPRR_GROUP_DELETE:
1995                reason = 'GROUP DELETE'
1996            else:
1997                reason = 'unknown'
1998
1999            self.logger.debug('OFPFlowRemoved received: '
2000                              'match=%s cookie=%d priority=%d reason=%s '
2001                              'duration_sec=%d duration_nsec=%d '
2002                              'idle_timeout=%d packet_count=%d byte_count=%d',
2003                              msg.match, msg.cookie, msg.priority, reason,
2004                              msg.duration_sec, msg.duration_nsec,
2005                              msg.idle_timeout, msg.packet_count,
2006                              msg.byte_count)
2007    """
2008
2009    def __init__(self, datapath):
2010        super(OFPFlowRemoved, self).__init__(datapath)
2011
2012    @classmethod
2013    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2014        msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
2015                                                msg_len, xid, buf)
2016
2017        msg.match = OFPMatch.parse(msg.buf, ofproto.OFP_HEADER_SIZE)
2018
2019        (msg.cookie,
2020         msg.priority,
2021         msg.reason,
2022         msg.duration_sec,
2023         msg.duration_nsec,
2024         msg.idle_timeout,
2025         msg.packet_count,
2026         msg.byte_count) = struct.unpack_from(
2027            ofproto.OFP_FLOW_REMOVED_PACK_STR0, msg.buf,
2028            ofproto.OFP_HEADER_SIZE + ofproto.OFP_MATCH_SIZE)
2029
2030        return msg
2031
2032
2033@_register_parser
2034@_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY)
2035class OFPQueueGetConfigReply(MsgBase):
2036    """
2037    Queue configuration reply message
2038
2039    The switch responds with this message to a queue configuration request.
2040
2041    ================ ======================================================
2042    Attribute        Description
2043    ================ ======================================================
2044    port             Port to be queried.
2045    queues           List of ``OFPPacketQueue`` instance.
2046    ================ ======================================================
2047
2048    Example::
2049
2050        @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
2051        def queue_get_config_reply_handler(self, ev):
2052            msg = ev.msg
2053
2054            self.logger.debug('OFPQueueGetConfigReply received: '
2055                              'port=%s queues=%s',
2056                              msg.port, msg.queues)
2057    """
2058
2059    def __init__(self, datapath):
2060        super(OFPQueueGetConfigReply, self).__init__(datapath)
2061
2062    @classmethod
2063    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2064        msg = super(OFPQueueGetConfigReply, cls).parser(
2065            datapath, version, msg_type, msg_len, xid, buf)
2066
2067        offset = ofproto.OFP_HEADER_SIZE
2068        (msg.port,) = struct.unpack_from(
2069            ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf, offset)
2070
2071        msg.queues = []
2072        offset = ofproto.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
2073        while offset + ofproto.OFP_PACKET_QUEUE_SIZE <= msg_len:
2074            queue = OFPPacketQueue.parser(msg.buf, offset)
2075            msg.queues.append(queue)
2076
2077            offset += queue.len
2078
2079        return msg
2080
2081
2082def _set_stats_type(stats_type, stats_body_cls):
2083    def _set_cls_stats_type(cls):
2084        cls.cls_stats_type = stats_type
2085        cls.cls_stats_body_cls = stats_body_cls
2086        return cls
2087    return _set_cls_stats_type
2088
2089
2090@_register_parser
2091@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2092class OFPStatsReply(MsgBase):
2093    _STATS_MSG_TYPES = {}
2094
2095    @staticmethod
2096    def register_stats_type(body_single_struct=False):
2097        def _register_stats_type(cls):
2098            assert cls.cls_stats_type is not None
2099            assert cls.cls_stats_type not in OFPStatsReply._STATS_MSG_TYPES
2100            assert cls.cls_stats_body_cls is not None
2101            cls.cls_body_single_struct = body_single_struct
2102            OFPStatsReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls
2103            return cls
2104        return _register_stats_type
2105
2106    def __init__(self, datapath):
2107        super(OFPStatsReply, self).__init__(datapath)
2108        self.type = None
2109        self.flags = None
2110        self.body = None
2111
2112    @classmethod
2113    def parser_stats_body(cls, buf, msg_len, offset):
2114        body_cls = cls.cls_stats_body_cls
2115        body = []
2116        while offset < msg_len:
2117            entry = body_cls.parser(buf, offset)
2118            body.append(entry)
2119            offset += entry.length
2120
2121        if cls.cls_body_single_struct:
2122            return body[0]
2123        return body
2124
2125    @classmethod
2126    def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf):
2127        # call MsgBase::parser, not OFPStatsReply::parser
2128        msg = MsgBase.parser.__func__(
2129            cls, datapath, version, msg_type, msg_len, xid, buf)
2130        msg.body = msg.parser_stats_body(msg.buf, msg.msg_len,
2131                                         ofproto.OFP_STATS_MSG_SIZE)
2132        return msg
2133
2134    @classmethod
2135    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2136        type_, flags = struct.unpack_from(ofproto.OFP_STATS_MSG_PACK_STR,
2137                                          six.binary_type(buf),
2138                                          ofproto.OFP_HEADER_SIZE)
2139        stats_type_cls = cls._STATS_MSG_TYPES.get(type_)
2140        msg = stats_type_cls.parser_stats(
2141            datapath, version, msg_type, msg_len, xid, buf)
2142        msg.type = type_
2143        msg.flags = flags
2144        return msg
2145
2146
2147@OFPStatsReply.register_stats_type(body_single_struct=True)
2148@_set_stats_type(ofproto.OFPST_DESC, OFPDescStats)
2149@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2150class OFPDescStatsReply(OFPStatsReply):
2151    """
2152    Description statistics reply message
2153
2154    The switch responds with a stats reply that include this message to
2155    a description statistics request.
2156
2157    ================ ======================================================
2158    Attribute        Description
2159    ================ ======================================================
2160    mfr_desc         Manufacturer description.
2161    hw_desc          Hardware description.
2162    sw_desc          Software description.
2163    serial_num       Serial number.
2164    dp_desc          Human readable description of datapath.
2165    ================ ======================================================
2166
2167    Example::
2168
2169        @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
2170        def desc_stats_reply_handler(self, ev):
2171            msg = ev.msg
2172            ofp = msg.datapath.ofproto
2173            body = ev.msg.body
2174
2175            self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
2176                              'serial_num=%s dp_desc=%s',
2177                              body.mfr_desc, body.hw_desc, body.sw_desc,
2178                              body.serial_num, body.dp_desc)
2179    """
2180
2181    def __init__(self, datapath):
2182        super(OFPDescStatsReply, self).__init__(datapath)
2183
2184
2185@OFPStatsReply.register_stats_type()
2186@_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats)
2187@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2188class OFPFlowStatsReply(OFPStatsReply):
2189    """
2190    Individual flow statistics reply message
2191
2192    The switch responds with a stats reply that include this message to
2193    an individual flow statistics request.
2194
2195    ================ ======================================================
2196    Attribute        Description
2197    ================ ======================================================
2198    table_id         ID of table flow came from.
2199    match            Instance of ``OFPMatch``.
2200    duration_sec     Time flow has been alive in seconds.
2201    duration_nsec    Time flow has been alive in nanoseconds beyond
2202                     duration_sec.
2203    priority         Priority of the entry. Only meaningful
2204                     when this is not an exact-match entry.
2205    idle_timeout     Number of seconds idle before expiration.
2206    hard_timeout     Number of seconds before expiration.
2207    cookie           Opaque controller-issued identifier.
2208    packet_count     Number of packets in flow.
2209    byte_count       Number of bytes in flow.
2210    actions          List of ``OFPAction*`` instance
2211    ================ ======================================================
2212
2213    Example::
2214
2215        @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
2216        def flow_stats_reply_handler(self, ev):
2217            msg = ev.msg
2218            ofp = msg.datapath.ofproto
2219            body = ev.msg.body
2220
2221            flows = []
2222            for stat in body:
2223                flows.append('table_id=%s match=%s '
2224                             'duration_sec=%d duration_nsec=%d '
2225                             'priority=%d '
2226                             'idle_timeout=%d hard_timeout=%d '
2227                             'cookie=%d packet_count=%d byte_count=%d '
2228                             'actions=%s' %
2229                             (stat.table_id, stat.match,
2230                              stat.duration_sec, stat.duration_nsec,
2231                              stat.priority,
2232                              stat.idle_timeout, stat.hard_timeout,
2233                              stat.cookie, stat.packet_count, stat.byte_count,
2234                              stat.actions))
2235            self.logger.debug('FlowStats: %s', flows)
2236    """
2237
2238    def __init__(self, datapath):
2239        super(OFPFlowStatsReply, self).__init__(datapath)
2240
2241
2242@OFPStatsReply.register_stats_type()
2243@_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats)
2244@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2245class OFPAggregateStatsReply(OFPStatsReply):
2246    """
2247    Aggregate flow statistics reply message
2248
2249    The switch responds with a stats reply that include this message to
2250    an aggregate flow statistics request.
2251
2252    ================ ======================================================
2253    Attribute        Description
2254    ================ ======================================================
2255    packet_count     Number of packets in flows.
2256    byte_count       Number of bytes in flows.
2257    flow_count       Number of flows.
2258    ================ ======================================================
2259
2260    Example::
2261
2262        @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
2263        def aggregate_stats_reply_handler(self, ev):
2264            msg = ev.msg
2265            ofp = msg.datapath.ofproto
2266            body = ev.msg.body
2267
2268            self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
2269                              'flow_count=%d',
2270                              body.packet_count, body.byte_count,
2271                              body.flow_count)
2272    """
2273
2274    def __init__(self, datapath):
2275        super(OFPAggregateStatsReply, self).__init__(datapath)
2276
2277
2278@OFPStatsReply.register_stats_type()
2279@_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats)
2280@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2281class OFPTableStatsReply(OFPStatsReply):
2282    """
2283    Table statistics reply message
2284
2285    The switch responds with a stats reply that include this message to
2286    a table statistics request.
2287
2288    ================ ======================================================
2289    Attribute        Description
2290    ================ ======================================================
2291    table_id         ID of table.
2292    name             table name.
2293    wildcards        Bitmap of OFPFW_* wildcards that are
2294                     supported by the table.
2295    max_entries      Max number of entries supported
2296    active_count     Number of active entries
2297    lookup_count     Number of packets looked up in table
2298    matched_count    Number of packets that hit table
2299    ================ ======================================================
2300
2301    Example::
2302
2303        @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
2304        def stats_reply_handler(self, ev):
2305            msg = ev.msg
2306            ofp = msg.datapath.ofproto
2307            body = ev.msg.body
2308
2309            tables = []
2310            for stat in body:
2311                tables.append('table_id=%d name=%s wildcards=0x%02x '
2312                              'max_entries=%d active_count=%d '
2313                              'lookup_count=%d matched_count=%d' %
2314                              (stat.table_id, stat.name, stat.wildcards,
2315                               stat.max_entries, stat.active_count,
2316                               stat.lookup_count, stat.matched_count))
2317            self.logger.debug('TableStats: %s', tables)
2318    """
2319
2320    def __init__(self, datapath):
2321        super(OFPTableStatsReply, self).__init__(datapath)
2322
2323
2324@OFPStatsReply.register_stats_type()
2325@_set_stats_type(ofproto.OFPST_PORT, OFPPortStats)
2326@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2327class OFPPortStatsReply(OFPStatsReply):
2328    """
2329    Port statistics reply message
2330
2331    The switch responds with a stats reply that include this message to
2332    a port statistics request.
2333
2334    ================ ======================================================
2335    Attribute        Description
2336    ================ ======================================================
2337    port_no          Port number.
2338    rx_packets       Number of received packets.
2339    tx_packets       Number of transmitted packets.
2340    rx_bytes         Number of received bytes.
2341    tx_bytes         Number of transmitted bytes.
2342    rx_dropped       Number of packets dropped by RX.
2343    tx_dropped       Number of packets dropped by TX.
2344    rx_errors        Number of receive errors.
2345    tx_errors        Number of transmit errors.
2346    rx_frame_err     Number of frame alignment errors.
2347    rx_over_err      Number of packet with RX overrun.
2348    rx_crc_err       Number of CRC errors.
2349    collisions       Number of collisions.
2350    ================ ======================================================
2351
2352    Example::
2353
2354        @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
2355        def port_stats_reply_handler(self, ev):
2356            msg = ev.msg
2357            ofp = msg.datapath.ofproto
2358            body = ev.msg.body
2359
2360            ports = []
2361            for stat in body:
2362                ports.append('port_no=%d '
2363                             'rx_packets=%d tx_packets=%d '
2364                             'rx_bytes=%d tx_bytes=%d '
2365                             'rx_dropped=%d tx_dropped=%d '
2366                             'rx_errors=%d tx_errors=%d '
2367                             'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
2368                             'collisions=%d' %
2369                             (stat.port_no,
2370                              stat.rx_packets, stat.tx_packets,
2371                              stat.rx_bytes, stat.tx_bytes,
2372                              stat.rx_dropped, stat.tx_dropped,
2373                              stat.rx_errors, stat.tx_errors,
2374                              stat.rx_frame_err, stat.rx_over_err,
2375                              stat.rx_crc_err, stat.collisions))
2376            self.logger.debug('PortStats: %s', ports)
2377    """
2378
2379    def __init__(self, datapath):
2380        super(OFPPortStatsReply, self).__init__(datapath)
2381
2382
2383@OFPStatsReply.register_stats_type()
2384@_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats)
2385@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2386class OFPQueueStatsReply(OFPStatsReply):
2387    """
2388    Queue statistics reply message
2389
2390    The switch responds with a stats reply that include this message to
2391    an aggregate flow statistics request.
2392
2393    ================ ======================================================
2394    Attribute        Description
2395    ================ ======================================================
2396    port_no          Port number.
2397    queue_id         ID of queue.
2398    tx_bytes         Number of transmitted bytes.
2399    tx_packets       Number of transmitted packets.
2400    tx_errors        Number of packets dropped due to overrun.
2401    ================ ======================================================
2402
2403    Example::
2404
2405        @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
2406        def stats_reply_handler(self, ev):
2407            msg = ev.msg
2408            ofp = msg.datapath.ofproto
2409            body = ev.msg.body
2410
2411            queues = []
2412            for stat in body:
2413                queues.append('port_no=%d queue_id=%d '
2414                              'tx_bytes=%d tx_packets=%d tx_errors=%d ' %
2415                              (stat.port_no, stat.queue_id,
2416                               stat.tx_bytes, stat.tx_packets, stat.tx_errors))
2417            self.logger.debug('QueueStats: %s', queues)
2418    """
2419
2420    def __init__(self, datapath):
2421        super(OFPQueueStatsReply, self).__init__(datapath)
2422
2423
2424@OFPStatsReply.register_stats_type()
2425@_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats)
2426@_set_msg_type(ofproto.OFPT_STATS_REPLY)
2427class OFPVendorStatsReply(OFPStatsReply):
2428    """
2429    Vendor statistics reply message
2430
2431    The switch responds with a stats reply that include this message to
2432    an vendor statistics request.
2433    """
2434    _STATS_VENDORS = {}
2435
2436    @staticmethod
2437    def register_stats_vendor(vendor):
2438        def _register_stats_vendor(cls):
2439            cls.cls_vendor = vendor
2440            OFPVendorStatsReply._STATS_VENDORS[cls.cls_vendor] = cls
2441            return cls
2442        return _register_stats_vendor
2443
2444    def __init__(self, datapath):
2445        super(OFPVendorStatsReply, self).__init__(datapath)
2446
2447    @classmethod
2448    def parser_stats(cls, datapath, version, msg_type, msg_len, xid,
2449                     buf):
2450        (type_,) = struct.unpack_from(
2451            ofproto.OFP_VENDOR_STATS_MSG_PACK_STR, six.binary_type(buf),
2452            ofproto.OFP_STATS_MSG_SIZE)
2453
2454        cls_ = cls._STATS_VENDORS.get(type_)
2455
2456        if cls_ is None:
2457            msg = MsgBase.parser.__func__(
2458                cls, datapath, version, msg_type, msg_len, xid, buf)
2459            body_cls = cls.cls_stats_body_cls
2460            body = body_cls.parser(buf,
2461                                   ofproto.OFP_STATS_MSG_SIZE)
2462            msg.body = body
2463            return msg
2464
2465        return cls_.parser(
2466            datapath, version, msg_type, msg_len, xid, buf,
2467            ofproto.OFP_VENDOR_STATS_MSG_SIZE)
2468
2469
2470@OFPVendorStatsReply.register_stats_vendor(ofproto_common.NX_EXPERIMENTER_ID)
2471class NXStatsReply(OFPStatsReply):
2472    _NX_STATS_TYPES = {}
2473
2474    @staticmethod
2475    def register_nx_stats_type(body_single_struct=False):
2476        def _register_nx_stats_type(cls):
2477            assert cls.cls_stats_type is not None
2478            assert cls.cls_stats_type not in \
2479                NXStatsReply._NX_STATS_TYPES
2480            assert cls.cls_stats_body_cls is not None
2481            cls.cls_body_single_struct = body_single_struct
2482            NXStatsReply._NX_STATS_TYPES[cls.cls_stats_type] = cls
2483            return cls
2484        return _register_nx_stats_type
2485
2486    @classmethod
2487    def parser_stats_body(cls, buf, msg_len, offset):
2488        body_cls = cls.cls_stats_body_cls
2489        body = []
2490        while offset < msg_len:
2491            entry = body_cls.parser(buf, offset)
2492            body.append(entry)
2493            offset += entry.length
2494
2495        if cls.cls_body_single_struct:
2496            return body[0]
2497        return body
2498
2499    @classmethod
2500    def parser_stats(cls, datapath, version, msg_type, msg_len, xid,
2501                     buf, offset):
2502        msg = MsgBase.parser.__func__(
2503            cls, datapath, version, msg_type, msg_len, xid, buf)
2504        msg.body = msg.parser_stats_body(msg.buf, msg.msg_len, offset)
2505
2506        return msg
2507
2508    @classmethod
2509    def parser(cls, datapath, version, msg_type, msg_len, xid, buf,
2510               offset):
2511        (type_,) = struct.unpack_from(
2512            ofproto.NX_STATS_MSG_PACK_STR, six.binary_type(buf), offset)
2513        offset += ofproto.NX_STATS_MSG0_SIZE
2514
2515        cls_ = cls._NX_STATS_TYPES.get(type_)
2516
2517        msg = cls_.parser_stats(
2518            datapath, version, msg_type, msg_len, xid, buf, offset)
2519
2520        return msg
2521
2522
2523@NXStatsReply.register_nx_stats_type()
2524@_set_stats_type(ofproto.NXST_FLOW, NXFlowStats)
2525class NXFlowStatsReply(NXStatsReply):
2526    def __init__(self, datapath):
2527        super(NXFlowStatsReply, self).__init__(datapath)
2528
2529
2530@NXStatsReply.register_nx_stats_type()
2531@_set_stats_type(ofproto.NXST_AGGREGATE, NXAggregateStats)
2532class NXAggregateStatsReply(NXStatsReply):
2533    def __init__(self, datapath):
2534        super(NXAggregateStatsReply, self).__init__(datapath)
2535
2536
2537#
2538# controller-to-switch message
2539# serializer only
2540#
2541
2542
2543@_set_msg_reply(OFPSwitchFeatures)
2544@_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
2545class OFPFeaturesRequest(MsgBase):
2546    """
2547    Features request message
2548
2549    The controller sends a feature request to the switch upon session
2550    establishment.
2551
2552    This message is handled by the Ryu framework, so the Ryu application
2553    do not need to process this typically.
2554
2555    Example::
2556
2557        def send_features_request(self, datapath):
2558            ofp_parser = datapath.ofproto_parser
2559
2560            req = ofp_parser.OFPFeaturesRequest(datapath)
2561            datapath.send_msg(req)
2562    """
2563
2564    def __init__(self, datapath):
2565        super(OFPFeaturesRequest, self).__init__(datapath)
2566
2567
2568@_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
2569class OFPGetConfigRequest(MsgBase):
2570    """
2571    Get config request message
2572
2573    The controller sends a get config request to query configuration
2574    parameters in the switch.
2575
2576    Example::
2577
2578        def send_get_config_request(self, datapath):
2579            ofp_parser = datapath.ofproto_parser
2580
2581            req = ofp_parser.OFPGetConfigRequest(datapath)
2582            datapath.send_msg(req)
2583    """
2584
2585    def __init__(self, datapath):
2586        super(OFPGetConfigRequest, self).__init__(datapath)
2587
2588
2589@_set_msg_type(ofproto.OFPT_SET_CONFIG)
2590class OFPSetConfig(MsgBase):
2591    """
2592    Set config request message
2593
2594    The controller sends a set config request message to set configuraion
2595    parameters.
2596
2597    ============= =========================================================
2598    Attribute     Description
2599    ============= =========================================================
2600    flags         One of the following configuration flags.
2601
2602                  | OFPC_FRAG_NORMAL
2603                  | OFPC_FRAG_DROP
2604                  | OFPC_FRAG_REASM
2605                  | OFPC_FRAG_MASK
2606    miss_send_len Max bytes of new flow that datapath should send to the
2607                  controller.
2608    ============= =========================================================
2609
2610    Example::
2611
2612        def send_set_config(self, datapath):
2613            ofp = datapath.ofproto
2614            ofp_parser = datapath.ofproto_parser
2615
2616            req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
2617            datapath.send_msg(req)
2618    """
2619
2620    def __init__(self, datapath, flags=None, miss_send_len=None):
2621        super(OFPSetConfig, self).__init__(datapath)
2622        self.flags = flags
2623        self.miss_send_len = miss_send_len
2624
2625    def _serialize_body(self):
2626        assert self.flags is not None
2627        assert self.miss_send_len is not None
2628        msg_pack_into(ofproto.OFP_SWITCH_CONFIG_PACK_STR,
2629                      self.buf, ofproto.OFP_HEADER_SIZE,
2630                      self.flags, self.miss_send_len)
2631
2632
2633@_set_msg_type(ofproto.OFPT_PACKET_OUT)
2634class OFPPacketOut(MsgBase):
2635    """
2636    Packet-Out message
2637
2638    The controller uses this message to send a packet out throught the
2639    switch.
2640
2641    ================ ======================================================
2642    Attribute        Description
2643    ================ ======================================================
2644    buffer_id        ID assigned by datapath (0xffffffff if none).
2645    in_port          Packet's input port (OFPP_NONE if none).
2646    actions          ist of ``OFPAction*`` instance.
2647    data             Packet data of a binary type value or
2648                     an instances of packet.Packet.
2649    ================ ======================================================
2650
2651    Example::
2652
2653        def send_packet_out(self, datapath):
2654            ofp = datapath.ofproto
2655            ofp_parser = datapath.ofproto_parser
2656
2657            buffer_id = 0xffffffff
2658            in_port = ofp.OFPP_NONE
2659            actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
2660            req = ofp_parser.OFPPacketOut(datapath, buffer_id,
2661                                          in_port, actions)
2662            datapath.send_msg(req)
2663    """
2664
2665    def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
2666                 data=None):
2667        super(OFPPacketOut, self).__init__(datapath)
2668        self.buffer_id = buffer_id
2669        self.in_port = in_port
2670        self._actions_len = None
2671        self.actions = actions
2672        self.data = data
2673
2674    def _serialize_body(self):
2675        assert self.buffer_id is not None
2676        assert self.in_port is not None
2677        assert self.actions is not None
2678
2679        self._actions_len = 0
2680        offset = ofproto.OFP_PACKET_OUT_SIZE
2681        for a in self.actions:
2682            a.serialize(self.buf, offset)
2683            offset += a.len
2684            self._actions_len += a.len
2685
2686        if self.data is not None:
2687            assert self.buffer_id == 0xffffffff
2688            if isinstance(self.data, packet.Packet):
2689                self.data.serialize()
2690                self.buf += self.data.data
2691            else:
2692                self.buf += self.data
2693
2694        msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR,
2695                      self.buf, ofproto.OFP_HEADER_SIZE,
2696                      self.buffer_id, self.in_port, self._actions_len)
2697
2698    @classmethod
2699    def from_jsondict(cls, dict_, decode_string=base64.b64decode,
2700                      **additional_args):
2701        if isinstance(dict_['data'], dict):
2702            data = dict_.pop('data')
2703            ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2704                                                         decode_string,
2705                                                         **additional_args)
2706            ins.data = packet.Packet.from_jsondict(data['Packet'])
2707            dict_['data'] = data
2708        else:
2709            ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2710                                                         decode_string,
2711                                                         **additional_args)
2712
2713        return ins
2714
2715
2716@_register_parser
2717@_set_msg_type(ofproto.OFPT_FLOW_MOD)
2718class OFPFlowMod(MsgBase):
2719    """
2720    Modify Flow entry message
2721
2722    The controller sends this message to modify the flow table.
2723
2724    ================ ======================================================
2725    Attribute        Description
2726    ================ ======================================================
2727    match            Instance of ``OFPMatch``.
2728    cookie           Opaque controller-issued identifier.
2729    command          One of the following values.
2730
2731                     | OFPFC_ADD
2732                     | OFPFC_MODIFY
2733                     | OFPFC_MODIFY_STRICT
2734                     | OFPFC_DELETE
2735                     | OFPFC_DELETE_STRICT
2736    idle_timeout     Idle time before discarding (seconds).
2737    hard_timeout     Max time before discarding (seconds).
2738    priority         Priority level of flow entry.
2739    buffer_id        Buffered packet to apply to (or 0xffffffff).
2740                     Not meaningful for OFPFC_DELETE*.
2741    out_port         For OFPFC_DELETE* commands, require
2742                     matching entries to include this as an
2743                     output port. A value of OFPP_NONE
2744                     indicates no restriction.
2745    flags            One of the following values.
2746
2747                     | OFPFF_SEND_FLOW_REM
2748                     | OFPFF_CHECK_OVERLAP
2749                     | OFPFF_EMERG
2750    actions          List of ``OFPAction*`` instance.
2751    ================ ======================================================
2752
2753    Example::
2754
2755        def send_flow_mod(self, datapath):
2756            ofp = datapath.ofproto
2757            ofp_parser = datapath.ofproto_parser
2758
2759            match = ofp_parser.OFPMatch(in_port=1)
2760            cookie = 0
2761            command = ofp.OFPFC_ADD
2762            idle_timeout = hard_timeout = 0
2763            priority = 32768
2764            buffer_id = 0xffffffff
2765            out_port = ofproto.OFPP_NONE
2766            flags = 0
2767            actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
2768            req = ofp_parser.OFPFlowMod(
2769                datapath, match, cookie, command, idle_timeout, hard_timeout,
2770                priority, buffer_id, out_port, flags, actions)
2771            datapath.send_msg(req)
2772    """
2773
2774    def __init__(self, datapath, match=None, cookie=0,
2775                 command=ofproto.OFPFC_ADD,
2776                 idle_timeout=0, hard_timeout=0,
2777                 priority=ofproto.OFP_DEFAULT_PRIORITY,
2778                 buffer_id=0xffffffff, out_port=ofproto.OFPP_NONE,
2779                 flags=0, actions=None):
2780        super(OFPFlowMod, self).__init__(datapath)
2781        self.match = OFPMatch() if match is None else match
2782        self.cookie = cookie
2783        self.command = command
2784        self.idle_timeout = idle_timeout
2785        self.hard_timeout = hard_timeout
2786        self.priority = priority
2787        self.buffer_id = buffer_id
2788        self.out_port = out_port
2789        self.flags = flags
2790        self.actions = [] if actions is None else actions
2791
2792    def _serialize_body(self):
2793        offset = ofproto.OFP_HEADER_SIZE
2794        self.match.serialize(self.buf, offset)
2795
2796        offset += ofproto.OFP_MATCH_SIZE
2797        msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf, offset,
2798                      self.cookie, self.command,
2799                      self.idle_timeout, self.hard_timeout,
2800                      self.priority, self.buffer_id, self.out_port,
2801                      self.flags)
2802
2803        offset = ofproto.OFP_FLOW_MOD_SIZE
2804        if self.actions is not None:
2805            for a in self.actions:
2806                a.serialize(self.buf, offset)
2807                offset += a.len
2808
2809    @classmethod
2810    def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2811        msg = super(OFPFlowMod, cls).parser(
2812            datapath, version, msg_type, msg_len, xid, buf)
2813        offset = ofproto.OFP_HEADER_SIZE
2814
2815        msg.match = OFPMatch.parse(msg.buf, offset)
2816        offset += ofproto.OFP_MATCH_SIZE
2817
2818        (msg.cookie, msg.command, msg.idle_timeout, msg.hard_timeout,
2819         msg.priority, msg.buffer_id, msg.out_port,
2820         msg.flags) = struct.unpack_from(
2821            ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf, offset)
2822        offset = ofproto.OFP_FLOW_MOD_SIZE
2823
2824        actions = []
2825        while offset < msg_len:
2826            a = OFPAction.parser(buf, offset)
2827            actions.append(a)
2828            offset += a.len
2829        msg.actions = actions
2830
2831        return msg
2832
2833
2834@_set_msg_type(ofproto.OFPT_PORT_MOD)
2835class OFPPortMod(MsgBase):
2836    """
2837    Port modification message
2838
2839    The controller send this message to modify the behavior of the port.
2840
2841    ================ ======================================================
2842    Attribute        Description
2843    ================ ======================================================
2844    port_no          Port number to modify.
2845    hw_addr          The hardware address that must be the same as hw_addr
2846                     of ``OFPPhyPort`` of ``OFPSwitchFeatures``.
2847    config           Bitmap of configuration flags.
2848
2849                     | OFPPC_PORT_DOWN
2850                     | OFPPC_NO_STP
2851                     | OFPPC_NO_RECV
2852                     | OFPPC_NO_RECV_STP
2853                     | OFPPC_NO_FLOOD
2854                     | OFPPC_NO_FWD
2855                     | OFPPC_NO_PACKET_IN
2856    mask             Bitmap of configuration flags above to be changed
2857    advertise        Bitmap of the following flags.
2858
2859                     | OFPPF_10MB_HD
2860                     | OFPPF_10MB_FD
2861                     | OFPPF_100MB_HD
2862                     | OFPPF_100MB_FD
2863                     | OFPPF_1GB_HD
2864                     | OFPPF_1GB_FD
2865                     | OFPPF_10GB_FD
2866                     | OFPPF_COPPER
2867                     | OFPPF_FIBER
2868                     | OFPPF_AUTONEG
2869                     | OFPPF_PAUSE
2870                     | OFPPF_PAUSE_ASYM
2871    ================ ======================================================
2872
2873    Example::
2874
2875        def send_port_mod(self, datapath):
2876            ofp = datapath.ofproto
2877            ofp_parser = datapath.ofproto_parser
2878
2879            port_no = 3
2880            hw_addr = 'fa:c8:e8:76:1d:7e'
2881            config = 0
2882            mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
2883                    ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
2884            advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
2885                         ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
2886                         ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
2887                         ofp.OFPPF_PAUSE_ASYM)
2888            req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
2889                                        mask, advertise)
2890            datapath.send_msg(req)
2891    """
2892    _TYPE = {
2893        'ascii': [
2894            'hw_addr',
2895        ]
2896    }
2897
2898    def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
2899                 config=0, mask=0, advertise=0):
2900        super(OFPPortMod, self).__init__(datapath)
2901        self.port_no = port_no
2902        self.hw_addr = hw_addr
2903        self.config = config
2904        self.mask = mask
2905        self.advertise = advertise
2906
2907    def _serialize_body(self):
2908        msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR,
2909                      self.buf, ofproto.OFP_HEADER_SIZE,
2910                      self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
2911                      self.config, self.mask, self.advertise)
2912
2913
2914@_set_msg_reply(OFPBarrierReply)
2915@_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
2916class OFPBarrierRequest(MsgBase):
2917    """
2918    Barrier request message
2919
2920    The controller sends this message to ensure message dependencies have
2921    been met or receive notifications for completed operations.
2922
2923    Example::
2924
2925        def send_barrier_request(self, datapath):
2926            ofp_parser = datapath.ofproto_parser
2927
2928            req = ofp_parser.OFPBarrierRequest(datapath)
2929            datapath.send_msg(req)
2930    """
2931
2932    def __init__(self, datapath):
2933        super(OFPBarrierRequest, self).__init__(datapath)
2934
2935
2936@_set_msg_reply(OFPQueueGetConfigReply)
2937@_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST)
2938class OFPQueueGetConfigRequest(MsgBase):
2939    """
2940    Queue configuration request message
2941
2942    ================ ======================================================
2943    Attribute        Description
2944    ================ ======================================================
2945    port             Port to be queried. Should refer
2946                     to a valid physical port (i.e. < OFPP_MAX).
2947    ================ ======================================================
2948
2949    Example::
2950
2951        def send_queue_get_config_request(self, datapath):
2952            ofp = datapath.ofproto
2953            ofp_parser = datapath.ofproto_parser
2954
2955            req = ofp_parser.OFPQueueGetConfigRequest(datapath,
2956                                                      ofp.OFPP_NONE)
2957            datapath.send_msg(req)
2958    """
2959
2960    def __init__(self, datapath, port):
2961        super(OFPQueueGetConfigRequest, self).__init__(datapath)
2962        self.port = port
2963
2964    def _serialize_body(self):
2965        msg_pack_into(ofproto.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR,
2966                      self.buf, ofproto.OFP_HEADER_SIZE, self.port)
2967
2968
2969class OFPStatsRequest(MsgBase):
2970    def __init__(self, datapath, flags):
2971        assert flags == 0       # none yet defined
2972
2973        super(OFPStatsRequest, self).__init__(datapath)
2974        self.type = self.__class__.cls_stats_type
2975        self.flags = flags
2976
2977    def _serialize_stats_body(self):
2978        pass
2979
2980    def _serialize_body(self):
2981        msg_pack_into(ofproto.OFP_STATS_MSG_PACK_STR,
2982                      self.buf, ofproto.OFP_HEADER_SIZE,
2983                      self.type, self.flags)
2984        self._serialize_stats_body()
2985
2986
2987@_set_msg_reply(OFPDescStatsReply)
2988@_set_stats_type(ofproto.OFPST_DESC, OFPDescStats)
2989@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2990class OFPDescStatsRequest(OFPStatsRequest):
2991    """
2992    Description statistics request message
2993
2994    The controller uses this message to query description of the switch.
2995
2996    ================ ======================================================
2997    Attribute        Description
2998    ================ ======================================================
2999    flags            Zero (none yet defined in the spec).
3000    ================ ======================================================
3001
3002    Example::
3003
3004        def send_desc_stats_request(self, datapath):
3005            ofp_parser = datapath.ofproto_parser
3006
3007            req = ofp_parser.OFPDescStatsRequest(datapath)
3008            datapath.send_msg(req)
3009    """
3010
3011    def __init__(self, datapath, flags):
3012        super(OFPDescStatsRequest, self).__init__(datapath, flags)
3013
3014
3015class OFPFlowStatsRequestBase(OFPStatsRequest):
3016    def __init__(self, datapath, flags, match, table_id, out_port):
3017        super(OFPFlowStatsRequestBase, self).__init__(datapath, flags)
3018        self.match = match
3019        self.table_id = table_id
3020        self.out_port = out_port
3021
3022    def _serialize_stats_body(self):
3023        offset = ofproto.OFP_STATS_MSG_SIZE
3024        self.match.serialize(self.buf, offset)
3025
3026        offset += ofproto.OFP_MATCH_SIZE
3027        msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_ID_PORT_STR,
3028                      self.buf, offset, self.table_id, self.out_port)
3029
3030
3031@_set_msg_reply(OFPFlowStatsReply)
3032@_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats)
3033@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3034class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
3035    """
3036    Individual flow statistics request message
3037
3038    The controller uses this message to query individual flow statistics.
3039
3040    ================ ======================================================
3041    Attribute        Description
3042    ================ ======================================================
3043    flags            Zero (none yet defined in the spec).
3044    match            Instance of ``OFPMatch``.
3045    table_id         ID of table to read (from ofp_table_stats),
3046                     0xff for all tables or 0xfe for emergency.
3047    out_port         Require matching entries to include this
3048                     as an output port. A value of OFPP_NONE
3049                     indicates no restriction.
3050    ================ ======================================================
3051
3052    Example::
3053
3054        def send_flow_stats_request(self, datapath):
3055            ofp = datapath.ofproto
3056            ofp_parser = datapath.ofproto_parser
3057
3058            match = ofp_parser.OFPMatch(in_port=1)
3059            table_id = 0xff
3060            out_port = ofp.OFPP_NONE
3061            req = ofp_parser.OFPFlowStatsRequest(
3062                datapath, 0, match, table_id, out_port)
3063
3064            datapath.send_msg(req)
3065    """
3066
3067    def __init__(self, datapath, flags, match, table_id, out_port):
3068        super(OFPFlowStatsRequest, self).__init__(
3069            datapath, flags, match, table_id, out_port)
3070
3071
3072@_set_msg_reply(OFPAggregateStatsReply)
3073@_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats)
3074@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3075class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
3076    """
3077    Aggregate flow statistics request message
3078
3079    The controller uses this message to query aggregate flow statictics.
3080
3081    ================ ======================================================
3082    Attribute        Description
3083    ================ ======================================================
3084    flags            Zero (none yet defined in the spec).
3085    match            Fields to match.
3086    table_id         ID of table to read (from ofp_table_stats)
3087                     0xff for all tables or 0xfe for emergency.
3088    out_port         Require matching entries to include this
3089                     as an output port. A value of OFPP_NONE
3090                     indicates no restriction.
3091    ================ ======================================================
3092
3093    Example::
3094
3095        def send_aggregate_stats_request(self, datapath):
3096            ofp = datapath.ofproto
3097            ofp_parser = datapath.ofproto_parser
3098
3099            cookie = cookie_mask = 0
3100            match = ofp_parser.OFPMatch(in_port=1)
3101            req = ofp_parser.OFPAggregateStatsRequest(
3102                datapath, 0, match, 0xff, ofp.OFPP_NONE)
3103
3104            datapath.send_msg(req)
3105    """
3106
3107    def __init__(self, datapath, flags, match, table_id, out_port):
3108        super(OFPAggregateStatsRequest, self).__init__(
3109            datapath, flags, match, table_id, out_port)
3110
3111
3112@_set_msg_reply(OFPTableStatsReply)
3113@_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats)
3114@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3115class OFPTableStatsRequest(OFPStatsRequest):
3116    """
3117    Table statistics request message
3118
3119    The controller uses this message to query flow table statictics.
3120
3121    ================ ======================================================
3122    Attribute        Description
3123    ================ ======================================================
3124    flags            Zero (none yet defined in the spec).
3125    ================ ======================================================
3126
3127    Example::
3128
3129        def send_table_stats_request(self, datapath):
3130            ofp_parser = datapath.ofproto_parser
3131
3132            req = ofp_parser.OFPTableStatsRequest(datapath)
3133            datapath.send_msg(req)
3134    """
3135
3136    def __init__(self, datapath, flags):
3137        super(OFPTableStatsRequest, self).__init__(datapath, flags)
3138
3139
3140@_set_msg_reply(OFPPortStatsReply)
3141@_set_stats_type(ofproto.OFPST_PORT, OFPPortStats)
3142@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3143class OFPPortStatsRequest(OFPStatsRequest):
3144    """
3145    Port statistics request message
3146
3147    The controller uses this message to query information about ports
3148    statistics.
3149
3150    ================ ======================================================
3151    Attribute        Description
3152    ================ ======================================================
3153    flags            Zero (none yet defined in the spec).
3154    port_no          Port number to read (OFPP_NONE to all ports).
3155    ================ ======================================================
3156
3157    Example::
3158
3159        def send_port_stats_request(self, datapath):
3160            ofp = datapath.ofproto
3161            ofp_parser = datapath.ofproto_parser
3162
3163            req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY)
3164            datapath.send_msg(req)
3165    """
3166
3167    def __init__(self, datapath, flags, port_no):
3168        super(OFPPortStatsRequest, self).__init__(datapath, flags)
3169        self.port_no = port_no
3170
3171    def _serialize_stats_body(self):
3172        msg_pack_into(ofproto.OFP_PORT_STATS_REQUEST_PACK_STR,
3173                      self.buf, ofproto.OFP_STATS_MSG_SIZE, self.port_no)
3174
3175
3176@_set_msg_reply(OFPQueueStatsReply)
3177@_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats)
3178@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3179class OFPQueueStatsRequest(OFPStatsRequest):
3180    """
3181    Queue statistics request message
3182
3183    The controller uses this message to query queue statictics.
3184
3185    ================ ======================================================
3186    Attribute        Description
3187    ================ ======================================================
3188    flags            Zero (none yet defined in the spec)
3189    port_no          Port number to read (All ports if OFPT_ALL).
3190    queue_id         ID of queue to read (All queues if OFPQ_ALL).
3191    ================ ======================================================
3192
3193    Example::
3194
3195        def send_queue_stats_request(self, datapath):
3196            ofp = datapath.ofproto
3197            ofp_parser = datapath.ofproto_parser
3198
3199            req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPT_ALL,
3200                                                  ofp.OFPQ_ALL)
3201            datapath.send_msg(req)
3202    """
3203
3204    def __init__(self, datapath, flags, port_no, queue_id):
3205        super(OFPQueueStatsRequest, self).__init__(datapath, flags)
3206        self.port_no = port_no
3207        self.queue_id = queue_id
3208
3209    def _serialize_stats_body(self):
3210        msg_pack_into(ofproto.OFP_QUEUE_STATS_REQUEST_PACK_STR,
3211                      self.buf, ofproto.OFP_STATS_MSG_SIZE,
3212                      self.port_no, self.queue_id)
3213
3214
3215@_set_msg_reply(OFPVendorStatsReply)
3216@_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats)
3217@_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3218class OFPVendorStatsRequest(OFPStatsRequest):
3219    """
3220    Vendor statistics request message
3221
3222    The controller uses this message to query vendor-specific information
3223    of a switch.
3224    """
3225
3226    def __init__(self, datapath, flags, vendor, specific_data=None):
3227        super(OFPVendorStatsRequest, self).__init__(datapath, flags)
3228        self.vendor = vendor
3229        self.specific_data = specific_data
3230
3231    def _serialize_vendor_stats(self):
3232        self.buf += self.specific_data
3233
3234    def _serialize_stats_body(self):
3235        msg_pack_into(ofproto.OFP_VENDOR_STATS_MSG_PACK_STR,
3236                      self.buf, ofproto.OFP_STATS_MSG_SIZE,
3237                      self.vendor)
3238        self._serialize_vendor_stats()
3239
3240
3241class NXStatsRequest(OFPVendorStatsRequest):
3242    def __init__(self, datapath, flags, subtype):
3243        super(NXStatsRequest, self).__init__(datapath, flags,
3244                                             ofproto_common.NX_EXPERIMENTER_ID)
3245        self.subtype = subtype
3246
3247    def _serialize_vendor_stats_body(self):
3248        pass
3249
3250    def _serialize_vendor_stats(self):
3251        msg_pack_into(ofproto.NX_STATS_MSG_PACK_STR, self.buf,
3252                      ofproto.OFP_VENDOR_STATS_MSG_SIZE,
3253                      self.subtype)
3254        self._serialize_vendor_stats_body()
3255
3256
3257class NXFlowStatsRequest(NXStatsRequest):
3258    def __init__(self, datapath, flags, out_port, table_id, rule=None):
3259        super(NXFlowStatsRequest, self).__init__(datapath, flags,
3260                                                 ofproto.NXST_FLOW)
3261        self.out_port = out_port
3262        self.table_id = table_id
3263        self.rule = rule
3264        self.match_len = 0
3265
3266    def _serialize_vendor_stats_body(self):
3267        if self.rule is not None:
3268            offset = ofproto.NX_STATS_MSG_SIZE + \
3269                ofproto.NX_FLOW_STATS_REQUEST_SIZE
3270            self.match_len = nx_match.serialize_nxm_match(
3271                self.rule, self.buf, offset)
3272
3273        msg_pack_into(
3274            ofproto.NX_FLOW_STATS_REQUEST_PACK_STR,
3275            self.buf, ofproto.NX_STATS_MSG_SIZE, self.out_port,
3276            self.match_len, self.table_id)
3277
3278
3279class NXAggregateStatsRequest(NXStatsRequest):
3280    def __init__(self, datapath, flags, out_port, table_id, rule=None):
3281        super(NXAggregateStatsRequest, self).__init__(
3282            datapath, flags, ofproto.NXST_AGGREGATE)
3283        self.out_port = out_port
3284        self.table_id = table_id
3285        self.rule = rule
3286        self.match_len = 0
3287
3288    def _serialize_vendor_stats_body(self):
3289        if self.rule is not None:
3290            offset = ofproto.NX_STATS_MSG_SIZE + \
3291                ofproto.NX_AGGREGATE_STATS_REQUEST_SIZE
3292            self.match_len = nx_match.serialize_nxm_match(
3293                self.rule, self.buf, offset)
3294
3295        msg_pack_into(
3296            ofproto.NX_AGGREGATE_STATS_REQUEST_PACK_STR,
3297            self.buf, ofproto.NX_STATS_MSG_SIZE, self.out_port,
3298            self.match_len, self.table_id)
3299
3300
3301nx_actions.generate(
3302    'ryu.ofproto.ofproto_v1_0',
3303    'ryu.ofproto.ofproto_v1_0_parser'
3304)
3305