backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / ofproto / ofproto_v1_2_parser.py
1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 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.2.
19 """
20
21 import struct
22 import base64
23
24 import six
25
26 from ryu.lib import addrconv
27 from ryu.lib import mac
28 from ryu.lib.pack_utils import msg_pack_into
29 from ryu.lib.packet import packet
30 from ryu import utils
31 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
32 from ryu.ofproto import ether
33 from ryu.ofproto import ofproto_parser
34 from ryu.ofproto import ofproto_v1_2 as ofproto
35
36 import logging
37 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_2_parser')
38
39 _MSG_PARSERS = {}
40
41
42 def _set_msg_type(msg_type):
43     def _set_cls_msg_type(cls):
44         cls.cls_msg_type = msg_type
45         return cls
46     return _set_cls_msg_type
47
48
49 def _register_parser(cls):
50     '''class decorator to register msg parser'''
51     assert cls.cls_msg_type is not None
52     assert cls.cls_msg_type not in _MSG_PARSERS
53     _MSG_PARSERS[cls.cls_msg_type] = cls.parser
54     return cls
55
56
57 @ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
58 def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
59     parser = _MSG_PARSERS.get(msg_type)
60     return parser(datapath, version, msg_type, msg_len, xid, buf)
61
62
63 @_register_parser
64 @_set_msg_type(ofproto.OFPT_HELLO)
65 class OFPHello(MsgBase):
66     """
67     Hello message
68
69     When connection is started, the hello message is exchanged between a
70     switch and a controller.
71
72     This message is handled by the Ryu framework, so the Ryu application
73     do not need to process this typically.
74     """
75
76     def __init__(self, datapath):
77         super(OFPHello, self).__init__(datapath)
78
79
80 @_register_parser
81 @_set_msg_type(ofproto.OFPT_ERROR)
82 class OFPErrorMsg(MsgBase):
83     """
84     Error message
85
86     The switch notifies controller of problems by this message.
87
88     ========== =========================================================
89     Attribute  Description
90     ========== =========================================================
91     type       High level type of error
92     code       Details depending on the type
93     data       Variable length data depending on the type and code
94     ========== =========================================================
95
96     ``type`` attribute corresponds to ``type_`` parameter of __init__.
97
98     Types and codes are defined in ``ryu.ofproto.ofproto``.
99
100     ============================= ===========
101     Type                          Code
102     ============================= ===========
103     OFPET_HELLO_FAILED            OFPHFC_*
104     OFPET_BAD_REQUEST             OFPBRC_*
105     OFPET_BAD_ACTION              OFPBAC_*
106     OFPET_BAD_INSTRUCTION         OFPBIC_*
107     OFPET_BAD_MATCH               OFPBMC_*
108     OFPET_FLOW_MOD_FAILED         OFPFMFC_*
109     OFPET_GROUP_MOD_FAILED        OFPGMFC_*
110     OFPET_PORT_MOD_FAILED         OFPPMFC_*
111     OFPET_TABLE_MOD_FAILED        OFPTMFC_*
112     OFPET_QUEUE_OP_FAILED         OFPQOFC_*
113     OFPET_SWITCH_CONFIG_FAILED    OFPSCFC_*
114     OFPET_ROLE_REQUEST_FAILED     OFPRRFC_*
115     OFPET_EXPERIMENTER            N/A
116     ============================= ===========
117
118     If ``type == OFPET_EXPERIMENTER``, this message has also the following
119     attributes.
120
121     ============= ======================================================
122     Attribute     Description
123     ============= ======================================================
124     exp_type      Experimenter defined type
125     experimenter  Experimenter ID
126     ============= ======================================================
127
128     Example::
129
130         @set_ev_cls(ofp_event.EventOFPErrorMsg,
131                     [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
132         def error_msg_handler(self, ev):
133             msg = ev.msg
134
135             self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
136                               'message=%s',
137                               msg.type, msg.code, utils.hex_array(msg.data))
138     """
139
140     def __init__(self, datapath, type_=None, code=None, data=None, **kwargs):
141         super(OFPErrorMsg, self).__init__(datapath)
142         self.type = type_
143         self.code = code
144         if isinstance(data, six.string_types):
145             data = data.encode('ascii')
146         self.data = data
147         if self.type == ofproto.OFPET_EXPERIMENTER:
148             self.exp_type = kwargs.get('exp_type', None)
149             self.experimenter = kwargs.get('experimenter', None)
150
151     @classmethod
152     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
153         type_, = struct.unpack_from('!H', six.binary_type(buf),
154                                     ofproto.OFP_HEADER_SIZE)
155         msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
156                                              msg_len, xid, buf)
157         if type_ == ofproto.OFPET_EXPERIMENTER:
158             (msg.type, msg.exp_type, msg.experimenter,
159              msg.data) = cls.parse_experimenter_body(buf)
160         else:
161             (msg.type, msg.code,
162              msg.data) = cls.parse_body(buf)
163         return msg
164
165     @classmethod
166     def parse_body(cls, buf):
167         type_, code = struct.unpack_from(
168             ofproto.OFP_ERROR_MSG_PACK_STR, buf,
169             ofproto.OFP_HEADER_SIZE)
170         data = buf[ofproto.OFP_ERROR_MSG_SIZE:]
171         return type_, code, data
172
173     @classmethod
174     def parse_experimenter_body(cls, buf):
175         type_, exp_type, experimenter = struct.unpack_from(
176             ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR, buf,
177             ofproto.OFP_HEADER_SIZE)
178         data = buf[ofproto.OFP_ERROR_EXPERIMENTER_MSG_SIZE:]
179         return type_, exp_type, experimenter, data
180
181     def _serialize_body(self):
182         assert self.data is not None
183         if self.type == ofproto.OFPET_EXPERIMENTER:
184             msg_pack_into(ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR,
185                           self.buf, ofproto.OFP_HEADER_SIZE,
186                           self.type, self.exp_type, self.experimenter)
187             self.buf += self.data
188         else:
189             msg_pack_into(ofproto.OFP_ERROR_MSG_PACK_STR,
190                           self.buf, ofproto.OFP_HEADER_SIZE,
191                           self.type, self.code)
192             self.buf += self.data
193
194
195 # For the backward compatibility
196 def OFPErrorExperimenterMsg(datapath, type_=None, exp_type=None,
197                             experimenter=None, data=None):
198     msg = OFPErrorMsg(datapath, data=data)
199     msg.type = ofproto.OFPET_EXPERIMENTER
200     msg.exp_type = exp_type
201     msg.experimenter = experimenter
202     return msg
203
204
205 @_register_parser
206 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
207 class OFPEchoRequest(MsgBase):
208     """
209     Echo request message
210
211     This message is handled by the Ryu framework, so the Ryu application
212     do not need to process this typically.
213
214     ========== =========================================================
215     Attribute  Description
216     ========== =========================================================
217     data       An arbitrary length data
218     ========== =========================================================
219
220     Example::
221
222         def send_echo_request(self, datapath, data):
223             ofp_parser = datapath.ofproto_parser
224
225             req = ofp_parser.OFPEchoRequest(datapath, data)
226             datapath.send_msg(req)
227
228         @set_ev_cls(ofp_event.EventOFPEchoRequest,
229                     [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
230         def echo_request_handler(self, ev):
231             self.logger.debug('OFPEchoRequest received: data=%s',
232                               utils.hex_array(ev.msg.data))
233     """
234
235     def __init__(self, datapath, data=None):
236         super(OFPEchoRequest, self).__init__(datapath)
237         self.data = data
238
239     @classmethod
240     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
241         msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
242                                                 msg_len, xid, buf)
243         msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
244         return msg
245
246     def _serialize_body(self):
247         if self.data is not None:
248             self.buf += self.data
249
250
251 @_register_parser
252 @_set_msg_type(ofproto.OFPT_ECHO_REPLY)
253 class OFPEchoReply(MsgBase):
254     """
255     Echo reply message
256
257     This message is handled by the Ryu framework, so the Ryu application
258     do not need to process this typically.
259
260     ========== =========================================================
261     Attribute  Description
262     ========== =========================================================
263     data       An arbitrary length data
264     ========== =========================================================
265
266     Example::
267
268         def send_echo_reply(self, datapath, data):
269             ofp_parser = datapath.ofproto_parser
270
271             reply = ofp_parser.OFPEchoReply(datapath, data)
272             datapath.send_msg(reply)
273
274         @set_ev_cls(ofp_event.EventOFPEchoReply,
275                     [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
276         def echo_reply_handler(self, ev):
277             self.logger.debug('OFPEchoReply received: data=%s',
278                               utils.hex_array(ev.msg.data))
279     """
280
281     def __init__(self, datapath, data=None):
282         super(OFPEchoReply, self).__init__(datapath)
283         self.data = data
284
285     @classmethod
286     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
287         msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
288                                               msg_len, xid, buf)
289         msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
290         return msg
291
292     def _serialize_body(self):
293         assert self.data is not None
294         self.buf += self.data
295
296
297 @_register_parser
298 @_set_msg_type(ofproto.OFPT_EXPERIMENTER)
299 class OFPExperimenter(MsgBase):
300     """
301     Experimenter extension message
302
303     ============= =========================================================
304     Attribute     Description
305     ============= =========================================================
306     experimenter  Experimenter ID
307     exp_type      Experimenter defined
308     data          Experimenter defined arbitrary additional data
309     ============= =========================================================
310     """
311
312     def __init__(self, datapath, experimenter=None, exp_type=None, data=None):
313         super(OFPExperimenter, self).__init__(datapath)
314         self.experimenter = experimenter
315         self.exp_type = exp_type
316         self.data = data
317
318     @classmethod
319     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
320         msg = super(OFPExperimenter, cls).parser(datapath, version, msg_type,
321                                                  msg_len, xid, buf)
322         (msg.experimenter, msg.exp_type) = struct.unpack_from(
323             ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR, msg.buf,
324             ofproto.OFP_HEADER_SIZE)
325         msg.data = msg.buf[ofproto.OFP_EXPERIMENTER_HEADER_SIZE:]
326
327         return msg
328
329     def _serialize_body(self):
330         assert self.data is not None
331         msg_pack_into(ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR,
332                       self.buf, ofproto.OFP_HEADER_SIZE,
333                       self.experimenter, self.exp_type)
334         self.buf += self.data
335
336
337 class OFPPort(ofproto_parser.namedtuple('OFPPort', (
338         'port_no', 'hw_addr', 'name', 'config', 'state', 'curr',
339         'advertised', 'supported', 'peer', 'curr_speed', 'max_speed'))):
340     """
341     Description of a port
342
343     ========== =========================================================
344     Attribute  Description
345     ========== =========================================================
346     port_no    Port number and it uniquely identifies a port within
347                a switch.
348     hw_addr    MAC address for the port.
349     name       Null-terminated string containing a human-readable name
350                for the interface.
351     config     Bitmap of port configration flags.
352
353                | OFPPC_PORT_DOWN
354                | OFPPC_NO_RECV
355                | OFPPC_NO_FWD
356                | OFPPC_NO_PACKET_IN
357     state      Bitmap of port state flags.
358
359                | OFPPS_LINK_DOWN
360                | OFPPS_BLOCKED
361                | OFPPS_LIVE
362     curr       Current features.
363     advertised Features being advertised by the port.
364     supported  Features supported by the port.
365     peer       Features advertised by peer.
366     curr_speed Current port bitrate in kbps.
367     max_speed  Max port bitrate in kbps.
368     ========== =========================================================
369     """
370
371     _TYPE = {
372         'ascii': [
373             'hw_addr',
374         ],
375         'utf-8': [
376             # OF spec is unclear about the encoding of name.
377             # we assumes UTF-8, which is used by OVS.
378             'name',
379         ]
380     }
381
382     @classmethod
383     def parser(cls, buf, offset):
384         port = struct.unpack_from(ofproto.OFP_PORT_PACK_STR, buf, offset)
385         port = list(port)
386         i = cls._fields.index('hw_addr')
387         port[i] = addrconv.mac.bin_to_text(port[i])
388         i = cls._fields.index('name')
389         port[i] = port[i].rstrip(b'\0')
390         return cls(*port)
391
392
393 @_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
394 class OFPFeaturesRequest(MsgBase):
395     """
396     Features request message
397
398     The controller sends a feature request to the switch upon session
399     establishment.
400
401     This message is handled by the Ryu framework, so the Ryu application
402     do not need to process this typically.
403
404     Example::
405
406         def send_features_request(self, datapath):
407             ofp_parser = datapath.ofproto_parser
408
409             req = ofp_parser.OFPFeaturesRequest(datapath)
410             datapath.send_msg(req)
411     """
412
413     def __init__(self, datapath):
414         super(OFPFeaturesRequest, self).__init__(datapath)
415
416
417 @_register_parser
418 @_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
419 class OFPSwitchFeatures(MsgBase):
420     """
421     Features reply message
422
423     The switch responds with a features reply message to a features
424     request.
425
426     This message is handled by the Ryu framework, so the Ryu application
427     do not need to process this typically.
428
429     Example::
430
431         @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
432         def switch_features_handler(self, ev):
433             msg = ev.msg
434
435             self.logger.debug('OFPSwitchFeatures received: '
436                               'datapath_id=0x%016x n_buffers=%d '
437                               'n_tables=%d capabilities=0x%08x ports=%s',
438                               msg.datapath_id, msg.n_buffers, msg.n_tables,
439                               msg.capabilities, msg.ports)
440     """
441
442     def __init__(self, datapath, datapath_id=None, n_buffers=None,
443                  n_tables=None, capabilities=None, ports=None):
444         super(OFPSwitchFeatures, self).__init__(datapath)
445         self.datapath_id = datapath_id
446         self.n_buffers = n_buffers
447         self.n_tables = n_tables
448         self.capabilities = capabilities
449         self.ports = ports
450
451     @classmethod
452     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
453         msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
454                                                    msg_len, xid, buf)
455         (msg.datapath_id,
456          msg.n_buffers,
457          msg.n_tables,
458          msg.capabilities,
459          msg._reserved) = struct.unpack_from(
460             ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
461             ofproto.OFP_HEADER_SIZE)
462
463         msg.ports = {}
464         n_ports = ((msg_len - ofproto.OFP_SWITCH_FEATURES_SIZE) //
465                    ofproto.OFP_PORT_SIZE)
466         offset = ofproto.OFP_SWITCH_FEATURES_SIZE
467         for i in range(n_ports):
468             port = OFPPort.parser(msg.buf, offset)
469             msg.ports[port.port_no] = port
470             offset += ofproto.OFP_PORT_SIZE
471
472         return msg
473
474
475 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
476 class OFPGetConfigRequest(MsgBase):
477     """
478     Get config request message
479
480     The controller sends a get config request to query configuration
481     parameters in the switch.
482
483     Example::
484
485         def send_get_config_request(self, datapath):
486             ofp_parser = datapath.ofproto_parser
487
488             req = ofp_parser.OFPGetConfigRequest(datapath)
489             datapath.send_msg(req)
490     """
491
492     def __init__(self, datapath):
493         super(OFPGetConfigRequest, self).__init__(datapath)
494
495
496 @_register_parser
497 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
498 class OFPGetConfigReply(MsgBase):
499     """
500     Get config reply message
501
502     The switch responds to a configuration request with a get config reply
503     message.
504
505     ============= =========================================================
506     Attribute     Description
507     ============= =========================================================
508     flags         One of the following configuration flags.
509
510                   | OFPC_FRAG_NORMAL
511                   | OFPC_FRAG_DROP
512                   | OFPC_FRAG_REASM
513                   | OFPC_FRAG_MASK
514                   | OFPC_INVALID_TTL_TO_CONTROLLER
515     miss_send_len Max bytes of new flow that datapath should send to the
516                   controller
517     ============= =========================================================
518
519     Example::
520
521         @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
522         def get_config_reply_handler(self, ev):
523             msg = ev.msg
524             dp = msg.datapath
525             ofp = dp.ofproto
526
527             if msg.flags == ofp.OFPC_FRAG_NORMAL:
528                 flags = 'NORMAL'
529             elif msg.flags == ofp.OFPC_FRAG_DROP:
530                 flags = 'DROP'
531             elif msg.flags == ofp.OFPC_FRAG_REASM:
532                 flags = 'REASM'
533             elif msg.flags == ofp.OFPC_FRAG_MASK:
534                 flags = 'MASK'
535             elif msg.flags == ofp.OFPC_INVALID_TTL_TO_CONTROLLER:
536                 flags = 'INVALID TTL TO CONTROLLER'
537             else:
538                 flags = 'unknown'
539             self.logger.debug('OFPGetConfigReply received: '
540                               'flags=%s miss_send_len=%d',
541                               flags, msg.miss_send_len)
542     """
543
544     def __init__(self, datapath, flags=None, miss_send_len=None):
545         super(OFPGetConfigReply, self).__init__(datapath)
546         self.flags = flags
547         self.miss_send_len = miss_send_len
548
549     @classmethod
550     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
551         msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
552                                                    msg_len, xid, buf)
553         msg.flags, msg.miss_send_len = struct.unpack_from(
554             ofproto.OFP_SWITCH_CONFIG_PACK_STR, msg.buf,
555             ofproto.OFP_HEADER_SIZE)
556         return msg
557
558
559 @_set_msg_type(ofproto.OFPT_SET_CONFIG)
560 class OFPSetConfig(MsgBase):
561     """
562     Set config request message
563
564     The controller sends a set config request message to set configuraion
565     parameters.
566
567     ============= =========================================================
568     Attribute     Description
569     ============= =========================================================
570     flags         One of the following configuration flags.
571
572                   | OFPC_FRAG_NORMAL
573                   | OFPC_FRAG_DROP
574                   | OFPC_FRAG_REASM
575                   | OFPC_FRAG_MASK
576                   | OFPC_INVALID_TTL_TO_CONTROLLER
577     miss_send_len Max bytes of new flow that datapath should send to the
578                   controller
579     ============= =========================================================
580
581     Example::
582
583         def send_set_config(self, datapath):
584             ofp = datapath.ofproto
585             ofp_parser = datapath.ofproto_parser
586
587             req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
588             datapath.send_msg(req)
589     """
590
591     def __init__(self, datapath, flags=0, miss_send_len=0):
592         super(OFPSetConfig, self).__init__(datapath)
593         self.flags = flags
594         self.miss_send_len = miss_send_len
595
596     def _serialize_body(self):
597         assert self.flags is not None
598         assert self.miss_send_len is not None
599         msg_pack_into(ofproto.OFP_SWITCH_CONFIG_PACK_STR,
600                       self.buf, ofproto.OFP_HEADER_SIZE,
601                       self.flags, self.miss_send_len)
602
603
604 @_register_parser
605 @_set_msg_type(ofproto.OFPT_PACKET_IN)
606 class OFPPacketIn(MsgBase):
607     """
608     Packet-In message
609
610     The switch sends the packet that received to the controller by this
611     message.
612
613     ============= =========================================================
614     Attribute     Description
615     ============= =========================================================
616     buffer_id     ID assigned by datapath
617     total_len     Full length of frame
618     reason        Reason packet is being sent.
619
620                   | OFPR_NO_MATCH
621                   | OFPR_ACTION
622                   | OFPR_INVALID_TTL
623     table_id      ID of the table that was looked up
624     match         Instance of ``OFPMatch``
625     data          Ethernet frame
626     ============= =========================================================
627
628     Example::
629
630         @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
631         def packet_in_handler(self, ev):
632             msg = ev.msg
633             dp = msg.datapath
634             ofp = dp.ofproto
635
636             if msg.reason == ofp.OFPR_NO_MATCH:
637                 reason = 'NO MATCH'
638             elif msg.reason == ofp.OFPR_ACTION:
639                 reason = 'ACTION'
640             elif msg.reason == ofp.OFPR_INVALID_TTL:
641                 reason = 'INVALID TTL'
642             else:
643                 reason = 'unknown'
644
645             self.logger.debug('OFPPacketIn received: '
646                               'buffer_id=%x total_len=%d reason=%s '
647                               'table_id=%d match=%s data=%s',
648                               msg.buffer_id, msg.total_len, reason,
649                               msg.table_id, msg.match,
650                               utils.hex_array(msg.data))
651     """
652
653     def __init__(self, datapath, buffer_id=None, total_len=None, reason=None,
654                  table_id=None, match=None, data=None):
655         super(OFPPacketIn, self).__init__(datapath)
656         self.buffer_id = buffer_id
657         self.total_len = total_len
658         self.reason = reason
659         self.table_id = table_id
660         self.match = match
661         self.data = data
662
663     @classmethod
664     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
665         msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
666                                              msg_len, xid, buf)
667         (msg.buffer_id, msg.total_len, msg.reason,
668          msg.table_id) = struct.unpack_from(
669             ofproto.OFP_PACKET_IN_PACK_STR,
670             msg.buf, ofproto.OFP_HEADER_SIZE)
671
672         msg.match = OFPMatch.parser(msg.buf, ofproto.OFP_PACKET_IN_SIZE -
673                                     ofproto.OFP_MATCH_SIZE)
674
675         match_len = utils.round_up(msg.match.length, 8)
676         msg.data = msg.buf[(ofproto.OFP_PACKET_IN_SIZE -
677                             ofproto.OFP_MATCH_SIZE + match_len + 2):]
678
679         if msg.total_len < len(msg.data):
680             # discard padding for 8-byte alignment of OFP packet
681             msg.data = msg.data[:msg.total_len]
682
683         return msg
684
685
686 @_register_parser
687 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
688 class OFPFlowRemoved(MsgBase):
689     """
690     Flow removed message
691
692     When flow entries time out or are deleted, the switch notifies controller
693     with this message.
694
695     ================ ======================================================
696     Attribute        Description
697     ================ ======================================================
698     cookie           Opaque controller-issued identifier
699     priority         Priority level of flow entry
700     reason           One of the following values.
701
702                      | OFPRR_IDLE_TIMEOUT
703                      | OFPRR_HARD_TIMEOUT
704                      | OFPRR_DELETE
705                      | OFPRR_GROUP_DELETE
706     table_id         ID of the table
707     duration_sec     Time flow was alive in seconds
708     duration_nsec    Time flow was alive in nanoseconds beyond duration_sec
709     idle_timeout     Idle timeout from original flow mod
710     hard_timeout     Hard timeout from original flow mod
711     packet_count     Number of packets that was associated with the flow
712     byte_count       Number of bytes that was associated with the flow
713     match            Instance of ``OFPMatch``
714     ================ ======================================================
715
716     Example::
717
718         @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
719         def flow_removed_handler(self, ev):
720             msg = ev.msg
721             dp = msg.datapath
722             ofp = dp.ofproto
723
724             if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
725                 reason = 'IDLE TIMEOUT'
726             elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
727                 reason = 'HARD TIMEOUT'
728             elif msg.reason == ofp.OFPRR_DELETE:
729                 reason = 'DELETE'
730             elif msg.reason == ofp.OFPRR_GROUP_DELETE:
731                 reason = 'GROUP DELETE'
732             else:
733                 reason = 'unknown'
734
735             self.logger.debug('OFPFlowRemoved received: '
736                               'cookie=%d priority=%d reason=%s table_id=%d '
737                               'duration_sec=%d duration_nsec=%d '
738                               'idle_timeout=%d hard_timeout=%d '
739                               'packet_count=%d byte_count=%d match.fields=%s',
740                               msg.cookie, msg.priority, reason, msg.table_id,
741                               msg.duration_sec, msg.duration_nsec,
742                               msg.idle_timeout, msg.hard_timeout,
743                               msg.packet_count, msg.byte_count, msg.match)
744     """
745
746     def __init__(self, datapath, cookie=None, priority=None, reason=None,
747                  table_id=None, duration_sec=None, duration_nsec=None,
748                  idle_timeout=None, hard_timeout=None, packet_count=None,
749                  byte_count=None, match=None):
750         super(OFPFlowRemoved, self).__init__(datapath)
751         self.cookie = cookie
752         self.priority = priority
753         self.reason = reason
754         self.table_id = table_id
755         self.duration_sec = duration_sec
756         self.duration_nsec = duration_nsec
757         self.idle_timeout = idle_timeout
758         self.hard_timeout = hard_timeout
759         self.packet_count = packet_count
760         self.byte_count = byte_count
761         self.match = match
762
763     @classmethod
764     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
765         msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
766                                                 msg_len, xid, buf)
767
768         (msg.cookie, msg.priority, msg.reason,
769          msg.table_id, msg.duration_sec, msg.duration_nsec,
770          msg.idle_timeout, msg.hard_timeout, msg.packet_count,
771          msg.byte_count) = struct.unpack_from(
772             ofproto.OFP_FLOW_REMOVED_PACK_STR0,
773             msg.buf,
774             ofproto.OFP_HEADER_SIZE)
775
776         offset = (ofproto.OFP_FLOW_REMOVED_SIZE -
777                   ofproto.OFP_MATCH_SIZE)
778
779         msg.match = OFPMatch.parser(msg.buf, offset)
780
781         return msg
782
783
784 @_register_parser
785 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
786 class OFPPortStatus(MsgBase):
787     """
788     Port status message
789
790     The switch notifies controller of change of ports.
791
792     ================ ======================================================
793     Attribute        Description
794     ================ ======================================================
795     reason           One of the following values.
796
797                      | OFPPR_ADD
798                      | OFPPR_DELETE
799                      | OFPPR_MODIFY
800     desc             instance of ``OFPPort``
801     ================ ======================================================
802
803     Example::
804
805         @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
806         def port_status_handler(self, ev):
807             msg = ev.msg
808             dp = msg.datapath
809             ofp = dp.ofproto
810
811             if msg.reason == ofp.OFPPR_ADD:
812                 reason = 'ADD'
813             elif msg.reason == ofp.OFPPR_DELETE:
814                 reason = 'DELETE'
815             elif msg.reason == ofp.OFPPR_MODIFY:
816                 reason = 'MODIFY'
817             else:
818                 reason = 'unknown'
819
820             self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
821                               reason, msg.desc)
822     """
823
824     def __init__(self, datapath, reason=None, desc=None):
825         super(OFPPortStatus, self).__init__(datapath)
826         self.reason = reason
827         self.desc = desc
828
829     @classmethod
830     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
831         msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
832                                                msg_len, xid, buf)
833         msg.reason = struct.unpack_from(
834             ofproto.OFP_PORT_STATUS_PACK_STR, msg.buf,
835             ofproto.OFP_HEADER_SIZE)[0]
836         msg.desc = OFPPort.parser(msg.buf,
837                                   ofproto.OFP_PORT_STATUS_DESC_OFFSET)
838         return msg
839
840
841 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
842 class OFPPacketOut(MsgBase):
843     """
844     Packet-Out message
845
846     The controller uses this message to send a packet out throught the
847     switch.
848
849     ================ ======================================================
850     Attribute        Description
851     ================ ======================================================
852     buffer_id        ID assigned by datapath (OFP_NO_BUFFER if none)
853     in_port          Packet's input port or ``OFPP_CONTROLLER``
854     actions          list of OpenFlow action class
855     data             Packet data of a binary type value or
856                      an instances of packet.Packet.
857     ================ ======================================================
858
859     Example::
860
861         def send_packet_out(self, datapath, buffer_id, in_port):
862             ofp = datapath.ofproto
863             ofp_parser = datapath.ofproto_parser
864
865             actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
866             req = ofp_parser.OFPPacketOut(datapath, buffer_id,
867                                           in_port, actions)
868             datapath.send_msg(req)
869     """
870
871     def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
872                  data=None, actions_len=None):
873         # The in_port field is the ingress port that must be associated
874         # with the packet for OpenFlow processing.
875         assert in_port is not None
876
877         super(OFPPacketOut, self).__init__(datapath)
878         self.buffer_id = buffer_id
879         self.in_port = in_port
880         self.actions_len = 0
881         self.actions = actions
882         self.data = data
883
884     def _serialize_body(self):
885         self.actions_len = 0
886         offset = ofproto.OFP_PACKET_OUT_SIZE
887         for a in self.actions:
888             a.serialize(self.buf, offset)
889             offset += a.len
890             self.actions_len += a.len
891
892         if self.data is not None:
893             assert self.buffer_id == 0xffffffff
894             if isinstance(self.data, packet.Packet):
895                 self.data.serialize()
896                 self.buf += self.data.data
897             else:
898                 self.buf += self.data
899
900         msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR,
901                       self.buf, ofproto.OFP_HEADER_SIZE,
902                       self.buffer_id, self.in_port, self.actions_len)
903
904     @classmethod
905     def from_jsondict(cls, dict_, decode_string=base64.b64decode,
906                       **additional_args):
907         if isinstance(dict_['data'], dict):
908             data = dict_.pop('data')
909             ins = super(OFPPacketOut, cls).from_jsondict(dict_,
910                                                          decode_string,
911                                                          **additional_args)
912             ins.data = packet.Packet.from_jsondict(data['Packet'])
913             dict_['data'] = data
914         else:
915             ins = super(OFPPacketOut, cls).from_jsondict(dict_,
916                                                          decode_string,
917                                                          **additional_args)
918
919         return ins
920
921
922 @_register_parser
923 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
924 class OFPFlowMod(MsgBase):
925     """
926     Modify Flow entry message
927
928     The controller sends this message to modify the flow table.
929
930     ================ ======================================================
931     Attribute        Description
932     ================ ======================================================
933     cookie           Opaque controller-issued identifier
934     cookie_mask      Mask used to restrict the cookie bits that must match
935                      when the command is ``OPFFC_MODIFY*`` or
936                      ``OFPFC_DELETE*``
937     table_id         ID of the table to put the flow in
938     command          One of the following values.
939
940                      | OFPFC_ADD
941                      | OFPFC_MODIFY
942                      | OFPFC_MODIFY_STRICT
943                      | OFPFC_DELETE
944                      | OFPFC_DELETE_STRICT
945     idle_timeout     Idle time before discarding (seconds)
946     hard_timeout     Max time before discarding (seconds)
947     priority         Priority level of flow entry
948     buffer_id        Buffered packet to apply to (or OFP_NO_BUFFER)
949     out_port         For ``OFPFC_DELETE*`` commands, require matching
950                      entries to include this as an output port
951     out_group        For ``OFPFC_DELETE*`` commands, require matching
952                      entries to include this as an output group
953     flags            One of the following values.
954
955                      | OFPFF_SEND_FLOW_REM
956                      | OFPFF_CHECK_OVERLAP
957                      | OFPFF_RESET_COUNTS
958     match            Instance of ``OFPMatch``
959     instructions     list of ``OFPInstruction*`` instance
960     ================ ======================================================
961
962     Example::
963
964         def send_flow_mod(self, datapath):
965             ofp = datapath.ofproto
966             ofp_parser = datapath.ofproto_parser
967
968             cookie = cookie_mask = 0
969             table_id = 0
970             idle_timeout = hard_timeout = 0
971             priority = 32768
972             buffer_id = ofp.OFP_NO_BUFFER
973             match = ofp_parser.OFPMatch(in_port=1, eth_dst='ff:ff:ff:ff:ff:ff')
974             actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
975             inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
976                                                      actions)]
977             req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask,
978                                         table_id, ofp.OFPFC_ADD,
979                                         idle_timeout, hard_timeout,
980                                         priority, buffer_id,
981                                         ofp.OFPP_ANY, ofp.OFPG_ANY,
982                                         ofp.OFPFF_SEND_FLOW_REM,
983                                         match, inst)
984             datapath.send_msg(req)
985     """
986
987     def __init__(self, datapath, cookie=0, cookie_mask=0, table_id=0,
988                  command=ofproto.OFPFC_ADD,
989                  idle_timeout=0, hard_timeout=0, priority=0,
990                  buffer_id=ofproto.OFP_NO_BUFFER,
991                  out_port=0, out_group=0, flags=0,
992                  match=None,
993                  instructions=None):
994         instructions = instructions if instructions else []
995         super(OFPFlowMod, self).__init__(datapath)
996         self.cookie = cookie
997         self.cookie_mask = cookie_mask
998         self.table_id = table_id
999         self.command = command
1000         self.idle_timeout = idle_timeout
1001         self.hard_timeout = hard_timeout
1002         self.priority = priority
1003         self.buffer_id = buffer_id
1004         self.out_port = out_port
1005         self.out_group = out_group
1006         self.flags = flags
1007         if match is None:
1008             match = OFPMatch()
1009         assert isinstance(match, OFPMatch)
1010         self.match = match
1011         for i in instructions:
1012             assert isinstance(i, OFPInstruction)
1013         self.instructions = instructions
1014
1015     def _serialize_body(self):
1016         msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf,
1017                       ofproto.OFP_HEADER_SIZE,
1018                       self.cookie, self.cookie_mask, self.table_id,
1019                       self.command, self.idle_timeout, self.hard_timeout,
1020                       self.priority, self.buffer_id, self.out_port,
1021                       self.out_group, self.flags)
1022
1023         offset = (ofproto.OFP_FLOW_MOD_SIZE -
1024                   ofproto.OFP_MATCH_SIZE)
1025
1026         match_len = self.match.serialize(self.buf, offset)
1027         offset += match_len
1028
1029         for inst in self.instructions:
1030             inst.serialize(self.buf, offset)
1031             offset += inst.len
1032
1033     @classmethod
1034     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1035         msg = super(OFPFlowMod, cls).parser(
1036             datapath, version, msg_type, msg_len, xid, buf)
1037
1038         (msg.cookie, msg.cookie_mask, msg.table_id,
1039          msg.command, msg.idle_timeout, msg.hard_timeout,
1040          msg.priority, msg.buffer_id, msg.out_port,
1041          msg.out_group, msg.flags) = struct.unpack_from(
1042             ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf,
1043             ofproto.OFP_HEADER_SIZE)
1044         offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE
1045
1046         msg.match = OFPMatch.parser(buf, offset)
1047         offset += utils.round_up(msg.match.length, 8)
1048
1049         instructions = []
1050         while offset < msg_len:
1051             i = OFPInstruction.parser(buf, offset)
1052             instructions.append(i)
1053             offset += i.len
1054         msg.instructions = instructions
1055
1056         return msg
1057
1058
1059 class OFPInstruction(StringifyMixin):
1060     _INSTRUCTION_TYPES = {}
1061
1062     @staticmethod
1063     def register_instruction_type(types):
1064         def _register_instruction_type(cls):
1065             for type_ in types:
1066                 OFPInstruction._INSTRUCTION_TYPES[type_] = cls
1067             return cls
1068         return _register_instruction_type
1069
1070     @classmethod
1071     def parser(cls, buf, offset):
1072         (type_, len_) = struct.unpack_from('!HH', buf, offset)
1073         cls_ = cls._INSTRUCTION_TYPES.get(type_)
1074         return cls_.parser(buf, offset)
1075
1076
1077 @OFPInstruction.register_instruction_type([ofproto.OFPIT_GOTO_TABLE])
1078 class OFPInstructionGotoTable(OFPInstruction):
1079     """
1080     Goto table instruction
1081
1082     This instruction indicates the next table in the processing pipeline.
1083
1084     ================ ======================================================
1085     Attribute        Description
1086     ================ ======================================================
1087     table_id         Next table
1088     ================ ======================================================
1089     """
1090
1091     def __init__(self, table_id, type_=None, len_=None):
1092         super(OFPInstructionGotoTable, self).__init__()
1093         self.type = ofproto.OFPIT_GOTO_TABLE
1094         self.len = ofproto.OFP_INSTRUCTION_GOTO_TABLE_SIZE
1095         self.table_id = table_id
1096
1097     @classmethod
1098     def parser(cls, buf, offset):
1099         (type_, len_, table_id) = struct.unpack_from(
1100             ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
1101             buf, offset)
1102         return cls(table_id)
1103
1104     def serialize(self, buf, offset):
1105         msg_pack_into(ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
1106                       buf, offset, self.type, self.len, self.table_id)
1107
1108
1109 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_METADATA])
1110 class OFPInstructionWriteMetadata(OFPInstruction):
1111     """
1112     Write metadata instruction
1113
1114     This instruction writes the masked metadata value into the metadata field.
1115
1116     ================ ======================================================
1117     Attribute        Description
1118     ================ ======================================================
1119     metadata         Metadata value to write
1120     metadata_mask    Metadata write bitmask
1121     ================ ======================================================
1122     """
1123
1124     def __init__(self, metadata, metadata_mask, type_=None, len_=None):
1125         super(OFPInstructionWriteMetadata, self).__init__()
1126         self.type = ofproto.OFPIT_WRITE_METADATA
1127         self.len = ofproto.OFP_INSTRUCTION_WRITE_METADATA_SIZE
1128         self.metadata = metadata
1129         self.metadata_mask = metadata_mask
1130
1131     @classmethod
1132     def parser(cls, buf, offset):
1133         (type_, len_, metadata, metadata_mask) = struct.unpack_from(
1134             ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
1135             buf, offset)
1136         return cls(metadata, metadata_mask)
1137
1138     def serialize(self, buf, offset):
1139         msg_pack_into(ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
1140                       buf, offset, self.type, self.len, self.metadata,
1141                       self.metadata_mask)
1142
1143
1144 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS,
1145                                            ofproto.OFPIT_APPLY_ACTIONS,
1146                                            ofproto.OFPIT_CLEAR_ACTIONS])
1147 class OFPInstructionActions(OFPInstruction):
1148     """
1149     Actions instruction
1150
1151     This instruction writes/applies/clears the actions.
1152
1153     ================ ======================================================
1154     Attribute        Description
1155     ================ ======================================================
1156     type             One of following values.
1157
1158                      | OFPIT_WRITE_ACTIONS
1159                      | OFPIT_APPLY_ACTIONS
1160                      | OFPIT_CLEAR_ACTIONS
1161     actions          list of OpenFlow action class
1162     ================ ======================================================
1163
1164     ``type`` attribute corresponds to ``type_`` parameter of __init__.
1165     """
1166
1167     def __init__(self, type_, actions=None, len_=None):
1168         super(OFPInstructionActions, self).__init__()
1169         self.type = type_
1170         for a in actions:
1171             assert isinstance(a, OFPAction)
1172         self.actions = actions
1173
1174     @classmethod
1175     def parser(cls, buf, offset):
1176         (type_, len_) = struct.unpack_from(
1177             ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
1178             buf, offset)
1179
1180         offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1181         actions = []
1182         actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1183         while actions_len > 0:
1184             a = OFPAction.parser(buf, offset)
1185             actions.append(a)
1186             actions_len -= a.len
1187             offset += a.len
1188
1189         inst = cls(type_, actions)
1190         inst.len = len_
1191         return inst
1192
1193     def serialize(self, buf, offset):
1194         action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1195         if self.actions:
1196             for a in self.actions:
1197                 assert isinstance(a, OFPAction)
1198                 a.serialize(buf, action_offset)
1199                 action_offset += a.len
1200
1201         self.len = action_offset - offset
1202         pad_len = utils.round_up(self.len, 8) - self.len
1203         msg_pack_into("%dx" % pad_len, buf, action_offset)
1204         self.len += pad_len
1205
1206         msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
1207                       buf, offset, self.type, self.len)
1208
1209
1210 class OFPActionHeader(StringifyMixin):
1211     def __init__(self, type_, len_):
1212         self.type = type_
1213         self.len = len_
1214
1215     def serialize(self, buf, offset):
1216         msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
1217                       buf, offset, self.type, self.len)
1218
1219
1220 class OFPAction(OFPActionHeader):
1221     _ACTION_TYPES = {}
1222
1223     @staticmethod
1224     def register_action_type(type_, len_):
1225         def _register_action_type(cls):
1226             cls.cls_action_type = type_
1227             cls.cls_action_len = len_
1228             OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
1229             return cls
1230         return _register_action_type
1231
1232     def __init__(self):
1233         cls = self.__class__
1234         super(OFPAction, self).__init__(cls.cls_action_type,
1235                                         cls.cls_action_len)
1236
1237     @classmethod
1238     def parser(cls, buf, offset):
1239         type_, len_ = struct.unpack_from(
1240             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1241         cls_ = cls._ACTION_TYPES.get(type_)
1242         assert cls_ is not None
1243         return cls_.parser(buf, offset)
1244
1245     def serialize(self, buf, offset):
1246         msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR, buf,
1247                       offset, self.type, self.len)
1248
1249
1250 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
1251                                 ofproto.OFP_ACTION_OUTPUT_SIZE)
1252 class OFPActionOutput(OFPAction):
1253     """
1254     Output action
1255
1256     This action indicates output a packet to the switch port.
1257
1258     ================ ======================================================
1259     Attribute        Description
1260     ================ ======================================================
1261     port             Output port
1262     max_len          Max length to send to controller
1263     ================ ======================================================
1264     """
1265
1266     def __init__(self, port, max_len=ofproto.OFPCML_MAX,
1267                  type_=None, len_=None):
1268         super(OFPActionOutput, self).__init__()
1269         self.port = port
1270         self.max_len = max_len
1271
1272     @classmethod
1273     def parser(cls, buf, offset):
1274         type_, len_, port, max_len = struct.unpack_from(
1275             ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
1276         return cls(port, max_len)
1277
1278     def serialize(self, buf, offset):
1279         msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
1280                       offset, self.type, self.len, self.port, self.max_len)
1281
1282
1283 @OFPAction.register_action_type(ofproto.OFPAT_GROUP,
1284                                 ofproto.OFP_ACTION_GROUP_SIZE)
1285 class OFPActionGroup(OFPAction):
1286     """
1287     Group action
1288
1289     This action indicates the group used to process the packet.
1290
1291     ================ ======================================================
1292     Attribute        Description
1293     ================ ======================================================
1294     group_id         Group identifier
1295     ================ ======================================================
1296     """
1297
1298     def __init__(self, group_id=0, type_=None, len_=None):
1299         super(OFPActionGroup, self).__init__()
1300         self.group_id = group_id
1301
1302     @classmethod
1303     def parser(cls, buf, offset):
1304         (type_, len_, group_id) = struct.unpack_from(
1305             ofproto.OFP_ACTION_GROUP_PACK_STR, buf, offset)
1306         return cls(group_id)
1307
1308     def serialize(self, buf, offset):
1309         msg_pack_into(ofproto.OFP_ACTION_GROUP_PACK_STR, buf,
1310                       offset, self.type, self.len, self.group_id)
1311
1312
1313 @OFPAction.register_action_type(ofproto.OFPAT_SET_QUEUE,
1314                                 ofproto.OFP_ACTION_SET_QUEUE_SIZE)
1315 class OFPActionSetQueue(OFPAction):
1316     """
1317     Set queue action
1318
1319     This action sets the queue id that will be used to map a flow to an
1320     already-configured queue on a port.
1321
1322     ================ ======================================================
1323     Attribute        Description
1324     ================ ======================================================
1325     queue_id         Queue ID for the packets
1326     ================ ======================================================
1327     """
1328
1329     def __init__(self, queue_id, type_=None, len_=None):
1330         super(OFPActionSetQueue, self).__init__()
1331         self.queue_id = queue_id
1332
1333     @classmethod
1334     def parser(cls, buf, offset):
1335         (type_, len_, queue_id) = struct.unpack_from(
1336             ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf, offset)
1337         return cls(queue_id)
1338
1339     def serialize(self, buf, offset):
1340         msg_pack_into(ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
1341                       offset, self.type, self.len, self.queue_id)
1342
1343
1344 @OFPAction.register_action_type(ofproto.OFPAT_SET_MPLS_TTL,
1345                                 ofproto.OFP_ACTION_MPLS_TTL_SIZE)
1346 class OFPActionSetMplsTtl(OFPAction):
1347     """
1348     Set MPLS TTL action
1349
1350     This action sets the MPLS TTL.
1351
1352     ================ ======================================================
1353     Attribute        Description
1354     ================ ======================================================
1355     mpls_ttl         MPLS TTL
1356     ================ ======================================================
1357     """
1358
1359     def __init__(self, mpls_ttl, type_=None, len_=None):
1360         super(OFPActionSetMplsTtl, self).__init__()
1361         self.mpls_ttl = mpls_ttl
1362
1363     @classmethod
1364     def parser(cls, buf, offset):
1365         (type_, len_, mpls_ttl) = struct.unpack_from(
1366             ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf, offset)
1367         return cls(mpls_ttl)
1368
1369     def serialize(self, buf, offset):
1370         msg_pack_into(ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf,
1371                       offset, self.type, self.len, self.mpls_ttl)
1372
1373
1374 @OFPAction.register_action_type(ofproto.OFPAT_DEC_MPLS_TTL,
1375                                 ofproto.OFP_ACTION_HEADER_SIZE)
1376 class OFPActionDecMplsTtl(OFPAction):
1377     """
1378     Decrement MPLS TTL action
1379
1380     This action decrements the MPLS TTL.
1381     """
1382
1383     def __init__(self, type_=None, len_=None):
1384         super(OFPActionDecMplsTtl, self).__init__()
1385
1386     @classmethod
1387     def parser(cls, buf, offset):
1388         (type_, len_) = struct.unpack_from(
1389             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1390         return cls()
1391
1392
1393 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TTL,
1394                                 ofproto.OFP_ACTION_NW_TTL_SIZE)
1395 class OFPActionSetNwTtl(OFPAction):
1396     """
1397     Set IP TTL action
1398
1399     This action sets the IP TTL.
1400
1401     ================ ======================================================
1402     Attribute        Description
1403     ================ ======================================================
1404     nw_ttl           IP TTL
1405     ================ ======================================================
1406     """
1407
1408     def __init__(self, nw_ttl, type_=None, len_=None):
1409         super(OFPActionSetNwTtl, self).__init__()
1410         self.nw_ttl = nw_ttl
1411
1412     @classmethod
1413     def parser(cls, buf, offset):
1414         (type_, len_, nw_ttl) = struct.unpack_from(
1415             ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
1416         return cls(nw_ttl)
1417
1418     def serialize(self, buf, offset):
1419         msg_pack_into(ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset,
1420                       self.type, self.len, self.nw_ttl)
1421
1422
1423 @OFPAction.register_action_type(ofproto.OFPAT_DEC_NW_TTL,
1424                                 ofproto.OFP_ACTION_HEADER_SIZE)
1425 class OFPActionDecNwTtl(OFPAction):
1426     """
1427     Decrement IP TTL action
1428
1429     This action decrements the IP TTL.
1430     """
1431
1432     def __init__(self, type_=None, len_=None):
1433         super(OFPActionDecNwTtl, self).__init__()
1434
1435     @classmethod
1436     def parser(cls, buf, offset):
1437         (type_, len_) = struct.unpack_from(
1438             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1439         return cls()
1440
1441
1442 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_OUT,
1443                                 ofproto.OFP_ACTION_HEADER_SIZE)
1444 class OFPActionCopyTtlOut(OFPAction):
1445     """
1446     Copy TTL Out action
1447
1448     This action copies the TTL from the next-to-outermost header with TTL to
1449     the outermost header with TTL.
1450     """
1451
1452     def __init__(self, type_=None, len_=None):
1453         super(OFPActionCopyTtlOut, self).__init__()
1454
1455     @classmethod
1456     def parser(cls, buf, offset):
1457         (type_, len_) = struct.unpack_from(
1458             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1459         return cls()
1460
1461
1462 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_IN,
1463                                 ofproto.OFP_ACTION_HEADER_SIZE)
1464 class OFPActionCopyTtlIn(OFPAction):
1465     """
1466     Copy TTL In action
1467
1468     This action copies the TTL from the outermost header with TTL to the
1469     next-to-outermost header with TTL.
1470     """
1471
1472     def __init__(self, type_=None, len_=None):
1473         super(OFPActionCopyTtlIn, self).__init__()
1474
1475     @classmethod
1476     def parser(cls, buf, offset):
1477         (type_, len_) = struct.unpack_from(
1478             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1479         return cls()
1480
1481
1482 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_VLAN,
1483                                 ofproto.OFP_ACTION_PUSH_SIZE)
1484 class OFPActionPushVlan(OFPAction):
1485     """
1486     Push VLAN action
1487
1488     This action pushes a new VLAN tag to the packet.
1489
1490     ================ ======================================================
1491     Attribute        Description
1492     ================ ======================================================
1493     ethertype        Ether type.  The default is 802.1Q. (0x8100)
1494     ================ ======================================================
1495     """
1496
1497     def __init__(self, ethertype=ether.ETH_TYPE_8021Q, type_=None, len_=None):
1498         super(OFPActionPushVlan, self).__init__()
1499         self.ethertype = ethertype
1500
1501     @classmethod
1502     def parser(cls, buf, offset):
1503         (type_, len_, ethertype) = struct.unpack_from(
1504             ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
1505         return cls(ethertype)
1506
1507     def serialize(self, buf, offset):
1508         msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
1509                       self.type, self.len, self.ethertype)
1510
1511
1512 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_MPLS,
1513                                 ofproto.OFP_ACTION_PUSH_SIZE)
1514 class OFPActionPushMpls(OFPAction):
1515     """
1516     Push MPLS action
1517
1518     This action pushes a new MPLS header to the packet.
1519
1520     ================ ======================================================
1521     Attribute        Description
1522     ================ ======================================================
1523     ethertype        Ether type
1524     ================ ======================================================
1525     """
1526
1527     def __init__(self, ethertype=ether.ETH_TYPE_MPLS, type_=None, len_=None):
1528         super(OFPActionPushMpls, self).__init__()
1529         self.ethertype = ethertype
1530
1531     @classmethod
1532     def parser(cls, buf, offset):
1533         (type_, len_, ethertype) = struct.unpack_from(
1534             ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
1535         return cls(ethertype)
1536
1537     def serialize(self, buf, offset):
1538         msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
1539                       self.type, self.len, self.ethertype)
1540
1541
1542 @OFPAction.register_action_type(ofproto.OFPAT_POP_VLAN,
1543                                 ofproto.OFP_ACTION_HEADER_SIZE)
1544 class OFPActionPopVlan(OFPAction):
1545     """
1546     Pop VLAN action
1547
1548     This action pops the outermost VLAN tag from the packet.
1549     """
1550
1551     def __init__(self, type_=None, len_=None):
1552         super(OFPActionPopVlan, self).__init__()
1553
1554     @classmethod
1555     def parser(cls, buf, offset):
1556         (type_, len_) = struct.unpack_from(
1557             ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1558         return cls()
1559
1560
1561 @OFPAction.register_action_type(ofproto.OFPAT_POP_MPLS,
1562                                 ofproto.OFP_ACTION_POP_MPLS_SIZE)
1563 class OFPActionPopMpls(OFPAction):
1564     """
1565     Pop MPLS action
1566
1567     This action pops the MPLS header from the packet.
1568     """
1569
1570     def __init__(self, ethertype=ether.ETH_TYPE_IP, type_=None, len_=None):
1571         super(OFPActionPopMpls, self).__init__()
1572         self.ethertype = ethertype
1573
1574     @classmethod
1575     def parser(cls, buf, offset):
1576         (type_, len_, ethertype) = struct.unpack_from(
1577             ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset)
1578         return cls(ethertype)
1579
1580     def serialize(self, buf, offset):
1581         msg_pack_into(ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset,
1582                       self.type, self.len, self.ethertype)
1583
1584
1585 @OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
1586                                 ofproto.OFP_ACTION_SET_FIELD_SIZE)
1587 class OFPActionSetField(OFPAction):
1588     """
1589     Set field action
1590
1591     This action modifies a header field in the packet.
1592
1593     The set of keywords available for this is same as OFPMatch.
1594
1595     Example::
1596
1597         set_field = OFPActionSetField(eth_src="00:00:00:00:00:00")
1598     """
1599
1600     def __init__(self, field=None, **kwargs):
1601         # old api
1602         #   OFPActionSetField(field)
1603         # new api
1604         #   OFPActionSetField(eth_src="00:00:00:00:00")
1605         super(OFPActionSetField, self).__init__()
1606         if isinstance(field, OFPMatchField):
1607             # old api compat
1608             assert len(kwargs) == 0
1609             self.field = field
1610         else:
1611             # new api
1612             assert len(kwargs) == 1
1613             key = list(kwargs.keys())[0]
1614             value = kwargs[key]
1615             assert isinstance(key, (str, six.text_type))
1616             assert not isinstance(value, tuple)  # no mask
1617             self.key = key
1618             self.value = value
1619
1620     @classmethod
1621     def parser(cls, buf, offset):
1622         (type_, len_) = struct.unpack_from('!HH', buf, offset)
1623         (n, value, mask, _len) = ofproto.oxm_parse(buf, offset + 4)
1624         k, uv = ofproto.oxm_to_user(n, value, mask)
1625         action = cls(**{k: uv})
1626         action.len = len_
1627
1628         # old api compat
1629         action.field = OFPMatchField.parser(buf, offset + 4)
1630
1631         return action
1632
1633     def serialize(self, buf, offset):
1634         # old api compat
1635         if self._composed_with_old_api():
1636             return self.serialize_old(buf, offset)
1637
1638         n, value, mask = ofproto.oxm_from_user(self.key, self.value)
1639         len_ = ofproto.oxm_serialize(n, value, mask, buf, offset + 4)
1640         self.len = utils.round_up(4 + len_, 8)
1641         msg_pack_into('!HH', buf, offset, self.type, self.len)
1642         pad_len = self.len - (4 + len_)
1643         msg_pack_into("%dx" % pad_len, buf, offset + 4 + len_)
1644
1645     # XXX old api compat
1646     def serialize_old(self, buf, offset):
1647         len_ = ofproto.OFP_ACTION_SET_FIELD_SIZE + self.field.oxm_len()
1648         self.len = utils.round_up(len_, 8)
1649         pad_len = self.len - len_
1650
1651         msg_pack_into('!HH', buf, offset, self.type, self.len)
1652         self.field.serialize(buf, offset + 4)
1653         offset += len_
1654         msg_pack_into("%dx" % pad_len, buf, offset)
1655
1656     # XXX old api compat
1657     def _composed_with_old_api(self):
1658         return not hasattr(self, 'value')
1659
1660     def to_jsondict(self):
1661         return {
1662             self.__class__.__name__: {
1663                 'field': ofproto.oxm_to_jsondict(self.key, self.value),
1664                 "len": self.len,
1665                 "type": self.type
1666             }
1667         }
1668
1669     @classmethod
1670     def from_jsondict(cls, dict_):
1671         k, v = ofproto.oxm_from_jsondict(dict_['field'])
1672         o = OFPActionSetField(**{k: v})
1673
1674         # XXX old api compat
1675         # serialize and parse to fill old attributes
1676         buf = bytearray()
1677         o.serialize(buf, 0)
1678         return OFPActionSetField.parser(six.binary_type(buf), 0)
1679
1680     # XXX old api compat
1681     def __str__(self):
1682         # XXX old api compat
1683         if self._composed_with_old_api():
1684             # copy object first because serialize_old is destructive
1685             o2 = OFPActionSetField(self.field)
1686             # serialize and parse to fill new fields
1687             buf = bytearray()
1688             o2.serialize(buf, 0)
1689             o = OFPActionSetField.parser(six.binary_type(buf), 0)
1690         else:
1691             o = self
1692         return super(OFPActionSetField, o).__str__()
1693
1694     __repr__ = __str__
1695
1696     def stringify_attrs(self):
1697         yield (self.key, self.value)
1698
1699
1700 @OFPAction.register_action_type(
1701     ofproto.OFPAT_EXPERIMENTER,
1702     ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
1703 class OFPActionExperimenter(OFPAction):
1704     """
1705     Experimenter action
1706
1707     This action is an extensible action for the experimenter.
1708
1709     ================ ======================================================
1710     Attribute        Description
1711     ================ ======================================================
1712     experimenter     Experimenter ID
1713     ================ ======================================================
1714
1715     .. Note::
1716
1717         For the list of the supported Nicira experimenter actions,
1718         please refer to :ref:`ryu.ofproto.nx_actions <nx_actions_structures>`.
1719     """
1720
1721     def __init__(self, experimenter, type_=None, len_=None):
1722         super(OFPActionExperimenter, self).__init__()
1723         self.experimenter = experimenter
1724
1725     @classmethod
1726     def parser(cls, buf, offset):
1727         (type_, len_, experimenter) = struct.unpack_from(
1728             ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset)
1729         ex = cls(experimenter)
1730         ex.len = len_
1731         return ex
1732
1733     def serialize(self, buf, offset):
1734         msg_pack_into(ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR,
1735                       buf, offset, self.type, self.len, self.experimenter)
1736
1737
1738 class OFPBucket(StringifyMixin):
1739     def __init__(self, weight=0, watch_port=ofproto.OFPP_ANY,
1740                  watch_group=ofproto.OFPG_ANY, actions=None, len_=None):
1741         super(OFPBucket, self).__init__()
1742         self.weight = weight
1743         self.watch_port = watch_port
1744         self.watch_group = watch_group
1745         self.actions = actions
1746
1747     @classmethod
1748     def parser(cls, buf, offset):
1749         (len_, weigth, watch_port, watch_group) = struct.unpack_from(
1750             ofproto.OFP_BUCKET_PACK_STR, buf, offset)
1751
1752         length = ofproto.OFP_BUCKET_SIZE
1753         offset += ofproto.OFP_BUCKET_SIZE
1754         actions = []
1755         while length < len_:
1756             action = OFPAction.parser(buf, offset)
1757             actions.append(action)
1758             offset += action.len
1759             length += action.len
1760
1761         m = cls(weigth, watch_port, watch_group, actions)
1762         m.len = len_
1763         return m
1764
1765     def serialize(self, buf, offset):
1766         action_offset = offset + ofproto.OFP_BUCKET_SIZE
1767         action_len = 0
1768         for a in self.actions:
1769             a.serialize(buf, action_offset)
1770             action_offset += a.len
1771             action_len += a.len
1772
1773         self.len = utils.round_up(ofproto.OFP_BUCKET_SIZE + action_len, 8)
1774         msg_pack_into(ofproto.OFP_BUCKET_PACK_STR, buf, offset,
1775                       self.len, self.weight, self.watch_port,
1776                       self.watch_group)
1777
1778
1779 @_set_msg_type(ofproto.OFPT_GROUP_MOD)
1780 class OFPGroupMod(MsgBase):
1781     """
1782     Modify group entry message
1783
1784     The controller sends this message to modify the group table.
1785
1786     ================ ======================================================
1787     Attribute        Description
1788     ================ ======================================================
1789     command          One of the following values.
1790
1791                      | OFPGC_ADD
1792                      | OFPGC_MODIFY
1793                      | OFPGC_DELETE
1794     type             One of the following values.
1795
1796                      | OFPGT_ALL
1797                      | OFPGT_SELECT
1798                      | OFPGT_INDIRECT
1799                      | OFPGT_FF
1800     group_id         Group identifier
1801     buckets          list of ``OFPBucket``
1802     ================ ======================================================
1803
1804     ``type`` attribute corresponds to ``type_`` parameter of __init__.
1805
1806     Example::
1807
1808         def send_group_mod(self, datapath):
1809             ofp = datapath.ofproto
1810             ofp_parser = datapath.ofproto_parser
1811
1812             port = 1
1813             max_len = 2000
1814             actions = [ofp_parser.OFPActionOutput(port, max_len)]
1815
1816             weight = 100
1817             watch_port = 0
1818             watch_group = 0
1819             buckets = [ofp_parser.OFPBucket(weight, watch_port, watch_group,
1820                                             actions)]
1821
1822             group_id = 1
1823             req = ofp_parser.OFPGroupMod(datapath, ofp.OFPGC_ADD,
1824                                          ofp.OFPGT_SELECT, group_id, buckets)
1825             datapath.send_msg(req)
1826     """
1827
1828     def __init__(self, datapath, command=ofproto.OFPGC_ADD,
1829                  type_=ofproto.OFPGT_ALL, group_id=0, buckets=None):
1830         buckets = buckets if buckets else []
1831         super(OFPGroupMod, self).__init__(datapath)
1832         self.command = command
1833         self.type = type_
1834         self.group_id = group_id
1835         self.buckets = buckets
1836
1837     def _serialize_body(self):
1838         msg_pack_into(ofproto.OFP_GROUP_MOD_PACK_STR, self.buf,
1839                       ofproto.OFP_HEADER_SIZE,
1840                       self.command, self.type, self.group_id)
1841
1842         offset = ofproto.OFP_GROUP_MOD_SIZE
1843         for b in self.buckets:
1844             b.serialize(self.buf, offset)
1845             offset += b.len
1846
1847
1848 @_set_msg_type(ofproto.OFPT_PORT_MOD)
1849 class OFPPortMod(MsgBase):
1850     """
1851     Port modification message
1852
1853     The controller sneds this message to modify the behavior of the port.
1854
1855     ================ ======================================================
1856     Attribute        Description
1857     ================ ======================================================
1858     port_no          Port number to modify
1859     hw_addr          The hardware address that must be the same as hw_addr
1860                      of ``OFPPort`` of ``OFPSwitchFeatures``
1861     config           Bitmap of configuration flags.
1862
1863                      | OFPPC_PORT_DOWN
1864                      | OFPPC_NO_RECV
1865                      | OFPPC_NO_FWD
1866                      | OFPPC_NO_PACKET_IN
1867     mask             Bitmap of configuration flags above to be changed
1868     advertise        Bitmap of the following flags.
1869
1870                      | OFPPF_10MB_HD
1871                      | OFPPF_10MB_FD
1872                      | OFPPF_100MB_HD
1873                      | OFPPF_100MB_FD
1874                      | OFPPF_1GB_HD
1875                      | OFPPF_1GB_FD
1876                      | OFPPF_10GB_FD
1877                      | OFPPF_40GB_FD
1878                      | OFPPF_100GB_FD
1879                      | OFPPF_1TB_FD
1880                      | OFPPF_OTHER
1881                      | OFPPF_COPPER
1882                      | OFPPF_FIBER
1883                      | OFPPF_AUTONEG
1884                      | OFPPF_PAUSE
1885                      | OFPPF_PAUSE_ASYM
1886     ================ ======================================================
1887
1888     Example::
1889
1890         def send_port_mod(self, datapath):
1891             ofp = datapath.ofproto
1892             ofp_parser = datapath.ofproto_parser
1893
1894             port_no = 3
1895             hw_addr = 'fa:c8:e8:76:1d:7e'
1896             config = 0
1897             mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
1898                     ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
1899             advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
1900                          ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
1901                          ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
1902                          ofp.OFPPF_PAUSE_ASYM)
1903             req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
1904                                         mask, advertise)
1905             datapath.send_msg(req)
1906     """
1907
1908     _TYPE = {
1909         'ascii': [
1910             'hw_addr',
1911         ]
1912     }
1913
1914     def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
1915                  config=0, mask=0, advertise=0):
1916         super(OFPPortMod, self).__init__(datapath)
1917         self.port_no = port_no
1918         self.hw_addr = hw_addr
1919         self.config = config
1920         self.mask = mask
1921         self.advertise = advertise
1922
1923     def _serialize_body(self):
1924         msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR, self.buf,
1925                       ofproto.OFP_HEADER_SIZE,
1926                       self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
1927                       self.config,
1928                       self.mask, self.advertise)
1929
1930
1931 @_set_msg_type(ofproto.OFPT_TABLE_MOD)
1932 class OFPTableMod(MsgBase):
1933     """
1934     Flow table configuration message
1935
1936     The controller sends this message to configure table state.
1937
1938     ================ ======================================================
1939     Attribute        Description
1940     ================ ======================================================
1941     table_id         ID of the table (OFPTT_ALL indicates all tables)
1942     config           Bitmap of the following flags.
1943
1944                      | OFPTC_TABLE_MISS_CONTROLLER
1945                      | OFPTC_TABLE_MISS_CONTINUE
1946                      | OFPTC_TABLE_MISS_DROP
1947                      | OFPTC_TABLE_MISS_MASK
1948     ================ ======================================================
1949
1950     Example::
1951
1952         def send_table_mod(self, datapath):
1953             ofp = datapath.ofproto
1954             ofp_parser = datapath.ofproto_parser
1955
1956             req = ofp_parser.OFPTableMod(datapath, ofp.OFPTT_ALL,
1957                                          ofp.OFPTC_TABLE_MISS_DROP)
1958             datapath.send_msg(req)
1959     """
1960
1961     def __init__(self, datapath, table_id, config):
1962         super(OFPTableMod, self).__init__(datapath)
1963         self.table_id = table_id
1964         self.config = config
1965
1966     def _serialize_body(self):
1967         msg_pack_into(ofproto.OFP_TABLE_MOD_PACK_STR, self.buf,
1968                       ofproto.OFP_HEADER_SIZE,
1969                       self.table_id, self.config)
1970
1971
1972 class OFPStatsRequest(MsgBase):
1973     def __init__(self, datapath, type_, flags=0):
1974         super(OFPStatsRequest, self).__init__(datapath)
1975         self.type = type_
1976         self.flags = flags
1977
1978     def to_jsondict(self):
1979         # remove some redundant attributes
1980         d = super(OFPStatsRequest, self).to_jsondict()
1981         v = d[self.__class__.__name__]
1982         del v['type']  # implied by subclass
1983         return d
1984
1985     def _serialize_stats_body(self):
1986         pass
1987
1988     def _serialize_body(self):
1989         msg_pack_into(ofproto.OFP_STATS_REQUEST_PACK_STR,
1990                       self.buf, ofproto.OFP_HEADER_SIZE,
1991                       self.type, self.flags)
1992
1993         self._serialize_stats_body()
1994
1995
1996 @_register_parser
1997 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
1998 class OFPStatsReply(MsgBase):
1999     _STATS_TYPES = {}
2000
2001     @staticmethod
2002     def register_stats_reply_type(type_, body_single_struct=False):
2003         def _register_stats_reply_type(cls):
2004             OFPStatsReply._STATS_TYPES[type_] = cls
2005             cls.cls_body_single_struct = body_single_struct
2006             return cls
2007         return _register_stats_reply_type
2008
2009     def __init__(self, datapath, type_=None, flags=None, body=None):
2010         super(OFPStatsReply, self).__init__(datapath)
2011         self.type = type_
2012         self.flags = flags
2013         self.body = body
2014
2015     @classmethod
2016     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2017         msg = super(OFPStatsReply, cls).parser(datapath, version, msg_type,
2018                                                msg_len, xid, buf)
2019         msg.type, msg.flags = struct.unpack_from(
2020             ofproto.OFP_STATS_REPLY_PACK_STR, msg.buf,
2021             ofproto.OFP_HEADER_SIZE)
2022         stats_type_cls = cls._STATS_TYPES.get(msg.type)
2023
2024         offset = ofproto.OFP_STATS_REPLY_SIZE
2025         body = []
2026         while offset < msg_len:
2027             r = stats_type_cls.parser(msg.buf, offset)
2028             body.append(r)
2029             offset += r.length
2030
2031         if stats_type_cls.cls_body_single_struct:
2032             msg.body = body[0]
2033         else:
2034             msg.body = body
2035
2036         return msg
2037
2038
2039 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2040 class OFPDescStatsRequest(OFPStatsRequest):
2041     """
2042     Description statistics request message
2043
2044     The controller uses this message to query description of the switch.
2045
2046     ================ ======================================================
2047     Attribute        Description
2048     ================ ======================================================
2049     flags            Zero (none yet defined in the spec)
2050     ================ ======================================================
2051
2052     Example::
2053
2054         def send_desc_stats_request(self, datapath):
2055             ofp_parser = datapath.ofproto_parser
2056
2057             req = ofp_parser.OFPDescStatsRequest(datapath)
2058             datapath.send_msg(req)
2059     """
2060
2061     def __init__(self, datapath, flags=0):
2062         super(OFPDescStatsRequest, self).__init__(datapath,
2063                                                   ofproto.OFPST_DESC,
2064                                                   flags)
2065
2066
2067 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_DESC,
2068                                          body_single_struct=True)
2069 class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
2070         'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
2071     """
2072     Description statistics reply message
2073
2074     The switch responds with a stats reply that include this message to
2075     a description statistics request.
2076
2077     ================ ======================================================
2078     Attribute        Description
2079     ================ ======================================================
2080     mfr_desc         Manufacturer description
2081     hw_desc          Hardware description
2082     sw_desc          Software description
2083     serial_num       Serial number
2084     dp_desc          Human readable description of datapath
2085     ================ ======================================================
2086
2087     Example::
2088
2089         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2090         def stats_reply_handler(self, ev):
2091             msg = ev.msg
2092             ofp = msg.datapath.ofproto
2093             body = ev.msg.body
2094
2095             if msg.type == ofp.OFPST_DESC:
2096                 self.desc_stats_reply_handler(body)
2097
2098         def desc_stats_reply_handler(self, body):
2099             self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
2100                               'serial_num=%s dp_desc=%s',
2101                               body.mfr_desc, body.hw_desc, body.sw_desc,
2102                               body.serial_num, body.dp_desc)
2103     """
2104
2105     _TYPE = {
2106         'ascii': [
2107             'mfr_desc',
2108             'hw_desc',
2109             'sw_desc',
2110             'serial_num',
2111             'dp_desc',
2112         ]
2113     }
2114
2115     @classmethod
2116     def parser(cls, buf, offset):
2117         desc = struct.unpack_from(ofproto.OFP_DESC_STATS_PACK_STR,
2118                                   buf, offset)
2119         desc = list(desc)
2120         desc = [x.rstrip(b'\0') for x in desc]
2121         stats = cls(*desc)
2122         stats.length = ofproto.OFP_DESC_STATS_SIZE
2123         return stats
2124
2125
2126 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2127 class OFPFlowStatsRequest(OFPStatsRequest):
2128     """
2129     Individual flow statistics request message
2130
2131     The controller uses this message to query individual flow statistics.
2132
2133     ================ ======================================================
2134     Attribute        Description
2135     ================ ======================================================
2136     table_id         ID of table to read
2137     out_port         Require matching entries to include this as an output
2138                      port
2139     out_group        Require matching entries to include this as an output
2140                      group
2141     cookie           Require matching entries to contain this cookie value
2142     cookie_mask      Mask used to restrict the cookie bits that must match
2143     match            Instance of ``OFPMatch``
2144     flags            Zero (none yet defined in the spec)
2145     ================ ======================================================
2146
2147     Example::
2148
2149         def send_flow_stats_request(self, datapath):
2150             ofp = datapath.ofproto
2151             ofp_parser = datapath.ofproto_parser
2152
2153             cookie = cookie_mask = 0
2154             match = ofp_parser.OFPMatch(in_port=1)
2155             req = ofp_parser.OFPFlowStatsRequest(datapath,
2156                                                  ofp.OFPTT_ALL,
2157                                                  ofp.OFPP_ANY, ofp.OFPG_ANY,
2158                                                  cookie, cookie_mask, match)
2159             datapath.send_msg(req)
2160     """
2161
2162     def __init__(self, datapath, table_id=ofproto.OFPTT_ALL,
2163                  out_port=ofproto.OFPP_ANY,
2164                  out_group=ofproto.OFPG_ANY,
2165                  cookie=0, cookie_mask=0, match=None, flags=0):
2166         super(OFPFlowStatsRequest, self).__init__(datapath,
2167                                                   ofproto.OFPST_FLOW,
2168                                                   flags)
2169         self.table_id = table_id
2170         self.out_port = out_port
2171         self.out_group = out_group
2172         self.cookie = cookie
2173         self.cookie_mask = cookie_mask
2174         if match is None:
2175             match = OFPMatch()
2176         self.match = match
2177
2178     def _serialize_stats_body(self):
2179         msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_PACK_STR,
2180                       self.buf, ofproto.OFP_STATS_REQUEST_SIZE,
2181                       self.table_id, self.out_port, self.out_group,
2182                       self.cookie, self.cookie_mask)
2183
2184         offset = (ofproto.OFP_STATS_REQUEST_SIZE +
2185                   ofproto.OFP_FLOW_STATS_REQUEST_SIZE -
2186                   ofproto.OFP_MATCH_SIZE)
2187
2188         self.match.serialize(self.buf, offset)
2189
2190
2191 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_FLOW)
2192 class OFPFlowStats(StringifyMixin):
2193     """
2194     Individual flow statistics reply message
2195
2196     The switch responds with a stats reply that include this message to
2197     an individual flow statistics request.
2198
2199     ================ ======================================================
2200     Attribute        Description
2201     ================ ======================================================
2202     table_id         ID of table flow came from
2203     duration_sec     Time flow has been alive in seconds
2204     duration_nsec    Time flow has been alive in nanoseconds beyond
2205                      duration_sec
2206     priority         Priority of the entry
2207     idle_timeout     Number of seconds idle before expiration
2208     hard_timeout     Number of seconds before expiration
2209     cookie           Opaque controller-issued identifier
2210     packet_count     Number of packets in flow
2211     byte_count       Number of bytes in flow
2212     match            Instance of ``OFPMatch``
2213     instructions     list of ``OFPInstruction*`` instance
2214     ================ ======================================================
2215
2216     Example::
2217
2218         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2219         def stats_reply_handler(self, ev):
2220             msg = ev.msg
2221             ofp = msg.datapath.ofproto
2222             body = ev.msg.body
2223
2224             if msg.type == ofp.OFPST_FLOW:
2225                  self.flow_stats_reply_handler(body)
2226
2227         def flow_stats_reply_handler(self, body):
2228             flows = []
2229             for stat in body:
2230                 flows.append('table_id=%s '
2231                              'duration_sec=%d duration_nsec=%d '
2232                              'priority=%d '
2233                              'idle_timeout=%d hard_timeout=%d '
2234                              'cookie=%d packet_count=%d byte_count=%d '
2235                              'match=%s instructions=%s' %
2236                              (stat.table_id,
2237                               stat.duration_sec, stat.duration_nsec,
2238                               stat.priority,
2239                               stat.idle_timeout, stat.hard_timeout,
2240                               stat.cookie, stat.packet_count, stat.byte_count,
2241                               stat.match, stat.instructions))
2242             self.logger.debug('FlowStats: %s', flows)
2243     """
2244
2245     def __init__(self, table_id, duration_sec, duration_nsec,
2246                  priority, idle_timeout, hard_timeout, cookie, packet_count,
2247                  byte_count, match, instructions=None, length=None):
2248         super(OFPFlowStats, self).__init__()
2249         self.table_id = table_id
2250         self.duration_sec = duration_sec
2251         self.duration_nsec = duration_nsec
2252         self.priority = priority
2253         self.idle_timeout = idle_timeout
2254         self.hard_timeout = hard_timeout
2255         self.cookie = cookie
2256         self.packet_count = packet_count
2257         self.byte_count = byte_count
2258         self.match = match
2259         self.instructions = instructions
2260         self.length = length
2261
2262     @classmethod
2263     def parser(cls, buf, offset):
2264         (length, table_id, duration_sec,
2265          duration_nsec, priority,
2266          idle_timeout, hard_timeout,
2267          cookie, packet_count, byte_count) = struct.unpack_from(
2268             ofproto.OFP_FLOW_STATS_PACK_STR,
2269             buf, offset)
2270         offset += (ofproto.OFP_FLOW_STATS_SIZE -
2271                    ofproto.OFP_MATCH_SIZE)
2272         match = OFPMatch.parser(buf, offset)
2273
2274         match_length = utils.round_up(match.length, 8)
2275         inst_length = (length - (ofproto.OFP_FLOW_STATS_SIZE -
2276                                  ofproto.OFP_MATCH_SIZE + match_length))
2277         offset += match_length
2278         instructions = []
2279         while inst_length > 0:
2280             inst = OFPInstruction.parser(buf, offset)
2281             instructions.append(inst)
2282             offset += inst.len
2283             inst_length -= inst.len
2284
2285         o = cls(table_id, duration_sec, duration_nsec, priority,
2286                 idle_timeout, hard_timeout, cookie, packet_count,
2287                 byte_count, match, instructions)
2288         o.length = length
2289         return o
2290
2291
2292 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2293 class OFPAggregateStatsRequest(OFPStatsRequest):
2294     """
2295     Aggregate flow statistics request message
2296
2297     The controller uses this message to query aggregate flow statictics.
2298
2299     ================ ======================================================
2300     Attribute        Description
2301     ================ ======================================================
2302     table_id         ID of table to read
2303     out_port         Require matching entries to include this as an output
2304                      port
2305     out_group        Require matching entries to include this as an output
2306                      group
2307     cookie           Require matching entries to contain this cookie value
2308     cookie_mask      Mask used to restrict the cookie bits that must match
2309     match            Instance of ``OFPMatch``
2310     flags            Zero (none yet defined in the spec)
2311     ================ ======================================================
2312
2313     Example::
2314
2315         def send_aggregate_stats_request(self, datapath):
2316             ofp = datapath.ofproto
2317             ofp_parser = datapath.ofproto_parser
2318
2319             cookie = cookie_mask = 0
2320             match = ofp_parser.OFPMatch(in_port=1)
2321             req = ofp_parser.OFPAggregateStatsRequest(datapath, 0,
2322                                                       ofp.OFPTT_ALL,
2323                                                       ofp.OFPP_ANY,
2324                                                       ofp.OFPG_ANY,
2325                                                       cookie, cookie_mask,
2326                                                       match)
2327             datapath.send_msg(req)
2328     """
2329
2330     def __init__(self, datapath, table_id=ofproto.OFPTT_ALL,
2331                  out_port=ofproto.OFPP_ANY,
2332                  out_group=ofproto.OFPP_ANY,
2333                  cookie=0, cookie_mask=0, match=None, flags=0):
2334         super(OFPAggregateStatsRequest, self).__init__(
2335             datapath,
2336             ofproto.OFPST_AGGREGATE,
2337             flags)
2338         self.table_id = table_id
2339         self.out_port = out_port
2340         self.out_group = out_group
2341         self.cookie = cookie
2342         self.cookie_mask = cookie_mask
2343         if match is None:
2344             match = OFPMatch()
2345         self.match = match
2346
2347     def _serialize_stats_body(self):
2348         msg_pack_into(ofproto.OFP_AGGREGATE_STATS_REQUEST_PACK_STR,
2349                       self.buf,
2350                       ofproto.OFP_STATS_REQUEST_SIZE,
2351                       self.table_id, self.out_port, self.out_group,
2352                       self.cookie, self.cookie_mask)
2353
2354         offset = (ofproto.OFP_STATS_REQUEST_SIZE +
2355                   ofproto.OFP_AGGREGATE_STATS_REQUEST_SIZE -
2356                   ofproto.OFP_MATCH_SIZE)
2357
2358         self.match.serialize(self.buf, offset)
2359
2360
2361 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_AGGREGATE,
2362                                          body_single_struct=True)
2363 class OFPAggregateStatsReply(ofproto_parser.namedtuple('OFPAggregateStats', (
2364         'packet_count', 'byte_count', 'flow_count'))):
2365     """
2366     Aggregate flow statistics reply message
2367
2368     The switch responds with a stats reply that include this message to
2369     an aggregate flow statistics request.
2370
2371     ================ ======================================================
2372     Attribute        Description
2373     ================ ======================================================
2374     packet_count     Number of packets in flows
2375     byte_count       Number of bytes in flows
2376     flow_count       Number of flows
2377     ================ ======================================================
2378
2379     Example::
2380
2381         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2382         def stats_reply_handler(self, ev):
2383             msg = ev.msg
2384             ofp = msg.datapath.ofproto
2385             body = ev.msg.body
2386
2387             if msg.type == ofp.OFPST_AGGREGATE:
2388                 self.aggregate_stats_reply_handler(body)
2389
2390         def aggregate_stats_reply_handler(self, body):
2391             self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
2392                               'flow_count=%d',
2393                               body.packet_count, body.byte_count,
2394                               body.flow_count)
2395     """
2396
2397     @classmethod
2398     def parser(cls, buf, offset):
2399         desc = struct.unpack_from(
2400             ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR,
2401             buf, offset)
2402         stats = cls(*desc)
2403         stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
2404         return stats
2405
2406
2407 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2408 class OFPTableStatsRequest(OFPStatsRequest):
2409     """
2410     Table statistics request message
2411
2412     The controller uses this message to query flow table statictics.
2413
2414     ================ ======================================================
2415     Attribute        Description
2416     ================ ======================================================
2417     flags            Zero (none yet defined in the spec)
2418     ================ ======================================================
2419
2420     Example::
2421
2422         def send_table_stats_request(self, datapath):
2423             ofp_parser = datapath.ofproto_parser
2424
2425             req = ofp_parser.OFPTableStatsRequest(datapath)
2426             datapath.send_msg(req)
2427     """
2428
2429     def __init__(self, datapath, flags=0):
2430         super(OFPTableStatsRequest, self).__init__(datapath,
2431                                                    ofproto.OFPST_TABLE,
2432                                                    flags)
2433
2434
2435 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_TABLE)
2436 class OFPTableStats(
2437     ofproto_parser.namedtuple('OFPTableStats',
2438                               ('table_id', 'name', 'match', 'wildcards',
2439                                'write_actions', 'apply_actions',
2440                                'write_setfields', 'apply_setfields',
2441                                'metadata_match', 'metadata_write',
2442                                'instructions', 'config',
2443                                'max_entries', 'active_count',
2444                                'lookup_count', 'matched_count'))):
2445     """
2446     Table statistics reply message
2447
2448     The switch responds with a stats reply that include this message to
2449     a table statistics request.
2450
2451     ================ ======================================================
2452     Attribute        Description
2453     ================ ======================================================
2454     table_id         ID of table
2455     name             table name
2456     match            Bitmap of (1 << OFPXMT_*) that indicate the fields
2457                      the table can match on
2458     wildcards        Bitmap of (1 << OFPXMT_*) wildcards that are supported
2459                      by the table
2460     write_actions    Bitmap of OFPAT_* that are supported by the table with
2461                      OFPIT_WRITE_ACTIONS
2462     apply_actions    Bitmap of OFPAT_* that are supported by the table with
2463                      OFPIT_APPLY_ACTIONS
2464     write_setfields  Bitmap of (1 << OFPXMT_*) header fields that can be set
2465                      with OFPIT_WRITE_ACTIONS
2466     apply_setfields  Bitmap of (1 << OFPXMT_*) header fields that can be set
2467                      with OFPIT_APPLY_ACTIONS
2468     metadata_match   Bits of metadata table can match
2469     metadata_write   Bits of metadata table can write
2470     instructions     Bitmap of OFPIT_* values supported
2471     config           Bitmap of OFPTC_* values
2472     max_entries      Max number of entries supported
2473     active_count     Number of active entries
2474     lookup_count     Number of packets looked up in table
2475     matched_count    Number of packets that hit table
2476     ================ ======================================================
2477
2478     Example::
2479
2480         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2481         def stats_reply_handler(self, ev):
2482             msg = ev.msg
2483             ofp = msg.datapath.ofproto
2484             body = ev.msg.body
2485
2486             if msg.type == ofp.OFPST_TABLE:
2487                 self.table_stats_reply_handler(body)
2488
2489         def table_stats_reply_handler(self, body):
2490             tables = []
2491             for stat in body:
2492                 tables.append('table_id=%d active_count=%d lookup_count=%d '
2493                               ' matched_count=%d' %
2494                               (stat.table_id, stat.active_count,
2495                                stat.lookup_count, stat.matched_count))
2496             self.logger.debug('TableStats: %s', tables)
2497     """
2498
2499     _TYPE = {
2500         'utf-8': [
2501             # OF spec is unclear about the encoding of name.
2502             # we assumes UTF-8.
2503             'name',
2504         ]
2505     }
2506
2507     @classmethod
2508     def parser(cls, buf, offset):
2509         table = struct.unpack_from(
2510             ofproto.OFP_TABLE_STATS_PACK_STR,
2511             buf, offset)
2512         table = list(table)
2513         i = cls._fields.index('name')
2514         table[i] = table[i].rstrip(b'\0')
2515         stats = cls(*table)
2516         stats.length = ofproto.OFP_TABLE_STATS_SIZE
2517         return stats
2518
2519
2520 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2521 class OFPPortStatsRequest(OFPStatsRequest):
2522     """
2523     Port statistics request message
2524
2525     The controller uses this message to query information about ports
2526     statistics.
2527
2528     ================ ======================================================
2529     Attribute        Description
2530     ================ ======================================================
2531     port_no          Port number to read (OFPP_ANY to all ports)
2532     flags            Zero (none yet defined in the spec)
2533     ================ ======================================================
2534
2535     Example::
2536
2537         def send_port_stats_request(self, datapath):
2538             ofp = datapath.ofproto
2539             ofp_parser = datapath.ofproto_parser
2540
2541             req = ofp_parser.OFPPortStatsRequest(datapath, ofp.OFPP_ANY)
2542             datapath.send_msg(req)
2543     """
2544
2545     def __init__(self, datapath, port_no=ofproto.OFPP_ANY, flags=0):
2546         super(OFPPortStatsRequest, self).__init__(datapath,
2547                                                   ofproto.OFPST_PORT,
2548                                                   flags)
2549         self.port_no = port_no
2550
2551     def _serialize_stats_body(self):
2552         msg_pack_into(ofproto.OFP_PORT_STATS_REQUEST_PACK_STR,
2553                       self.buf, ofproto.OFP_STATS_REQUEST_SIZE,
2554                       self.port_no)
2555
2556
2557 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_PORT)
2558 class OFPPortStats(
2559     ofproto_parser.namedtuple('OFPPortStats',
2560                               ('port_no', 'rx_packets', 'tx_packets',
2561                                'rx_bytes', 'tx_bytes',
2562                                'rx_dropped', 'tx_dropped',
2563                                'rx_errors', 'tx_errors',
2564                                'rx_frame_err', 'rx_over_err',
2565                                'rx_crc_err', 'collisions'))):
2566     """
2567     Port statistics reply message
2568
2569     The switch responds with a stats reply that include this message to
2570     a port statistics request.
2571
2572     ================ ======================================================
2573     Attribute        Description
2574     ================ ======================================================
2575     port_no          Port number
2576     rx_packets       Number of received packets
2577     tx_packets       Number of transmitted packets
2578     rx_bytes         Number of received bytes
2579     tx_bytes         Number of transmitted bytes
2580     rx_dropped       Number of packets dropped by RX
2581     tx_dropped       Number of packets dropped by TX
2582     rx_errors        Number of receive errors
2583     tx_errors        Number of transmit errors
2584     rx_frame_err     Number of frame alignment errors
2585     rx_over_err      Number of packet with RX overrun
2586     rx_crc_err       Number of CRC errors
2587     collisions       Number of collisions
2588     ================ ======================================================
2589
2590     Example::
2591
2592         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2593         def stats_reply_handler(self, ev):
2594             msg = ev.msg
2595             ofp = msg.datapath.ofproto
2596             body = ev.msg.body
2597
2598             if msg.type == ofp.OFPST_PORT:
2599                 self.port_stats_reply_handler(body)
2600
2601         def port_stats_reply_handler(self, body):
2602             ports = []
2603             for stat in body:
2604                 ports.append('port_no=%d '
2605                              'rx_packets=%d tx_packets=%d '
2606                              'rx_bytes=%d tx_bytes=%d '
2607                              'rx_dropped=%d tx_dropped=%d '
2608                              'rx_errors=%d tx_errors=%d '
2609                              'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
2610                              'collisions=%d' %
2611                              (stat.port_no,
2612                               stat.rx_packets, stat.tx_packets,
2613                               stat.rx_bytes, stat.tx_bytes,
2614                               stat.rx_dropped, stat.tx_dropped,
2615                               stat.rx_errors, stat.tx_errors,
2616                               stat.rx_frame_err, stat.rx_over_err,
2617                               stat.rx_crc_err, stat.collisions))
2618             self.logger.debug('PortStats: %s', ports)
2619     """
2620     @classmethod
2621     def parser(cls, buf, offset):
2622         port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR,
2623                                   buf, offset)
2624         stats = cls(*port)
2625         stats.length = ofproto.OFP_PORT_STATS_SIZE
2626         return stats
2627
2628
2629 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2630 class OFPQueueStatsRequest(OFPStatsRequest):
2631     """
2632     Queue statistics request message
2633
2634     The controller uses this message to query queue statictics.
2635
2636     ================ ======================================================
2637     Attribute        Description
2638     ================ ======================================================
2639     port_no          Port number to read
2640     queue_id         ID of queue to read
2641     flags            Zero (none yet defined in the spec)
2642     ================ ======================================================
2643
2644     Example::
2645
2646         def send_queue_stats_request(self, datapath):
2647             ofp = datapath.ofproto
2648             ofp_parser = datapath.ofproto_parser
2649
2650             req = ofp_parser.OFPQueueStatsRequest(datapath, ofp.OFPP_ANY,
2651                                                   ofp.OFPQ_ALL)
2652             datapath.send_msg(req)
2653     """
2654
2655     def __init__(self, datapath, port_no=ofproto.OFPP_ANY,
2656                  queue_id=ofproto.OFPQ_ALL, flags=0):
2657         super(OFPQueueStatsRequest, self).__init__(datapath,
2658                                                    ofproto.OFPST_QUEUE,
2659                                                    flags)
2660         self.port_no = port_no
2661         self.queue_id = queue_id
2662
2663     def _serialize_stats_body(self):
2664         msg_pack_into(ofproto.OFP_QUEUE_STATS_REQUEST_PACK_STR,
2665                       self.buf, ofproto.OFP_STATS_REQUEST_SIZE,
2666                       self.port_no, self.queue_id)
2667
2668
2669 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_QUEUE)
2670 class OFPQueueStats(
2671     ofproto_parser.namedtuple('OFPQueueStats',
2672                               ('port_no', 'queue_id', 'tx_bytes',
2673                                'tx_packets', 'tx_errors'))):
2674     """
2675     Queue statistics reply message
2676
2677     The switch responds with a stats reply that include this message to
2678     an aggregate flow statistics request.
2679
2680     ================ ======================================================
2681     Attribute        Description
2682     ================ ======================================================
2683     port_no          Port number
2684     queue_id         ID of queue
2685     tx_bytes         Number of transmitted bytes
2686     tx_packets       Number of transmitted packets
2687     tx_errors        Number of packets dropped due to overrun
2688     ================ ======================================================
2689
2690     Example::
2691
2692         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2693         def stats_reply_handler(self, ev):
2694             msg = ev.msg
2695             ofp = msg.datapath.ofproto
2696             body = ev.msg.body
2697
2698             if msg.type == ofp.OFPST_QUEUE:
2699                 self.queue_stats_reply_handler(body)
2700
2701         def queue_stats_reply_handler(self, body):
2702             queues = []
2703             for stat in body:
2704                 queues.append('port_no=%d queue_id=%d '
2705                               'tx_bytes=%d tx_packets=%d tx_errors=%d ' %
2706                               (stat.port_no, stat.queue_id,
2707                                stat.tx_bytes, stat.tx_packets, stat.tx_errors))
2708             self.logger.debug('QueueStats: %s', queues)
2709     """
2710     @classmethod
2711     def parser(cls, buf, offset):
2712         queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR,
2713                                    buf, offset)
2714         stats = cls(*queue)
2715         stats.length = ofproto.OFP_QUEUE_STATS_SIZE
2716         return stats
2717
2718
2719 class OFPBucketCounter(StringifyMixin):
2720     def __init__(self, packet_count, byte_count):
2721         super(OFPBucketCounter, self).__init__()
2722         self.packet_count = packet_count
2723         self.byte_count = byte_count
2724
2725     @classmethod
2726     def parser(cls, buf, offset):
2727         packet, byte = struct.unpack_from(
2728             ofproto.OFP_BUCKET_COUNTER_PACK_STR,
2729             buf, offset)
2730         return cls(packet, byte)
2731
2732
2733 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2734 class OFPGroupStatsRequest(OFPStatsRequest):
2735     """
2736     Group statistics request message
2737
2738     The controller uses this message to query statistics of one or more
2739     groups.
2740
2741     ================ ======================================================
2742     Attribute        Description
2743     ================ ======================================================
2744     group_id         ID of group to read (OFPG_ALL to all groups)
2745     flags            Zero (none yet defined in the spec)
2746     ================ ======================================================
2747
2748     Example::
2749
2750         def send_group_stats_request(self, datapath):
2751             ofp = datapath.ofproto
2752             ofp_parser = datapath.ofproto_parser
2753
2754             req = ofp_parser.OFPGroupStatsRequest(datapath, ofp.OFPG_ALL)
2755             datapath.send_msg(req)
2756     """
2757
2758     def __init__(self, datapath, group_id=ofproto.OFPG_ALL, flags=0):
2759         super(OFPGroupStatsRequest, self).__init__(datapath,
2760                                                    ofproto.OFPST_GROUP,
2761                                                    flags)
2762         self.group_id = group_id
2763
2764     def _serialize_stats_body(self):
2765         msg_pack_into(ofproto.OFP_GROUP_STATS_REQUEST_PACK_STR,
2766                       self.buf, ofproto.OFP_STATS_REQUEST_SIZE,
2767                       self.group_id)
2768
2769
2770 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP)
2771 class OFPGroupStats(StringifyMixin):
2772     """
2773     Group statistics reply message
2774
2775     The switch responds with a stats reply that include this message to
2776     a group statistics request.
2777
2778     ================ ======================================================
2779     Attribute        Description
2780     ================ ======================================================
2781     group_id         Group identifier
2782     ref_count        Number of flows or groups that directly forward to
2783                      this group
2784     packet_count     Number of packets processed by group
2785     byte_count       Number of bytes processed by group
2786     bucket_counters  List of ``OFPBucketCounter`` instance
2787     ================ ======================================================
2788
2789     Example::
2790
2791         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2792         def stats_reply_handler(self, ev):
2793             msg = ev.msg
2794             ofp = msg.datapath.ofproto
2795             body = ev.msg.body
2796
2797             if msg.type == ofp.OFPST_GROUP:
2798                 self.group_stats_reply_handler(body)
2799
2800         def group_stats_reply_handler(self, body):
2801             groups = []
2802             for stat in body:
2803                 groups.append('group_id=%d ref_count=%d packet_count=%d '
2804                               'byte_count=%d bucket_counters=%s' %
2805                               (stat.group_id,
2806                                stat.ref_count, stat.packet_count,
2807                                stat.byte_count, stat.bucket_counters))
2808             self.logger.debug('GroupStats: %s', groups)
2809     """
2810
2811     def __init__(self, group_id, ref_count, packet_count,
2812                  byte_count, bucket_counters, length=None):
2813         super(OFPGroupStats, self).__init__()
2814         self.group_id = group_id
2815         self.ref_count = ref_count
2816         self.packet_count = packet_count
2817         self.byte_count = byte_count
2818         self.bucket_counters = bucket_counters
2819         self.length = length
2820
2821     @classmethod
2822     def parser(cls, buf, offset):
2823         (length, group_id, ref_count, packet_count,
2824          byte_count) = struct.unpack_from(
2825             ofproto.OFP_GROUP_STATS_PACK_STR,
2826             buf, offset)
2827
2828         bucket_len = length - ofproto.OFP_GROUP_STATS_SIZE
2829         offset += ofproto.OFP_GROUP_STATS_SIZE
2830         bucket_counters = []
2831         while bucket_len > 0:
2832             bucket_counters.append(OFPBucketCounter.parser(buf, offset))
2833             offset += ofproto.OFP_BUCKET_COUNTER_SIZE
2834             bucket_len -= ofproto.OFP_BUCKET_COUNTER_SIZE
2835
2836         o = cls(group_id, ref_count, packet_count,
2837                 byte_count, bucket_counters)
2838         o.length = length
2839         return o
2840
2841
2842 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2843 class OFPGroupDescStatsRequest(OFPStatsRequest):
2844     """
2845     Group description request message
2846
2847     The controller uses this message to list the set of groups on a switch.
2848
2849     ================ ======================================================
2850     Attribute        Description
2851     ================ ======================================================
2852     flags            Zero (none yet defined in the spec)
2853     ================ ======================================================
2854
2855     Example::
2856
2857         def send_group_desc_stats_request(self, datapath):
2858             ofp_parser = datapath.ofproto_parser
2859
2860             req = ofp_parser.OFPGroupDescStatsRequest(datapath)
2861             datapath.send_msg(req)
2862     """
2863
2864     def __init__(self, datapath, flags=0):
2865         super(OFPGroupDescStatsRequest, self).__init__(
2866             datapath,
2867             ofproto.OFPST_GROUP_DESC,
2868             flags)
2869
2870
2871 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP_DESC)
2872 class OFPGroupDescStats(StringifyMixin):
2873     """
2874     Group description reply message
2875
2876     The switch responds with a stats reply that include this message to
2877     a group description request.
2878
2879     ================ ======================================================
2880     Attribute        Description
2881     ================ ======================================================
2882     type             One of OFPGT_*
2883     group_id         Group identifier
2884     buckets          List of ``OFPBucket`` instance
2885     ================ ======================================================
2886
2887     ``type`` attribute corresponds to ``type_`` parameter of __init__.
2888
2889     Example::
2890
2891         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2892         def stats_reply_handler(self, ev):
2893             msg = ev.msg
2894             ofp = msg.datapath.ofproto
2895             body = ev.msg.body
2896
2897             if msg.type == ofp.OFPST_GROUP_DESC:
2898                 self.group_desc_stats_reply_handler(body)
2899
2900         def group_desc_stats_reply_handler(self, body):
2901             descs = []
2902             for stat in body:
2903                 descs.append('type=%d group_id=%d buckets=%s' %
2904                              (stat.type, stat.group_id, stat.buckets))
2905             self.logger.debug('GroupDescStats: %s', descs)
2906     """
2907
2908     def __init__(self, type_, group_id, buckets, length=None):
2909         self.type = type_
2910         self.group_id = group_id
2911         self.buckets = buckets
2912
2913     @classmethod
2914     def parser(cls, buf, offset):
2915         (length, type_, group_id) = struct.unpack_from(
2916             ofproto.OFP_GROUP_DESC_STATS_PACK_STR,
2917             buf, offset)
2918
2919         bucket_len = length - ofproto.OFP_GROUP_DESC_STATS_SIZE
2920         offset += ofproto.OFP_GROUP_DESC_STATS_SIZE
2921         buckets = []
2922         while bucket_len > 0:
2923             bucket = OFPBucket.parser(buf, offset)
2924             buckets.append(bucket)
2925             offset += bucket.len
2926             bucket_len -= bucket.len
2927
2928         o = cls(type_, group_id, buckets)
2929         o.length = length
2930         return o
2931
2932
2933 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2934 class OFPGroupFeaturesStatsRequest(OFPStatsRequest):
2935     """
2936     Group features request message
2937
2938     The controller uses this message to list the capabilities of groups on
2939     a switch.
2940
2941     ================ ======================================================
2942     Attribute        Description
2943     ================ ======================================================
2944     flags            Zero (none yet defined in the spec)
2945     ================ ======================================================
2946
2947     Example::
2948
2949         def send_group_features_stats_request(self, datapath):
2950             ofp_parser = datapath.ofproto_parser
2951
2952             req = ofp_parser.OFPGroupFeaturesStatsRequest(datapath)
2953             datapath.send_msg(req)
2954     """
2955
2956     def __init__(self, datapath, flags=0):
2957         super(OFPGroupFeaturesStatsRequest, self).__init__(
2958             datapath,
2959             ofproto.OFPST_GROUP_FEATURES,
2960             flags)
2961
2962
2963 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP_FEATURES,
2964                                          body_single_struct=True)
2965 class OFPGroupFeaturesStats(StringifyMixin):
2966     """
2967     Group features reply message
2968
2969     The switch responds with a stats reply that include this message to
2970     a group features request.
2971
2972     ================ ======================================================
2973     Attribute        Description
2974     ================ ======================================================
2975     types            Bitmap of OFPGT_* values supported
2976     capabilities     Bitmap of OFPGFC_* capability supported
2977     max_groups       Maximum number of groups for each type
2978     actions          Bitmaps of OFPAT_* that are supported
2979     ================ ======================================================
2980
2981     Example::
2982
2983         @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2984         def stats_reply_handler(self, ev):
2985             msg = ev.msg
2986             ofp = msg.datapath.ofproto
2987             body = ev.msg.body
2988
2989             if msg.type == ofp.OFPST_GROUP_FEATURES:
2990                 self.group_features_stats_reply_handler(body)
2991
2992         def group_features_stats_reply_handler(self, body):
2993             self.logger.debug('GroupFeaturesStats: types=%d '
2994                               'capabilities=0x%08x max_groups=%s '
2995                               'actions=%s',
2996                               body.types, body.capabilities, body.max_groups,
2997                               body.actions)
2998     """
2999
3000     def __init__(self, types, capabilities, max_groups, actions, length=None):
3001         self.types = types
3002         self.capabilities = capabilities
3003         self.max_groups = max_groups
3004         self.actions = actions
3005
3006     @classmethod
3007     def parser(cls, buf, offset):
3008         stats = struct.unpack_from(
3009             ofproto.OFP_GROUP_FEATURES_STATS_PACK_STR, buf, offset)
3010         types = stats[0]
3011         capabilities = stats[1]
3012         max_groups = list(stats[2:6])
3013         actions = list(stats[6:10])
3014
3015         o = cls(types, capabilities, max_groups, actions)
3016         o.length = ofproto.OFP_GROUP_FEATURES_STATS_SIZE
3017         return o
3018
3019
3020 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST)
3021 class OFPQueueGetConfigRequest(MsgBase):
3022     """
3023     Queue configuration request message
3024
3025     ================ ======================================================
3026     Attribute        Description
3027     ================ ======================================================
3028     port             Port to be queried (OFPP_ANY to all configured queues)
3029     ================ ======================================================
3030
3031     Example::
3032
3033         def send_queue_get_config_request(self, datapath):
3034             ofp = datapath.ofproto
3035             ofp_parser = datapath.ofproto_parser
3036
3037             req = ofp_parser.OFPQueueGetConfigRequest(datapath, ofp.OFPP_ANY)
3038             datapath.send_msg(req)
3039     """
3040
3041     def __init__(self, datapath, port):
3042         super(OFPQueueGetConfigRequest, self).__init__(datapath)
3043         self.port = port
3044
3045     def _serialize_body(self):
3046         msg_pack_into(ofproto.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR,
3047                       self.buf, ofproto.OFP_HEADER_SIZE, self.port)
3048
3049
3050 class OFPQueuePropHeader(StringifyMixin):
3051     def __init__(self, property_, len_=None):
3052         self.property = property_
3053         self.len = len_
3054
3055     def serialize(self, buf, offset):
3056         msg_pack_into(ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
3057                       buf, offset, self.property, self.len)
3058
3059
3060 class OFPQueueProp(OFPQueuePropHeader):
3061     _QUEUE_PROP_PROPERTIES = {}
3062
3063     @staticmethod
3064     def register_property(property_, len_):
3065         def _register_property(cls):
3066             cls.cls_property = property_
3067             cls.cls_len = len_
3068             OFPQueueProp._QUEUE_PROP_PROPERTIES[cls.cls_property] = cls
3069             return cls
3070         return _register_property
3071
3072     def __init__(self):
3073         cls = self.__class__
3074         super(OFPQueueProp, self).__init__(cls.cls_property,
3075                                            cls.cls_len)
3076
3077     @classmethod
3078     def parser(cls, buf, offset):
3079         (property_, len_) = struct.unpack_from(
3080             ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
3081             buf, offset)
3082         cls_ = cls._QUEUE_PROP_PROPERTIES.get(property_)
3083         offset += ofproto.OFP_QUEUE_PROP_HEADER_SIZE
3084         return cls_.parser(buf, offset)
3085
3086
3087 class OFPPacketQueue(StringifyMixin):
3088     def __init__(self, queue_id, port, properties, len_=None):
3089         super(OFPPacketQueue, self).__init__()
3090         self.queue_id = queue_id
3091         self.port = port
3092         self.len = len_
3093         self.properties = properties
3094
3095     @classmethod
3096     def parser(cls, buf, offset):
3097         (queue_id, port, len_) = struct.unpack_from(
3098             ofproto.OFP_PACKET_QUEUE_PACK_STR, buf, offset)
3099         length = ofproto.OFP_PACKET_QUEUE_SIZE
3100         offset += ofproto.OFP_PACKET_QUEUE_SIZE
3101         properties = []
3102         while length < len_:
3103             queue_prop = OFPQueueProp.parser(buf, offset)
3104             properties.append(queue_prop)
3105             offset += queue_prop.len
3106             length += queue_prop.len
3107         o = cls(queue_id, port, properties)
3108         o.len = len_
3109         return o
3110
3111
3112 @OFPQueueProp.register_property(ofproto.OFPQT_MIN_RATE,
3113                                 ofproto.OFP_QUEUE_PROP_MIN_RATE_SIZE)
3114 class OFPQueuePropMinRate(OFPQueueProp):
3115     def __init__(self, rate, property_=None, len_=None):
3116         super(OFPQueuePropMinRate, self).__init__()
3117         self.rate = rate
3118
3119     @classmethod
3120     def parser(cls, buf, offset):
3121         (rate,) = struct.unpack_from(
3122             ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, buf, offset)
3123         return cls(rate)
3124
3125
3126 @OFPQueueProp.register_property(ofproto.OFPQT_MAX_RATE,
3127                                 ofproto.OFP_QUEUE_PROP_MAX_RATE_SIZE)
3128 class OFPQueuePropMaxRate(OFPQueueProp):
3129     def __init__(self, rate, property_=None, len_=None):
3130         super(OFPQueuePropMaxRate, self).__init__()
3131         self.rate = rate
3132
3133     @classmethod
3134     def parser(cls, buf, offset):
3135         (rate,) = struct.unpack_from(
3136             ofproto.OFP_QUEUE_PROP_MAX_RATE_PACK_STR, buf, offset)
3137         return cls(rate)
3138
3139
3140 @_register_parser
3141 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY)
3142 class OFPQueueGetConfigReply(MsgBase):
3143     """
3144     Queue configuration reply message
3145
3146     The switch responds with this message to a queue configuration request.
3147
3148     ================ ======================================================
3149     Attribute        Description
3150     ================ ======================================================
3151     port             Port which was queried
3152     queues           list of ``OFPPacketQueue`` instance
3153     ================ ======================================================
3154
3155     Example::
3156
3157         @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
3158         def queue_get_config_reply_handler(self, ev):
3159             msg = ev.msg
3160
3161             self.logger.debug('OFPQueueGetConfigReply received: '
3162                               'port=%s queues=%s',
3163                               msg.port, msg.queues)
3164     """
3165
3166     def __init__(self, datapath, port=None, queues=None):
3167         super(OFPQueueGetConfigReply, self).__init__(datapath)
3168         self.port = port
3169         self.queues = queues
3170
3171     @classmethod
3172     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
3173         msg = super(OFPQueueGetConfigReply, cls).parser(datapath, version,
3174                                                         msg_type,
3175                                                         msg_len, xid, buf)
3176         (msg.port,) = struct.unpack_from(
3177             ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf,
3178             ofproto.OFP_HEADER_SIZE)
3179
3180         msg.queues = []
3181         length = ofproto.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
3182         offset = ofproto.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
3183         while length < msg.msg_len:
3184             queue = OFPPacketQueue.parser(msg.buf, offset)
3185             msg.queues.append(queue)
3186
3187             offset += queue.len
3188             length += queue.len
3189
3190         return msg
3191
3192
3193 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
3194 class OFPBarrierRequest(MsgBase):
3195     """
3196     Barrier request message
3197
3198     The controller sends this message to ensure message dependencies have
3199     been met or receive notifications for completed operations.
3200
3201     Example::
3202
3203         def send_barrier_request(self, datapath):
3204             ofp_parser = datapath.ofproto_parser
3205
3206             req = ofp_parser.OFPBarrierRequest(datapath)
3207             datapath.send_msg(req)
3208     """
3209
3210     def __init__(self, datapath):
3211         super(OFPBarrierRequest, self).__init__(datapath)
3212
3213
3214 @_register_parser
3215 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
3216 class OFPBarrierReply(MsgBase):
3217     """
3218     Barrier reply message
3219
3220     The switch responds with this message to a barrier request.
3221
3222     Example::
3223
3224         @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
3225         def barrier_reply_handler(self, ev):
3226             self.logger.debug('OFPBarrierReply received')
3227     """
3228
3229     def __init__(self, datapath):
3230         super(OFPBarrierReply, self).__init__(datapath)
3231
3232
3233 @_set_msg_type(ofproto.OFPT_ROLE_REQUEST)
3234 class OFPRoleRequest(MsgBase):
3235     """
3236     Role request message
3237
3238     The controller uses this message to change its role.
3239
3240     ================ ======================================================
3241     Attribute        Description
3242     ================ ======================================================
3243     role             One of the following values.
3244
3245                      | OFPCR_ROLE_NOCHANGE
3246                      | OFPCR_ROLE_EQUAL
3247                      | OFPCR_ROLE_MASTER
3248                      | OFPCR_ROLE_SLAVE
3249     generation_id    Master Election Generation ID
3250     ================ ======================================================
3251
3252     Example::
3253
3254         def send_role_request(self, datapath):
3255             ofp = datapath.ofproto
3256             ofp_parser = datapath.ofproto_parser
3257
3258             req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
3259             datapath.send_msg(req)
3260     """
3261
3262     def __init__(self, datapath, role, generation_id):
3263         super(OFPRoleRequest, self).__init__(datapath)
3264         self.role = role
3265         self.generation_id = generation_id
3266
3267     def _serialize_body(self):
3268         msg_pack_into(ofproto.OFP_ROLE_REQUEST_PACK_STR,
3269                       self.buf, ofproto.OFP_HEADER_SIZE,
3270                       self.role, self.generation_id)
3271
3272
3273 @_register_parser
3274 @_set_msg_type(ofproto.OFPT_ROLE_REPLY)
3275 class OFPRoleReply(MsgBase):
3276     """
3277     Role reply message
3278
3279     The switch responds with this message to a role request.
3280
3281     ================ ======================================================
3282     Attribute        Description
3283     ================ ======================================================
3284     role             One of the following values.
3285
3286                      | OFPCR_ROLE_NOCHANGE
3287                      | OFPCR_ROLE_EQUAL
3288                      | OFPCR_ROLE_MASTER
3289                      | OFPCR_ROLE_SLAVE
3290     generation_id    Master Election Generation ID
3291     ================ ======================================================
3292
3293     Example::
3294
3295         @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
3296         def role_reply_handler(self, ev):
3297             msg = ev.msg
3298             dp = msg.datapath
3299             ofp = dp.ofproto
3300
3301             if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
3302                 role = 'NOCHANGE'
3303             elif msg.role == ofp.OFPCR_ROLE_EQUAL:
3304                 role = 'EQUAL'
3305             elif msg.role == ofp.OFPCR_ROLE_MASTER:
3306                 role = 'MASTER'
3307             elif msg.role == ofp.OFPCR_ROLE_SLAVE:
3308                 role = 'SLAVE'
3309             else:
3310                 role = 'unknown'
3311
3312             self.logger.debug('OFPRoleReply received: '
3313                               'role=%s generation_id=%d',
3314                               role, msg.generation_id)
3315     """
3316
3317     def __init__(self, datapath, role=None, generation_id=None):
3318         super(OFPRoleReply, self).__init__(datapath)
3319         self.role = role
3320         self.generation_id = generation_id
3321
3322     @classmethod
3323     def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
3324         msg = super(OFPRoleReply, cls).parser(datapath, version,
3325                                               msg_type,
3326                                               msg_len, xid, buf)
3327         (msg.role, msg.generation_id) = struct.unpack_from(
3328             ofproto.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
3329             ofproto.OFP_HEADER_SIZE)
3330
3331         return msg
3332
3333
3334 UINT64_MAX = (1 << 64) - 1
3335 UINT32_MAX = (1 << 32) - 1
3336 UINT16_MAX = (1 << 16) - 1
3337
3338
3339 class Flow(object):
3340     def __init__(self):
3341         self.in_port = 0
3342         self.in_phy_port = 0
3343         self.metadata = 0
3344         self.dl_dst = mac.DONTCARE
3345         self.dl_src = mac.DONTCARE
3346         self.dl_type = 0
3347         self.vlan_vid = 0
3348         self.vlan_pcp = 0
3349         self.ip_dscp = 0
3350         self.ip_ecn = 0
3351         self.ip_proto = 0
3352         self.ipv4_src = 0
3353         self.ipv4_dst = 0
3354         self.tcp_src = 0
3355         self.tcp_dst = 0
3356         self.udp_src = 0
3357         self.udp_dst = 0
3358         self.sctp_src = 0
3359         self.sctp_dst = 0
3360         self.icmpv4_type = 0
3361         self.icmpv4_code = 0
3362         self.arp_op = 0
3363         self.arp_spa = 0
3364         self.arp_tpa = 0
3365         self.arp_sha = 0
3366         self.arp_tha = 0
3367         self.ipv6_src = []
3368         self.ipv6_dst = []
3369         self.ipv6_flabel = 0
3370         self.icmpv6_type = 0
3371         self.icmpv6_code = 0
3372         self.ipv6_nd_target = []
3373         self.ipv6_nd_sll = 0
3374         self.ipv6_nd_tll = 0
3375         self.mpls_label = 0
3376         self.mpls_tc = 0
3377
3378
3379 class FlowWildcards(object):
3380     def __init__(self):
3381         self.metadata_mask = 0
3382         self.dl_dst_mask = 0
3383         self.dl_src_mask = 0
3384         self.vlan_vid_mask = 0
3385         self.ipv4_src_mask = 0
3386         self.ipv4_dst_mask = 0
3387         self.arp_spa_mask = 0
3388         self.arp_tpa_mask = 0
3389         self.arp_sha_mask = 0
3390         self.arp_tha_mask = 0
3391         self.ipv6_src_mask = []
3392         self.ipv6_dst_mask = []
3393         self.ipv6_flabel_mask = 0
3394         self.wildcards = (1 << 64) - 1
3395
3396     def ft_set(self, shift):
3397         self.wildcards &= ~(1 << shift)
3398
3399     def ft_test(self, shift):
3400         return not self.wildcards & (1 << shift)
3401
3402
3403 class OFPMatch(StringifyMixin):
3404     """
3405     Flow Match Structure
3406
3407     This class is implementation of the flow match structure having
3408     compose/query API.
3409     There are new API and old API for compatibility. the old API is
3410     supposed to be removed later.
3411
3412     You can define the flow match by the keyword arguments.
3413     The following arguments are available.
3414
3415     ================ =============== ==================================
3416     Argument         Value           Description
3417     ================ =============== ==================================
3418     in_port          Integer 32bit   Switch input port
3419     in_phy_port      Integer 32bit   Switch physical input port
3420     metadata         Integer 64bit   Metadata passed between tables
3421     eth_dst          MAC address     Ethernet destination address
3422     eth_src          MAC address     Ethernet source address
3423     eth_type         Integer 16bit   Ethernet frame type
3424     vlan_vid         Integer 16bit   VLAN id
3425     vlan_pcp         Integer 8bit    VLAN priority
3426     ip_dscp          Integer 8bit    IP DSCP (6 bits in ToS field)
3427     ip_ecn           Integer 8bit    IP ECN (2 bits in ToS field)
3428     ip_proto         Integer 8bit    IP protocol
3429     ipv4_src         IPv4 address    IPv4 source address
3430     ipv4_dst         IPv4 address    IPv4 destination address
3431     tcp_src          Integer 16bit   TCP source port
3432     tcp_dst          Integer 16bit   TCP destination port
3433     udp_src          Integer 16bit   UDP source port
3434     udp_dst          Integer 16bit   UDP destination port
3435     sctp_src         Integer 16bit   SCTP source port
3436     sctp_dst         Integer 16bit   SCTP destination port
3437     icmpv4_type      Integer 8bit    ICMP type
3438     icmpv4_code      Integer 8bit    ICMP code
3439     arp_op           Integer 16bit   ARP opcode
3440     arp_spa          IPv4 address    ARP source IPv4 address
3441     arp_tpa          IPv4 address    ARP target IPv4 address
3442     arp_sha          MAC address     ARP source hardware address
3443     arp_tha          MAC address     ARP target hardware address
3444     ipv6_src         IPv6 address    IPv6 source address
3445     ipv6_dst         IPv6 address    IPv6 destination address
3446     ipv6_flabel      Integer 32bit   IPv6 Flow Label
3447     icmpv6_type      Integer 8bit    ICMPv6 type
3448     icmpv6_code      Integer 8bit    ICMPv6 code
3449     ipv6_nd_target   IPv6 address    Target address for ND
3450     ipv6_nd_sll      MAC address     Source link-layer for ND
3451     ipv6_nd_tll      MAC address     Target link-layer for ND
3452     mpls_label       Integer 32bit   MPLS label
3453     mpls_tc          Integer 8bit    MPLS TC
3454     pbb_uca          Integer 8bit    PBB UCA header field
3455                                      (EXT-256 Old version of ONF Extension)
3456     tcp_flags        Integer 16bit   TCP flags
3457                                      (EXT-109 ONF Extension)
3458     actset_output    Integer 32bit   Output port from action set metadata
3459                                      (EXT-233 ONF Extension)
3460     ================ =============== ==================================
3461
3462     Example::
3463
3464         >>> # compose
3465         >>> match = parser.OFPMatch(
3466         ...     in_port=1,
3467         ...     eth_type=0x86dd,
3468         ...     ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
3469         ...               'ffff:ffff:ffff:ffff::'),
3470         ...     ipv6_dst='2001:db8:bd05:1d2:288a:1fc0:1:10ee')
3471         >>> # query
3472         >>> if 'ipv6_src' in match:
3473         ...     print match['ipv6_src']
3474         ...
3475         ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::')
3476
3477     .. Note::
3478
3479         For the list of the supported Nicira experimenter matches,
3480         please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`.
3481
3482     .. Note::
3483
3484         For VLAN id match field, special values are defined in OpenFlow Spec.
3485
3486         1) Packets with and without a VLAN tag
3487
3488             - Example::
3489
3490                 match = parser.OFPMatch()
3491
3492             - Packet Matching
3493
3494                 ====================== =====
3495                 non-VLAN-tagged        MATCH
3496                 VLAN-tagged(vlan_id=3) MATCH
3497                 VLAN-tagged(vlan_id=5) MATCH
3498                 ====================== =====
3499
3500         2) Only packets without a VLAN tag
3501
3502             - Example::
3503
3504                 match = parser.OFPMatch(vlan_vid=0x0000)
3505
3506             - Packet Matching
3507
3508                 ====================== =====
3509                 non-VLAN-tagged        MATCH
3510                 VLAN-tagged(vlan_id=3)   x
3511                 VLAN-tagged(vlan_id=5)   x
3512                 ====================== =====
3513
3514         3) Only packets with a VLAN tag regardless of its value
3515
3516             - Example::
3517
3518                 match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000))
3519
3520             - Packet Matching
3521
3522                 ====================== =====
3523                 non-VLAN-tagged          x
3524                 VLAN-tagged(vlan_id=3) MATCH
3525                 VLAN-tagged(vlan_id=5) MATCH
3526                 ====================== =====
3527
3528         4) Only packets with VLAN tag and VID equal
3529
3530             - Example::
3531
3532                 match = parser.OFPMatch(vlan_vid=(0x1000 | 3))
3533
3534             - Packet Matching
3535
3536                 ====================== =====
3537                 non-VLAN-tagged          x
3538                 VLAN-tagged(vlan_id=3) MATCH
3539                 VLAN-tagged(vlan_id=5)   x
3540                 ====================== =====
3541     """
3542
3543     def __init__(self, type_=None, length=None, _ordered_fields=None,
3544                  **kwargs):
3545         super(OFPMatch, self).__init__()
3546         self._wc = FlowWildcards()
3547         self._flow = Flow()
3548         self.fields = []
3549         self.type = ofproto.OFPMT_OXM
3550         self.length = length
3551
3552         if _ordered_fields is not None:
3553             assert not kwargs
3554             self._fields2 = _ordered_fields
3555         else:
3556             # eg.
3557             #   OFPMatch(eth_src=('ff:ff:ff:00:00:00'), eth_type=0x800,
3558             #            ipv4_src='10.0.0.1')
3559             kwargs = dict(ofproto.oxm_normalize_user(k, v) for
3560                           (k, v) in kwargs.items())
3561             fields = [ofproto.oxm_from_user(k, v) for (k, v)
3562                       in kwargs.items()]
3563             # assumption: sorting by OXM type values makes fields
3564             # meet ordering requirements (eg. eth_type before ipv4_src)
3565             fields.sort(
3566                 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
3567             self._fields2 = [ofproto.oxm_to_user(n, v, m) for (n, v, m)
3568                              in fields]
3569
3570     def __getitem__(self, key):
3571         return dict(self._fields2)[key]
3572
3573     def __contains__(self, key):
3574         return key in dict(self._fields2)
3575
3576     def iteritems(self):
3577         return iter(dict(self._fields2).items())
3578
3579     def items(self):
3580         return self._fields2
3581
3582     def get(self, key, default=None):
3583         return dict(self._fields2).get(key, default)
3584
3585     def stringify_attrs(self):
3586         yield "oxm_fields", dict(self._fields2)
3587
3588     def to_jsondict(self):
3589         """
3590         Returns a dict expressing the flow match.
3591         """
3592         # XXX old api compat
3593         if self._composed_with_old_api():
3594             # copy object first because serialize_old is destructive
3595             o2 = OFPMatch()
3596             o2.fields = self.fields[:]
3597             # serialize and parse to fill OFPMatch._fields2
3598             buf = bytearray()
3599             o2.serialize(buf, 0)
3600             o = OFPMatch.parser(six.binary_type(buf), 0)
3601         else:
3602             o = self
3603
3604         body = {"oxm_fields": [ofproto.oxm_to_jsondict(k, uv) for k, uv
3605                                in o._fields2],
3606                 "length": o.length,
3607                 "type": o.type}
3608         return {self.__class__.__name__: body}
3609
3610     @classmethod
3611     def from_jsondict(cls, dict_):
3612         """
3613         Returns an object which is generated from a dict.
3614
3615         Exception raises:
3616         KeyError -- Unknown match field is defined in dict
3617         """
3618         fields = [ofproto.oxm_from_jsondict(f) for f
3619                   in dict_['oxm_fields']]
3620         o = OFPMatch(_ordered_fields=fields)
3621         # XXX old api compat
3622         # serialize and parse to fill OFPMatch.fields
3623         buf = bytearray()
3624         o.serialize(buf, 0)
3625         return OFPMatch.parser(six.binary_type(buf), 0)
3626
3627     def __str__(self):
3628         # XXX old api compat
3629         if self._composed_with_old_api():
3630             # copy object first because serialize_old is destructive
3631             o2 = OFPMatch()
3632             o2.fields = self.fields[:]
3633             # serialize and parse to fill OFPMatch._fields2
3634             buf = bytearray()
3635             o2.serialize(buf, 0)
3636             o = OFPMatch.parser(six.binary_type(buf), 0)
3637         else:
3638             o = self
3639         return super(OFPMatch, o).__str__()
3640
3641     __repr__ = __str__
3642
3643     def append_field(self, header, value, mask=None):
3644         """
3645         Append a match field.
3646
3647         ========= =======================================================
3648         Argument  Description
3649         ========= =======================================================
3650         header    match field header ID which is defined automatically in
3651                   ``ofproto_v1_3``
3652         value     match field value
3653         mask      mask value to the match field
3654         ========= =======================================================
3655
3656         The available ``header`` is as follows.
3657
3658         ====================== ===================================
3659         Header ID              Description
3660         ====================== ===================================
3661         OXM_OF_IN_PORT         Switch input port
3662         OXM_OF_IN_PHY_PORT     Switch physical input port
3663         OXM_OF_METADATA        Metadata passed between tables
3664         OXM_OF_ETH_DST         Ethernet destination address
3665         OXM_OF_ETH_SRC         Ethernet source address
3666         OXM_OF_ETH_TYPE        Ethernet frame type
3667         OXM_OF_VLAN_VID        VLAN id
3668         OXM_OF_VLAN_PCP        VLAN priority
3669         OXM_OF_IP_DSCP         IP DSCP (6 bits in ToS field)
3670         OXM_OF_IP_ECN          IP ECN (2 bits in ToS field)
3671         OXM_OF_IP_PROTO        IP protocol
3672         OXM_OF_IPV4_SRC        IPv4 source address
3673         OXM_OF_IPV4_DST        IPv4 destination address
3674         OXM_OF_TCP_SRC         TCP source port
3675         OXM_OF_TCP_DST         TCP destination port
3676         OXM_OF_UDP_SRC         UDP source port
3677         OXM_OF_UDP_DST         UDP destination port
3678         OXM_OF_SCTP_SRC        SCTP source port
3679         OXM_OF_SCTP_DST        SCTP destination port
3680         OXM_OF_ICMPV4_TYPE     ICMP type
3681         OXM_OF_ICMPV4_CODE     ICMP code
3682         OXM_OF_ARP_OP          ARP opcode
3683         OXM_OF_ARP_SPA         ARP source IPv4 address
3684         OXM_OF_ARP_TPA         ARP target IPv4 address
3685         OXM_OF_ARP_SHA         ARP source hardware address
3686         OXM_OF_ARP_THA         ARP target hardware address
3687         OXM_OF_IPV6_SRC        IPv6 source address
3688         OXM_OF_IPV6_DST        IPv6 destination address
3689         OXM_OF_IPV6_FLABEL     IPv6 Flow Label
3690         OXM_OF_ICMPV6_TYPE     ICMPv6 type
3691         OXM_OF_ICMPV6_CODE     ICMPv6 code
3692         OXM_OF_IPV6_ND_TARGET  Target address for ND
3693         OXM_OF_IPV6_ND_SLL     Source link-layer for ND
3694         OXM_OF_IPV6_ND_TLL     Target link-layer for ND
3695         OXM_OF_MPLS_LABEL      MPLS label
3696         OXM_OF_MPLS_TC         MPLS TC
3697         ====================== ===================================
3698         """
3699         self.fields.append(OFPMatchField.make(header, value, mask))
3700
3701     def _composed_with_old_api(self):
3702         return (self.fields and not self._fields2) or \
3703             self._wc.__dict__ != FlowWildcards().__dict__
3704
3705     def serialize(self, buf, offset):
3706         """
3707         Outputs the expression of the wire protocol of the flow match into
3708         the buf.
3709         Returns the output length.
3710         """
3711         # XXX compat
3712         if self._composed_with_old_api():
3713             return self.serialize_old(buf, offset)
3714
3715         fields = [ofproto.oxm_from_user(k, uv) for (k, uv)
3716                   in self._fields2]
3717
3718         hdr_pack_str = '!HH'
3719         field_offset = offset + struct.calcsize(hdr_pack_str)
3720         for (n, value, mask) in fields:
3721             field_offset += ofproto.oxm_serialize(n, value, mask, buf,
3722                                                   field_offset)
3723
3724         length = field_offset - offset
3725         msg_pack_into(hdr_pack_str, buf, offset,
3726                       ofproto.OFPMT_OXM, length)
3727         self.length = length
3728
3729         pad_len = utils.round_up(length, 8) - length
3730         msg_pack_into("%dx" % pad_len, buf, field_offset)
3731
3732         return length + pad_len
3733
3734     def serialize_old(self, buf, offset):
3735         if hasattr(self, '_serialized'):
3736             raise Exception('serializing an OFPMatch composed with '
3737                             'old API multiple times is not supported')
3738         self._serialized = True
3739
3740         if self._wc.ft_test(ofproto.OFPXMT_OFB_IN_PORT):
3741             self.append_field(ofproto.OXM_OF_IN_PORT,
3742                               self._flow.in_port)
3743
3744         if self._wc.ft_test(ofproto.OFPXMT_OFB_IN_PHY_PORT):
3745             self.append_field(ofproto.OXM_OF_IN_PHY_PORT,
3746                               self._flow.in_phy_port)
3747
3748         if self._wc.ft_test(ofproto.OFPXMT_OFB_METADATA):
3749             if self._wc.metadata_mask == UINT64_MAX:
3750                 header = ofproto.OXM_OF_METADATA
3751             else:
3752                 header = ofproto.OXM_OF_METADATA_W
3753             self.append_field(header, self._flow.metadata,
3754                               self._wc.metadata_mask)
3755
3756         if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_DST):
3757             if self._wc.dl_dst_mask:
3758                 header = ofproto.OXM_OF_ETH_DST_W
3759             else:
3760                 header = ofproto.OXM_OF_ETH_DST
3761             self.append_field(header, self._flow.dl_dst, self._wc.dl_dst_mask)
3762
3763         if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_SRC):
3764             if self._wc.dl_src_mask:
3765                 header = ofproto.OXM_OF_ETH_SRC_W
3766             else:
3767                 header = ofproto.OXM_OF_ETH_SRC
3768             self.append_field(header, self._flow.dl_src, self._wc.dl_src_mask)
3769
3770         if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_TYPE):
3771             self.append_field(ofproto.OXM_OF_ETH_TYPE, self._flow.dl_type)
3772
3773         if self._wc.ft_test(ofproto.OFPXMT_OFB_VLAN_VID):
3774             if self._wc.vlan_vid_mask == UINT16_MAX:
3775                 header = ofproto.OXM_OF_VLAN_VID
3776             else:
3777                 header = ofproto.OXM_OF_VLAN_VID_W
3778             self.append_field(header, self._flow.vlan_vid,
3779                               self._wc.vlan_vid_mask)
3780
3781         if self._wc.ft_test(ofproto.OFPXMT_OFB_VLAN_PCP):
3782             self.append_field(ofproto.OXM_OF_VLAN_PCP,
3783                               self._flow.vlan_pcp)
3784
3785         if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_DSCP):
3786             self.append_field(ofproto.OXM_OF_IP_DSCP, self._flow.ip_dscp)
3787
3788         if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_ECN):
3789             self.append_field(ofproto.OXM_OF_IP_ECN, self._flow.ip_ecn)
3790
3791         if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_PROTO):
3792             self.append_field(ofproto.OXM_OF_IP_PROTO,
3793                               self._flow.ip_proto)
3794
3795         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV4_SRC):
3796             if self._wc.ipv4_src_mask == UINT32_MAX:
3797                 header = ofproto.OXM_OF_IPV4_SRC
3798             else:
3799                 header = ofproto.OXM_OF_IPV4_SRC_W
3800             self.append_field(header, self._flow.ipv4_src,
3801                               self._wc.ipv4_src_mask)
3802
3803         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV4_DST):
3804             if self._wc.ipv4_dst_mask == UINT32_MAX:
3805                 header = ofproto.OXM_OF_IPV4_DST
3806             else:
3807                 header = ofproto.OXM_OF_IPV4_DST_W
3808             self.append_field(header, self._flow.ipv4_dst,
3809                               self._wc.ipv4_dst_mask)
3810
3811         if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_SRC):
3812             self.append_field(ofproto.OXM_OF_TCP_SRC, self._flow.tcp_src)
3813
3814         if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_DST):
3815             self.append_field(ofproto.OXM_OF_TCP_DST, self._flow.tcp_dst)
3816
3817         if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_SRC):
3818             self.append_field(ofproto.OXM_OF_UDP_SRC, self._flow.udp_src)
3819
3820         if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_DST):
3821             self.append_field(ofproto.OXM_OF_UDP_DST, self._flow.udp_dst)
3822
3823         if self._wc.ft_test(ofproto.OFPXMT_OFB_SCTP_SRC):
3824             self.append_field(ofproto.OXM_OF_SCTP_SRC,
3825                               self._flow.sctp_src)
3826
3827         if self._wc.ft_test(ofproto.OFPXMT_OFB_SCTP_DST):
3828             self.append_field(ofproto.OXM_OF_SCTP_DST,
3829                               self._flow.sctp_dst)
3830
3831         if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV4_TYPE):
3832             self.append_field(ofproto.OXM_OF_ICMPV4_TYPE,
3833                               self._flow.icmpv4_type)
3834
3835         if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV4_CODE):
3836             self.append_field(ofproto.OXM_OF_ICMPV4_CODE,
3837                               self._flow.icmpv4_code)
3838
3839         if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_OP):
3840             self.append_field(ofproto.OXM_OF_ARP_OP, self._flow.arp_op)
3841
3842         if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_SPA):
3843             if self._wc.arp_spa_mask == UINT32_MAX:
3844                 header = ofproto.OXM_OF_ARP_SPA
3845             else:
3846                 header = ofproto.OXM_OF_ARP_SPA_W
3847             self.append_field(header, self._flow.arp_spa,
3848                               self._wc.arp_spa_mask)
3849
3850         if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_TPA):
3851             if self._wc.arp_tpa_mask == UINT32_MAX:
3852                 header = ofproto.OXM_OF_ARP_TPA
3853             else:
3854                 header = ofproto.OXM_OF_ARP_TPA_W
3855             self.append_field(header, self._flow.arp_tpa,
3856                               self._wc.arp_tpa_mask)
3857
3858         if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_SHA):
3859             if self._wc.arp_sha_mask:
3860                 header = ofproto.OXM_OF_ARP_SHA_W
3861             else:
3862                 header = ofproto.OXM_OF_ARP_SHA
3863             self.append_field(header, self._flow.arp_sha,
3864                               self._wc.arp_sha_mask)
3865
3866         if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_THA):
3867             if self._wc.arp_tha_mask:
3868                 header = ofproto.OXM_OF_ARP_THA_W
3869             else:
3870                 header = ofproto.OXM_OF_ARP_THA
3871             self.append_field(header, self._flow.arp_tha,
3872                               self._wc.arp_tha_mask)
3873
3874         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_SRC):
3875             if len(self._wc.ipv6_src_mask):
3876                 header = ofproto.OXM_OF_IPV6_SRC_W
3877             else:
3878                 header = ofproto.OXM_OF_IPV6_SRC
3879             self.append_field(header, self._flow.ipv6_src,
3880                               self._wc.ipv6_src_mask)
3881
3882         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_DST):
3883             if len(self._wc.ipv6_dst_mask):
3884                 header = ofproto.OXM_OF_IPV6_DST_W
3885             else:
3886                 header = ofproto.OXM_OF_IPV6_DST
3887             self.append_field(header, self._flow.ipv6_dst,
3888                               self._wc.ipv6_dst_mask)
3889
3890         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_FLABEL):
3891             if self._wc.ipv6_flabel_mask == UINT32_MAX:
3892                 header = ofproto.OXM_OF_IPV6_FLABEL
3893             else:
3894                 header = ofproto.OXM_OF_IPV6_FLABEL_W
3895             self.append_field(header, self._flow.ipv6_flabel,
3896                               self._wc.ipv6_flabel_mask)
3897
3898         if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV6_TYPE):
3899             self.append_field(ofproto.OXM_OF_ICMPV6_TYPE,
3900                               self._flow.icmpv6_type)
3901
3902         if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV6_CODE):
3903             self.append_field(ofproto.OXM_OF_ICMPV6_CODE,
3904                               self._flow.icmpv6_code)
3905
3906         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_TARGET):
3907             self.append_field(ofproto.OXM_OF_IPV6_ND_TARGET,
3908                               self._flow.ipv6_nd_target)
3909
3910         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_SLL):
3911             self.append_field(ofproto.OXM_OF_IPV6_ND_SLL,
3912                               self._flow.ipv6_nd_sll)
3913
3914         if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_TLL):
3915             self.append_field(ofproto.OXM_OF_IPV6_ND_TLL,
3916                               self._flow.ipv6_nd_tll)
3917
3918         if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_LABEL):
3919             self.append_field(ofproto.OXM_OF_MPLS_LABEL,
3920                               self._flow.mpls_label)
3921
3922         if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_TC):
3923             self.append_field(ofproto.OXM_OF_MPLS_TC,
3924                               self._flow.mpls_tc)
3925
3926         field_offset = offset + 4
3927         for f in self.fields:
3928             f.serialize(buf, field_offset)
3929             field_offset += f.length
3930
3931         length = field_offset - offset
3932         msg_pack_into('!HH', buf, offset, ofproto.OFPMT_OXM, length)
3933
3934         pad_len = utils.round_up(length, 8) - length
3935         msg_pack_into("%dx" % pad_len, buf, field_offset)
3936
3937         return length + pad_len
3938
3939     @classmethod
3940     def parser(cls, buf, offset):
3941         """
3942         Returns an object which is generated from a buffer including the
3943         expression of the wire protocol of the flow match.
3944         """
3945         match = OFPMatch()
3946         type_, length = struct.unpack_from('!HH', buf, offset)
3947
3948         match.type = type_
3949         match.length = length
3950
3951         # ofp_match adjustment
3952         offset += 4
3953         length -= 4
3954
3955         # XXXcompat
3956         cls.parser_old(match, buf, offset, length)
3957
3958         fields = []
3959         while length > 0:
3960             n, value, mask, field_len = ofproto.oxm_parse(buf, offset)
3961             k, uv = ofproto.oxm_to_user(n, value, mask)
3962             fields.append((k, uv))
3963             offset += field_len
3964             length -= field_len
3965         match._fields2 = fields
3966         return match
3967
3968     @staticmethod
3969     def parser_old(match, buf, offset, length):
3970         while length > 0:
3971             field = OFPMatchField.parser(buf, offset)
3972             offset += field.length
3973             length -= field.length
3974             match.fields.append(field)
3975
3976     def set_in_port(self, port):
3977         self._wc.ft_set(ofproto.OFPXMT_OFB_IN_PORT)
3978         self._flow.in_port = port
3979
3980     def set_in_phy_port(self, phy_port):
3981         self._wc.ft_set(ofproto.OFPXMT_OFB_IN_PHY_PORT)
3982         self._flow.in_phy_port = phy_port
3983
3984     def set_metadata(self, metadata):
3985         self.set_metadata_masked(metadata, UINT64_MAX)
3986
3987     def set_metadata_masked(self, metadata, mask):
3988         self._wc.ft_set(ofproto.OFPXMT_OFB_METADATA)
3989         self._wc.metadata_mask = mask
3990         self._flow.metadata = metadata & mask
3991
3992     def set_dl_dst(self, dl_dst):
3993         self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_DST)
3994         self._flow.dl_dst = dl_dst
3995
3996     def set_dl_dst_masked(self, dl_dst, mask):
3997         self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_DST)
3998         self._wc.dl_dst_mask = mask
3999         # bit-wise and of the corresponding elements of dl_dst and mask
4000         self._flow.dl_dst = mac.haddr_bitand(dl_dst, mask)
4001
4002     def set_dl_src(self, dl_src):
4003         self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_SRC)
4004         self._flow.dl_src = dl_src
4005
4006     def set_dl_src_masked(self, dl_src, mask):
4007         self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_SRC)
4008         self._wc.dl_src_mask = mask
4009         self._flow.dl_src = mac.haddr_bitand(dl_src, mask)
4010
4011     def set_dl_type(self, dl_type):
4012         self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_TYPE)
4013         self._flow.dl_type = dl_type
4014
4015     def set_vlan_vid_none(self):
4016         self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_VID)
4017         self._wc.vlan_vid_mask = UINT16_MAX
4018         self._flow.vlan_vid = ofproto.OFPVID_NONE
4019
4020     def set_vlan_vid(self, vid):
4021         self.set_vlan_vid_masked(vid, UINT16_MAX)
4022
4023     def set_vlan_vid_masked(self, vid, mask):
4024         vid |= ofproto.OFPVID_PRESENT
4025         self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_VID)
4026         self._wc.vlan_vid_mask = mask
4027         self._flow.vlan_vid = vid
4028
4029     def set_vlan_pcp(self, pcp):
4030         self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_PCP)
4031         self._flow.vlan_pcp = pcp
4032
4033     def set_ip_dscp(self, ip_dscp):
4034         self._wc.ft_set(ofproto.OFPXMT_OFB_IP_DSCP)
4035         self._flow.ip_dscp = ip_dscp
4036
4037     def set_ip_ecn(self, ip_ecn):
4038         self._wc.ft_set(ofproto.OFPXMT_OFB_IP_ECN)
4039         self._flow.ip_ecn = ip_ecn
4040
4041     def set_ip_proto(self, ip_proto):
4042         self._wc.ft_set(ofproto.OFPXMT_OFB_IP_PROTO)
4043         self._flow.ip_proto = ip_proto
4044
4045     def set_ipv4_src(self, ipv4_src):
4046         self.set_ipv4_src_masked(ipv4_src, UINT32_MAX)
4047
4048     def set_ipv4_src_masked(self, ipv4_src, mask):
4049         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV4_SRC)
4050         self._flow.ipv4_src = ipv4_src
4051         self._wc.ipv4_src_mask = mask
4052
4053     def set_ipv4_dst(self, ipv4_dst):
4054         self.set_ipv4_dst_masked(ipv4_dst, UINT32_MAX)
4055
4056     def set_ipv4_dst_masked(self, ipv4_dst, mask):
4057         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV4_DST)
4058         self._flow.ipv4_dst = ipv4_dst
4059         self._wc.ipv4_dst_mask = mask
4060
4061     def set_tcp_src(self, tcp_src):
4062         self._wc.ft_set(ofproto.OFPXMT_OFB_TCP_SRC)
4063         self._flow.tcp_src = tcp_src
4064
4065     def set_tcp_dst(self, tcp_dst):
4066         self._wc.ft_set(ofproto.OFPXMT_OFB_TCP_DST)
4067         self._flow.tcp_dst = tcp_dst
4068
4069     def set_udp_src(self, udp_src):
4070         self._wc.ft_set(ofproto.OFPXMT_OFB_UDP_SRC)
4071         self._flow.udp_src = udp_src
4072
4073     def set_udp_dst(self, udp_dst):
4074         self._wc.ft_set(ofproto.OFPXMT_OFB_UDP_DST)
4075         self._flow.udp_dst = udp_dst
4076
4077     def set_sctp_src(self, sctp_src):
4078         self._wc.ft_set(ofproto.OFPXMT_OFB_SCTP_SRC)
4079         self._flow.sctp_src = sctp_src
4080
4081     def set_sctp_dst(self, sctp_dst):
4082         self._wc.ft_set(ofproto.OFPXMT_OFB_SCTP_DST)
4083         self._flow.sctp_dst = sctp_dst
4084
4085     def set_icmpv4_type(self, icmpv4_type):
4086         self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV4_TYPE)
4087         self._flow.icmpv4_type = icmpv4_type
4088
4089     def set_icmpv4_code(self, icmpv4_code):
4090         self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV4_CODE)
4091         self._flow.icmpv4_code = icmpv4_code
4092
4093     def set_arp_opcode(self, arp_op):
4094         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_OP)
4095         self._flow.arp_op = arp_op
4096
4097     def set_arp_spa(self, arp_spa):
4098         self.set_arp_spa_masked(arp_spa, UINT32_MAX)
4099
4100     def set_arp_spa_masked(self, arp_spa, mask):
4101         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SPA)
4102         self._wc.arp_spa_mask = mask
4103         self._flow.arp_spa = arp_spa
4104
4105     def set_arp_tpa(self, arp_tpa):
4106         self.set_arp_tpa_masked(arp_tpa, UINT32_MAX)
4107
4108     def set_arp_tpa_masked(self, arp_tpa, mask):
4109         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_TPA)
4110         self._wc.arp_tpa_mask = mask
4111         self._flow.arp_tpa = arp_tpa
4112
4113     def set_arp_sha(self, arp_sha):
4114         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SHA)
4115         self._flow.arp_sha = arp_sha
4116
4117     def set_arp_sha_masked(self, arp_sha, mask):
4118         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SHA)
4119         self._wc.arp_sha_mask = mask
4120         self._flow.arp_sha = mac.haddr_bitand(arp_sha, mask)
4121
4122     def set_arp_tha(self, arp_tha):
4123         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_THA)
4124         self._flow.arp_tha = arp_tha
4125
4126     def set_arp_tha_masked(self, arp_tha, mask):
4127         self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_THA)
4128         self._wc.arp_tha_mask = mask
4129         self._flow.arp_tha = mac.haddr_bitand(arp_tha, mask)
4130
4131     def set_ipv6_src(self, src):
4132         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_SRC)
4133         self._flow.ipv6_src = src
4134
4135     def set_ipv6_src_masked(self, src, mask):
4136         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_SRC)
4137         self._wc.ipv6_src_mask = mask
4138         self._flow.ipv6_src = [x & y for (x, y) in zip(src, mask)]
4139
4140     def set_ipv6_dst(self, dst):
4141         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_DST)
4142         self._flow.ipv6_dst = dst
4143
4144     def set_ipv6_dst_masked(self, dst, mask):
4145         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_DST)
4146         self._wc.ipv6_dst_mask = mask
4147         self._flow.ipv6_dst = [x & y for (x, y) in zip(dst, mask)]
4148
4149     def set_ipv6_flabel(self, flabel):
4150         self.set_ipv6_flabel_masked(flabel, UINT32_MAX)
4151
4152     def set_ipv6_flabel_masked(self, flabel, mask):
4153         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_FLABEL)
4154         self._wc.ipv6_flabel_mask = mask
4155         self._flow.ipv6_flabel = flabel
4156
4157     def set_icmpv6_type(self, icmpv6_type):
4158         self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV6_TYPE)
4159         self._flow.icmpv6_type = icmpv6_type
4160
4161     def set_icmpv6_code(self, icmpv6_code):
4162         self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV6_CODE)
4163         self._flow.icmpv6_code = icmpv6_code
4164
4165     def set_ipv6_nd_target(self, target):
4166         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_TARGET)
4167         self._flow.ipv6_nd_target = target
4168
4169     def set_ipv6_nd_sll(self, ipv6_nd_sll):
4170         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_SLL)
4171         self._flow.ipv6_nd_sll = ipv6_nd_sll
4172
4173     def set_ipv6_nd_tll(self, ipv6_nd_tll):
4174         self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_TLL)
4175         self._flow.ipv6_nd_tll = ipv6_nd_tll
4176
4177     def set_mpls_label(self, mpls_label):
4178         self._wc.ft_set(ofproto.OFPXMT_OFB_MPLS_LABEL)
4179         self._flow.mpls_label = mpls_label
4180
4181     def set_mpls_tc(self, mpls_tc):
4182         self._wc.ft_set(ofproto.OFPXMT_OFB_MPLS_TC)
4183         self._flow.mpls_tc = mpls_tc
4184
4185
4186 class OFPMatchField(StringifyMixin):
4187     _FIELDS_HEADERS = {}
4188
4189     @staticmethod
4190     def register_field_header(headers):
4191         def _register_field_header(cls):
4192             for header in headers:
4193                 OFPMatchField._FIELDS_HEADERS[header] = cls
4194             return cls
4195         return _register_field_header
4196
4197     def __init__(self, header):
4198         self.header = header
4199         self.n_bytes = ofproto.oxm_tlv_header_extract_length(header)
4200         self.length = 0
4201
4202     @classmethod
4203     def cls_to_header(cls, cls_, hasmask):
4204         # XXX efficiency
4205         inv = dict((v, k) for k, v in cls._FIELDS_HEADERS.items()
4206                    if (((k >> 8) & 1) != 0) == hasmask)
4207         return inv[cls_]
4208
4209     @staticmethod
4210     def make(header, value, mask=None):
4211         cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
4212         return cls_(header, value, mask)
4213
4214     @classmethod
4215     def parser(cls, buf, offset):
4216         (header,) = struct.unpack_from('!I', buf, offset)
4217         cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
4218         if cls_:
4219             field = cls_.field_parser(header, buf, offset)
4220         else:
4221             field = OFPMatchField(header)
4222         field.length = (header & 0xff) + 4
4223         return field
4224
4225     @classmethod
4226     def field_parser(cls, header, buf, offset):
4227         mask = None
4228         if ofproto.oxm_tlv_header_extract_hasmask(header):
4229             pack_str = '!' + cls.pack_str[1:] * 2
4230             (value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
4231         else:
4232             (value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
4233         return cls(header, value, mask)
4234
4235     def serialize(self, buf, offset):
4236         if ofproto.oxm_tlv_header_extract_hasmask(self.header):
4237             self.put_w(buf, offset, self.value, self.mask)
4238         else:
4239             self.put(buf, offset, self.value)
4240
4241     def _put_header(self, buf, offset):
4242         msg_pack_into('!I', buf, offset, self.header)
4243         self.length = 4
4244
4245     def _put(self, buf, offset, value):
4246         msg_pack_into(self.pack_str, buf, offset, value)
4247         self.length += self.n_bytes
4248
4249     def put_w(self, buf, offset, value, mask):
4250         self._put_header(buf, offset)
4251         self._put(buf, offset + self.length, value)
4252         self._put(buf, offset + self.length, mask)
4253
4254     def put(self, buf, offset, value):
4255         self._put_header(buf, offset)
4256         self._put(buf, offset + self.length, value)
4257
4258     def _putv6(self, buf, offset, value):
4259         msg_pack_into(self.pack_str, buf, offset, *value)
4260         self.length += self.n_bytes
4261
4262     def putv6(self, buf, offset, value, mask=None):
4263         self._put_header(buf, offset)
4264         self._putv6(buf, offset + self.length, value)
4265         if mask and len(mask):
4266             self._putv6(buf, offset + self.length, mask)
4267
4268     def oxm_len(self):
4269         return self.header & 0xff
4270
4271     def to_jsondict(self):
4272         # remove some redundant attributes
4273         d = super(OFPMatchField, self).to_jsondict()
4274         v = d[self.__class__.__name__]
4275         del v['header']
4276         del v['length']
4277         del v['n_bytes']
4278         return d
4279
4280     @classmethod
4281     def from_jsondict(cls, dict_):
4282         # just pass the dict around.
4283         # it will be converted by OFPMatch.__init__().
4284         return {cls.__name__: dict_}
4285
4286     def stringify_attrs(self):
4287         f = super(OFPMatchField, self).stringify_attrs
4288         if not ofproto.oxm_tlv_header_extract_hasmask(self.header):
4289             # something like the following, but yield two values (k,v)
4290             # return itertools.ifilter(lambda k, v: k != 'mask', iter())
4291             def g():
4292                 for k, v in f():
4293                     if k != 'mask':
4294                         yield (k, v)
4295             return g()
4296         else:
4297             return f()
4298
4299
4300 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PORT])
4301 class MTInPort(OFPMatchField):
4302     pack_str = '!I'
4303
4304     def __init__(self, header, value, mask=None):
4305         super(MTInPort, self).__init__(header)
4306         self.value = value
4307
4308
4309 @OFPMatchField.register_field_header([ofproto.OXM_OF_METADATA,
4310                                       ofproto.OXM_OF_METADATA_W])
4311 class MTMetadata(OFPMatchField):
4312     pack_str = '!Q'
4313
4314     def __init__(self, header, value, mask=None):
4315         super(MTMetadata, self).__init__(header)
4316         self.value = value
4317         self.mask = mask
4318
4319
4320 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PHY_PORT])
4321 class MTInPhyPort(OFPMatchField):
4322     pack_str = '!I'
4323
4324     def __init__(self, header, value, mask=None):
4325         super(MTInPhyPort, self).__init__(header)
4326         self.value = value
4327
4328
4329 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_DST,
4330                                       ofproto.OXM_OF_ETH_DST_W])
4331 class MTEthDst(OFPMatchField):
4332     pack_str = '!6s'
4333
4334     def __init__(self, header, value, mask=None):
4335         super(MTEthDst, self).__init__(header)
4336         self.value = value
4337         self.mask = mask
4338
4339
4340 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_SRC,
4341                                       ofproto.OXM_OF_ETH_SRC_W])
4342 class MTEthSrc(OFPMatchField):
4343     pack_str = '!6s'
4344
4345     def __init__(self, header, value, mask=None):
4346         super(MTEthSrc, self).__init__(header)
4347         self.value = value
4348         self.mask = mask
4349
4350
4351 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_TYPE])
4352 class MTEthType(OFPMatchField):
4353     pack_str = '!H'
4354
4355     def __init__(self, header, value, mask=None):
4356         super(MTEthType, self).__init__(header)
4357         self.value = value
4358
4359
4360 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_VID,
4361                                       ofproto.OXM_OF_VLAN_VID_W])
4362 class MTVlanVid(OFPMatchField):
4363     pack_str = '!H'
4364
4365     def __init__(self, header, value, mask=None):
4366         super(MTVlanVid, self).__init__(header)
4367         self.value = value
4368         self.mask = mask
4369
4370     @classmethod
4371     def field_parser(cls, header, buf, offset):
4372         m = super(MTVlanVid, cls).field_parser(header, buf, offset)
4373         m.value &= ~ofproto.OFPVID_PRESENT
4374         return m
4375
4376
4377 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_PCP])
4378 class MTVlanPcp(OFPMatchField):
4379     pack_str = '!B'
4380
4381     def __init__(self, header, value, mask=None):
4382         super(MTVlanPcp, self).__init__(header)
4383         self.value = value
4384
4385
4386 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_DSCP])
4387 class MTIPDscp(OFPMatchField):
4388     pack_str = '!B'
4389
4390     def __init__(self, header, value, mask=None):
4391         super(MTIPDscp, self).__init__(header)
4392         self.value = value
4393
4394
4395 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_ECN])
4396 class MTIPECN(OFPMatchField):
4397     pack_str = '!B'
4398
4399     def __init__(self, header, value, mask=None):
4400         super(MTIPECN, self).__init__(header)
4401         self.value = value
4402
4403
4404 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_PROTO])
4405 class MTIPProto(OFPMatchField):
4406     pack_str = '!B'
4407
4408     def __init__(self, header, value, mask=None):
4409         super(MTIPProto, self).__init__(header)
4410         self.value = value
4411
4412
4413 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_SRC,
4414                                       ofproto.OXM_OF_IPV4_SRC_W])
4415 class MTIPV4Src(OFPMatchField):
4416     pack_str = '!I'
4417
4418     def __init__(self, header, value, mask=None):
4419         super(MTIPV4Src, self).__init__(header)
4420         self.value = value
4421         self.mask = mask
4422
4423
4424 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_DST,
4425                                       ofproto.OXM_OF_IPV4_DST_W])
4426 class MTIPV4Dst(OFPMatchField):
4427     pack_str = '!I'
4428
4429     def __init__(self, header, value, mask=None):
4430         super(MTIPV4Dst, self).__init__(header)
4431         self.value = value
4432         self.mask = mask
4433
4434
4435 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_SRC])
4436 class MTTCPSrc(OFPMatchField):
4437     pack_str = '!H'
4438
4439     def __init__(self, header, value, mask=None):
4440         super(MTTCPSrc, self).__init__(header)
4441         self.value = value
4442
4443
4444 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_DST])
4445 class MTTCPDst(OFPMatchField):
4446     pack_str = '!H'
4447
4448     def __init__(self, header, value, mask=None):
4449         super(MTTCPDst, self).__init__(header)
4450         self.value = value
4451
4452
4453 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_SRC])
4454 class MTUDPSrc(OFPMatchField):
4455     pack_str = '!H'
4456
4457     def __init__(self, header, value, mask=None):
4458         super(MTUDPSrc, self).__init__(header)
4459         self.value = value
4460
4461
4462 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_DST])
4463 class MTUDPDst(OFPMatchField):
4464     pack_str = '!H'
4465
4466     def __init__(self, header, value, mask=None):
4467         super(MTUDPDst, self).__init__(header)
4468         self.value = value
4469
4470
4471 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_SRC])
4472 class MTSCTPSrc(OFPMatchField):
4473     pack_str = '!H'
4474
4475     def __init__(self, header, value, mask=None):
4476         super(MTSCTPSrc, self).__init__(header)
4477         self.value = value
4478
4479
4480 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_DST])
4481 class MTSCTPDst(OFPMatchField):
4482     pack_str = '!H'
4483
4484     def __init__(self, header, value, mask=None):
4485         super(MTSCTPDst, self).__init__(header)
4486         self.value = value
4487
4488
4489 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_TYPE])
4490 class MTICMPV4Type(OFPMatchField):
4491     pack_str = '!B'
4492
4493     def __init__(self, header, value, mask=None):
4494         super(MTICMPV4Type, self).__init__(header)
4495         self.value = value
4496
4497
4498 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_CODE])
4499 class MTICMPV4Code(OFPMatchField):
4500     pack_str = '!B'
4501
4502     def __init__(self, header, value, mask=None):
4503         super(MTICMPV4Code, self).__init__(header)
4504         self.value = value
4505
4506
4507 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_OP])
4508 class MTArpOp(OFPMatchField):
4509     pack_str = '!H'
4510
4511     def __init__(self, header, value, mask=None):
4512         super(MTArpOp, self).__init__(header)
4513         self.value = value
4514
4515
4516 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SPA,
4517                                       ofproto.OXM_OF_ARP_SPA_W])
4518 class MTArpSpa(OFPMatchField):
4519     pack_str = '!I'
4520
4521     def __init__(self, header, value, mask=None):
4522         super(MTArpSpa, self).__init__(header)
4523         self.value = value
4524         self.mask = mask
4525
4526
4527 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_TPA,
4528                                       ofproto.OXM_OF_ARP_TPA_W])
4529 class MTArpTpa(OFPMatchField):
4530     pack_str = '!I'
4531
4532     def __init__(self, header, value, mask=None):
4533         super(MTArpTpa, self).__init__(header)
4534         self.value = value
4535         self.mask = mask
4536
4537
4538 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SHA,
4539                                       ofproto.OXM_OF_ARP_SHA_W])
4540 class MTArpSha(OFPMatchField):
4541     pack_str = '!6s'
4542
4543     def __init__(self, header, value, mask=None):
4544         super(MTArpSha, self).__init__(header)
4545         self.value = value
4546         self.mask = mask
4547
4548
4549 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_THA,
4550                                       ofproto.OXM_OF_ARP_THA_W])
4551 class MTArpTha(OFPMatchField):
4552     pack_str = '!6s'
4553
4554     def __init__(self, header, value, mask=None):
4555         super(MTArpTha, self).__init__(header)
4556         self.value = value
4557         self.mask = mask
4558
4559
4560 class MTIPv6(object):
4561     @classmethod
4562     def field_parser(cls, header, buf, offset):
4563         if ofproto.oxm_tlv_header_extract_hasmask(header):
4564             pack_str = '!' + cls.pack_str[1:] * 2
4565             value = struct.unpack_from(pack_str, buf, offset + 4)
4566             return cls(header, list(value[:8]), list(value[8:]))
4567         else:
4568             value = struct.unpack_from(cls.pack_str, buf, offset + 4)
4569             return cls(header, list(value))
4570
4571     def serialize(self, buf, offset):
4572         self.putv6(buf, offset, self.value, self.mask)
4573
4574
4575 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_SRC,
4576                                       ofproto.OXM_OF_IPV6_SRC_W])
4577 class MTIPv6Src(MTIPv6, OFPMatchField):
4578     pack_str = '!8H'
4579
4580     def __init__(self, header, value, mask=None):
4581         super(MTIPv6Src, self).__init__(header)
4582         self.value = value
4583         self.mask = mask
4584
4585
4586 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_DST,
4587                                       ofproto.OXM_OF_IPV6_DST_W])
4588 class MTIPv6Dst(MTIPv6, OFPMatchField):
4589     pack_str = '!8H'
4590
4591     def __init__(self, header, value, mask=None):
4592         super(MTIPv6Dst, self).__init__(header)
4593         self.value = value
4594         self.mask = mask
4595
4596
4597 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_FLABEL,
4598                                       ofproto.OXM_OF_IPV6_FLABEL_W])
4599 class MTIPv6Flabel(OFPMatchField):
4600     pack_str = '!I'
4601
4602     def __init__(self, header, value, mask=None):
4603         super(MTIPv6Flabel, self).__init__(header)
4604         self.value = value
4605         self.mask = mask
4606
4607
4608 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_LABEL])
4609 class MTMplsLabel(OFPMatchField):
4610     pack_str = '!I'
4611
4612     def __init__(self, header, value, mask=None):
4613         super(MTMplsLabel, self).__init__(header)
4614         self.value = value
4615
4616
4617 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_TYPE])
4618 class MTICMPV6Type(OFPMatchField):
4619     pack_str = '!B'
4620
4621     def __init__(self, header, value, mask=None):
4622         super(MTICMPV6Type, self).__init__(header)
4623         self.value = value
4624
4625
4626 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_CODE])
4627 class MTICMPV6Code(OFPMatchField):
4628     pack_str = '!B'
4629
4630     def __init__(self, header, value, mask=None):
4631         super(MTICMPV6Code, self).__init__(header)
4632         self.value = value
4633
4634
4635 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TARGET])
4636 class MTIPv6NdTarget(MTIPv6, OFPMatchField):
4637     pack_str = '!8H'
4638
4639     def __init__(self, header, value, mask=None):
4640         super(MTIPv6NdTarget, self).__init__(header)
4641         self.value = value
4642
4643     def serialize(self, buf, offset):
4644         self.putv6(buf, offset, self.value)
4645
4646
4647 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_SLL])
4648 class MTIPv6NdSll(OFPMatchField):
4649     pack_str = '!6s'
4650
4651     def __init__(self, header, value, mask=None):
4652         super(MTIPv6NdSll, self).__init__(header)
4653         self.value = value
4654
4655
4656 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TLL])
4657 class MTIPv6NdTll(OFPMatchField):
4658     pack_str = '!6s'
4659
4660     def __init__(self, header, value, mask=None):
4661         super(MTIPv6NdTll, self).__init__(header)
4662         self.value = value
4663
4664
4665 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_TC])
4666 class MTMplsTc(OFPMatchField):
4667     pack_str = '!B'
4668
4669     def __init__(self, header, value, mask=None):
4670         super(MTMplsTc, self).__init__(header)
4671         self.value = value