backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / ofproto / ofproto_v1_0_parser.py
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 """
18 Decoder/Encoder implementations of OpenFlow 1.0.
19 """
20
21 import struct
22 import base64
23
24 import six
25 import netaddr
26
27 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
28 from ryu.lib import addrconv
29 from ryu.lib import ip
30 from ryu.lib import mac
31 from ryu.lib.packet import packet
32 from ryu.lib.pack_utils import msg_pack_into
33 from ryu.ofproto import nx_match
34 from ryu.ofproto import ofproto_common
35 from ryu.ofproto import ofproto_parser
36 from ryu.ofproto import ofproto_v1_0 as ofproto
37 from ryu.ofproto import nx_actions
38 from ryu import utils
39
40 import logging
41 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_0_parser')
42
43 _MSG_PARSERS = {}
44
45
46 def _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
54 def _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)
63 def 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 #     }
82 def _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
94 class 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
154 class 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
366 class 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
378 class 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)
406 class 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)
445 class 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)
477 class 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)
509 class 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
528 class 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)
560 class 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)
579 class 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
596 class 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)
627 class 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)
646 class 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)
665 class 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
695 class 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)
716 class 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)
735 class 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)
754 class 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)
787 class 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
840 OFPActionExperimenter = OFPActionVendor
841
842
843 class 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)
864 class 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
892 class 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
916 class 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
966 class 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
977 class 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
1001 class 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
1014 class 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
1025 class 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
1034 class 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
1088 class 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
1100 class 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)
1130 class 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)
1141 class 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
1154 class 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)
1199 class 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)
1216 class 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)
1284 class 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)
1324 class 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)
1364 class 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)
1412 class 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
1444 class 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
1456 class 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
1502 class 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)
1515 class 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
1528 class 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)
1542 class 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
1573 class 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)
1587 class 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
1619 class 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
1628 class 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
1646 class 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)
1667 class 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)
1747 class 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)
1804 class 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)
1877 class 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)
1935 class 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)
1954 class 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)
2035 class 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
2082 def _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)
2092 class 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)
2150 class 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)
2188 class 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)
2245 class 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)
2281 class 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)
2327 class 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)
2386 class 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)
2427 class 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)
2471 class 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)
2525 class 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)
2532 class 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)
2545 class 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)
2569 class 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)
2590 class 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)
2634 class 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)
2718 class 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)
2835 class 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)
2916 class 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)
2938 class 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
2969 class 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)
2990 class 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
3015 class 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)
3034 class 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)
3075 class 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)
3115 class 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)
3143 class 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)
3179 class 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)
3218 class 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
3241 class 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
3257 class 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
3279 class 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
3301 nx_actions.generate(
3302     'ryu.ofproto.ofproto_v1_0',
3303     'ryu.ofproto.ofproto_v1_0_parser'
3304 )