1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2012 Isaku Yamahata <yamahata at valinux co jp>
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 Decoder/Encoder implementations of OpenFlow 1.2.
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
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
37 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_2_parser')
42 def _set_msg_type(msg_type):
43 def _set_cls_msg_type(cls):
44 cls.cls_msg_type = msg_type
46 return _set_cls_msg_type
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
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)
64 @_set_msg_type(ofproto.OFPT_HELLO)
65 class OFPHello(MsgBase):
69 When connection is started, the hello message is exchanged between a
70 switch and a controller.
72 This message is handled by the Ryu framework, so the Ryu application
73 do not need to process this typically.
76 def __init__(self, datapath):
77 super(OFPHello, self).__init__(datapath)
81 @_set_msg_type(ofproto.OFPT_ERROR)
82 class OFPErrorMsg(MsgBase):
86 The switch notifies controller of problems by this message.
88 ========== =========================================================
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 ========== =========================================================
96 ``type`` attribute corresponds to ``type_`` parameter of __init__.
98 Types and codes are defined in ``ryu.ofproto.ofproto``.
100 ============================= ===========
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 ============================= ===========
118 If ``type == OFPET_EXPERIMENTER``, this message has also the following
121 ============= ======================================================
122 Attribute Description
123 ============= ======================================================
124 exp_type Experimenter defined type
125 experimenter Experimenter ID
126 ============= ======================================================
130 @set_ev_cls(ofp_event.EventOFPErrorMsg,
131 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
132 def error_msg_handler(self, ev):
135 self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
137 msg.type, msg.code, utils.hex_array(msg.data))
140 def __init__(self, datapath, type_=None, code=None, data=None, **kwargs):
141 super(OFPErrorMsg, self).__init__(datapath)
144 if isinstance(data, six.string_types):
145 data = data.encode('ascii')
147 if self.type == ofproto.OFPET_EXPERIMENTER:
148 self.exp_type = kwargs.get('exp_type', None)
149 self.experimenter = kwargs.get('experimenter', None)
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,
157 if type_ == ofproto.OFPET_EXPERIMENTER:
158 (msg.type, msg.exp_type, msg.experimenter,
159 msg.data) = cls.parse_experimenter_body(buf)
162 msg.data) = cls.parse_body(buf)
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
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
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
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
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
206 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
207 class OFPEchoRequest(MsgBase):
211 This message is handled by the Ryu framework, so the Ryu application
212 do not need to process this typically.
214 ========== =========================================================
215 Attribute Description
216 ========== =========================================================
217 data An arbitrary length data
218 ========== =========================================================
222 def send_echo_request(self, datapath, data):
223 ofp_parser = datapath.ofproto_parser
225 req = ofp_parser.OFPEchoRequest(datapath, data)
226 datapath.send_msg(req)
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))
235 def __init__(self, datapath, data=None):
236 super(OFPEchoRequest, self).__init__(datapath)
240 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
241 msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
243 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
246 def _serialize_body(self):
247 if self.data is not None:
248 self.buf += self.data
252 @_set_msg_type(ofproto.OFPT_ECHO_REPLY)
253 class OFPEchoReply(MsgBase):
257 This message is handled by the Ryu framework, so the Ryu application
258 do not need to process this typically.
260 ========== =========================================================
261 Attribute Description
262 ========== =========================================================
263 data An arbitrary length data
264 ========== =========================================================
268 def send_echo_reply(self, datapath, data):
269 ofp_parser = datapath.ofproto_parser
271 reply = ofp_parser.OFPEchoReply(datapath, data)
272 datapath.send_msg(reply)
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))
281 def __init__(self, datapath, data=None):
282 super(OFPEchoReply, self).__init__(datapath)
286 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
287 msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
289 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
292 def _serialize_body(self):
293 assert self.data is not None
294 self.buf += self.data
298 @_set_msg_type(ofproto.OFPT_EXPERIMENTER)
299 class OFPExperimenter(MsgBase):
301 Experimenter extension message
303 ============= =========================================================
304 Attribute Description
305 ============= =========================================================
306 experimenter Experimenter ID
307 exp_type Experimenter defined
308 data Experimenter defined arbitrary additional data
309 ============= =========================================================
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
319 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
320 msg = super(OFPExperimenter, cls).parser(datapath, version, msg_type,
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:]
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
337 class OFPPort(ofproto_parser.namedtuple('OFPPort', (
338 'port_no', 'hw_addr', 'name', 'config', 'state', 'curr',
339 'advertised', 'supported', 'peer', 'curr_speed', 'max_speed'))):
341 Description of a port
343 ========== =========================================================
344 Attribute Description
345 ========== =========================================================
346 port_no Port number and it uniquely identifies a port within
348 hw_addr MAC address for the port.
349 name Null-terminated string containing a human-readable name
351 config Bitmap of port configration flags.
357 state Bitmap of port state flags.
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 ========== =========================================================
376 # OF spec is unclear about the encoding of name.
377 # we assumes UTF-8, which is used by OVS.
383 def parser(cls, buf, offset):
384 port = struct.unpack_from(ofproto.OFP_PORT_PACK_STR, buf, offset)
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')
393 @_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
394 class OFPFeaturesRequest(MsgBase):
396 Features request message
398 The controller sends a feature request to the switch upon session
401 This message is handled by the Ryu framework, so the Ryu application
402 do not need to process this typically.
406 def send_features_request(self, datapath):
407 ofp_parser = datapath.ofproto_parser
409 req = ofp_parser.OFPFeaturesRequest(datapath)
410 datapath.send_msg(req)
413 def __init__(self, datapath):
414 super(OFPFeaturesRequest, self).__init__(datapath)
418 @_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
419 class OFPSwitchFeatures(MsgBase):
421 Features reply message
423 The switch responds with a features reply message to a features
426 This message is handled by the Ryu framework, so the Ryu application
427 do not need to process this typically.
431 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
432 def switch_features_handler(self, ev):
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)
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
452 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
453 msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
459 msg._reserved) = struct.unpack_from(
460 ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
461 ofproto.OFP_HEADER_SIZE)
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
475 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
476 class OFPGetConfigRequest(MsgBase):
478 Get config request message
480 The controller sends a get config request to query configuration
481 parameters in the switch.
485 def send_get_config_request(self, datapath):
486 ofp_parser = datapath.ofproto_parser
488 req = ofp_parser.OFPGetConfigRequest(datapath)
489 datapath.send_msg(req)
492 def __init__(self, datapath):
493 super(OFPGetConfigRequest, self).__init__(datapath)
497 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
498 class OFPGetConfigReply(MsgBase):
500 Get config reply message
502 The switch responds to a configuration request with a get config reply
505 ============= =========================================================
506 Attribute Description
507 ============= =========================================================
508 flags One of the following configuration flags.
514 | OFPC_INVALID_TTL_TO_CONTROLLER
515 miss_send_len Max bytes of new flow that datapath should send to the
517 ============= =========================================================
521 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
522 def get_config_reply_handler(self, ev):
527 if msg.flags == ofp.OFPC_FRAG_NORMAL:
529 elif msg.flags == ofp.OFPC_FRAG_DROP:
531 elif msg.flags == ofp.OFPC_FRAG_REASM:
533 elif msg.flags == ofp.OFPC_FRAG_MASK:
535 elif msg.flags == ofp.OFPC_INVALID_TTL_TO_CONTROLLER:
536 flags = 'INVALID TTL TO CONTROLLER'
539 self.logger.debug('OFPGetConfigReply received: '
540 'flags=%s miss_send_len=%d',
541 flags, msg.miss_send_len)
544 def __init__(self, datapath, flags=None, miss_send_len=None):
545 super(OFPGetConfigReply, self).__init__(datapath)
547 self.miss_send_len = miss_send_len
550 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
551 msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
553 msg.flags, msg.miss_send_len = struct.unpack_from(
554 ofproto.OFP_SWITCH_CONFIG_PACK_STR, msg.buf,
555 ofproto.OFP_HEADER_SIZE)
559 @_set_msg_type(ofproto.OFPT_SET_CONFIG)
560 class OFPSetConfig(MsgBase):
562 Set config request message
564 The controller sends a set config request message to set configuraion
567 ============= =========================================================
568 Attribute Description
569 ============= =========================================================
570 flags One of the following configuration flags.
576 | OFPC_INVALID_TTL_TO_CONTROLLER
577 miss_send_len Max bytes of new flow that datapath should send to the
579 ============= =========================================================
583 def send_set_config(self, datapath):
584 ofp = datapath.ofproto
585 ofp_parser = datapath.ofproto_parser
587 req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
588 datapath.send_msg(req)
591 def __init__(self, datapath, flags=0, miss_send_len=0):
592 super(OFPSetConfig, self).__init__(datapath)
594 self.miss_send_len = miss_send_len
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)
605 @_set_msg_type(ofproto.OFPT_PACKET_IN)
606 class OFPPacketIn(MsgBase):
610 The switch sends the packet that received to the controller by this
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.
623 table_id ID of the table that was looked up
624 match Instance of ``OFPMatch``
626 ============= =========================================================
630 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
631 def packet_in_handler(self, ev):
636 if msg.reason == ofp.OFPR_NO_MATCH:
638 elif msg.reason == ofp.OFPR_ACTION:
640 elif msg.reason == ofp.OFPR_INVALID_TTL:
641 reason = 'INVALID TTL'
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))
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
659 self.table_id = table_id
664 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
665 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
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)
672 msg.match = OFPMatch.parser(msg.buf, ofproto.OFP_PACKET_IN_SIZE -
673 ofproto.OFP_MATCH_SIZE)
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):]
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]
687 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
688 class OFPFlowRemoved(MsgBase):
692 When flow entries time out or are deleted, the switch notifies controller
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.
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 ================ ======================================================
718 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
719 def flow_removed_handler(self, ev):
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:
730 elif msg.reason == ofp.OFPRR_GROUP_DELETE:
731 reason = 'GROUP DELETE'
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)
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)
752 self.priority = priority
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
764 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
765 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
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,
774 ofproto.OFP_HEADER_SIZE)
776 offset = (ofproto.OFP_FLOW_REMOVED_SIZE -
777 ofproto.OFP_MATCH_SIZE)
779 msg.match = OFPMatch.parser(msg.buf, offset)
785 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
786 class OFPPortStatus(MsgBase):
790 The switch notifies controller of change of ports.
792 ================ ======================================================
793 Attribute Description
794 ================ ======================================================
795 reason One of the following values.
800 desc instance of ``OFPPort``
801 ================ ======================================================
805 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
806 def port_status_handler(self, ev):
811 if msg.reason == ofp.OFPPR_ADD:
813 elif msg.reason == ofp.OFPPR_DELETE:
815 elif msg.reason == ofp.OFPPR_MODIFY:
820 self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
824 def __init__(self, datapath, reason=None, desc=None):
825 super(OFPPortStatus, self).__init__(datapath)
830 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
831 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
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)
841 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
842 class OFPPacketOut(MsgBase):
846 The controller uses this message to send a packet out throught the
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 ================ ======================================================
861 def send_packet_out(self, datapath, buffer_id, in_port):
862 ofp = datapath.ofproto
863 ofp_parser = datapath.ofproto_parser
865 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
866 req = ofp_parser.OFPPacketOut(datapath, buffer_id,
868 datapath.send_msg(req)
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
877 super(OFPPacketOut, self).__init__(datapath)
878 self.buffer_id = buffer_id
879 self.in_port = in_port
881 self.actions = actions
884 def _serialize_body(self):
886 offset = ofproto.OFP_PACKET_OUT_SIZE
887 for a in self.actions:
888 a.serialize(self.buf, offset)
890 self.actions_len += a.len
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
898 self.buf += self.data
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)
905 def from_jsondict(cls, dict_, decode_string=base64.b64decode,
907 if isinstance(dict_['data'], dict):
908 data = dict_.pop('data')
909 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
912 ins.data = packet.Packet.from_jsondict(data['Packet'])
915 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
923 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
924 class OFPFlowMod(MsgBase):
926 Modify Flow entry message
928 The controller sends this message to modify the flow table.
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
937 table_id ID of the table to put the flow in
938 command One of the following values.
942 | OFPFC_MODIFY_STRICT
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.
955 | OFPFF_SEND_FLOW_REM
956 | OFPFF_CHECK_OVERLAP
958 match Instance of ``OFPMatch``
959 instructions list of ``OFPInstruction*`` instance
960 ================ ======================================================
964 def send_flow_mod(self, datapath):
965 ofp = datapath.ofproto
966 ofp_parser = datapath.ofproto_parser
968 cookie = cookie_mask = 0
970 idle_timeout = hard_timeout = 0
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,
977 req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask,
978 table_id, ofp.OFPFC_ADD,
979 idle_timeout, hard_timeout,
981 ofp.OFPP_ANY, ofp.OFPG_ANY,
982 ofp.OFPFF_SEND_FLOW_REM,
984 datapath.send_msg(req)
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,
994 instructions = instructions if instructions else []
995 super(OFPFlowMod, self).__init__(datapath)
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
1009 assert isinstance(match, OFPMatch)
1011 for i in instructions:
1012 assert isinstance(i, OFPInstruction)
1013 self.instructions = instructions
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)
1023 offset = (ofproto.OFP_FLOW_MOD_SIZE -
1024 ofproto.OFP_MATCH_SIZE)
1026 match_len = self.match.serialize(self.buf, offset)
1029 for inst in self.instructions:
1030 inst.serialize(self.buf, offset)
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)
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
1046 msg.match = OFPMatch.parser(buf, offset)
1047 offset += utils.round_up(msg.match.length, 8)
1050 while offset < msg_len:
1051 i = OFPInstruction.parser(buf, offset)
1052 instructions.append(i)
1054 msg.instructions = instructions
1059 class OFPInstruction(StringifyMixin):
1060 _INSTRUCTION_TYPES = {}
1063 def register_instruction_type(types):
1064 def _register_instruction_type(cls):
1066 OFPInstruction._INSTRUCTION_TYPES[type_] = cls
1068 return _register_instruction_type
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)
1077 @OFPInstruction.register_instruction_type([ofproto.OFPIT_GOTO_TABLE])
1078 class OFPInstructionGotoTable(OFPInstruction):
1080 Goto table instruction
1082 This instruction indicates the next table in the processing pipeline.
1084 ================ ======================================================
1085 Attribute Description
1086 ================ ======================================================
1088 ================ ======================================================
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
1098 def parser(cls, buf, offset):
1099 (type_, len_, table_id) = struct.unpack_from(
1100 ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
1102 return cls(table_id)
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)
1109 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_METADATA])
1110 class OFPInstructionWriteMetadata(OFPInstruction):
1112 Write metadata instruction
1114 This instruction writes the masked metadata value into the metadata field.
1116 ================ ======================================================
1117 Attribute Description
1118 ================ ======================================================
1119 metadata Metadata value to write
1120 metadata_mask Metadata write bitmask
1121 ================ ======================================================
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
1132 def parser(cls, buf, offset):
1133 (type_, len_, metadata, metadata_mask) = struct.unpack_from(
1134 ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
1136 return cls(metadata, metadata_mask)
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,
1144 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS,
1145 ofproto.OFPIT_APPLY_ACTIONS,
1146 ofproto.OFPIT_CLEAR_ACTIONS])
1147 class OFPInstructionActions(OFPInstruction):
1151 This instruction writes/applies/clears the actions.
1153 ================ ======================================================
1154 Attribute Description
1155 ================ ======================================================
1156 type One of following values.
1158 | OFPIT_WRITE_ACTIONS
1159 | OFPIT_APPLY_ACTIONS
1160 | OFPIT_CLEAR_ACTIONS
1161 actions list of OpenFlow action class
1162 ================ ======================================================
1164 ``type`` attribute corresponds to ``type_`` parameter of __init__.
1167 def __init__(self, type_, actions=None, len_=None):
1168 super(OFPInstructionActions, self).__init__()
1171 assert isinstance(a, OFPAction)
1172 self.actions = actions
1175 def parser(cls, buf, offset):
1176 (type_, len_) = struct.unpack_from(
1177 ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
1180 offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1182 actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1183 while actions_len > 0:
1184 a = OFPAction.parser(buf, offset)
1186 actions_len -= a.len
1189 inst = cls(type_, actions)
1193 def serialize(self, buf, offset):
1194 action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
1196 for a in self.actions:
1197 assert isinstance(a, OFPAction)
1198 a.serialize(buf, action_offset)
1199 action_offset += a.len
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)
1206 msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
1207 buf, offset, self.type, self.len)
1210 class OFPActionHeader(StringifyMixin):
1211 def __init__(self, type_, len_):
1215 def serialize(self, buf, offset):
1216 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
1217 buf, offset, self.type, self.len)
1220 class OFPAction(OFPActionHeader):
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
1230 return _register_action_type
1233 cls = self.__class__
1234 super(OFPAction, self).__init__(cls.cls_action_type,
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)
1245 def serialize(self, buf, offset):
1246 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR, buf,
1247 offset, self.type, self.len)
1250 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
1251 ofproto.OFP_ACTION_OUTPUT_SIZE)
1252 class OFPActionOutput(OFPAction):
1256 This action indicates output a packet to the switch port.
1258 ================ ======================================================
1259 Attribute Description
1260 ================ ======================================================
1262 max_len Max length to send to controller
1263 ================ ======================================================
1266 def __init__(self, port, max_len=ofproto.OFPCML_MAX,
1267 type_=None, len_=None):
1268 super(OFPActionOutput, self).__init__()
1270 self.max_len = max_len
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)
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)
1283 @OFPAction.register_action_type(ofproto.OFPAT_GROUP,
1284 ofproto.OFP_ACTION_GROUP_SIZE)
1285 class OFPActionGroup(OFPAction):
1289 This action indicates the group used to process the packet.
1291 ================ ======================================================
1292 Attribute Description
1293 ================ ======================================================
1294 group_id Group identifier
1295 ================ ======================================================
1298 def __init__(self, group_id=0, type_=None, len_=None):
1299 super(OFPActionGroup, self).__init__()
1300 self.group_id = group_id
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)
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)
1313 @OFPAction.register_action_type(ofproto.OFPAT_SET_QUEUE,
1314 ofproto.OFP_ACTION_SET_QUEUE_SIZE)
1315 class OFPActionSetQueue(OFPAction):
1319 This action sets the queue id that will be used to map a flow to an
1320 already-configured queue on a port.
1322 ================ ======================================================
1323 Attribute Description
1324 ================ ======================================================
1325 queue_id Queue ID for the packets
1326 ================ ======================================================
1329 def __init__(self, queue_id, type_=None, len_=None):
1330 super(OFPActionSetQueue, self).__init__()
1331 self.queue_id = queue_id
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)
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)
1344 @OFPAction.register_action_type(ofproto.OFPAT_SET_MPLS_TTL,
1345 ofproto.OFP_ACTION_MPLS_TTL_SIZE)
1346 class OFPActionSetMplsTtl(OFPAction):
1350 This action sets the MPLS TTL.
1352 ================ ======================================================
1353 Attribute Description
1354 ================ ======================================================
1356 ================ ======================================================
1359 def __init__(self, mpls_ttl, type_=None, len_=None):
1360 super(OFPActionSetMplsTtl, self).__init__()
1361 self.mpls_ttl = mpls_ttl
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)
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)
1374 @OFPAction.register_action_type(ofproto.OFPAT_DEC_MPLS_TTL,
1375 ofproto.OFP_ACTION_HEADER_SIZE)
1376 class OFPActionDecMplsTtl(OFPAction):
1378 Decrement MPLS TTL action
1380 This action decrements the MPLS TTL.
1383 def __init__(self, type_=None, len_=None):
1384 super(OFPActionDecMplsTtl, self).__init__()
1387 def parser(cls, buf, offset):
1388 (type_, len_) = struct.unpack_from(
1389 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1393 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TTL,
1394 ofproto.OFP_ACTION_NW_TTL_SIZE)
1395 class OFPActionSetNwTtl(OFPAction):
1399 This action sets the IP TTL.
1401 ================ ======================================================
1402 Attribute Description
1403 ================ ======================================================
1405 ================ ======================================================
1408 def __init__(self, nw_ttl, type_=None, len_=None):
1409 super(OFPActionSetNwTtl, self).__init__()
1410 self.nw_ttl = nw_ttl
1413 def parser(cls, buf, offset):
1414 (type_, len_, nw_ttl) = struct.unpack_from(
1415 ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
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)
1423 @OFPAction.register_action_type(ofproto.OFPAT_DEC_NW_TTL,
1424 ofproto.OFP_ACTION_HEADER_SIZE)
1425 class OFPActionDecNwTtl(OFPAction):
1427 Decrement IP TTL action
1429 This action decrements the IP TTL.
1432 def __init__(self, type_=None, len_=None):
1433 super(OFPActionDecNwTtl, self).__init__()
1436 def parser(cls, buf, offset):
1437 (type_, len_) = struct.unpack_from(
1438 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1442 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_OUT,
1443 ofproto.OFP_ACTION_HEADER_SIZE)
1444 class OFPActionCopyTtlOut(OFPAction):
1448 This action copies the TTL from the next-to-outermost header with TTL to
1449 the outermost header with TTL.
1452 def __init__(self, type_=None, len_=None):
1453 super(OFPActionCopyTtlOut, self).__init__()
1456 def parser(cls, buf, offset):
1457 (type_, len_) = struct.unpack_from(
1458 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1462 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_IN,
1463 ofproto.OFP_ACTION_HEADER_SIZE)
1464 class OFPActionCopyTtlIn(OFPAction):
1468 This action copies the TTL from the outermost header with TTL to the
1469 next-to-outermost header with TTL.
1472 def __init__(self, type_=None, len_=None):
1473 super(OFPActionCopyTtlIn, self).__init__()
1476 def parser(cls, buf, offset):
1477 (type_, len_) = struct.unpack_from(
1478 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1482 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_VLAN,
1483 ofproto.OFP_ACTION_PUSH_SIZE)
1484 class OFPActionPushVlan(OFPAction):
1488 This action pushes a new VLAN tag to the packet.
1490 ================ ======================================================
1491 Attribute Description
1492 ================ ======================================================
1493 ethertype Ether type. The default is 802.1Q. (0x8100)
1494 ================ ======================================================
1497 def __init__(self, ethertype=ether.ETH_TYPE_8021Q, type_=None, len_=None):
1498 super(OFPActionPushVlan, self).__init__()
1499 self.ethertype = ethertype
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)
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)
1512 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_MPLS,
1513 ofproto.OFP_ACTION_PUSH_SIZE)
1514 class OFPActionPushMpls(OFPAction):
1518 This action pushes a new MPLS header to the packet.
1520 ================ ======================================================
1521 Attribute Description
1522 ================ ======================================================
1523 ethertype Ether type
1524 ================ ======================================================
1527 def __init__(self, ethertype=ether.ETH_TYPE_MPLS, type_=None, len_=None):
1528 super(OFPActionPushMpls, self).__init__()
1529 self.ethertype = ethertype
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)
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)
1542 @OFPAction.register_action_type(ofproto.OFPAT_POP_VLAN,
1543 ofproto.OFP_ACTION_HEADER_SIZE)
1544 class OFPActionPopVlan(OFPAction):
1548 This action pops the outermost VLAN tag from the packet.
1551 def __init__(self, type_=None, len_=None):
1552 super(OFPActionPopVlan, self).__init__()
1555 def parser(cls, buf, offset):
1556 (type_, len_) = struct.unpack_from(
1557 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
1561 @OFPAction.register_action_type(ofproto.OFPAT_POP_MPLS,
1562 ofproto.OFP_ACTION_POP_MPLS_SIZE)
1563 class OFPActionPopMpls(OFPAction):
1567 This action pops the MPLS header from the packet.
1570 def __init__(self, ethertype=ether.ETH_TYPE_IP, type_=None, len_=None):
1571 super(OFPActionPopMpls, self).__init__()
1572 self.ethertype = ethertype
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)
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)
1585 @OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
1586 ofproto.OFP_ACTION_SET_FIELD_SIZE)
1587 class OFPActionSetField(OFPAction):
1591 This action modifies a header field in the packet.
1593 The set of keywords available for this is same as OFPMatch.
1597 set_field = OFPActionSetField(eth_src="00:00:00:00:00:00")
1600 def __init__(self, field=None, **kwargs):
1602 # OFPActionSetField(field)
1604 # OFPActionSetField(eth_src="00:00:00:00:00")
1605 super(OFPActionSetField, self).__init__()
1606 if isinstance(field, OFPMatchField):
1608 assert len(kwargs) == 0
1612 assert len(kwargs) == 1
1613 key = list(kwargs.keys())[0]
1615 assert isinstance(key, (str, six.text_type))
1616 assert not isinstance(value, tuple) # no mask
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})
1629 action.field = OFPMatchField.parser(buf, offset + 4)
1633 def serialize(self, buf, offset):
1635 if self._composed_with_old_api():
1636 return self.serialize_old(buf, offset)
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_)
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_
1651 msg_pack_into('!HH', buf, offset, self.type, self.len)
1652 self.field.serialize(buf, offset + 4)
1654 msg_pack_into("%dx" % pad_len, buf, offset)
1656 # XXX old api compat
1657 def _composed_with_old_api(self):
1658 return not hasattr(self, 'value')
1660 def to_jsondict(self):
1662 self.__class__.__name__: {
1663 'field': ofproto.oxm_to_jsondict(self.key, self.value),
1670 def from_jsondict(cls, dict_):
1671 k, v = ofproto.oxm_from_jsondict(dict_['field'])
1672 o = OFPActionSetField(**{k: v})
1674 # XXX old api compat
1675 # serialize and parse to fill old attributes
1678 return OFPActionSetField.parser(six.binary_type(buf), 0)
1680 # XXX old api compat
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
1688 o2.serialize(buf, 0)
1689 o = OFPActionSetField.parser(six.binary_type(buf), 0)
1692 return super(OFPActionSetField, o).__str__()
1696 def stringify_attrs(self):
1697 yield (self.key, self.value)
1700 @OFPAction.register_action_type(
1701 ofproto.OFPAT_EXPERIMENTER,
1702 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
1703 class OFPActionExperimenter(OFPAction):
1707 This action is an extensible action for the experimenter.
1709 ================ ======================================================
1710 Attribute Description
1711 ================ ======================================================
1712 experimenter Experimenter ID
1713 ================ ======================================================
1717 For the list of the supported Nicira experimenter actions,
1718 please refer to :ref:`ryu.ofproto.nx_actions <nx_actions_structures>`.
1721 def __init__(self, experimenter, type_=None, len_=None):
1722 super(OFPActionExperimenter, self).__init__()
1723 self.experimenter = experimenter
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)
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)
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
1748 def parser(cls, buf, offset):
1749 (len_, weigth, watch_port, watch_group) = struct.unpack_from(
1750 ofproto.OFP_BUCKET_PACK_STR, buf, offset)
1752 length = ofproto.OFP_BUCKET_SIZE
1753 offset += ofproto.OFP_BUCKET_SIZE
1755 while length < len_:
1756 action = OFPAction.parser(buf, offset)
1757 actions.append(action)
1758 offset += action.len
1759 length += action.len
1761 m = cls(weigth, watch_port, watch_group, actions)
1765 def serialize(self, buf, offset):
1766 action_offset = offset + ofproto.OFP_BUCKET_SIZE
1768 for a in self.actions:
1769 a.serialize(buf, action_offset)
1770 action_offset += a.len
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,
1779 @_set_msg_type(ofproto.OFPT_GROUP_MOD)
1780 class OFPGroupMod(MsgBase):
1782 Modify group entry message
1784 The controller sends this message to modify the group table.
1786 ================ ======================================================
1787 Attribute Description
1788 ================ ======================================================
1789 command One of the following values.
1794 type One of the following values.
1800 group_id Group identifier
1801 buckets list of ``OFPBucket``
1802 ================ ======================================================
1804 ``type`` attribute corresponds to ``type_`` parameter of __init__.
1808 def send_group_mod(self, datapath):
1809 ofp = datapath.ofproto
1810 ofp_parser = datapath.ofproto_parser
1814 actions = [ofp_parser.OFPActionOutput(port, max_len)]
1819 buckets = [ofp_parser.OFPBucket(weight, watch_port, watch_group,
1823 req = ofp_parser.OFPGroupMod(datapath, ofp.OFPGC_ADD,
1824 ofp.OFPGT_SELECT, group_id, buckets)
1825 datapath.send_msg(req)
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
1834 self.group_id = group_id
1835 self.buckets = buckets
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)
1842 offset = ofproto.OFP_GROUP_MOD_SIZE
1843 for b in self.buckets:
1844 b.serialize(self.buf, offset)
1848 @_set_msg_type(ofproto.OFPT_PORT_MOD)
1849 class OFPPortMod(MsgBase):
1851 Port modification message
1853 The controller sneds this message to modify the behavior of the port.
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.
1866 | OFPPC_NO_PACKET_IN
1867 mask Bitmap of configuration flags above to be changed
1868 advertise Bitmap of the following flags.
1886 ================ ======================================================
1890 def send_port_mod(self, datapath):
1891 ofp = datapath.ofproto
1892 ofp_parser = datapath.ofproto_parser
1895 hw_addr = 'fa:c8:e8:76:1d:7e'
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,
1905 datapath.send_msg(req)
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
1921 self.advertise = advertise
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),
1928 self.mask, self.advertise)
1931 @_set_msg_type(ofproto.OFPT_TABLE_MOD)
1932 class OFPTableMod(MsgBase):
1934 Flow table configuration message
1936 The controller sends this message to configure table state.
1938 ================ ======================================================
1939 Attribute Description
1940 ================ ======================================================
1941 table_id ID of the table (OFPTT_ALL indicates all tables)
1942 config Bitmap of the following flags.
1944 | OFPTC_TABLE_MISS_CONTROLLER
1945 | OFPTC_TABLE_MISS_CONTINUE
1946 | OFPTC_TABLE_MISS_DROP
1947 | OFPTC_TABLE_MISS_MASK
1948 ================ ======================================================
1952 def send_table_mod(self, datapath):
1953 ofp = datapath.ofproto
1954 ofp_parser = datapath.ofproto_parser
1956 req = ofp_parser.OFPTableMod(datapath, ofp.OFPTT_ALL,
1957 ofp.OFPTC_TABLE_MISS_DROP)
1958 datapath.send_msg(req)
1961 def __init__(self, datapath, table_id, config):
1962 super(OFPTableMod, self).__init__(datapath)
1963 self.table_id = table_id
1964 self.config = config
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)
1972 class OFPStatsRequest(MsgBase):
1973 def __init__(self, datapath, type_, flags=0):
1974 super(OFPStatsRequest, self).__init__(datapath)
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
1985 def _serialize_stats_body(self):
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)
1993 self._serialize_stats_body()
1997 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
1998 class OFPStatsReply(MsgBase):
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
2007 return _register_stats_reply_type
2009 def __init__(self, datapath, type_=None, flags=None, body=None):
2010 super(OFPStatsReply, self).__init__(datapath)
2016 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2017 msg = super(OFPStatsReply, cls).parser(datapath, version, msg_type,
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)
2024 offset = ofproto.OFP_STATS_REPLY_SIZE
2026 while offset < msg_len:
2027 r = stats_type_cls.parser(msg.buf, offset)
2031 if stats_type_cls.cls_body_single_struct:
2039 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2040 class OFPDescStatsRequest(OFPStatsRequest):
2042 Description statistics request message
2044 The controller uses this message to query description of the switch.
2046 ================ ======================================================
2047 Attribute Description
2048 ================ ======================================================
2049 flags Zero (none yet defined in the spec)
2050 ================ ======================================================
2054 def send_desc_stats_request(self, datapath):
2055 ofp_parser = datapath.ofproto_parser
2057 req = ofp_parser.OFPDescStatsRequest(datapath)
2058 datapath.send_msg(req)
2061 def __init__(self, datapath, flags=0):
2062 super(OFPDescStatsRequest, self).__init__(datapath,
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'))):
2072 Description statistics reply message
2074 The switch responds with a stats reply that include this message to
2075 a description statistics request.
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 ================ ======================================================
2089 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2090 def stats_reply_handler(self, ev):
2092 ofp = msg.datapath.ofproto
2095 if msg.type == ofp.OFPST_DESC:
2096 self.desc_stats_reply_handler(body)
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)
2116 def parser(cls, buf, offset):
2117 desc = struct.unpack_from(ofproto.OFP_DESC_STATS_PACK_STR,
2120 desc = [x.rstrip(b'\0') for x in desc]
2122 stats.length = ofproto.OFP_DESC_STATS_SIZE
2126 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2127 class OFPFlowStatsRequest(OFPStatsRequest):
2129 Individual flow statistics request message
2131 The controller uses this message to query individual flow statistics.
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
2139 out_group Require matching entries to include this as an output
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 ================ ======================================================
2149 def send_flow_stats_request(self, datapath):
2150 ofp = datapath.ofproto
2151 ofp_parser = datapath.ofproto_parser
2153 cookie = cookie_mask = 0
2154 match = ofp_parser.OFPMatch(in_port=1)
2155 req = ofp_parser.OFPFlowStatsRequest(datapath,
2157 ofp.OFPP_ANY, ofp.OFPG_ANY,
2158 cookie, cookie_mask, match)
2159 datapath.send_msg(req)
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,
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
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)
2184 offset = (ofproto.OFP_STATS_REQUEST_SIZE +
2185 ofproto.OFP_FLOW_STATS_REQUEST_SIZE -
2186 ofproto.OFP_MATCH_SIZE)
2188 self.match.serialize(self.buf, offset)
2191 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_FLOW)
2192 class OFPFlowStats(StringifyMixin):
2194 Individual flow statistics reply message
2196 The switch responds with a stats reply that include this message to
2197 an individual flow statistics request.
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
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 ================ ======================================================
2218 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2219 def stats_reply_handler(self, ev):
2221 ofp = msg.datapath.ofproto
2224 if msg.type == ofp.OFPST_FLOW:
2225 self.flow_stats_reply_handler(body)
2227 def flow_stats_reply_handler(self, body):
2230 flows.append('table_id=%s '
2231 'duration_sec=%d duration_nsec=%d '
2233 'idle_timeout=%d hard_timeout=%d '
2234 'cookie=%d packet_count=%d byte_count=%d '
2235 'match=%s instructions=%s' %
2237 stat.duration_sec, stat.duration_nsec,
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)
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
2259 self.instructions = instructions
2260 self.length = length
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,
2270 offset += (ofproto.OFP_FLOW_STATS_SIZE -
2271 ofproto.OFP_MATCH_SIZE)
2272 match = OFPMatch.parser(buf, offset)
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
2279 while inst_length > 0:
2280 inst = OFPInstruction.parser(buf, offset)
2281 instructions.append(inst)
2283 inst_length -= inst.len
2285 o = cls(table_id, duration_sec, duration_nsec, priority,
2286 idle_timeout, hard_timeout, cookie, packet_count,
2287 byte_count, match, instructions)
2292 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2293 class OFPAggregateStatsRequest(OFPStatsRequest):
2295 Aggregate flow statistics request message
2297 The controller uses this message to query aggregate flow statictics.
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
2305 out_group Require matching entries to include this as an output
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 ================ ======================================================
2315 def send_aggregate_stats_request(self, datapath):
2316 ofp = datapath.ofproto
2317 ofp_parser = datapath.ofproto_parser
2319 cookie = cookie_mask = 0
2320 match = ofp_parser.OFPMatch(in_port=1)
2321 req = ofp_parser.OFPAggregateStatsRequest(datapath, 0,
2325 cookie, cookie_mask,
2327 datapath.send_msg(req)
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__(
2336 ofproto.OFPST_AGGREGATE,
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
2347 def _serialize_stats_body(self):
2348 msg_pack_into(ofproto.OFP_AGGREGATE_STATS_REQUEST_PACK_STR,
2350 ofproto.OFP_STATS_REQUEST_SIZE,
2351 self.table_id, self.out_port, self.out_group,
2352 self.cookie, self.cookie_mask)
2354 offset = (ofproto.OFP_STATS_REQUEST_SIZE +
2355 ofproto.OFP_AGGREGATE_STATS_REQUEST_SIZE -
2356 ofproto.OFP_MATCH_SIZE)
2358 self.match.serialize(self.buf, offset)
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'))):
2366 Aggregate flow statistics reply message
2368 The switch responds with a stats reply that include this message to
2369 an aggregate flow statistics request.
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 ================ ======================================================
2381 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2382 def stats_reply_handler(self, ev):
2384 ofp = msg.datapath.ofproto
2387 if msg.type == ofp.OFPST_AGGREGATE:
2388 self.aggregate_stats_reply_handler(body)
2390 def aggregate_stats_reply_handler(self, body):
2391 self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
2393 body.packet_count, body.byte_count,
2398 def parser(cls, buf, offset):
2399 desc = struct.unpack_from(
2400 ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR,
2403 stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
2407 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2408 class OFPTableStatsRequest(OFPStatsRequest):
2410 Table statistics request message
2412 The controller uses this message to query flow table statictics.
2414 ================ ======================================================
2415 Attribute Description
2416 ================ ======================================================
2417 flags Zero (none yet defined in the spec)
2418 ================ ======================================================
2422 def send_table_stats_request(self, datapath):
2423 ofp_parser = datapath.ofproto_parser
2425 req = ofp_parser.OFPTableStatsRequest(datapath)
2426 datapath.send_msg(req)
2429 def __init__(self, datapath, flags=0):
2430 super(OFPTableStatsRequest, self).__init__(datapath,
2431 ofproto.OFPST_TABLE,
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'))):
2446 Table statistics reply message
2448 The switch responds with a stats reply that include this message to
2449 a table statistics request.
2451 ================ ======================================================
2452 Attribute Description
2453 ================ ======================================================
2454 table_id ID of table
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
2460 write_actions Bitmap of OFPAT_* that are supported by the table with
2462 apply_actions Bitmap of OFPAT_* that are supported by the table with
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 ================ ======================================================
2480 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2481 def stats_reply_handler(self, ev):
2483 ofp = msg.datapath.ofproto
2486 if msg.type == ofp.OFPST_TABLE:
2487 self.table_stats_reply_handler(body)
2489 def table_stats_reply_handler(self, 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)
2501 # OF spec is unclear about the encoding of name.
2508 def parser(cls, buf, offset):
2509 table = struct.unpack_from(
2510 ofproto.OFP_TABLE_STATS_PACK_STR,
2513 i = cls._fields.index('name')
2514 table[i] = table[i].rstrip(b'\0')
2516 stats.length = ofproto.OFP_TABLE_STATS_SIZE
2520 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2521 class OFPPortStatsRequest(OFPStatsRequest):
2523 Port statistics request message
2525 The controller uses this message to query information about ports
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 ================ ======================================================
2537 def send_port_stats_request(self, datapath):
2538 ofp = datapath.ofproto
2539 ofp_parser = datapath.ofproto_parser
2541 req = ofp_parser.OFPPortStatsRequest(datapath, ofp.OFPP_ANY)
2542 datapath.send_msg(req)
2545 def __init__(self, datapath, port_no=ofproto.OFPP_ANY, flags=0):
2546 super(OFPPortStatsRequest, self).__init__(datapath,
2549 self.port_no = port_no
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,
2557 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_PORT)
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'))):
2567 Port statistics reply message
2569 The switch responds with a stats reply that include this message to
2570 a port statistics request.
2572 ================ ======================================================
2573 Attribute Description
2574 ================ ======================================================
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 ================ ======================================================
2592 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2593 def stats_reply_handler(self, ev):
2595 ofp = msg.datapath.ofproto
2598 if msg.type == ofp.OFPST_PORT:
2599 self.port_stats_reply_handler(body)
2601 def port_stats_reply_handler(self, 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 '
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)
2621 def parser(cls, buf, offset):
2622 port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR,
2625 stats.length = ofproto.OFP_PORT_STATS_SIZE
2629 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2630 class OFPQueueStatsRequest(OFPStatsRequest):
2632 Queue statistics request message
2634 The controller uses this message to query queue statictics.
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 ================ ======================================================
2646 def send_queue_stats_request(self, datapath):
2647 ofp = datapath.ofproto
2648 ofp_parser = datapath.ofproto_parser
2650 req = ofp_parser.OFPQueueStatsRequest(datapath, ofp.OFPP_ANY,
2652 datapath.send_msg(req)
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,
2660 self.port_no = port_no
2661 self.queue_id = queue_id
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)
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'))):
2675 Queue statistics reply message
2677 The switch responds with a stats reply that include this message to
2678 an aggregate flow statistics request.
2680 ================ ======================================================
2681 Attribute Description
2682 ================ ======================================================
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 ================ ======================================================
2692 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2693 def stats_reply_handler(self, ev):
2695 ofp = msg.datapath.ofproto
2698 if msg.type == ofp.OFPST_QUEUE:
2699 self.queue_stats_reply_handler(body)
2701 def queue_stats_reply_handler(self, 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)
2711 def parser(cls, buf, offset):
2712 queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR,
2715 stats.length = ofproto.OFP_QUEUE_STATS_SIZE
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
2726 def parser(cls, buf, offset):
2727 packet, byte = struct.unpack_from(
2728 ofproto.OFP_BUCKET_COUNTER_PACK_STR,
2730 return cls(packet, byte)
2733 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2734 class OFPGroupStatsRequest(OFPStatsRequest):
2736 Group statistics request message
2738 The controller uses this message to query statistics of one or more
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 ================ ======================================================
2750 def send_group_stats_request(self, datapath):
2751 ofp = datapath.ofproto
2752 ofp_parser = datapath.ofproto_parser
2754 req = ofp_parser.OFPGroupStatsRequest(datapath, ofp.OFPG_ALL)
2755 datapath.send_msg(req)
2758 def __init__(self, datapath, group_id=ofproto.OFPG_ALL, flags=0):
2759 super(OFPGroupStatsRequest, self).__init__(datapath,
2760 ofproto.OFPST_GROUP,
2762 self.group_id = group_id
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,
2770 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP)
2771 class OFPGroupStats(StringifyMixin):
2773 Group statistics reply message
2775 The switch responds with a stats reply that include this message to
2776 a group statistics request.
2778 ================ ======================================================
2779 Attribute Description
2780 ================ ======================================================
2781 group_id Group identifier
2782 ref_count Number of flows or groups that directly forward to
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 ================ ======================================================
2791 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2792 def stats_reply_handler(self, ev):
2794 ofp = msg.datapath.ofproto
2797 if msg.type == ofp.OFPST_GROUP:
2798 self.group_stats_reply_handler(body)
2800 def group_stats_reply_handler(self, body):
2803 groups.append('group_id=%d ref_count=%d packet_count=%d '
2804 'byte_count=%d bucket_counters=%s' %
2806 stat.ref_count, stat.packet_count,
2807 stat.byte_count, stat.bucket_counters))
2808 self.logger.debug('GroupStats: %s', groups)
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
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,
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
2836 o = cls(group_id, ref_count, packet_count,
2837 byte_count, bucket_counters)
2842 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2843 class OFPGroupDescStatsRequest(OFPStatsRequest):
2845 Group description request message
2847 The controller uses this message to list the set of groups on a switch.
2849 ================ ======================================================
2850 Attribute Description
2851 ================ ======================================================
2852 flags Zero (none yet defined in the spec)
2853 ================ ======================================================
2857 def send_group_desc_stats_request(self, datapath):
2858 ofp_parser = datapath.ofproto_parser
2860 req = ofp_parser.OFPGroupDescStatsRequest(datapath)
2861 datapath.send_msg(req)
2864 def __init__(self, datapath, flags=0):
2865 super(OFPGroupDescStatsRequest, self).__init__(
2867 ofproto.OFPST_GROUP_DESC,
2871 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP_DESC)
2872 class OFPGroupDescStats(StringifyMixin):
2874 Group description reply message
2876 The switch responds with a stats reply that include this message to
2877 a group description request.
2879 ================ ======================================================
2880 Attribute Description
2881 ================ ======================================================
2883 group_id Group identifier
2884 buckets List of ``OFPBucket`` instance
2885 ================ ======================================================
2887 ``type`` attribute corresponds to ``type_`` parameter of __init__.
2891 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2892 def stats_reply_handler(self, ev):
2894 ofp = msg.datapath.ofproto
2897 if msg.type == ofp.OFPST_GROUP_DESC:
2898 self.group_desc_stats_reply_handler(body)
2900 def group_desc_stats_reply_handler(self, 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)
2908 def __init__(self, type_, group_id, buckets, length=None):
2910 self.group_id = group_id
2911 self.buckets = buckets
2914 def parser(cls, buf, offset):
2915 (length, type_, group_id) = struct.unpack_from(
2916 ofproto.OFP_GROUP_DESC_STATS_PACK_STR,
2919 bucket_len = length - ofproto.OFP_GROUP_DESC_STATS_SIZE
2920 offset += ofproto.OFP_GROUP_DESC_STATS_SIZE
2922 while bucket_len > 0:
2923 bucket = OFPBucket.parser(buf, offset)
2924 buckets.append(bucket)
2925 offset += bucket.len
2926 bucket_len -= bucket.len
2928 o = cls(type_, group_id, buckets)
2933 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2934 class OFPGroupFeaturesStatsRequest(OFPStatsRequest):
2936 Group features request message
2938 The controller uses this message to list the capabilities of groups on
2941 ================ ======================================================
2942 Attribute Description
2943 ================ ======================================================
2944 flags Zero (none yet defined in the spec)
2945 ================ ======================================================
2949 def send_group_features_stats_request(self, datapath):
2950 ofp_parser = datapath.ofproto_parser
2952 req = ofp_parser.OFPGroupFeaturesStatsRequest(datapath)
2953 datapath.send_msg(req)
2956 def __init__(self, datapath, flags=0):
2957 super(OFPGroupFeaturesStatsRequest, self).__init__(
2959 ofproto.OFPST_GROUP_FEATURES,
2963 @OFPStatsReply.register_stats_reply_type(ofproto.OFPST_GROUP_FEATURES,
2964 body_single_struct=True)
2965 class OFPGroupFeaturesStats(StringifyMixin):
2967 Group features reply message
2969 The switch responds with a stats reply that include this message to
2970 a group features request.
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 ================ ======================================================
2983 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
2984 def stats_reply_handler(self, ev):
2986 ofp = msg.datapath.ofproto
2989 if msg.type == ofp.OFPST_GROUP_FEATURES:
2990 self.group_features_stats_reply_handler(body)
2992 def group_features_stats_reply_handler(self, body):
2993 self.logger.debug('GroupFeaturesStats: types=%d '
2994 'capabilities=0x%08x max_groups=%s '
2996 body.types, body.capabilities, body.max_groups,
3000 def __init__(self, types, capabilities, max_groups, actions, length=None):
3002 self.capabilities = capabilities
3003 self.max_groups = max_groups
3004 self.actions = actions
3007 def parser(cls, buf, offset):
3008 stats = struct.unpack_from(
3009 ofproto.OFP_GROUP_FEATURES_STATS_PACK_STR, buf, offset)
3011 capabilities = stats[1]
3012 max_groups = list(stats[2:6])
3013 actions = list(stats[6:10])
3015 o = cls(types, capabilities, max_groups, actions)
3016 o.length = ofproto.OFP_GROUP_FEATURES_STATS_SIZE
3020 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST)
3021 class OFPQueueGetConfigRequest(MsgBase):
3023 Queue configuration request message
3025 ================ ======================================================
3026 Attribute Description
3027 ================ ======================================================
3028 port Port to be queried (OFPP_ANY to all configured queues)
3029 ================ ======================================================
3033 def send_queue_get_config_request(self, datapath):
3034 ofp = datapath.ofproto
3035 ofp_parser = datapath.ofproto_parser
3037 req = ofp_parser.OFPQueueGetConfigRequest(datapath, ofp.OFPP_ANY)
3038 datapath.send_msg(req)
3041 def __init__(self, datapath, port):
3042 super(OFPQueueGetConfigRequest, self).__init__(datapath)
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)
3050 class OFPQueuePropHeader(StringifyMixin):
3051 def __init__(self, property_, len_=None):
3052 self.property = property_
3055 def serialize(self, buf, offset):
3056 msg_pack_into(ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
3057 buf, offset, self.property, self.len)
3060 class OFPQueueProp(OFPQueuePropHeader):
3061 _QUEUE_PROP_PROPERTIES = {}
3064 def register_property(property_, len_):
3065 def _register_property(cls):
3066 cls.cls_property = property_
3068 OFPQueueProp._QUEUE_PROP_PROPERTIES[cls.cls_property] = cls
3070 return _register_property
3073 cls = self.__class__
3074 super(OFPQueueProp, self).__init__(cls.cls_property,
3078 def parser(cls, buf, offset):
3079 (property_, len_) = struct.unpack_from(
3080 ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
3082 cls_ = cls._QUEUE_PROP_PROPERTIES.get(property_)
3083 offset += ofproto.OFP_QUEUE_PROP_HEADER_SIZE
3084 return cls_.parser(buf, offset)
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
3093 self.properties = properties
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
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)
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__()
3120 def parser(cls, buf, offset):
3121 (rate,) = struct.unpack_from(
3122 ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, buf, offset)
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__()
3134 def parser(cls, buf, offset):
3135 (rate,) = struct.unpack_from(
3136 ofproto.OFP_QUEUE_PROP_MAX_RATE_PACK_STR, buf, offset)
3141 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY)
3142 class OFPQueueGetConfigReply(MsgBase):
3144 Queue configuration reply message
3146 The switch responds with this message to a queue configuration request.
3148 ================ ======================================================
3149 Attribute Description
3150 ================ ======================================================
3151 port Port which was queried
3152 queues list of ``OFPPacketQueue`` instance
3153 ================ ======================================================
3157 @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
3158 def queue_get_config_reply_handler(self, ev):
3161 self.logger.debug('OFPQueueGetConfigReply received: '
3162 'port=%s queues=%s',
3163 msg.port, msg.queues)
3166 def __init__(self, datapath, port=None, queues=None):
3167 super(OFPQueueGetConfigReply, self).__init__(datapath)
3169 self.queues = queues
3172 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
3173 msg = super(OFPQueueGetConfigReply, cls).parser(datapath, version,
3176 (msg.port,) = struct.unpack_from(
3177 ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf,
3178 ofproto.OFP_HEADER_SIZE)
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)
3193 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
3194 class OFPBarrierRequest(MsgBase):
3196 Barrier request message
3198 The controller sends this message to ensure message dependencies have
3199 been met or receive notifications for completed operations.
3203 def send_barrier_request(self, datapath):
3204 ofp_parser = datapath.ofproto_parser
3206 req = ofp_parser.OFPBarrierRequest(datapath)
3207 datapath.send_msg(req)
3210 def __init__(self, datapath):
3211 super(OFPBarrierRequest, self).__init__(datapath)
3215 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
3216 class OFPBarrierReply(MsgBase):
3218 Barrier reply message
3220 The switch responds with this message to a barrier request.
3224 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
3225 def barrier_reply_handler(self, ev):
3226 self.logger.debug('OFPBarrierReply received')
3229 def __init__(self, datapath):
3230 super(OFPBarrierReply, self).__init__(datapath)
3233 @_set_msg_type(ofproto.OFPT_ROLE_REQUEST)
3234 class OFPRoleRequest(MsgBase):
3236 Role request message
3238 The controller uses this message to change its role.
3240 ================ ======================================================
3241 Attribute Description
3242 ================ ======================================================
3243 role One of the following values.
3245 | OFPCR_ROLE_NOCHANGE
3249 generation_id Master Election Generation ID
3250 ================ ======================================================
3254 def send_role_request(self, datapath):
3255 ofp = datapath.ofproto
3256 ofp_parser = datapath.ofproto_parser
3258 req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
3259 datapath.send_msg(req)
3262 def __init__(self, datapath, role, generation_id):
3263 super(OFPRoleRequest, self).__init__(datapath)
3265 self.generation_id = generation_id
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)
3274 @_set_msg_type(ofproto.OFPT_ROLE_REPLY)
3275 class OFPRoleReply(MsgBase):
3279 The switch responds with this message to a role request.
3281 ================ ======================================================
3282 Attribute Description
3283 ================ ======================================================
3284 role One of the following values.
3286 | OFPCR_ROLE_NOCHANGE
3290 generation_id Master Election Generation ID
3291 ================ ======================================================
3295 @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
3296 def role_reply_handler(self, ev):
3301 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
3303 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
3305 elif msg.role == ofp.OFPCR_ROLE_MASTER:
3307 elif msg.role == ofp.OFPCR_ROLE_SLAVE:
3312 self.logger.debug('OFPRoleReply received: '
3313 'role=%s generation_id=%d',
3314 role, msg.generation_id)
3317 def __init__(self, datapath, role=None, generation_id=None):
3318 super(OFPRoleReply, self).__init__(datapath)
3320 self.generation_id = generation_id
3323 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
3324 msg = super(OFPRoleReply, cls).parser(datapath, version,
3327 (msg.role, msg.generation_id) = struct.unpack_from(
3328 ofproto.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
3329 ofproto.OFP_HEADER_SIZE)
3334 UINT64_MAX = (1 << 64) - 1
3335 UINT32_MAX = (1 << 32) - 1
3336 UINT16_MAX = (1 << 16) - 1
3342 self.in_phy_port = 0
3344 self.dl_dst = mac.DONTCARE
3345 self.dl_src = mac.DONTCARE
3360 self.icmpv4_type = 0
3361 self.icmpv4_code = 0
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
3379 class FlowWildcards(object):
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
3396 def ft_set(self, shift):
3397 self.wildcards &= ~(1 << shift)
3399 def ft_test(self, shift):
3400 return not self.wildcards & (1 << shift)
3403 class OFPMatch(StringifyMixin):
3405 Flow Match Structure
3407 This class is implementation of the flow match structure having
3409 There are new API and old API for compatibility. the old API is
3410 supposed to be removed later.
3412 You can define the flow match by the keyword arguments.
3413 The following arguments are available.
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 ================ =============== ==================================
3465 >>> match = parser.OFPMatch(
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')
3472 >>> if 'ipv6_src' in match:
3473 ... print match['ipv6_src']
3475 ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::')
3479 For the list of the supported Nicira experimenter matches,
3480 please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`.
3484 For VLAN id match field, special values are defined in OpenFlow Spec.
3486 1) Packets with and without a VLAN tag
3490 match = parser.OFPMatch()
3494 ====================== =====
3495 non-VLAN-tagged MATCH
3496 VLAN-tagged(vlan_id=3) MATCH
3497 VLAN-tagged(vlan_id=5) MATCH
3498 ====================== =====
3500 2) Only packets without a VLAN tag
3504 match = parser.OFPMatch(vlan_vid=0x0000)
3508 ====================== =====
3509 non-VLAN-tagged MATCH
3510 VLAN-tagged(vlan_id=3) x
3511 VLAN-tagged(vlan_id=5) x
3512 ====================== =====
3514 3) Only packets with a VLAN tag regardless of its value
3518 match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000))
3522 ====================== =====
3524 VLAN-tagged(vlan_id=3) MATCH
3525 VLAN-tagged(vlan_id=5) MATCH
3526 ====================== =====
3528 4) Only packets with VLAN tag and VID equal
3532 match = parser.OFPMatch(vlan_vid=(0x1000 | 3))
3536 ====================== =====
3538 VLAN-tagged(vlan_id=3) MATCH
3539 VLAN-tagged(vlan_id=5) x
3540 ====================== =====
3543 def __init__(self, type_=None, length=None, _ordered_fields=None,
3545 super(OFPMatch, self).__init__()
3546 self._wc = FlowWildcards()
3549 self.type = ofproto.OFPMT_OXM
3550 self.length = length
3552 if _ordered_fields is not None:
3554 self._fields2 = _ordered_fields
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)
3563 # assumption: sorting by OXM type values makes fields
3564 # meet ordering requirements (eg. eth_type before ipv4_src)
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)
3570 def __getitem__(self, key):
3571 return dict(self._fields2)[key]
3573 def __contains__(self, key):
3574 return key in dict(self._fields2)
3576 def iteritems(self):
3577 return iter(dict(self._fields2).items())
3580 return self._fields2
3582 def get(self, key, default=None):
3583 return dict(self._fields2).get(key, default)
3585 def stringify_attrs(self):
3586 yield "oxm_fields", dict(self._fields2)
3588 def to_jsondict(self):
3590 Returns a dict expressing the flow match.
3592 # XXX old api compat
3593 if self._composed_with_old_api():
3594 # copy object first because serialize_old is destructive
3596 o2.fields = self.fields[:]
3597 # serialize and parse to fill OFPMatch._fields2
3599 o2.serialize(buf, 0)
3600 o = OFPMatch.parser(six.binary_type(buf), 0)
3604 body = {"oxm_fields": [ofproto.oxm_to_jsondict(k, uv) for k, uv
3608 return {self.__class__.__name__: body}
3611 def from_jsondict(cls, dict_):
3613 Returns an object which is generated from a dict.
3616 KeyError -- Unknown match field is defined in dict
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
3625 return OFPMatch.parser(six.binary_type(buf), 0)
3628 # XXX old api compat
3629 if self._composed_with_old_api():
3630 # copy object first because serialize_old is destructive
3632 o2.fields = self.fields[:]
3633 # serialize and parse to fill OFPMatch._fields2
3635 o2.serialize(buf, 0)
3636 o = OFPMatch.parser(six.binary_type(buf), 0)
3639 return super(OFPMatch, o).__str__()
3643 def append_field(self, header, value, mask=None):
3645 Append a match field.
3647 ========= =======================================================
3648 Argument Description
3649 ========= =======================================================
3650 header match field header ID which is defined automatically in
3652 value match field value
3653 mask mask value to the match field
3654 ========= =======================================================
3656 The available ``header`` is as follows.
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 ====================== ===================================
3699 self.fields.append(OFPMatchField.make(header, value, mask))
3701 def _composed_with_old_api(self):
3702 return (self.fields and not self._fields2) or \
3703 self._wc.__dict__ != FlowWildcards().__dict__
3705 def serialize(self, buf, offset):
3707 Outputs the expression of the wire protocol of the flow match into
3709 Returns the output length.
3712 if self._composed_with_old_api():
3713 return self.serialize_old(buf, offset)
3715 fields = [ofproto.oxm_from_user(k, uv) for (k, uv)
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,
3724 length = field_offset - offset
3725 msg_pack_into(hdr_pack_str, buf, offset,
3726 ofproto.OFPMT_OXM, length)
3727 self.length = length
3729 pad_len = utils.round_up(length, 8) - length
3730 msg_pack_into("%dx" % pad_len, buf, field_offset)
3732 return length + pad_len
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
3740 if self._wc.ft_test(ofproto.OFPXMT_OFB_IN_PORT):
3741 self.append_field(ofproto.OXM_OF_IN_PORT,
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)
3748 if self._wc.ft_test(ofproto.OFPXMT_OFB_METADATA):
3749 if self._wc.metadata_mask == UINT64_MAX:
3750 header = ofproto.OXM_OF_METADATA
3752 header = ofproto.OXM_OF_METADATA_W
3753 self.append_field(header, self._flow.metadata,
3754 self._wc.metadata_mask)
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
3760 header = ofproto.OXM_OF_ETH_DST
3761 self.append_field(header, self._flow.dl_dst, self._wc.dl_dst_mask)
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
3767 header = ofproto.OXM_OF_ETH_SRC
3768 self.append_field(header, self._flow.dl_src, self._wc.dl_src_mask)
3770 if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_TYPE):
3771 self.append_field(ofproto.OXM_OF_ETH_TYPE, self._flow.dl_type)
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
3777 header = ofproto.OXM_OF_VLAN_VID_W
3778 self.append_field(header, self._flow.vlan_vid,
3779 self._wc.vlan_vid_mask)
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)
3785 if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_DSCP):
3786 self.append_field(ofproto.OXM_OF_IP_DSCP, self._flow.ip_dscp)
3788 if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_ECN):
3789 self.append_field(ofproto.OXM_OF_IP_ECN, self._flow.ip_ecn)
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)
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
3799 header = ofproto.OXM_OF_IPV4_SRC_W
3800 self.append_field(header, self._flow.ipv4_src,
3801 self._wc.ipv4_src_mask)
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
3807 header = ofproto.OXM_OF_IPV4_DST_W
3808 self.append_field(header, self._flow.ipv4_dst,
3809 self._wc.ipv4_dst_mask)
3811 if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_SRC):
3812 self.append_field(ofproto.OXM_OF_TCP_SRC, self._flow.tcp_src)
3814 if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_DST):
3815 self.append_field(ofproto.OXM_OF_TCP_DST, self._flow.tcp_dst)
3817 if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_SRC):
3818 self.append_field(ofproto.OXM_OF_UDP_SRC, self._flow.udp_src)
3820 if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_DST):
3821 self.append_field(ofproto.OXM_OF_UDP_DST, self._flow.udp_dst)
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)
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)
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)
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)
3839 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_OP):
3840 self.append_field(ofproto.OXM_OF_ARP_OP, self._flow.arp_op)
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
3846 header = ofproto.OXM_OF_ARP_SPA_W
3847 self.append_field(header, self._flow.arp_spa,
3848 self._wc.arp_spa_mask)
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
3854 header = ofproto.OXM_OF_ARP_TPA_W
3855 self.append_field(header, self._flow.arp_tpa,
3856 self._wc.arp_tpa_mask)
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
3862 header = ofproto.OXM_OF_ARP_SHA
3863 self.append_field(header, self._flow.arp_sha,
3864 self._wc.arp_sha_mask)
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
3870 header = ofproto.OXM_OF_ARP_THA
3871 self.append_field(header, self._flow.arp_tha,
3872 self._wc.arp_tha_mask)
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
3878 header = ofproto.OXM_OF_IPV6_SRC
3879 self.append_field(header, self._flow.ipv6_src,
3880 self._wc.ipv6_src_mask)
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
3886 header = ofproto.OXM_OF_IPV6_DST
3887 self.append_field(header, self._flow.ipv6_dst,
3888 self._wc.ipv6_dst_mask)
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
3894 header = ofproto.OXM_OF_IPV6_FLABEL_W
3895 self.append_field(header, self._flow.ipv6_flabel,
3896 self._wc.ipv6_flabel_mask)
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)
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)
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)
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)
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)
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)
3922 if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_TC):
3923 self.append_field(ofproto.OXM_OF_MPLS_TC,
3926 field_offset = offset + 4
3927 for f in self.fields:
3928 f.serialize(buf, field_offset)
3929 field_offset += f.length
3931 length = field_offset - offset
3932 msg_pack_into('!HH', buf, offset, ofproto.OFPMT_OXM, length)
3934 pad_len = utils.round_up(length, 8) - length
3935 msg_pack_into("%dx" % pad_len, buf, field_offset)
3937 return length + pad_len
3940 def parser(cls, buf, offset):
3942 Returns an object which is generated from a buffer including the
3943 expression of the wire protocol of the flow match.
3946 type_, length = struct.unpack_from('!HH', buf, offset)
3949 match.length = length
3951 # ofp_match adjustment
3956 cls.parser_old(match, buf, offset, length)
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))
3965 match._fields2 = fields
3969 def parser_old(match, buf, offset, length):
3971 field = OFPMatchField.parser(buf, offset)
3972 offset += field.length
3973 length -= field.length
3974 match.fields.append(field)
3976 def set_in_port(self, port):
3977 self._wc.ft_set(ofproto.OFPXMT_OFB_IN_PORT)
3978 self._flow.in_port = port
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
3984 def set_metadata(self, metadata):
3985 self.set_metadata_masked(metadata, UINT64_MAX)
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
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
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)
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
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)
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
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
4020 def set_vlan_vid(self, vid):
4021 self.set_vlan_vid_masked(vid, UINT16_MAX)
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
4029 def set_vlan_pcp(self, pcp):
4030 self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_PCP)
4031 self._flow.vlan_pcp = pcp
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
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
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
4045 def set_ipv4_src(self, ipv4_src):
4046 self.set_ipv4_src_masked(ipv4_src, UINT32_MAX)
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
4053 def set_ipv4_dst(self, ipv4_dst):
4054 self.set_ipv4_dst_masked(ipv4_dst, UINT32_MAX)
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
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
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
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
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
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
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
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
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
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
4097 def set_arp_spa(self, arp_spa):
4098 self.set_arp_spa_masked(arp_spa, UINT32_MAX)
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
4105 def set_arp_tpa(self, arp_tpa):
4106 self.set_arp_tpa_masked(arp_tpa, UINT32_MAX)
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
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
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)
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
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)
4131 def set_ipv6_src(self, src):
4132 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_SRC)
4133 self._flow.ipv6_src = src
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)]
4140 def set_ipv6_dst(self, dst):
4141 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_DST)
4142 self._flow.ipv6_dst = dst
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)]
4149 def set_ipv6_flabel(self, flabel):
4150 self.set_ipv6_flabel_masked(flabel, UINT32_MAX)
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
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
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
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
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
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
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
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
4186 class OFPMatchField(StringifyMixin):
4187 _FIELDS_HEADERS = {}
4190 def register_field_header(headers):
4191 def _register_field_header(cls):
4192 for header in headers:
4193 OFPMatchField._FIELDS_HEADERS[header] = cls
4195 return _register_field_header
4197 def __init__(self, header):
4198 self.header = header
4199 self.n_bytes = ofproto.oxm_tlv_header_extract_length(header)
4203 def cls_to_header(cls, cls_, hasmask):
4205 inv = dict((v, k) for k, v in cls._FIELDS_HEADERS.items()
4206 if (((k >> 8) & 1) != 0) == hasmask)
4210 def make(header, value, mask=None):
4211 cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
4212 return cls_(header, value, mask)
4215 def parser(cls, buf, offset):
4216 (header,) = struct.unpack_from('!I', buf, offset)
4217 cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
4219 field = cls_.field_parser(header, buf, offset)
4221 field = OFPMatchField(header)
4222 field.length = (header & 0xff) + 4
4226 def field_parser(cls, header, buf, offset):
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)
4232 (value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
4233 return cls(header, value, mask)
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)
4239 self.put(buf, offset, self.value)
4241 def _put_header(self, buf, offset):
4242 msg_pack_into('!I', buf, offset, self.header)
4245 def _put(self, buf, offset, value):
4246 msg_pack_into(self.pack_str, buf, offset, value)
4247 self.length += self.n_bytes
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)
4254 def put(self, buf, offset, value):
4255 self._put_header(buf, offset)
4256 self._put(buf, offset + self.length, value)
4258 def _putv6(self, buf, offset, value):
4259 msg_pack_into(self.pack_str, buf, offset, *value)
4260 self.length += self.n_bytes
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)
4269 return self.header & 0xff
4271 def to_jsondict(self):
4272 # remove some redundant attributes
4273 d = super(OFPMatchField, self).to_jsondict()
4274 v = d[self.__class__.__name__]
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_}
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())
4300 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PORT])
4301 class MTInPort(OFPMatchField):
4304 def __init__(self, header, value, mask=None):
4305 super(MTInPort, self).__init__(header)
4309 @OFPMatchField.register_field_header([ofproto.OXM_OF_METADATA,
4310 ofproto.OXM_OF_METADATA_W])
4311 class MTMetadata(OFPMatchField):
4314 def __init__(self, header, value, mask=None):
4315 super(MTMetadata, self).__init__(header)
4320 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PHY_PORT])
4321 class MTInPhyPort(OFPMatchField):
4324 def __init__(self, header, value, mask=None):
4325 super(MTInPhyPort, self).__init__(header)
4329 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_DST,
4330 ofproto.OXM_OF_ETH_DST_W])
4331 class MTEthDst(OFPMatchField):
4334 def __init__(self, header, value, mask=None):
4335 super(MTEthDst, self).__init__(header)
4340 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_SRC,
4341 ofproto.OXM_OF_ETH_SRC_W])
4342 class MTEthSrc(OFPMatchField):
4345 def __init__(self, header, value, mask=None):
4346 super(MTEthSrc, self).__init__(header)
4351 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_TYPE])
4352 class MTEthType(OFPMatchField):
4355 def __init__(self, header, value, mask=None):
4356 super(MTEthType, self).__init__(header)
4360 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_VID,
4361 ofproto.OXM_OF_VLAN_VID_W])
4362 class MTVlanVid(OFPMatchField):
4365 def __init__(self, header, value, mask=None):
4366 super(MTVlanVid, self).__init__(header)
4371 def field_parser(cls, header, buf, offset):
4372 m = super(MTVlanVid, cls).field_parser(header, buf, offset)
4373 m.value &= ~ofproto.OFPVID_PRESENT
4377 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_PCP])
4378 class MTVlanPcp(OFPMatchField):
4381 def __init__(self, header, value, mask=None):
4382 super(MTVlanPcp, self).__init__(header)
4386 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_DSCP])
4387 class MTIPDscp(OFPMatchField):
4390 def __init__(self, header, value, mask=None):
4391 super(MTIPDscp, self).__init__(header)
4395 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_ECN])
4396 class MTIPECN(OFPMatchField):
4399 def __init__(self, header, value, mask=None):
4400 super(MTIPECN, self).__init__(header)
4404 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_PROTO])
4405 class MTIPProto(OFPMatchField):
4408 def __init__(self, header, value, mask=None):
4409 super(MTIPProto, self).__init__(header)
4413 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_SRC,
4414 ofproto.OXM_OF_IPV4_SRC_W])
4415 class MTIPV4Src(OFPMatchField):
4418 def __init__(self, header, value, mask=None):
4419 super(MTIPV4Src, self).__init__(header)
4424 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_DST,
4425 ofproto.OXM_OF_IPV4_DST_W])
4426 class MTIPV4Dst(OFPMatchField):
4429 def __init__(self, header, value, mask=None):
4430 super(MTIPV4Dst, self).__init__(header)
4435 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_SRC])
4436 class MTTCPSrc(OFPMatchField):
4439 def __init__(self, header, value, mask=None):
4440 super(MTTCPSrc, self).__init__(header)
4444 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_DST])
4445 class MTTCPDst(OFPMatchField):
4448 def __init__(self, header, value, mask=None):
4449 super(MTTCPDst, self).__init__(header)
4453 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_SRC])
4454 class MTUDPSrc(OFPMatchField):
4457 def __init__(self, header, value, mask=None):
4458 super(MTUDPSrc, self).__init__(header)
4462 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_DST])
4463 class MTUDPDst(OFPMatchField):
4466 def __init__(self, header, value, mask=None):
4467 super(MTUDPDst, self).__init__(header)
4471 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_SRC])
4472 class MTSCTPSrc(OFPMatchField):
4475 def __init__(self, header, value, mask=None):
4476 super(MTSCTPSrc, self).__init__(header)
4480 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_DST])
4481 class MTSCTPDst(OFPMatchField):
4484 def __init__(self, header, value, mask=None):
4485 super(MTSCTPDst, self).__init__(header)
4489 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_TYPE])
4490 class MTICMPV4Type(OFPMatchField):
4493 def __init__(self, header, value, mask=None):
4494 super(MTICMPV4Type, self).__init__(header)
4498 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_CODE])
4499 class MTICMPV4Code(OFPMatchField):
4502 def __init__(self, header, value, mask=None):
4503 super(MTICMPV4Code, self).__init__(header)
4507 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_OP])
4508 class MTArpOp(OFPMatchField):
4511 def __init__(self, header, value, mask=None):
4512 super(MTArpOp, self).__init__(header)
4516 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SPA,
4517 ofproto.OXM_OF_ARP_SPA_W])
4518 class MTArpSpa(OFPMatchField):
4521 def __init__(self, header, value, mask=None):
4522 super(MTArpSpa, self).__init__(header)
4527 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_TPA,
4528 ofproto.OXM_OF_ARP_TPA_W])
4529 class MTArpTpa(OFPMatchField):
4532 def __init__(self, header, value, mask=None):
4533 super(MTArpTpa, self).__init__(header)
4538 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SHA,
4539 ofproto.OXM_OF_ARP_SHA_W])
4540 class MTArpSha(OFPMatchField):
4543 def __init__(self, header, value, mask=None):
4544 super(MTArpSha, self).__init__(header)
4549 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_THA,
4550 ofproto.OXM_OF_ARP_THA_W])
4551 class MTArpTha(OFPMatchField):
4554 def __init__(self, header, value, mask=None):
4555 super(MTArpTha, self).__init__(header)
4560 class MTIPv6(object):
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:]))
4568 value = struct.unpack_from(cls.pack_str, buf, offset + 4)
4569 return cls(header, list(value))
4571 def serialize(self, buf, offset):
4572 self.putv6(buf, offset, self.value, self.mask)
4575 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_SRC,
4576 ofproto.OXM_OF_IPV6_SRC_W])
4577 class MTIPv6Src(MTIPv6, OFPMatchField):
4580 def __init__(self, header, value, mask=None):
4581 super(MTIPv6Src, self).__init__(header)
4586 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_DST,
4587 ofproto.OXM_OF_IPV6_DST_W])
4588 class MTIPv6Dst(MTIPv6, OFPMatchField):
4591 def __init__(self, header, value, mask=None):
4592 super(MTIPv6Dst, self).__init__(header)
4597 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_FLABEL,
4598 ofproto.OXM_OF_IPV6_FLABEL_W])
4599 class MTIPv6Flabel(OFPMatchField):
4602 def __init__(self, header, value, mask=None):
4603 super(MTIPv6Flabel, self).__init__(header)
4608 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_LABEL])
4609 class MTMplsLabel(OFPMatchField):
4612 def __init__(self, header, value, mask=None):
4613 super(MTMplsLabel, self).__init__(header)
4617 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_TYPE])
4618 class MTICMPV6Type(OFPMatchField):
4621 def __init__(self, header, value, mask=None):
4622 super(MTICMPV6Type, self).__init__(header)
4626 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_CODE])
4627 class MTICMPV6Code(OFPMatchField):
4630 def __init__(self, header, value, mask=None):
4631 super(MTICMPV6Code, self).__init__(header)
4635 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TARGET])
4636 class MTIPv6NdTarget(MTIPv6, OFPMatchField):
4639 def __init__(self, header, value, mask=None):
4640 super(MTIPv6NdTarget, self).__init__(header)
4643 def serialize(self, buf, offset):
4644 self.putv6(buf, offset, self.value)
4647 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_SLL])
4648 class MTIPv6NdSll(OFPMatchField):
4651 def __init__(self, header, value, mask=None):
4652 super(MTIPv6NdSll, self).__init__(header)
4656 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TLL])
4657 class MTIPv6NdTll(OFPMatchField):
4660 def __init__(self, header, value, mask=None):
4661 super(MTIPv6NdTll, self).__init__(header)
4665 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_TC])
4666 class MTMplsTc(OFPMatchField):
4669 def __init__(self, header, value, mask=None):
4670 super(MTMplsTc, self).__init__(header)