1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2012, 2013 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 This module implements OpenFlow 1.3.x.
20 This module also implements some of extensions shown in
21 "OpenFlow Extensions for 1.3.X Pack 1".
22 Namely, the following extensions are implemented.
24 - EXT-230 Bundle Extension (without bundle properties)
25 - EXT-236 Bad flow entry priority error Extension
26 - EXT-237 Set async config error Extension
27 - EXT-256 PBB UCA header field Extension
28 - EXT-260 Duplicate instruction error Extension
29 - EXT-264 Multipart timeout errors Extension
31 The following extensions are partially implemented.
33 - EXT-187 Flow entry notifications Extension (ONFMP_FLOW_MONITOR only)
34 - EXT-232 Table synchronisation Extension (Error codes only)
36 The following extensions are not implemented yet.
38 - EXT-191 Role Status Extension
39 - EXT-192-e Flow entry eviction Extension
40 - EXT-192-v Vacancy events Extension
48 from ryu.lib import addrconv
49 from ryu.lib import mac
50 from ryu.lib.pack_utils import msg_pack_into
51 from ryu.lib.packet import packet
52 from ryu import exception
54 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
55 from ryu.ofproto import ether
56 from ryu.ofproto import nx_actions
57 from ryu.ofproto import ofproto_parser
58 from ryu.ofproto import ofproto_common
59 from ryu.ofproto import ofproto_v1_3 as ofproto
62 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_3_parser')
67 def _set_msg_type(msg_type):
68 def _set_cls_msg_type(cls):
69 cls.cls_msg_type = msg_type
71 return _set_cls_msg_type
74 def _register_parser(cls):
75 '''class decorator to register msg parser'''
76 assert cls.cls_msg_type is not None
77 assert cls.cls_msg_type not in _MSG_PARSERS
78 _MSG_PARSERS[cls.cls_msg_type] = cls.parser
82 def _register_exp_type(experimenter, exp_type):
83 assert exp_type not in OFPExperimenter._subtypes
86 OFPExperimenter._subtypes[(experimenter, exp_type)] = cls
91 @ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
92 def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
93 parser = _MSG_PARSERS.get(msg_type)
94 return parser(datapath, version, msg_type, msg_len, xid, buf)
98 @_set_msg_type(ofproto.OFPT_HELLO)
99 class OFPHello(MsgBase):
103 When connection is started, the hello message is exchanged between a
104 switch and a controller.
106 This message is handled by the Ryu framework, so the Ryu application
107 do not need to process this typically.
109 ========== =========================================================
110 Attribute Description
111 ========== =========================================================
112 elements list of ``OFPHelloElemVersionBitmap`` instance
113 ========== =========================================================
116 def __init__(self, datapath, elements=None):
117 elements = elements if elements else []
118 super(OFPHello, self).__init__(datapath)
119 self.elements = elements
122 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
123 msg = super(OFPHello, cls).parser(datapath, version, msg_type,
126 offset = ofproto.OFP_HELLO_HEADER_SIZE
128 while offset < msg.msg_len:
129 type_, length = struct.unpack_from(
130 ofproto.OFP_HELLO_ELEM_HEADER_PACK_STR, msg.buf, offset)
132 # better to register Hello Element classes but currently
133 # Only VerisonBitmap is supported so let's be simple.
135 if type_ == ofproto.OFPHET_VERSIONBITMAP:
136 elem = OFPHelloElemVersionBitmap.parser(msg.buf, offset)
144 class OFPHelloElemVersionBitmap(StringifyMixin):
146 Version bitmap Hello Element
148 ========== =========================================================
149 Attribute Description
150 ========== =========================================================
151 versions list of versions of OpenFlow protocol a device supports
152 ========== =========================================================
155 def __init__(self, versions, type_=None, length=None):
156 super(OFPHelloElemVersionBitmap, self).__init__()
157 self.type = ofproto.OFPHET_VERSIONBITMAP
160 self.versions = versions
163 def parser(cls, buf, offset):
164 type_, length = struct.unpack_from(
165 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_PACK_STR,
167 assert type_ == ofproto.OFPHET_VERSIONBITMAP
169 bitmaps_len = (length -
170 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE)
171 offset += ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE
173 while bitmaps_len >= 4:
174 bitmap = struct.unpack_from('!I', buf, offset)
175 bitmaps.append(bitmap[0])
179 versions = [i * 32 + shift
180 for i, bitmap in enumerate(bitmaps)
181 for shift in range(31) if bitmap & (1 << shift)]
184 elem._bitmaps = bitmaps
189 @_set_msg_type(ofproto.OFPT_ERROR)
190 class OFPErrorMsg(MsgBase):
194 The switch notifies controller of problems by this message.
196 ========== =========================================================
197 Attribute Description
198 ========== =========================================================
199 type High level type of error
200 code Details depending on the type
201 data Variable length data depending on the type and code
202 ========== =========================================================
204 ``type`` attribute corresponds to ``type_`` parameter of __init__.
206 Types and codes are defined in ``ryu.ofproto.ofproto``.
208 ============================= ===========
210 ============================= ===========
211 OFPET_HELLO_FAILED OFPHFC_*
212 OFPET_BAD_REQUEST OFPBRC_*
213 OFPET_BAD_ACTION OFPBAC_*
214 OFPET_BAD_INSTRUCTION OFPBIC_*
215 OFPET_BAD_MATCH OFPBMC_*
216 OFPET_FLOW_MOD_FAILED OFPFMFC_*
217 OFPET_GROUP_MOD_FAILED OFPGMFC_*
218 OFPET_PORT_MOD_FAILED OFPPMFC_*
219 OFPET_TABLE_MOD_FAILED OFPTMFC_*
220 OFPET_QUEUE_OP_FAILED OFPQOFC_*
221 OFPET_SWITCH_CONFIG_FAILED OFPSCFC_*
222 OFPET_ROLE_REQUEST_FAILED OFPRRFC_*
223 OFPET_METER_MOD_FAILED OFPMMFC_*
224 OFPET_TABLE_FEATURES_FAILED OFPTFFC_*
225 OFPET_EXPERIMENTER N/A
226 ============================= ===========
228 If ``type == OFPET_EXPERIMENTER``, this message has also the following
231 ============= ======================================================
232 Attribute Description
233 ============= ======================================================
234 exp_type Experimenter defined type
235 experimenter Experimenter ID
236 ============= ======================================================
240 @set_ev_cls(ofp_event.EventOFPErrorMsg,
241 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
242 def error_msg_handler(self, ev):
245 self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
247 msg.type, msg.code, utils.hex_array(msg.data))
250 def __init__(self, datapath, type_=None, code=None, data=None, **kwargs):
251 super(OFPErrorMsg, self).__init__(datapath)
254 if isinstance(data, six.string_types):
255 data = data.encode('ascii')
257 if self.type == ofproto.OFPET_EXPERIMENTER:
258 self.exp_type = kwargs.get('exp_type', None)
259 self.experimenter = kwargs.get('experimenter', None)
262 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
263 type_, = struct.unpack_from('!H', six.binary_type(buf),
264 ofproto.OFP_HEADER_SIZE)
265 msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
267 if type_ == ofproto.OFPET_EXPERIMENTER:
268 (msg.type, msg.exp_type, msg.experimenter,
269 msg.data) = cls.parse_experimenter_body(buf)
272 msg.data) = cls.parse_body(buf)
276 def parse_body(cls, buf):
277 type_, code = struct.unpack_from(
278 ofproto.OFP_ERROR_MSG_PACK_STR, buf,
279 ofproto.OFP_HEADER_SIZE)
280 data = buf[ofproto.OFP_ERROR_MSG_SIZE:]
281 return type_, code, data
284 def parse_experimenter_body(cls, buf):
285 type_, exp_type, experimenter = struct.unpack_from(
286 ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR, buf,
287 ofproto.OFP_HEADER_SIZE)
288 data = buf[ofproto.OFP_ERROR_EXPERIMENTER_MSG_SIZE:]
289 return type_, exp_type, experimenter, data
291 def _serialize_body(self):
292 assert self.data is not None
293 if self.type == ofproto.OFPET_EXPERIMENTER:
294 msg_pack_into(ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR,
295 self.buf, ofproto.OFP_HEADER_SIZE,
296 self.type, self.exp_type, self.experimenter)
297 self.buf += self.data
299 msg_pack_into(ofproto.OFP_ERROR_MSG_PACK_STR,
300 self.buf, ofproto.OFP_HEADER_SIZE,
301 self.type, self.code)
302 self.buf += self.data
305 # For the backward compatibility
306 def OFPErrorExperimenterMsg(datapath, type_=None, exp_type=None,
307 experimenter=None, data=None):
308 msg = OFPErrorMsg(datapath, data=data)
309 msg.type = ofproto.OFPET_EXPERIMENTER
310 msg.exp_type = exp_type
311 msg.experimenter = experimenter
316 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
317 class OFPEchoRequest(MsgBase):
321 This message is handled by the Ryu framework, so the Ryu application
322 do not need to process this typically.
324 ========== =========================================================
325 Attribute Description
326 ========== =========================================================
327 data An arbitrary length data
328 ========== =========================================================
332 def send_echo_request(self, datapath, data):
333 ofp_parser = datapath.ofproto_parser
335 req = ofp_parser.OFPEchoRequest(datapath, data)
336 datapath.send_msg(req)
338 @set_ev_cls(ofp_event.EventOFPEchoRequest,
339 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
340 def echo_request_handler(self, ev):
341 self.logger.debug('OFPEchoRequest received: data=%s',
342 utils.hex_array(ev.msg.data))
345 def __init__(self, datapath, data=None):
346 super(OFPEchoRequest, self).__init__(datapath)
350 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
351 msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
353 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
356 def _serialize_body(self):
357 if self.data is not None:
358 self.buf += self.data
362 @_set_msg_type(ofproto.OFPT_ECHO_REPLY)
363 class OFPEchoReply(MsgBase):
367 This message is handled by the Ryu framework, so the Ryu application
368 do not need to process this typically.
370 ========== =========================================================
371 Attribute Description
372 ========== =========================================================
373 data An arbitrary length data
374 ========== =========================================================
378 def send_echo_reply(self, datapath, data):
379 ofp_parser = datapath.ofproto_parser
381 reply = ofp_parser.OFPEchoReply(datapath, data)
382 datapath.send_msg(reply)
384 @set_ev_cls(ofp_event.EventOFPEchoReply,
385 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
386 def echo_reply_handler(self, ev):
387 self.logger.debug('OFPEchoReply received: data=%s',
388 utils.hex_array(ev.msg.data))
391 def __init__(self, datapath, data=None):
392 super(OFPEchoReply, self).__init__(datapath)
396 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
397 msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
399 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
402 def _serialize_body(self):
403 assert self.data is not None
404 self.buf += self.data
408 @_set_msg_type(ofproto.OFPT_EXPERIMENTER)
409 class OFPExperimenter(MsgBase):
411 Experimenter extension message
413 ============= =========================================================
414 Attribute Description
415 ============= =========================================================
416 experimenter Experimenter ID
417 exp_type Experimenter defined
418 data Experimenter defined arbitrary additional data
419 ============= =========================================================
423 def __init__(self, datapath, experimenter=None, exp_type=None, data=None):
424 super(OFPExperimenter, self).__init__(datapath)
425 self.experimenter = experimenter
426 self.exp_type = exp_type
430 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
431 msg = super(OFPExperimenter, cls).parser(datapath, version,
434 (msg.experimenter, msg.exp_type) = struct.unpack_from(
435 ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR, msg.buf,
436 ofproto.OFP_HEADER_SIZE)
437 msg.data = msg.buf[ofproto.OFP_EXPERIMENTER_HEADER_SIZE:]
438 if (msg.experimenter, msg.exp_type) in cls._subtypes:
439 new_msg = cls._subtypes[
440 (msg.experimenter, msg.exp_type)].parser_subtype(msg)
441 new_msg.set_headers(msg.version, msg.msg_type, msg.msg_len,
443 new_msg.set_buf(msg.buf)
448 def _serialize_body(self):
449 assert self.data is not None
450 msg_pack_into(ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR,
451 self.buf, ofproto.OFP_HEADER_SIZE,
452 self.experimenter, self.exp_type)
453 self.buf += self.data
456 @_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
457 class OFPFeaturesRequest(MsgBase):
459 Features request message
461 The controller sends a feature request to the switch upon session
464 This message is handled by the Ryu framework, so the Ryu application
465 do not need to process this typically.
469 def send_features_request(self, datapath):
470 ofp_parser = datapath.ofproto_parser
472 req = ofp_parser.OFPFeaturesRequest(datapath)
473 datapath.send_msg(req)
476 def __init__(self, datapath):
477 super(OFPFeaturesRequest, self).__init__(datapath)
481 @_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
482 class OFPSwitchFeatures(MsgBase):
484 Features reply message
486 The switch responds with a features reply message to a features
489 This message is handled by the Ryu framework, so the Ryu application
490 do not need to process this typically.
494 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
495 def switch_features_handler(self, ev):
498 self.logger.debug('OFPSwitchFeatures received: '
499 'datapath_id=0x%016x n_buffers=%d '
500 'n_tables=%d auxiliary_id=%d '
501 'capabilities=0x%08x',
502 msg.datapath_id, msg.n_buffers, msg.n_tables,
503 msg.auxiliary_id, msg.capabilities)
506 def __init__(self, datapath, datapath_id=None, n_buffers=None,
507 n_tables=None, auxiliary_id=None, capabilities=None):
508 super(OFPSwitchFeatures, self).__init__(datapath)
509 self.datapath_id = datapath_id
510 self.n_buffers = n_buffers
511 self.n_tables = n_tables
512 self.auxiliary_id = auxiliary_id
513 self.capabilities = capabilities
516 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
517 msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
524 msg._reserved) = struct.unpack_from(
525 ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
526 ofproto.OFP_HEADER_SIZE)
530 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
531 class OFPGetConfigRequest(MsgBase):
533 Get config request message
535 The controller sends a get config request to query configuration
536 parameters in the switch.
540 def send_get_config_request(self, datapath):
541 ofp_parser = datapath.ofproto_parser
543 req = ofp_parser.OFPGetConfigRequest(datapath)
544 datapath.send_msg(req)
547 def __init__(self, datapath):
548 super(OFPGetConfigRequest, self).__init__(datapath)
552 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
553 class OFPGetConfigReply(MsgBase):
555 Get config reply message
557 The switch responds to a configuration request with a get config reply
560 ============= =========================================================
561 Attribute Description
562 ============= =========================================================
563 flags Bitmap of the following flags.
569 miss_send_len Max bytes of new flow that datapath should send to the
571 ============= =========================================================
575 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
576 def get_config_reply_handler(self, ev):
582 if msg.flags & ofp.OFPC_FRAG_NORMAL:
583 flags.append('NORMAL')
584 if msg.flags & ofp.OFPC_FRAG_DROP:
586 if msg.flags & ofp.OFPC_FRAG_REASM:
587 flags.append('REASM')
588 self.logger.debug('OFPGetConfigReply received: '
589 'flags=%s miss_send_len=%d',
590 ','.join(flags), msg.miss_send_len)
593 def __init__(self, datapath, flags=None, miss_send_len=None):
594 super(OFPGetConfigReply, self).__init__(datapath)
596 self.miss_send_len = miss_send_len
599 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
600 msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
602 msg.flags, msg.miss_send_len = struct.unpack_from(
603 ofproto.OFP_SWITCH_CONFIG_PACK_STR, msg.buf,
604 ofproto.OFP_HEADER_SIZE)
608 @_set_msg_type(ofproto.OFPT_SET_CONFIG)
609 class OFPSetConfig(MsgBase):
611 Set config request message
613 The controller sends a set config request message to set configuraion
616 ============= =========================================================
617 Attribute Description
618 ============= =========================================================
619 flags Bitmap of the following flags.
624 miss_send_len Max bytes of new flow that datapath should send to the
626 ============= =========================================================
630 def send_set_config(self, datapath):
631 ofp = datapath.ofproto
632 ofp_parser = datapath.ofproto_parser
634 req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
635 datapath.send_msg(req)
638 def __init__(self, datapath, flags=0, miss_send_len=0):
639 super(OFPSetConfig, self).__init__(datapath)
641 self.miss_send_len = miss_send_len
643 def _serialize_body(self):
644 assert self.flags is not None
645 assert self.miss_send_len is not None
646 msg_pack_into(ofproto.OFP_SWITCH_CONFIG_PACK_STR,
647 self.buf, ofproto.OFP_HEADER_SIZE,
648 self.flags, self.miss_send_len)
651 UINT64_MAX = (1 << 64) - 1
652 UINT32_MAX = (1 << 32) - 1
653 UINT16_MAX = (1 << 16) - 1
661 self.dl_dst = mac.DONTCARE
662 self.dl_src = mac.DONTCARE
689 self.ipv6_nd_target = []
700 class FlowWildcards(object):
702 self.metadata_mask = 0
705 self.vlan_vid_mask = 0
706 self.ipv4_src_mask = 0
707 self.ipv4_dst_mask = 0
708 self.arp_spa_mask = 0
709 self.arp_tpa_mask = 0
710 self.arp_sha_mask = 0
711 self.arp_tha_mask = 0
712 self.ipv6_src_mask = []
713 self.ipv6_dst_mask = []
714 self.ipv6_flabel_mask = 0
715 self.pbb_isid_mask = 0
716 self.tunnel_id_mask = 0
717 self.ipv6_exthdr_mask = 0
718 self.wildcards = (1 << 64) - 1
720 def ft_set(self, shift):
721 self.wildcards &= ~(1 << shift)
723 def ft_test(self, shift):
724 return not self.wildcards & (1 << shift)
727 class OFPMatch(StringifyMixin):
731 This class is implementation of the flow match structure having
733 There are new API and old API for compatibility. the old API is
734 supposed to be removed later.
736 You can define the flow match by the keyword arguments.
737 The following arguments are available.
739 ================ =============== ==================================
740 Argument Value Description
741 ================ =============== ==================================
742 in_port Integer 32bit Switch input port
743 in_phy_port Integer 32bit Switch physical input port
744 metadata Integer 64bit Metadata passed between tables
745 eth_dst MAC address Ethernet destination address
746 eth_src MAC address Ethernet source address
747 eth_type Integer 16bit Ethernet frame type
748 vlan_vid Integer 16bit VLAN id
749 vlan_pcp Integer 8bit VLAN priority
750 ip_dscp Integer 8bit IP DSCP (6 bits in ToS field)
751 ip_ecn Integer 8bit IP ECN (2 bits in ToS field)
752 ip_proto Integer 8bit IP protocol
753 ipv4_src IPv4 address IPv4 source address
754 ipv4_dst IPv4 address IPv4 destination address
755 tcp_src Integer 16bit TCP source port
756 tcp_dst Integer 16bit TCP destination port
757 udp_src Integer 16bit UDP source port
758 udp_dst Integer 16bit UDP destination port
759 sctp_src Integer 16bit SCTP source port
760 sctp_dst Integer 16bit SCTP destination port
761 icmpv4_type Integer 8bit ICMP type
762 icmpv4_code Integer 8bit ICMP code
763 arp_op Integer 16bit ARP opcode
764 arp_spa IPv4 address ARP source IPv4 address
765 arp_tpa IPv4 address ARP target IPv4 address
766 arp_sha MAC address ARP source hardware address
767 arp_tha MAC address ARP target hardware address
768 ipv6_src IPv6 address IPv6 source address
769 ipv6_dst IPv6 address IPv6 destination address
770 ipv6_flabel Integer 32bit IPv6 Flow Label
771 icmpv6_type Integer 8bit ICMPv6 type
772 icmpv6_code Integer 8bit ICMPv6 code
773 ipv6_nd_target IPv6 address Target address for ND
774 ipv6_nd_sll MAC address Source link-layer for ND
775 ipv6_nd_tll MAC address Target link-layer for ND
776 mpls_label Integer 32bit MPLS label
777 mpls_tc Integer 8bit MPLS TC
778 mpls_bos Integer 8bit MPLS BoS bit
779 pbb_isid Integer 24bit PBB I-SID
780 tunnel_id Integer 64bit Logical Port Metadata
781 ipv6_exthdr Integer 16bit IPv6 Extension Header pseudo-field
782 pbb_uca Integer 8bit PBB UCA header field
783 (EXT-256 Old version of ONF Extension)
784 tcp_flags Integer 16bit TCP flags
785 (EXT-109 ONF Extension)
786 actset_output Integer 32bit Output port from action set metadata
787 (EXT-233 ONF Extension)
788 ================ =============== ==================================
793 >>> match = parser.OFPMatch(
796 ... ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
797 ... 'ffff:ffff:ffff:ffff::'),
798 ... ipv6_dst='2001:db8:bd05:1d2:288a:1fc0:1:10ee')
800 >>> if 'ipv6_src' in match:
801 ... print match['ipv6_src']
803 ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::')
807 For the list of the supported Nicira experimenter matches,
808 please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`.
812 For VLAN id match field, special values are defined in OpenFlow Spec.
814 1) Packets with and without a VLAN tag
818 match = parser.OFPMatch()
822 ====================== =====
823 non-VLAN-tagged MATCH
824 VLAN-tagged(vlan_id=3) MATCH
825 VLAN-tagged(vlan_id=5) MATCH
826 ====================== =====
828 2) Only packets without a VLAN tag
832 match = parser.OFPMatch(vlan_vid=0x0000)
836 ====================== =====
837 non-VLAN-tagged MATCH
838 VLAN-tagged(vlan_id=3) x
839 VLAN-tagged(vlan_id=5) x
840 ====================== =====
842 3) Only packets with a VLAN tag regardless of its value
846 match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000))
850 ====================== =====
852 VLAN-tagged(vlan_id=3) MATCH
853 VLAN-tagged(vlan_id=5) MATCH
854 ====================== =====
856 4) Only packets with VLAN tag and VID equal
860 match = parser.OFPMatch(vlan_vid=(0x1000 | 3))
864 ====================== =====
866 VLAN-tagged(vlan_id=3) MATCH
867 VLAN-tagged(vlan_id=5) x
868 ====================== =====
871 def __init__(self, type_=None, length=None, _ordered_fields=None,
874 You can define the flow match by the keyword arguments.
875 Please refer to ofproto.oxm_types for the key which you can
878 super(OFPMatch, self).__init__()
879 self._wc = FlowWildcards()
882 self.type = ofproto.OFPMT_OXM
885 if _ordered_fields is not None:
887 self._fields2 = _ordered_fields
890 # OFPMatch(eth_src=('ff:ff:ff:00:00:00'), eth_type=0x800,
891 # ipv4_src='10.0.0.1')
892 kwargs = dict(ofproto.oxm_normalize_user(k, v) for
893 (k, v) in kwargs.items())
894 fields = [ofproto.oxm_from_user(k, v) for (k, v)
896 # assumption: sorting by OXM type values makes fields
897 # meet ordering requirements (eg. eth_type before ipv4_src)
899 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
900 self._fields2 = [ofproto.oxm_to_user(n, v, m) for (n, v, m)
903 def __getitem__(self, key):
904 return dict(self._fields2)[key]
906 def __contains__(self, key):
907 return key in dict(self._fields2)
910 return iter(dict(self._fields2).items())
915 def get(self, key, default=None):
916 return dict(self._fields2).get(key, default)
918 def stringify_attrs(self):
919 yield "oxm_fields", dict(self._fields2)
921 def to_jsondict(self):
923 Returns a dict expressing the flow match.
926 if self._composed_with_old_api():
927 # copy object first because serialize_old is destructive
929 o2.fields = self.fields[:]
930 # serialize and parse to fill OFPMatch._fields2
933 o = OFPMatch.parser(six.binary_type(buf), 0)
937 body = {"oxm_fields": [ofproto.oxm_to_jsondict(k, uv) for k, uv
941 return {self.__class__.__name__: body}
944 def from_jsondict(cls, dict_):
946 Returns an object which is generated from a dict.
949 KeyError -- Unknown match field is defined in dict
951 fields = [ofproto.oxm_from_jsondict(f) for f
952 in dict_['oxm_fields']]
953 o = OFPMatch(_ordered_fields=fields)
955 # serialize and parse to fill OFPMatch.fields
958 return OFPMatch.parser(six.binary_type(buf), 0)
962 if self._composed_with_old_api():
963 # copy object first because serialize_old is destructive
965 o2.fields = self.fields[:]
966 # serialize and parse to fill OFPMatch._fields2
969 o = OFPMatch.parser(six.binary_type(buf), 0)
972 return super(OFPMatch, o).__str__()
976 def append_field(self, header, value, mask=None):
978 Append a match field.
980 ========= =======================================================
982 ========= =======================================================
983 header match field header ID which is defined automatically in
985 value match field value
986 mask mask value to the match field
987 ========= =======================================================
989 The available ``header`` is as follows.
991 ====================== ===================================
992 Header ID Description
993 ====================== ===================================
994 OXM_OF_IN_PORT Switch input port
995 OXM_OF_IN_PHY_PORT Switch physical input port
996 OXM_OF_METADATA Metadata passed between tables
997 OXM_OF_ETH_DST Ethernet destination address
998 OXM_OF_ETH_SRC Ethernet source address
999 OXM_OF_ETH_TYPE Ethernet frame type
1000 OXM_OF_VLAN_VID VLAN id
1001 OXM_OF_VLAN_PCP VLAN priority
1002 OXM_OF_IP_DSCP IP DSCP (6 bits in ToS field)
1003 OXM_OF_IP_ECN IP ECN (2 bits in ToS field)
1004 OXM_OF_IP_PROTO IP protocol
1005 OXM_OF_IPV4_SRC IPv4 source address
1006 OXM_OF_IPV4_DST IPv4 destination address
1007 OXM_OF_TCP_SRC TCP source port
1008 OXM_OF_TCP_DST TCP destination port
1009 OXM_OF_UDP_SRC UDP source port
1010 OXM_OF_UDP_DST UDP destination port
1011 OXM_OF_SCTP_SRC SCTP source port
1012 OXM_OF_SCTP_DST SCTP destination port
1013 OXM_OF_ICMPV4_TYPE ICMP type
1014 OXM_OF_ICMPV4_CODE ICMP code
1015 OXM_OF_ARP_OP ARP opcode
1016 OXM_OF_ARP_SPA ARP source IPv4 address
1017 OXM_OF_ARP_TPA ARP target IPv4 address
1018 OXM_OF_ARP_SHA ARP source hardware address
1019 OXM_OF_ARP_THA ARP target hardware address
1020 OXM_OF_IPV6_SRC IPv6 source address
1021 OXM_OF_IPV6_DST IPv6 destination address
1022 OXM_OF_IPV6_FLABEL IPv6 Flow Label
1023 OXM_OF_ICMPV6_TYPE ICMPv6 type
1024 OXM_OF_ICMPV6_CODE ICMPv6 code
1025 OXM_OF_IPV6_ND_TARGET Target address for ND
1026 OXM_OF_IPV6_ND_SLL Source link-layer for ND
1027 OXM_OF_IPV6_ND_TLL Target link-layer for ND
1028 OXM_OF_MPLS_LABEL MPLS label
1029 OXM_OF_MPLS_TC MPLS TC
1030 OXM_OF_MPLS_BOS MPLS BoS bit
1031 OXM_OF_PBB_ISID PBB I-SID
1032 OXM_OF_TUNNEL_ID Logical Port Metadata
1033 OXM_OF_IPV6_EXTHDR IPv6 Extension Header pseudo-field
1034 ====================== ===================================
1036 self.fields.append(OFPMatchField.make(header, value, mask))
1038 def _composed_with_old_api(self):
1039 return (self.fields and not self._fields2) or \
1040 self._wc.__dict__ != FlowWildcards().__dict__
1042 def serialize(self, buf, offset):
1044 Outputs the expression of the wire protocol of the flow match into
1046 Returns the output length.
1049 if self._composed_with_old_api():
1050 return self.serialize_old(buf, offset)
1052 fields = [ofproto.oxm_from_user(k, uv) for (k, uv)
1055 hdr_pack_str = '!HH'
1056 field_offset = offset + struct.calcsize(hdr_pack_str)
1057 for (n, value, mask) in fields:
1058 field_offset += ofproto.oxm_serialize(n, value, mask, buf,
1061 length = field_offset - offset
1062 msg_pack_into(hdr_pack_str, buf, offset,
1063 ofproto.OFPMT_OXM, length)
1064 self.length = length
1066 pad_len = utils.round_up(length, 8) - length
1067 msg_pack_into("%dx" % pad_len, buf, field_offset)
1069 return length + pad_len
1071 def serialize_old(self, buf, offset):
1072 if hasattr(self, '_serialized'):
1073 raise Exception('serializing an OFPMatch composed with '
1074 'old API multiple times is not supported')
1075 self._serialized = True
1077 if self._wc.ft_test(ofproto.OFPXMT_OFB_IN_PORT):
1078 self.append_field(ofproto.OXM_OF_IN_PORT,
1081 if self._wc.ft_test(ofproto.OFPXMT_OFB_IN_PHY_PORT):
1082 self.append_field(ofproto.OXM_OF_IN_PHY_PORT,
1083 self._flow.in_phy_port)
1085 if self._wc.ft_test(ofproto.OFPXMT_OFB_METADATA):
1086 if self._wc.metadata_mask == UINT64_MAX:
1087 header = ofproto.OXM_OF_METADATA
1089 header = ofproto.OXM_OF_METADATA_W
1090 self.append_field(header, self._flow.metadata,
1091 self._wc.metadata_mask)
1093 if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_DST):
1094 if self._wc.dl_dst_mask:
1095 header = ofproto.OXM_OF_ETH_DST_W
1097 header = ofproto.OXM_OF_ETH_DST
1098 self.append_field(header, self._flow.dl_dst, self._wc.dl_dst_mask)
1100 if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_SRC):
1101 if self._wc.dl_src_mask:
1102 header = ofproto.OXM_OF_ETH_SRC_W
1104 header = ofproto.OXM_OF_ETH_SRC
1105 self.append_field(header, self._flow.dl_src, self._wc.dl_src_mask)
1107 if self._wc.ft_test(ofproto.OFPXMT_OFB_ETH_TYPE):
1108 self.append_field(ofproto.OXM_OF_ETH_TYPE, self._flow.dl_type)
1110 if self._wc.ft_test(ofproto.OFPXMT_OFB_VLAN_VID):
1111 if self._wc.vlan_vid_mask == UINT16_MAX:
1112 header = ofproto.OXM_OF_VLAN_VID
1114 header = ofproto.OXM_OF_VLAN_VID_W
1115 self.append_field(header, self._flow.vlan_vid,
1116 self._wc.vlan_vid_mask)
1118 if self._wc.ft_test(ofproto.OFPXMT_OFB_VLAN_PCP):
1119 self.append_field(ofproto.OXM_OF_VLAN_PCP,
1120 self._flow.vlan_pcp)
1122 if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_DSCP):
1123 self.append_field(ofproto.OXM_OF_IP_DSCP, self._flow.ip_dscp)
1125 if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_ECN):
1126 self.append_field(ofproto.OXM_OF_IP_ECN, self._flow.ip_ecn)
1128 if self._wc.ft_test(ofproto.OFPXMT_OFB_IP_PROTO):
1129 self.append_field(ofproto.OXM_OF_IP_PROTO,
1130 self._flow.ip_proto)
1132 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV4_SRC):
1133 if self._wc.ipv4_src_mask == UINT32_MAX:
1134 header = ofproto.OXM_OF_IPV4_SRC
1136 header = ofproto.OXM_OF_IPV4_SRC_W
1137 self.append_field(header, self._flow.ipv4_src,
1138 self._wc.ipv4_src_mask)
1140 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV4_DST):
1141 if self._wc.ipv4_dst_mask == UINT32_MAX:
1142 header = ofproto.OXM_OF_IPV4_DST
1144 header = ofproto.OXM_OF_IPV4_DST_W
1145 self.append_field(header, self._flow.ipv4_dst,
1146 self._wc.ipv4_dst_mask)
1148 if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_SRC):
1149 self.append_field(ofproto.OXM_OF_TCP_SRC, self._flow.tcp_src)
1151 if self._wc.ft_test(ofproto.OFPXMT_OFB_TCP_DST):
1152 self.append_field(ofproto.OXM_OF_TCP_DST, self._flow.tcp_dst)
1154 if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_SRC):
1155 self.append_field(ofproto.OXM_OF_UDP_SRC, self._flow.udp_src)
1157 if self._wc.ft_test(ofproto.OFPXMT_OFB_UDP_DST):
1158 self.append_field(ofproto.OXM_OF_UDP_DST, self._flow.udp_dst)
1160 if self._wc.ft_test(ofproto.OFPXMT_OFB_SCTP_SRC):
1161 self.append_field(ofproto.OXM_OF_SCTP_SRC,
1162 self._flow.sctp_src)
1164 if self._wc.ft_test(ofproto.OFPXMT_OFB_SCTP_DST):
1165 self.append_field(ofproto.OXM_OF_SCTP_DST,
1166 self._flow.sctp_dst)
1168 if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV4_TYPE):
1169 self.append_field(ofproto.OXM_OF_ICMPV4_TYPE,
1170 self._flow.icmpv4_type)
1172 if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV4_CODE):
1173 self.append_field(ofproto.OXM_OF_ICMPV4_CODE,
1174 self._flow.icmpv4_code)
1176 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_OP):
1177 self.append_field(ofproto.OXM_OF_ARP_OP, self._flow.arp_op)
1179 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_SPA):
1180 if self._wc.arp_spa_mask == UINT32_MAX:
1181 header = ofproto.OXM_OF_ARP_SPA
1183 header = ofproto.OXM_OF_ARP_SPA_W
1184 self.append_field(header, self._flow.arp_spa,
1185 self._wc.arp_spa_mask)
1187 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_TPA):
1188 if self._wc.arp_tpa_mask == UINT32_MAX:
1189 header = ofproto.OXM_OF_ARP_TPA
1191 header = ofproto.OXM_OF_ARP_TPA_W
1192 self.append_field(header, self._flow.arp_tpa,
1193 self._wc.arp_tpa_mask)
1195 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_SHA):
1196 if self._wc.arp_sha_mask:
1197 header = ofproto.OXM_OF_ARP_SHA_W
1199 header = ofproto.OXM_OF_ARP_SHA
1200 self.append_field(header, self._flow.arp_sha,
1201 self._wc.arp_sha_mask)
1203 if self._wc.ft_test(ofproto.OFPXMT_OFB_ARP_THA):
1204 if self._wc.arp_tha_mask:
1205 header = ofproto.OXM_OF_ARP_THA_W
1207 header = ofproto.OXM_OF_ARP_THA
1208 self.append_field(header, self._flow.arp_tha,
1209 self._wc.arp_tha_mask)
1211 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_SRC):
1212 if len(self._wc.ipv6_src_mask):
1213 header = ofproto.OXM_OF_IPV6_SRC_W
1215 header = ofproto.OXM_OF_IPV6_SRC
1216 self.append_field(header, self._flow.ipv6_src,
1217 self._wc.ipv6_src_mask)
1219 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_DST):
1220 if len(self._wc.ipv6_dst_mask):
1221 header = ofproto.OXM_OF_IPV6_DST_W
1223 header = ofproto.OXM_OF_IPV6_DST
1224 self.append_field(header, self._flow.ipv6_dst,
1225 self._wc.ipv6_dst_mask)
1227 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_FLABEL):
1228 if self._wc.ipv6_flabel_mask == UINT32_MAX:
1229 header = ofproto.OXM_OF_IPV6_FLABEL
1231 header = ofproto.OXM_OF_IPV6_FLABEL_W
1232 self.append_field(header, self._flow.ipv6_flabel,
1233 self._wc.ipv6_flabel_mask)
1235 if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV6_TYPE):
1236 self.append_field(ofproto.OXM_OF_ICMPV6_TYPE,
1237 self._flow.icmpv6_type)
1239 if self._wc.ft_test(ofproto.OFPXMT_OFB_ICMPV6_CODE):
1240 self.append_field(ofproto.OXM_OF_ICMPV6_CODE,
1241 self._flow.icmpv6_code)
1243 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_TARGET):
1244 self.append_field(ofproto.OXM_OF_IPV6_ND_TARGET,
1245 self._flow.ipv6_nd_target)
1247 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_SLL):
1248 self.append_field(ofproto.OXM_OF_IPV6_ND_SLL,
1249 self._flow.ipv6_nd_sll)
1251 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_ND_TLL):
1252 self.append_field(ofproto.OXM_OF_IPV6_ND_TLL,
1253 self._flow.ipv6_nd_tll)
1255 if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_LABEL):
1256 self.append_field(ofproto.OXM_OF_MPLS_LABEL,
1257 self._flow.mpls_label)
1259 if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_TC):
1260 self.append_field(ofproto.OXM_OF_MPLS_TC,
1263 if self._wc.ft_test(ofproto.OFPXMT_OFB_MPLS_BOS):
1264 self.append_field(ofproto.OXM_OF_MPLS_BOS,
1265 self._flow.mpls_bos)
1267 if self._wc.ft_test(ofproto.OFPXMT_OFB_PBB_ISID):
1268 if self._wc.pbb_isid_mask:
1269 header = ofproto.OXM_OF_PBB_ISID_W
1271 header = ofproto.OXM_OF_PBB_ISID
1272 self.append_field(header, self._flow.pbb_isid,
1273 self._wc.pbb_isid_mask)
1275 if self._wc.ft_test(ofproto.OFPXMT_OFB_TUNNEL_ID):
1276 if self._wc.tunnel_id_mask:
1277 header = ofproto.OXM_OF_TUNNEL_ID_W
1279 header = ofproto.OXM_OF_TUNNEL_ID
1280 self.append_field(header, self._flow.tunnel_id,
1281 self._wc.tunnel_id_mask)
1283 if self._wc.ft_test(ofproto.OFPXMT_OFB_IPV6_EXTHDR):
1284 if self._wc.ipv6_exthdr_mask:
1285 header = ofproto.OXM_OF_IPV6_EXTHDR_W
1287 header = ofproto.OXM_OF_IPV6_EXTHDR
1288 self.append_field(header, self._flow.ipv6_exthdr,
1289 self._wc.ipv6_exthdr_mask)
1291 field_offset = offset + 4
1292 for f in self.fields:
1293 f.serialize(buf, field_offset)
1294 field_offset += f.length
1296 length = field_offset - offset
1297 msg_pack_into('!HH', buf, offset, ofproto.OFPMT_OXM, length)
1299 pad_len = utils.round_up(length, 8) - length
1300 msg_pack_into("%dx" % pad_len, buf, field_offset)
1302 return length + pad_len
1305 def parser(cls, buf, offset):
1307 Returns an object which is generated from a buffer including the
1308 expression of the wire protocol of the flow match.
1311 type_, length = struct.unpack_from('!HH', buf, offset)
1314 match.length = length
1316 # ofp_match adjustment
1324 cls.parser_old(match, buf, offset, length)
1325 except struct.error as e:
1331 n, value, mask, field_len = ofproto.oxm_parse(buf, offset)
1332 k, uv = ofproto.oxm_to_user(n, value, mask)
1333 fields.append((k, uv))
1336 except struct.error as e:
1338 residue = buf[offset:]
1339 match._fields2 = fields
1341 raise exception.OFPTruncatedMessage(match, residue, exc)
1345 def parser_old(match, buf, offset, length):
1347 field = OFPMatchField.parser(buf, offset)
1348 offset += field.length
1349 length -= field.length
1350 match.fields.append(field)
1352 def set_in_port(self, port):
1353 self._wc.ft_set(ofproto.OFPXMT_OFB_IN_PORT)
1354 self._flow.in_port = port
1356 def set_in_phy_port(self, phy_port):
1357 self._wc.ft_set(ofproto.OFPXMT_OFB_IN_PHY_PORT)
1358 self._flow.in_phy_port = phy_port
1360 def set_metadata(self, metadata):
1361 self.set_metadata_masked(metadata, UINT64_MAX)
1363 def set_metadata_masked(self, metadata, mask):
1364 self._wc.ft_set(ofproto.OFPXMT_OFB_METADATA)
1365 self._wc.metadata_mask = mask
1366 self._flow.metadata = metadata & mask
1368 def set_dl_dst(self, dl_dst):
1369 self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_DST)
1370 self._flow.dl_dst = dl_dst
1372 def set_dl_dst_masked(self, dl_dst, mask):
1373 self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_DST)
1374 self._wc.dl_dst_mask = mask
1375 # bit-wise and of the corresponding elements of dl_dst and mask
1376 self._flow.dl_dst = mac.haddr_bitand(dl_dst, mask)
1378 def set_dl_src(self, dl_src):
1379 self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_SRC)
1380 self._flow.dl_src = dl_src
1382 def set_dl_src_masked(self, dl_src, mask):
1383 self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_SRC)
1384 self._wc.dl_src_mask = mask
1385 self._flow.dl_src = mac.haddr_bitand(dl_src, mask)
1387 def set_dl_type(self, dl_type):
1388 self._wc.ft_set(ofproto.OFPXMT_OFB_ETH_TYPE)
1389 self._flow.dl_type = dl_type
1391 def set_vlan_vid_none(self):
1392 self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_VID)
1393 self._wc.vlan_vid_mask = UINT16_MAX
1394 self._flow.vlan_vid = ofproto.OFPVID_NONE
1396 def set_vlan_vid(self, vid):
1397 self.set_vlan_vid_masked(vid, UINT16_MAX)
1399 def set_vlan_vid_masked(self, vid, mask):
1400 vid |= ofproto.OFPVID_PRESENT
1401 self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_VID)
1402 self._wc.vlan_vid_mask = mask
1403 self._flow.vlan_vid = vid
1405 def set_vlan_pcp(self, pcp):
1406 self._wc.ft_set(ofproto.OFPXMT_OFB_VLAN_PCP)
1407 self._flow.vlan_pcp = pcp
1409 def set_ip_dscp(self, ip_dscp):
1410 self._wc.ft_set(ofproto.OFPXMT_OFB_IP_DSCP)
1411 self._flow.ip_dscp = ip_dscp
1413 def set_ip_ecn(self, ip_ecn):
1414 self._wc.ft_set(ofproto.OFPXMT_OFB_IP_ECN)
1415 self._flow.ip_ecn = ip_ecn
1417 def set_ip_proto(self, ip_proto):
1418 self._wc.ft_set(ofproto.OFPXMT_OFB_IP_PROTO)
1419 self._flow.ip_proto = ip_proto
1421 def set_ipv4_src(self, ipv4_src):
1422 self.set_ipv4_src_masked(ipv4_src, UINT32_MAX)
1424 def set_ipv4_src_masked(self, ipv4_src, mask):
1425 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV4_SRC)
1426 self._flow.ipv4_src = ipv4_src
1427 self._wc.ipv4_src_mask = mask
1429 def set_ipv4_dst(self, ipv4_dst):
1430 self.set_ipv4_dst_masked(ipv4_dst, UINT32_MAX)
1432 def set_ipv4_dst_masked(self, ipv4_dst, mask):
1433 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV4_DST)
1434 self._flow.ipv4_dst = ipv4_dst
1435 self._wc.ipv4_dst_mask = mask
1437 def set_tcp_src(self, tcp_src):
1438 self._wc.ft_set(ofproto.OFPXMT_OFB_TCP_SRC)
1439 self._flow.tcp_src = tcp_src
1441 def set_tcp_dst(self, tcp_dst):
1442 self._wc.ft_set(ofproto.OFPXMT_OFB_TCP_DST)
1443 self._flow.tcp_dst = tcp_dst
1445 def set_udp_src(self, udp_src):
1446 self._wc.ft_set(ofproto.OFPXMT_OFB_UDP_SRC)
1447 self._flow.udp_src = udp_src
1449 def set_udp_dst(self, udp_dst):
1450 self._wc.ft_set(ofproto.OFPXMT_OFB_UDP_DST)
1451 self._flow.udp_dst = udp_dst
1453 def set_sctp_src(self, sctp_src):
1454 self._wc.ft_set(ofproto.OFPXMT_OFB_SCTP_SRC)
1455 self._flow.sctp_src = sctp_src
1457 def set_sctp_dst(self, sctp_dst):
1458 self._wc.ft_set(ofproto.OFPXMT_OFB_SCTP_DST)
1459 self._flow.sctp_dst = sctp_dst
1461 def set_icmpv4_type(self, icmpv4_type):
1462 self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV4_TYPE)
1463 self._flow.icmpv4_type = icmpv4_type
1465 def set_icmpv4_code(self, icmpv4_code):
1466 self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV4_CODE)
1467 self._flow.icmpv4_code = icmpv4_code
1469 def set_arp_opcode(self, arp_op):
1470 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_OP)
1471 self._flow.arp_op = arp_op
1473 def set_arp_spa(self, arp_spa):
1474 self.set_arp_spa_masked(arp_spa, UINT32_MAX)
1476 def set_arp_spa_masked(self, arp_spa, mask):
1477 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SPA)
1478 self._wc.arp_spa_mask = mask
1479 self._flow.arp_spa = arp_spa
1481 def set_arp_tpa(self, arp_tpa):
1482 self.set_arp_tpa_masked(arp_tpa, UINT32_MAX)
1484 def set_arp_tpa_masked(self, arp_tpa, mask):
1485 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_TPA)
1486 self._wc.arp_tpa_mask = mask
1487 self._flow.arp_tpa = arp_tpa
1489 def set_arp_sha(self, arp_sha):
1490 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SHA)
1491 self._flow.arp_sha = arp_sha
1493 def set_arp_sha_masked(self, arp_sha, mask):
1494 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_SHA)
1495 self._wc.arp_sha_mask = mask
1496 self._flow.arp_sha = mac.haddr_bitand(arp_sha, mask)
1498 def set_arp_tha(self, arp_tha):
1499 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_THA)
1500 self._flow.arp_tha = arp_tha
1502 def set_arp_tha_masked(self, arp_tha, mask):
1503 self._wc.ft_set(ofproto.OFPXMT_OFB_ARP_THA)
1504 self._wc.arp_tha_mask = mask
1505 self._flow.arp_tha = mac.haddr_bitand(arp_tha, mask)
1507 def set_ipv6_src(self, src):
1508 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_SRC)
1509 self._flow.ipv6_src = src
1511 def set_ipv6_src_masked(self, src, mask):
1512 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_SRC)
1513 self._wc.ipv6_src_mask = mask
1514 self._flow.ipv6_src = [x & y for (x, y) in zip(src, mask)]
1516 def set_ipv6_dst(self, dst):
1517 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_DST)
1518 self._flow.ipv6_dst = dst
1520 def set_ipv6_dst_masked(self, dst, mask):
1521 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_DST)
1522 self._wc.ipv6_dst_mask = mask
1523 self._flow.ipv6_dst = [x & y for (x, y) in zip(dst, mask)]
1525 def set_ipv6_flabel(self, flabel):
1526 self.set_ipv6_flabel_masked(flabel, UINT32_MAX)
1528 def set_ipv6_flabel_masked(self, flabel, mask):
1529 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_FLABEL)
1530 self._wc.ipv6_flabel_mask = mask
1531 self._flow.ipv6_flabel = flabel
1533 def set_icmpv6_type(self, icmpv6_type):
1534 self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV6_TYPE)
1535 self._flow.icmpv6_type = icmpv6_type
1537 def set_icmpv6_code(self, icmpv6_code):
1538 self._wc.ft_set(ofproto.OFPXMT_OFB_ICMPV6_CODE)
1539 self._flow.icmpv6_code = icmpv6_code
1541 def set_ipv6_nd_target(self, target):
1542 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_TARGET)
1543 self._flow.ipv6_nd_target = target
1545 def set_ipv6_nd_sll(self, ipv6_nd_sll):
1546 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_SLL)
1547 self._flow.ipv6_nd_sll = ipv6_nd_sll
1549 def set_ipv6_nd_tll(self, ipv6_nd_tll):
1550 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_ND_TLL)
1551 self._flow.ipv6_nd_tll = ipv6_nd_tll
1553 def set_mpls_label(self, mpls_label):
1554 self._wc.ft_set(ofproto.OFPXMT_OFB_MPLS_LABEL)
1555 self._flow.mpls_label = mpls_label
1557 def set_mpls_tc(self, mpls_tc):
1558 self._wc.ft_set(ofproto.OFPXMT_OFB_MPLS_TC)
1559 self._flow.mpls_tc = mpls_tc
1561 def set_mpls_bos(self, bos):
1562 self._wc.ft_set(ofproto.OFPXMT_OFB_MPLS_BOS)
1563 self._flow.mpls_bos = bos
1565 def set_pbb_isid(self, isid):
1566 self._wc.ft_set(ofproto.OFPXMT_OFB_PBB_ISID)
1567 self._flow.pbb_isid = isid
1569 def set_pbb_isid_masked(self, isid, mask):
1570 self._wc.ft_set(ofproto.OFPXMT_OFB_PBB_ISID)
1571 self._wc.pbb_isid_mask = mask
1572 self._flow.pbb_isid = isid
1574 def set_tunnel_id(self, tunnel_id):
1575 self._wc.ft_set(ofproto.OFPXMT_OFB_TUNNEL_ID)
1576 self._flow.tunnel_id = tunnel_id
1578 def set_tunnel_id_masked(self, tunnel_id, mask):
1579 self._wc.ft_set(ofproto.OFPXMT_OFB_TUNNEL_ID)
1580 self._wc.tunnel_id_mask = mask
1581 self._flow.tunnel_id = tunnel_id
1583 def set_ipv6_exthdr(self, hdr):
1584 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_EXTHDR)
1585 self._flow.ipv6_exthdr = hdr
1587 def set_ipv6_exthdr_masked(self, hdr, mask):
1588 self._wc.ft_set(ofproto.OFPXMT_OFB_IPV6_EXTHDR)
1589 self._wc.ipv6_exthdr_mask = mask
1590 self._flow.ipv6_exthdr = hdr
1593 class OFPPropUnknown(StringifyMixin):
1594 def __init__(self, type_=None, length=None, buf=None):
1598 def parser(cls, buf):
1602 class OFPPropBase(StringifyMixin):
1604 # _TYPES = {} must be an attribute of subclass
1606 def __init__(self, type_, length=None):
1608 self.length = length
1611 def register_type(cls, type_):
1612 def _register_type(subcls):
1613 cls._TYPES[type_] = subcls
1615 return _register_type
1618 def parse(cls, buf):
1619 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
1620 rest = buf[utils.round_up(length, 8):]
1622 subcls = cls._TYPES[type_]
1624 subcls = OFPPropUnknown
1625 prop = subcls.parser(buf)
1627 prop.length = length
1631 def get_rest(cls, buf):
1632 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
1633 offset = struct.calcsize(cls._PACK_STR)
1634 return buf[offset:length]
1636 def serialize(self):
1638 # serialize_body should be implemented by subclass
1640 body += self.serialize_body()
1643 self.length = len(body) + struct.calcsize(self._PACK_STR)
1647 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.length)
1651 pad_len = utils.round_up(self.length, 8) - self.length
1652 msg_pack_into("%dx" % pad_len, buf, len(buf))
1657 class OFPPropCommonExperimenter4ByteData(StringifyMixin):
1659 _EXPERIMENTER_DATA_PACK_STR = '!I'
1660 _EXPERIMENTER_DATA_SIZE = 4
1662 def __init__(self, type_=None, length=None, experimenter=None,
1663 exp_type=None, data=bytearray()):
1665 self.length = length
1666 self.experimenter = experimenter
1667 self.exp_type = exp_type
1671 def parser(cls, buf):
1672 (type_, length, experimenter, exp_type) = struct.unpack_from(
1673 ofproto.OFP_PROP_EXPERIMENTER_PACK_STR, buf, 0)
1675 rest = buf[ofproto.OFP_PROP_EXPERIMENTER_SIZE:length]
1678 (d,) = struct.unpack_from(
1679 cls._EXPERIMENTER_DATA_PACK_STR, rest, 0)
1681 rest = rest[cls._EXPERIMENTER_DATA_SIZE:]
1683 return cls(type_, length, experimenter, exp_type, data)
1685 def serialize(self):
1687 bin_data = bytearray()
1689 msg_pack_into(self._EXPERIMENTER_DATA_PACK_STR,
1690 bin_data, offset, d)
1691 offset += self._EXPERIMENTER_DATA_SIZE
1694 self.length = struct.calcsize(self._PACK_STR)
1695 self.length += len(bin_data)
1698 msg_pack_into(self._PACK_STR, buf,
1699 0, self.type, self.length, self.experimenter,
1704 pad_len = utils.round_up(self.length, 8) - self.length
1705 msg_pack_into("%dx" % pad_len, buf, len(buf))
1710 class OFPMatchField(StringifyMixin):
1711 _FIELDS_HEADERS = {}
1714 def register_field_header(headers):
1715 def _register_field_header(cls):
1716 for header in headers:
1717 OFPMatchField._FIELDS_HEADERS[header] = cls
1719 return _register_field_header
1721 def __init__(self, header):
1722 self.header = header
1723 self.n_bytes = ofproto.oxm_tlv_header_extract_length(header)
1727 def cls_to_header(cls, cls_, hasmask):
1729 inv = dict((v, k) for k, v in cls._FIELDS_HEADERS.items()
1730 if (((k >> 8) & 1) != 0) == hasmask)
1734 def make(header, value, mask=None):
1735 cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
1736 return cls_(header, value, mask)
1739 def parser(cls, buf, offset):
1740 (header,) = struct.unpack_from('!I', buf, offset)
1741 cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
1743 field = cls_.field_parser(header, buf, offset)
1745 field = OFPMatchField(header)
1746 field.length = (header & 0xff) + 4
1750 def field_parser(cls, header, buf, offset):
1752 if ofproto.oxm_tlv_header_extract_hasmask(header):
1753 pack_str = '!' + cls.pack_str[1:] * 2
1754 (value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
1756 (value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
1757 return cls(header, value, mask)
1759 def serialize(self, buf, offset):
1760 if ofproto.oxm_tlv_header_extract_hasmask(self.header):
1761 self.put_w(buf, offset, self.value, self.mask)
1763 self.put(buf, offset, self.value)
1765 def _put_header(self, buf, offset):
1766 msg_pack_into('!I', buf, offset, self.header)
1769 def _put(self, buf, offset, value):
1770 msg_pack_into(self.pack_str, buf, offset, value)
1771 self.length += self.n_bytes
1773 def put_w(self, buf, offset, value, mask):
1774 self._put_header(buf, offset)
1775 self._put(buf, offset + self.length, value)
1776 self._put(buf, offset + self.length, mask)
1778 def put(self, buf, offset, value):
1779 self._put_header(buf, offset)
1780 self._put(buf, offset + self.length, value)
1782 def _putv6(self, buf, offset, value):
1783 msg_pack_into(self.pack_str, buf, offset, *value)
1784 self.length += self.n_bytes
1786 def putv6(self, buf, offset, value, mask=None):
1787 self._put_header(buf, offset)
1788 self._putv6(buf, offset + self.length, value)
1789 if mask and len(mask):
1790 self._putv6(buf, offset + self.length, mask)
1793 return self.header & 0xff
1795 def to_jsondict(self):
1796 # remove some redundant attributes
1797 d = super(OFPMatchField, self).to_jsondict()
1798 v = d[self.__class__.__name__]
1805 def from_jsondict(cls, dict_):
1806 # just pass the dict around.
1807 # it will be converted by OFPMatch.__init__().
1808 return {cls.__name__: dict_}
1810 def stringify_attrs(self):
1811 f = super(OFPMatchField, self).stringify_attrs
1812 if not ofproto.oxm_tlv_header_extract_hasmask(self.header):
1813 # something like the following, but yield two values (k,v)
1814 # return itertools.ifilter(lambda k, v: k != 'mask', iter())
1824 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PORT])
1825 class MTInPort(OFPMatchField):
1828 def __init__(self, header, value, mask=None):
1829 super(MTInPort, self).__init__(header)
1833 @OFPMatchField.register_field_header([ofproto.OXM_OF_METADATA,
1834 ofproto.OXM_OF_METADATA_W])
1835 class MTMetadata(OFPMatchField):
1838 def __init__(self, header, value, mask=None):
1839 super(MTMetadata, self).__init__(header)
1844 @OFPMatchField.register_field_header([ofproto.OXM_OF_IN_PHY_PORT])
1845 class MTInPhyPort(OFPMatchField):
1848 def __init__(self, header, value, mask=None):
1849 super(MTInPhyPort, self).__init__(header)
1853 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_DST,
1854 ofproto.OXM_OF_ETH_DST_W])
1855 class MTEthDst(OFPMatchField):
1858 def __init__(self, header, value, mask=None):
1859 super(MTEthDst, self).__init__(header)
1864 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_SRC,
1865 ofproto.OXM_OF_ETH_SRC_W])
1866 class MTEthSrc(OFPMatchField):
1869 def __init__(self, header, value, mask=None):
1870 super(MTEthSrc, self).__init__(header)
1875 @OFPMatchField.register_field_header([ofproto.OXM_OF_ETH_TYPE])
1876 class MTEthType(OFPMatchField):
1879 def __init__(self, header, value, mask=None):
1880 super(MTEthType, self).__init__(header)
1884 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_VID,
1885 ofproto.OXM_OF_VLAN_VID_W])
1886 class MTVlanVid(OFPMatchField):
1889 def __init__(self, header, value, mask=None):
1890 super(MTVlanVid, self).__init__(header)
1895 def field_parser(cls, header, buf, offset):
1896 m = super(MTVlanVid, cls).field_parser(header, buf, offset)
1897 m.value &= ~ofproto.OFPVID_PRESENT
1901 @OFPMatchField.register_field_header([ofproto.OXM_OF_VLAN_PCP])
1902 class MTVlanPcp(OFPMatchField):
1905 def __init__(self, header, value, mask=None):
1906 super(MTVlanPcp, self).__init__(header)
1910 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_DSCP])
1911 class MTIPDscp(OFPMatchField):
1914 def __init__(self, header, value, mask=None):
1915 super(MTIPDscp, self).__init__(header)
1919 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_ECN])
1920 class MTIPECN(OFPMatchField):
1923 def __init__(self, header, value, mask=None):
1924 super(MTIPECN, self).__init__(header)
1928 @OFPMatchField.register_field_header([ofproto.OXM_OF_IP_PROTO])
1929 class MTIPProto(OFPMatchField):
1932 def __init__(self, header, value, mask=None):
1933 super(MTIPProto, self).__init__(header)
1937 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_SRC,
1938 ofproto.OXM_OF_IPV4_SRC_W])
1939 class MTIPV4Src(OFPMatchField):
1942 def __init__(self, header, value, mask=None):
1943 super(MTIPV4Src, self).__init__(header)
1948 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV4_DST,
1949 ofproto.OXM_OF_IPV4_DST_W])
1950 class MTIPV4Dst(OFPMatchField):
1953 def __init__(self, header, value, mask=None):
1954 super(MTIPV4Dst, self).__init__(header)
1959 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_SRC])
1960 class MTTCPSrc(OFPMatchField):
1963 def __init__(self, header, value, mask=None):
1964 super(MTTCPSrc, self).__init__(header)
1968 @OFPMatchField.register_field_header([ofproto.OXM_OF_TCP_DST])
1969 class MTTCPDst(OFPMatchField):
1972 def __init__(self, header, value, mask=None):
1973 super(MTTCPDst, self).__init__(header)
1977 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_SRC])
1978 class MTUDPSrc(OFPMatchField):
1981 def __init__(self, header, value, mask=None):
1982 super(MTUDPSrc, self).__init__(header)
1986 @OFPMatchField.register_field_header([ofproto.OXM_OF_UDP_DST])
1987 class MTUDPDst(OFPMatchField):
1990 def __init__(self, header, value, mask=None):
1991 super(MTUDPDst, self).__init__(header)
1995 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_SRC])
1996 class MTSCTPSrc(OFPMatchField):
1999 def __init__(self, header, value, mask=None):
2000 super(MTSCTPSrc, self).__init__(header)
2004 @OFPMatchField.register_field_header([ofproto.OXM_OF_SCTP_DST])
2005 class MTSCTPDst(OFPMatchField):
2008 def __init__(self, header, value, mask=None):
2009 super(MTSCTPDst, self).__init__(header)
2013 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_TYPE])
2014 class MTICMPV4Type(OFPMatchField):
2017 def __init__(self, header, value, mask=None):
2018 super(MTICMPV4Type, self).__init__(header)
2022 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV4_CODE])
2023 class MTICMPV4Code(OFPMatchField):
2026 def __init__(self, header, value, mask=None):
2027 super(MTICMPV4Code, self).__init__(header)
2031 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_OP])
2032 class MTArpOp(OFPMatchField):
2035 def __init__(self, header, value, mask=None):
2036 super(MTArpOp, self).__init__(header)
2040 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SPA,
2041 ofproto.OXM_OF_ARP_SPA_W])
2042 class MTArpSpa(OFPMatchField):
2045 def __init__(self, header, value, mask=None):
2046 super(MTArpSpa, self).__init__(header)
2051 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_TPA,
2052 ofproto.OXM_OF_ARP_TPA_W])
2053 class MTArpTpa(OFPMatchField):
2056 def __init__(self, header, value, mask=None):
2057 super(MTArpTpa, self).__init__(header)
2062 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_SHA,
2063 ofproto.OXM_OF_ARP_SHA_W])
2064 class MTArpSha(OFPMatchField):
2067 def __init__(self, header, value, mask=None):
2068 super(MTArpSha, self).__init__(header)
2073 @OFPMatchField.register_field_header([ofproto.OXM_OF_ARP_THA,
2074 ofproto.OXM_OF_ARP_THA_W])
2075 class MTArpTha(OFPMatchField):
2078 def __init__(self, header, value, mask=None):
2079 super(MTArpTha, self).__init__(header)
2084 class MTIPv6(StringifyMixin):
2086 def field_parser(cls, header, buf, offset):
2087 if ofproto.oxm_tlv_header_extract_hasmask(header):
2088 pack_str = '!' + cls.pack_str[1:] * 2
2089 value = struct.unpack_from(pack_str, buf, offset + 4)
2090 return cls(header, list(value[:8]), list(value[8:]))
2092 value = struct.unpack_from(cls.pack_str, buf, offset + 4)
2093 return cls(header, list(value))
2095 def serialize(self, buf, offset):
2096 self.putv6(buf, offset, self.value, self.mask)
2099 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_SRC,
2100 ofproto.OXM_OF_IPV6_SRC_W])
2101 class MTIPv6Src(MTIPv6, OFPMatchField):
2104 def __init__(self, header, value, mask=None):
2105 super(MTIPv6Src, self).__init__(header)
2110 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_DST,
2111 ofproto.OXM_OF_IPV6_DST_W])
2112 class MTIPv6Dst(MTIPv6, OFPMatchField):
2115 def __init__(self, header, value, mask=None):
2116 super(MTIPv6Dst, self).__init__(header)
2121 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_FLABEL,
2122 ofproto.OXM_OF_IPV6_FLABEL_W])
2123 class MTIPv6Flabel(OFPMatchField):
2126 def __init__(self, header, value, mask=None):
2127 super(MTIPv6Flabel, self).__init__(header)
2132 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_LABEL])
2133 class MTMplsLabel(OFPMatchField):
2136 def __init__(self, header, value, mask=None):
2137 super(MTMplsLabel, self).__init__(header)
2141 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_TYPE])
2142 class MTICMPV6Type(OFPMatchField):
2145 def __init__(self, header, value, mask=None):
2146 super(MTICMPV6Type, self).__init__(header)
2150 @OFPMatchField.register_field_header([ofproto.OXM_OF_ICMPV6_CODE])
2151 class MTICMPV6Code(OFPMatchField):
2154 def __init__(self, header, value, mask=None):
2155 super(MTICMPV6Code, self).__init__(header)
2159 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TARGET])
2160 class MTIPv6NdTarget(MTIPv6, OFPMatchField):
2163 def __init__(self, header, value, mask=None):
2164 super(MTIPv6NdTarget, self).__init__(header)
2167 def serialize(self, buf, offset):
2168 self.putv6(buf, offset, self.value)
2171 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_SLL])
2172 class MTIPv6NdSll(OFPMatchField):
2175 def __init__(self, header, value, mask=None):
2176 super(MTIPv6NdSll, self).__init__(header)
2180 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_ND_TLL])
2181 class MTIPv6NdTll(OFPMatchField):
2184 def __init__(self, header, value, mask=None):
2185 super(MTIPv6NdTll, self).__init__(header)
2189 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_TC])
2190 class MTMplsTc(OFPMatchField):
2193 def __init__(self, header, value, mask=None):
2194 super(MTMplsTc, self).__init__(header)
2198 @OFPMatchField.register_field_header([ofproto.OXM_OF_MPLS_BOS])
2199 class MTMplsBos(OFPMatchField):
2202 def __init__(self, header, value, mask=None):
2203 super(MTMplsBos, self).__init__(header)
2207 @OFPMatchField.register_field_header([ofproto.OXM_OF_PBB_ISID,
2208 ofproto.OXM_OF_PBB_ISID_W])
2209 class MTPbbIsid(OFPMatchField):
2212 def __init__(self, header, value, mask=None):
2213 super(MTPbbIsid, self).__init__(header)
2218 def field_parser(cls, header, buf, offset):
2220 if ofproto.oxm_tlv_header_extract_hasmask(header):
2221 pack_str = '!' + cls.pack_str[1:] * 2
2222 (v1, v2, v3, m1, m2, m3) = struct.unpack_from(pack_str, buf,
2224 value = v1 << 16 | v2 << 8 | v3
2225 mask = m1 << 16 | m2 << 8 | m3
2227 (v1, v2, v3,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
2228 value = v1 << 16 | v2 << 8 | v3
2229 return cls(header, value, mask)
2231 def _put(self, buf, offset, value):
2232 msg_pack_into(self.pack_str, buf, offset,
2233 (value >> 16) & 0xff,
2234 (value >> 8) & 0xff,
2235 (value >> 0) & 0xff)
2236 self.length += self.n_bytes
2239 @OFPMatchField.register_field_header([ofproto.OXM_OF_TUNNEL_ID,
2240 ofproto.OXM_OF_TUNNEL_ID_W])
2241 class MTTunnelId(OFPMatchField):
2244 def __init__(self, header, value, mask=None):
2245 super(MTTunnelId, self).__init__(header)
2250 @OFPMatchField.register_field_header([ofproto.OXM_OF_IPV6_EXTHDR,
2251 ofproto.OXM_OF_IPV6_EXTHDR_W])
2252 class MTIPv6ExtHdr(OFPMatchField):
2255 def __init__(self, header, value, mask=None):
2256 super(MTIPv6ExtHdr, self).__init__(header)
2262 @_set_msg_type(ofproto.OFPT_PACKET_IN)
2263 class OFPPacketIn(MsgBase):
2267 The switch sends the packet that received to the controller by this
2270 ============= =========================================================
2271 Attribute Description
2272 ============= =========================================================
2273 buffer_id ID assigned by datapath
2274 total_len Full length of frame
2275 reason Reason packet is being sent.
2280 table_id ID of the table that was looked up
2281 cookie Cookie of the flow entry that was looked up
2282 match Instance of ``OFPMatch``
2284 ============= =========================================================
2288 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
2289 def packet_in_handler(self, ev):
2294 if msg.reason == ofp.OFPR_NO_MATCH:
2296 elif msg.reason == ofp.OFPR_ACTION:
2298 elif msg.reason == ofp.OFPR_INVALID_TTL:
2299 reason = 'INVALID TTL'
2303 self.logger.debug('OFPPacketIn received: '
2304 'buffer_id=%x total_len=%d reason=%s '
2305 'table_id=%d cookie=%d match=%s data=%s',
2306 msg.buffer_id, msg.total_len, reason,
2307 msg.table_id, msg.cookie, msg.match,
2308 utils.hex_array(msg.data))
2311 def __init__(self, datapath, buffer_id=None, total_len=None, reason=None,
2312 table_id=None, cookie=None, match=None, data=None):
2313 super(OFPPacketIn, self).__init__(datapath)
2314 self.buffer_id = buffer_id
2315 self.total_len = total_len
2316 self.reason = reason
2317 self.table_id = table_id
2318 self.cookie = cookie
2323 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2324 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
2326 (msg.buffer_id, msg.total_len, msg.reason,
2327 msg.table_id, msg.cookie) = struct.unpack_from(
2328 ofproto.OFP_PACKET_IN_PACK_STR,
2329 msg.buf, ofproto.OFP_HEADER_SIZE)
2331 msg.match = OFPMatch.parser(msg.buf, ofproto.OFP_PACKET_IN_SIZE -
2332 ofproto.OFP_MATCH_SIZE)
2334 match_len = utils.round_up(msg.match.length, 8)
2335 msg.data = msg.buf[(ofproto.OFP_PACKET_IN_SIZE -
2336 ofproto.OFP_MATCH_SIZE + match_len + 2):]
2338 if msg.total_len < len(msg.data):
2339 # discard padding for 8-byte alignment of OFP packet
2340 msg.data = msg.data[:msg.total_len]
2346 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
2347 class OFPFlowRemoved(MsgBase):
2349 Flow removed message
2351 When flow entries time out or are deleted, the switch notifies controller
2354 ================ ======================================================
2355 Attribute Description
2356 ================ ======================================================
2357 cookie Opaque controller-issued identifier
2358 priority Priority level of flow entry
2359 reason One of the following values.
2361 | OFPRR_IDLE_TIMEOUT
2362 | OFPRR_HARD_TIMEOUT
2364 | OFPRR_GROUP_DELETE
2365 table_id ID of the table
2366 duration_sec Time flow was alive in seconds
2367 duration_nsec Time flow was alive in nanoseconds beyond duration_sec
2368 idle_timeout Idle timeout from original flow mod
2369 hard_timeout Hard timeout from original flow mod
2370 packet_count Number of packets that was associated with the flow
2371 byte_count Number of bytes that was associated with the flow
2372 match Instance of ``OFPMatch``
2373 ================ ======================================================
2377 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
2378 def flow_removed_handler(self, ev):
2383 if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
2384 reason = 'IDLE TIMEOUT'
2385 elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
2386 reason = 'HARD TIMEOUT'
2387 elif msg.reason == ofp.OFPRR_DELETE:
2389 elif msg.reason == ofp.OFPRR_GROUP_DELETE:
2390 reason = 'GROUP DELETE'
2394 self.logger.debug('OFPFlowRemoved received: '
2395 'cookie=%d priority=%d reason=%s table_id=%d '
2396 'duration_sec=%d duration_nsec=%d '
2397 'idle_timeout=%d hard_timeout=%d '
2398 'packet_count=%d byte_count=%d match.fields=%s',
2399 msg.cookie, msg.priority, reason, msg.table_id,
2400 msg.duration_sec, msg.duration_nsec,
2401 msg.idle_timeout, msg.hard_timeout,
2402 msg.packet_count, msg.byte_count, msg.match)
2405 def __init__(self, datapath, cookie=None, priority=None, reason=None,
2406 table_id=None, duration_sec=None, duration_nsec=None,
2407 idle_timeout=None, hard_timeout=None, packet_count=None,
2408 byte_count=None, match=None):
2409 super(OFPFlowRemoved, self).__init__(datapath)
2410 self.cookie = cookie
2411 self.priority = priority
2412 self.reason = reason
2413 self.table_id = table_id
2414 self.duration_sec = duration_sec
2415 self.duration_nsec = duration_nsec
2416 self.idle_timeout = idle_timeout
2417 self.hard_timeout = hard_timeout
2418 self.packet_count = packet_count
2419 self.byte_count = byte_count
2423 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2424 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
2427 (msg.cookie, msg.priority, msg.reason,
2428 msg.table_id, msg.duration_sec, msg.duration_nsec,
2429 msg.idle_timeout, msg.hard_timeout, msg.packet_count,
2430 msg.byte_count) = struct.unpack_from(
2431 ofproto.OFP_FLOW_REMOVED_PACK_STR0,
2432 msg.buf, ofproto.OFP_HEADER_SIZE)
2434 offset = (ofproto.OFP_FLOW_REMOVED_SIZE -
2435 ofproto.OFP_MATCH_SIZE)
2437 msg.match = OFPMatch.parser(msg.buf, offset)
2442 class OFPPort(ofproto_parser.namedtuple('OFPPort', (
2443 'port_no', 'hw_addr', 'name', 'config', 'state', 'curr',
2444 'advertised', 'supported', 'peer', 'curr_speed', 'max_speed'))):
2446 Description of a port
2448 ========== =========================================================
2449 Attribute Description
2450 ========== =========================================================
2451 port_no Port number and it uniquely identifies a port within
2453 hw_addr MAC address for the port.
2454 name Null-terminated string containing a human-readable name
2456 config Bitmap of port configration flags.
2461 | OFPPC_NO_PACKET_IN
2462 state Bitmap of port state flags.
2467 curr Current features.
2468 advertised Features being advertised by the port.
2469 supported Features supported by the port.
2470 peer Features advertised by peer.
2471 curr_speed Current port bitrate in kbps.
2472 max_speed Max port bitrate in kbps.
2473 ========== =========================================================
2481 # OF spec is unclear about the encoding of name.
2482 # we assumes UTF-8, which is used by OVS.
2488 def parser(cls, buf, offset):
2489 port = struct.unpack_from(ofproto.OFP_PORT_PACK_STR, buf, offset)
2491 i = cls._fields.index('hw_addr')
2492 port[i] = addrconv.mac.bin_to_text(port[i])
2493 i = cls._fields.index('name')
2494 port[i] = port[i].rstrip(b'\0')
2495 ofpport = cls(*port)
2496 ofpport.length = ofproto.OFP_PORT_SIZE
2501 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
2502 class OFPPortStatus(MsgBase):
2506 The switch notifies controller of change of ports.
2508 ================ ======================================================
2509 Attribute Description
2510 ================ ======================================================
2511 reason One of the following values.
2516 desc instance of ``OFPPort``
2517 ================ ======================================================
2521 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
2522 def port_status_handler(self, ev):
2527 if msg.reason == ofp.OFPPR_ADD:
2529 elif msg.reason == ofp.OFPPR_DELETE:
2531 elif msg.reason == ofp.OFPPR_MODIFY:
2536 self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
2540 def __init__(self, datapath, reason=None, desc=None):
2541 super(OFPPortStatus, self).__init__(datapath)
2542 self.reason = reason
2546 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2547 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
2549 msg.reason = struct.unpack_from(
2550 ofproto.OFP_PORT_STATUS_PACK_STR, msg.buf,
2551 ofproto.OFP_HEADER_SIZE)[0]
2552 msg.desc = OFPPort.parser(msg.buf,
2553 ofproto.OFP_PORT_STATUS_DESC_OFFSET)
2557 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
2558 class OFPPacketOut(MsgBase):
2562 The controller uses this message to send a packet out throught the
2565 ================ ======================================================
2566 Attribute Description
2567 ================ ======================================================
2568 buffer_id ID assigned by datapath (OFP_NO_BUFFER if none)
2569 in_port Packet's input port or ``OFPP_CONTROLLER``
2570 actions list of OpenFlow action class
2571 data Packet data of a binary type value or
2572 an instances of packet.Packet.
2573 ================ ======================================================
2577 def send_packet_out(self, datapath, buffer_id, in_port):
2578 ofp = datapath.ofproto
2579 ofp_parser = datapath.ofproto_parser
2581 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
2582 req = ofp_parser.OFPPacketOut(datapath, buffer_id,
2584 datapath.send_msg(req)
2587 def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
2588 data=None, actions_len=None):
2589 assert in_port is not None
2591 super(OFPPacketOut, self).__init__(datapath)
2592 self.buffer_id = buffer_id
2593 self.in_port = in_port
2594 self.actions_len = 0
2595 self.actions = actions
2598 def _serialize_body(self):
2599 self.actions_len = 0
2600 offset = ofproto.OFP_PACKET_OUT_SIZE
2601 for a in self.actions:
2602 a.serialize(self.buf, offset)
2604 self.actions_len += a.len
2606 if self.data is not None:
2607 assert self.buffer_id == 0xffffffff
2608 if isinstance(self.data, packet.Packet):
2609 self.data.serialize()
2610 self.buf += self.data.data
2612 self.buf += self.data
2614 msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR,
2615 self.buf, ofproto.OFP_HEADER_SIZE,
2616 self.buffer_id, self.in_port, self.actions_len)
2619 def from_jsondict(cls, dict_, decode_string=base64.b64decode,
2621 if isinstance(dict_['data'], dict):
2622 data = dict_.pop('data')
2623 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2626 ins.data = packet.Packet.from_jsondict(data['Packet'])
2627 dict_['data'] = data
2629 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2637 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
2638 class OFPFlowMod(MsgBase):
2640 Modify Flow entry message
2642 The controller sends this message to modify the flow table.
2644 ================ ======================================================
2645 Attribute Description
2646 ================ ======================================================
2647 cookie Opaque controller-issued identifier
2648 cookie_mask Mask used to restrict the cookie bits that must match
2649 when the command is ``OPFFC_MODIFY*`` or
2651 table_id ID of the table to put the flow in
2652 command One of the following values.
2656 | OFPFC_MODIFY_STRICT
2658 | OFPFC_DELETE_STRICT
2659 idle_timeout Idle time before discarding (seconds)
2660 hard_timeout Max time before discarding (seconds)
2661 priority Priority level of flow entry
2662 buffer_id Buffered packet to apply to (or OFP_NO_BUFFER)
2663 out_port For ``OFPFC_DELETE*`` commands, require matching
2664 entries to include this as an output port
2665 out_group For ``OFPFC_DELETE*`` commands, require matching
2666 entries to include this as an output group
2667 flags Bitmap of the following flags.
2669 | OFPFF_SEND_FLOW_REM
2670 | OFPFF_CHECK_OVERLAP
2671 | OFPFF_RESET_COUNTS
2672 | OFPFF_NO_PKT_COUNTS
2673 | OFPFF_NO_BYT_COUNTS
2674 match Instance of ``OFPMatch``
2675 instructions list of ``OFPInstruction*`` instance
2676 ================ ======================================================
2680 def send_flow_mod(self, datapath):
2681 ofp = datapath.ofproto
2682 ofp_parser = datapath.ofproto_parser
2684 cookie = cookie_mask = 0
2686 idle_timeout = hard_timeout = 0
2688 buffer_id = ofp.OFP_NO_BUFFER
2689 match = ofp_parser.OFPMatch(in_port=1, eth_dst='ff:ff:ff:ff:ff:ff')
2690 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
2691 inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
2693 req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask,
2694 table_id, ofp.OFPFC_ADD,
2695 idle_timeout, hard_timeout,
2696 priority, buffer_id,
2697 ofp.OFPP_ANY, ofp.OFPG_ANY,
2698 ofp.OFPFF_SEND_FLOW_REM,
2700 datapath.send_msg(req)
2703 def __init__(self, datapath, cookie=0, cookie_mask=0, table_id=0,
2704 command=ofproto.OFPFC_ADD,
2705 idle_timeout=0, hard_timeout=0,
2706 priority=ofproto.OFP_DEFAULT_PRIORITY,
2707 buffer_id=ofproto.OFP_NO_BUFFER,
2708 out_port=0, out_group=0, flags=0,
2711 instructions = instructions if instructions else []
2712 super(OFPFlowMod, self).__init__(datapath)
2713 self.cookie = cookie
2714 self.cookie_mask = cookie_mask
2715 self.table_id = table_id
2716 self.command = command
2717 self.idle_timeout = idle_timeout
2718 self.hard_timeout = hard_timeout
2719 self.priority = priority
2720 self.buffer_id = buffer_id
2721 self.out_port = out_port
2722 self.out_group = out_group
2726 assert isinstance(match, OFPMatch)
2728 for i in instructions:
2729 assert isinstance(i, OFPInstruction)
2730 self.instructions = instructions
2732 def _serialize_body(self):
2733 msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf,
2734 ofproto.OFP_HEADER_SIZE,
2735 self.cookie, self.cookie_mask, self.table_id,
2736 self.command, self.idle_timeout, self.hard_timeout,
2737 self.priority, self.buffer_id, self.out_port,
2738 self.out_group, self.flags)
2740 offset = (ofproto.OFP_FLOW_MOD_SIZE -
2741 ofproto.OFP_MATCH_SIZE)
2743 match_len = self.match.serialize(self.buf, offset)
2746 for inst in self.instructions:
2747 inst.serialize(self.buf, offset)
2751 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2752 msg = super(OFPFlowMod, cls).parser(
2753 datapath, version, msg_type, msg_len, xid, buf)
2755 (msg.cookie, msg.cookie_mask, msg.table_id,
2756 msg.command, msg.idle_timeout, msg.hard_timeout,
2757 msg.priority, msg.buffer_id, msg.out_port,
2758 msg.out_group, msg.flags) = struct.unpack_from(
2759 ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf,
2760 ofproto.OFP_HEADER_SIZE)
2761 offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE
2764 msg.match = OFPMatch.parser(buf, offset)
2765 except exception.OFPTruncatedMessage as e:
2766 msg.match = e.ofpmsg
2770 offset += utils.round_up(msg.match.length, 8)
2774 while offset < msg_len:
2775 i = OFPInstruction.parser(buf, offset)
2776 instructions.append(i)
2778 except exception.OFPTruncatedMessage as e:
2779 instructions.append(e.ofpmsg)
2780 msg.instructions = instructions
2783 except struct.error as e:
2784 msg.instructions = instructions
2785 raise exception.OFPTruncatedMessage(ofpmsg=msg,
2786 residue=buf[offset:],
2787 original_exception=e)
2788 msg.instructions = instructions
2793 class OFPInstruction(StringifyMixin):
2794 _INSTRUCTION_TYPES = {}
2797 def register_instruction_type(types):
2798 def _register_instruction_type(cls):
2800 OFPInstruction._INSTRUCTION_TYPES[type_] = cls
2802 return _register_instruction_type
2805 def parser(cls, buf, offset):
2806 (type_, len_) = struct.unpack_from('!HH', buf, offset)
2807 cls_ = cls._INSTRUCTION_TYPES.get(type_)
2808 return cls_.parser(buf, offset)
2811 @OFPInstruction.register_instruction_type([ofproto.OFPIT_GOTO_TABLE])
2812 class OFPInstructionGotoTable(OFPInstruction):
2814 Goto table instruction
2816 This instruction indicates the next table in the processing pipeline.
2818 ================ ======================================================
2819 Attribute Description
2820 ================ ======================================================
2822 ================ ======================================================
2825 def __init__(self, table_id, type_=None, len_=None):
2826 super(OFPInstructionGotoTable, self).__init__()
2827 self.type = ofproto.OFPIT_GOTO_TABLE
2828 self.len = ofproto.OFP_INSTRUCTION_GOTO_TABLE_SIZE
2829 self.table_id = table_id
2832 def parser(cls, buf, offset):
2833 (type_, len_, table_id) = struct.unpack_from(
2834 ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
2836 return cls(table_id)
2838 def serialize(self, buf, offset):
2839 msg_pack_into(ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
2840 buf, offset, self.type, self.len, self.table_id)
2843 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_METADATA])
2844 class OFPInstructionWriteMetadata(OFPInstruction):
2846 Write metadata instruction
2848 This instruction writes the masked metadata value into the metadata field.
2850 ================ ======================================================
2851 Attribute Description
2852 ================ ======================================================
2853 metadata Metadata value to write
2854 metadata_mask Metadata write bitmask
2855 ================ ======================================================
2858 def __init__(self, metadata, metadata_mask, type_=None, len_=None):
2859 super(OFPInstructionWriteMetadata, self).__init__()
2860 self.type = ofproto.OFPIT_WRITE_METADATA
2861 self.len = ofproto.OFP_INSTRUCTION_WRITE_METADATA_SIZE
2862 self.metadata = metadata
2863 self.metadata_mask = metadata_mask
2866 def parser(cls, buf, offset):
2867 (type_, len_, metadata, metadata_mask) = struct.unpack_from(
2868 ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
2870 return cls(metadata, metadata_mask)
2872 def serialize(self, buf, offset):
2873 msg_pack_into(ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
2874 buf, offset, self.type, self.len, self.metadata,
2878 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS,
2879 ofproto.OFPIT_APPLY_ACTIONS,
2880 ofproto.OFPIT_CLEAR_ACTIONS])
2881 class OFPInstructionActions(OFPInstruction):
2885 This instruction writes/applies/clears the actions.
2887 ================ ======================================================
2888 Attribute Description
2889 ================ ======================================================
2890 type One of following values.
2892 | OFPIT_WRITE_ACTIONS
2893 | OFPIT_APPLY_ACTIONS
2894 | OFPIT_CLEAR_ACTIONS
2895 actions list of OpenFlow action class
2896 ================ ======================================================
2898 ``type`` attribute corresponds to ``type_`` parameter of __init__.
2901 def __init__(self, type_, actions=None, len_=None):
2902 super(OFPInstructionActions, self).__init__()
2905 assert isinstance(a, OFPAction)
2906 self.actions = actions
2909 def parser(cls, buf, offset):
2910 (type_, len_) = struct.unpack_from(
2911 ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
2914 offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
2916 actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
2919 while actions_len > 0:
2920 a = OFPAction.parser(buf, offset)
2922 actions_len -= a.len
2924 except struct.error as e:
2927 inst = cls(type_, actions)
2930 raise exception.OFPTruncatedMessage(ofpmsg=inst,
2931 residue=buf[offset:],
2932 original_exception=exc)
2935 def serialize(self, buf, offset):
2936 action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
2938 for a in self.actions:
2939 a.serialize(buf, action_offset)
2940 action_offset += a.len
2942 self.len = action_offset - offset
2943 pad_len = utils.round_up(self.len, 8) - self.len
2944 msg_pack_into("%dx" % pad_len, buf, action_offset)
2947 msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
2948 buf, offset, self.type, self.len)
2951 @OFPInstruction.register_instruction_type([ofproto.OFPIT_METER])
2952 class OFPInstructionMeter(OFPInstruction):
2956 This instruction applies the meter.
2958 ================ ======================================================
2959 Attribute Description
2960 ================ ======================================================
2961 meter_id Meter instance
2962 ================ ======================================================
2965 def __init__(self, meter_id=1, type_=None, len_=None):
2966 super(OFPInstructionMeter, self).__init__()
2967 self.type = ofproto.OFPIT_METER
2968 self.len = ofproto.OFP_INSTRUCTION_METER_SIZE
2969 self.meter_id = meter_id
2972 def parser(cls, buf, offset):
2973 (type_, len_, meter_id) = struct.unpack_from(
2974 ofproto.OFP_INSTRUCTION_METER_PACK_STR,
2976 return cls(meter_id)
2978 def serialize(self, buf, offset):
2979 msg_pack_into(ofproto.OFP_INSTRUCTION_METER_PACK_STR,
2980 buf, offset, self.type, self.len, self.meter_id)
2983 class OFPActionHeader(StringifyMixin):
2984 def __init__(self, type_, len_):
2988 def serialize(self, buf, offset):
2989 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
2990 buf, offset, self.type, self.len)
2993 class OFPAction(OFPActionHeader):
2997 def register_action_type(type_, len_):
2998 def _register_action_type(cls):
2999 cls.cls_action_type = type_
3000 cls.cls_action_len = len_
3001 OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
3003 return _register_action_type
3006 cls = self.__class__
3007 super(OFPAction, self).__init__(cls.cls_action_type,
3011 def parser(cls, buf, offset):
3012 type_, len_ = struct.unpack_from(
3013 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3014 cls_ = cls._ACTION_TYPES.get(type_)
3015 assert cls_ is not None
3016 return cls_.parser(buf, offset)
3019 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
3020 ofproto.OFP_ACTION_OUTPUT_SIZE)
3021 class OFPActionOutput(OFPAction):
3025 This action indicates output a packet to the switch port.
3027 ================ ======================================================
3028 Attribute Description
3029 ================ ======================================================
3031 max_len Max length to send to controller
3032 ================ ======================================================
3035 def __init__(self, port, max_len=ofproto.OFPCML_MAX,
3036 type_=None, len_=None):
3037 super(OFPActionOutput, self).__init__()
3039 self.max_len = max_len
3042 def parser(cls, buf, offset):
3043 type_, len_, port, max_len = struct.unpack_from(
3044 ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
3045 return cls(port, max_len)
3047 def serialize(self, buf, offset):
3048 msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
3049 offset, self.type, self.len, self.port, self.max_len)
3052 @OFPAction.register_action_type(ofproto.OFPAT_GROUP,
3053 ofproto.OFP_ACTION_GROUP_SIZE)
3054 class OFPActionGroup(OFPAction):
3058 This action indicates the group used to process the packet.
3060 ================ ======================================================
3061 Attribute Description
3062 ================ ======================================================
3063 group_id Group identifier
3064 ================ ======================================================
3067 def __init__(self, group_id=0, type_=None, len_=None):
3068 super(OFPActionGroup, self).__init__()
3069 self.group_id = group_id
3072 def parser(cls, buf, offset):
3073 (type_, len_, group_id) = struct.unpack_from(
3074 ofproto.OFP_ACTION_GROUP_PACK_STR, buf, offset)
3075 return cls(group_id)
3077 def serialize(self, buf, offset):
3078 msg_pack_into(ofproto.OFP_ACTION_GROUP_PACK_STR, buf,
3079 offset, self.type, self.len, self.group_id)
3082 @OFPAction.register_action_type(ofproto.OFPAT_SET_QUEUE,
3083 ofproto.OFP_ACTION_SET_QUEUE_SIZE)
3084 class OFPActionSetQueue(OFPAction):
3088 This action sets the queue id that will be used to map a flow to an
3089 already-configured queue on a port.
3091 ================ ======================================================
3092 Attribute Description
3093 ================ ======================================================
3094 queue_id Queue ID for the packets
3095 ================ ======================================================
3098 def __init__(self, queue_id, type_=None, len_=None):
3099 super(OFPActionSetQueue, self).__init__()
3100 self.queue_id = queue_id
3103 def parser(cls, buf, offset):
3104 (type_, len_, queue_id) = struct.unpack_from(
3105 ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf, offset)
3106 return cls(queue_id)
3108 def serialize(self, buf, offset):
3109 msg_pack_into(ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
3110 offset, self.type, self.len, self.queue_id)
3113 @OFPAction.register_action_type(ofproto.OFPAT_SET_MPLS_TTL,
3114 ofproto.OFP_ACTION_MPLS_TTL_SIZE)
3115 class OFPActionSetMplsTtl(OFPAction):
3119 This action sets the MPLS TTL.
3121 ================ ======================================================
3122 Attribute Description
3123 ================ ======================================================
3125 ================ ======================================================
3128 def __init__(self, mpls_ttl, type_=None, len_=None):
3129 super(OFPActionSetMplsTtl, self).__init__()
3130 self.mpls_ttl = mpls_ttl
3133 def parser(cls, buf, offset):
3134 (type_, len_, mpls_ttl) = struct.unpack_from(
3135 ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf, offset)
3136 return cls(mpls_ttl)
3138 def serialize(self, buf, offset):
3139 msg_pack_into(ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf,
3140 offset, self.type, self.len, self.mpls_ttl)
3143 @OFPAction.register_action_type(ofproto.OFPAT_DEC_MPLS_TTL,
3144 ofproto.OFP_ACTION_HEADER_SIZE)
3145 class OFPActionDecMplsTtl(OFPAction):
3147 Decrement MPLS TTL action
3149 This action decrements the MPLS TTL.
3152 def __init__(self, type_=None, len_=None):
3153 super(OFPActionDecMplsTtl, self).__init__()
3156 def parser(cls, buf, offset):
3157 (type_, len_) = struct.unpack_from(
3158 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3162 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TTL,
3163 ofproto.OFP_ACTION_NW_TTL_SIZE)
3164 class OFPActionSetNwTtl(OFPAction):
3168 This action sets the IP TTL.
3170 ================ ======================================================
3171 Attribute Description
3172 ================ ======================================================
3174 ================ ======================================================
3177 def __init__(self, nw_ttl, type_=None, len_=None):
3178 super(OFPActionSetNwTtl, self).__init__()
3179 self.nw_ttl = nw_ttl
3182 def parser(cls, buf, offset):
3183 (type_, len_, nw_ttl) = struct.unpack_from(
3184 ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
3187 def serialize(self, buf, offset):
3188 msg_pack_into(ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset,
3189 self.type, self.len, self.nw_ttl)
3192 @OFPAction.register_action_type(ofproto.OFPAT_DEC_NW_TTL,
3193 ofproto.OFP_ACTION_HEADER_SIZE)
3194 class OFPActionDecNwTtl(OFPAction):
3196 Decrement IP TTL action
3198 This action decrements the IP TTL.
3201 def __init__(self, type_=None, len_=None):
3202 super(OFPActionDecNwTtl, self).__init__()
3205 def parser(cls, buf, offset):
3206 (type_, len_) = struct.unpack_from(
3207 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3211 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_OUT,
3212 ofproto.OFP_ACTION_HEADER_SIZE)
3213 class OFPActionCopyTtlOut(OFPAction):
3217 This action copies the TTL from the next-to-outermost header with TTL to
3218 the outermost header with TTL.
3221 def __init__(self, type_=None, len_=None):
3222 super(OFPActionCopyTtlOut, self).__init__()
3225 def parser(cls, buf, offset):
3226 (type_, len_) = struct.unpack_from(
3227 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3231 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_IN,
3232 ofproto.OFP_ACTION_HEADER_SIZE)
3233 class OFPActionCopyTtlIn(OFPAction):
3237 This action copies the TTL from the outermost header with TTL to the
3238 next-to-outermost header with TTL.
3241 def __init__(self, type_=None, len_=None):
3242 super(OFPActionCopyTtlIn, self).__init__()
3245 def parser(cls, buf, offset):
3246 (type_, len_) = struct.unpack_from(
3247 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3251 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_VLAN,
3252 ofproto.OFP_ACTION_PUSH_SIZE)
3253 class OFPActionPushVlan(OFPAction):
3257 This action pushes a new VLAN tag to the packet.
3259 ================ ======================================================
3260 Attribute Description
3261 ================ ======================================================
3262 ethertype Ether type. The default is 802.1Q. (0x8100)
3263 ================ ======================================================
3266 def __init__(self, ethertype=ether.ETH_TYPE_8021Q, type_=None, len_=None):
3267 super(OFPActionPushVlan, self).__init__()
3268 self.ethertype = ethertype
3271 def parser(cls, buf, offset):
3272 (type_, len_, ethertype) = struct.unpack_from(
3273 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
3274 return cls(ethertype)
3276 def serialize(self, buf, offset):
3277 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
3278 self.type, self.len, self.ethertype)
3281 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_MPLS,
3282 ofproto.OFP_ACTION_PUSH_SIZE)
3283 class OFPActionPushMpls(OFPAction):
3287 This action pushes a new MPLS header to the packet.
3289 ================ ======================================================
3290 Attribute Description
3291 ================ ======================================================
3292 ethertype Ether type
3293 ================ ======================================================
3296 def __init__(self, ethertype=ether.ETH_TYPE_MPLS, type_=None, len_=None):
3297 super(OFPActionPushMpls, self).__init__()
3298 self.ethertype = ethertype
3301 def parser(cls, buf, offset):
3302 (type_, len_, ethertype) = struct.unpack_from(
3303 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
3304 return cls(ethertype)
3306 def serialize(self, buf, offset):
3307 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
3308 self.type, self.len, self.ethertype)
3311 @OFPAction.register_action_type(ofproto.OFPAT_POP_VLAN,
3312 ofproto.OFP_ACTION_HEADER_SIZE)
3313 class OFPActionPopVlan(OFPAction):
3317 This action pops the outermost VLAN tag from the packet.
3320 def __init__(self, type_=None, len_=None):
3321 super(OFPActionPopVlan, self).__init__()
3324 def parser(cls, buf, offset):
3325 (type_, len_) = struct.unpack_from(
3326 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3330 @OFPAction.register_action_type(ofproto.OFPAT_POP_MPLS,
3331 ofproto.OFP_ACTION_POP_MPLS_SIZE)
3332 class OFPActionPopMpls(OFPAction):
3336 This action pops the MPLS header from the packet.
3339 def __init__(self, ethertype=ether.ETH_TYPE_IP, type_=None, len_=None):
3340 super(OFPActionPopMpls, self).__init__()
3341 self.ethertype = ethertype
3344 def parser(cls, buf, offset):
3345 (type_, len_, ethertype) = struct.unpack_from(
3346 ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset)
3347 return cls(ethertype)
3349 def serialize(self, buf, offset):
3350 msg_pack_into(ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset,
3351 self.type, self.len, self.ethertype)
3354 @OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
3355 ofproto.OFP_ACTION_SET_FIELD_SIZE)
3356 class OFPActionSetField(OFPAction):
3360 This action modifies a header field in the packet.
3362 The set of keywords available for this is same as OFPMatch.
3366 set_field = OFPActionSetField(eth_src="00:00:00:00:00:00")
3369 def __init__(self, field=None, **kwargs):
3371 # OFPActionSetField(field)
3373 # OFPActionSetField(eth_src="00:00:00:00:00")
3374 super(OFPActionSetField, self).__init__()
3375 if isinstance(field, OFPMatchField):
3377 assert len(kwargs) == 0
3381 assert len(kwargs) == 1
3382 key = list(kwargs.keys())[0]
3384 assert isinstance(key, (str, six.text_type))
3385 assert not isinstance(value, tuple) # no mask
3390 def parser(cls, buf, offset):
3391 (type_, len_) = struct.unpack_from(
3392 ofproto.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
3393 (n, value, mask, _len) = ofproto.oxm_parse(buf, offset + 4)
3394 k, uv = ofproto.oxm_to_user(n, value, mask)
3395 action = cls(**{k: uv})
3399 action.field = OFPMatchField.parser(buf, offset + 4)
3403 def serialize(self, buf, offset):
3405 if self._composed_with_old_api():
3406 return self.serialize_old(buf, offset)
3408 n, value, mask = ofproto.oxm_from_user(self.key, self.value)
3409 len_ = ofproto.oxm_serialize(n, value, mask, buf, offset + 4)
3410 self.len = utils.round_up(4 + len_, 8)
3411 msg_pack_into('!HH', buf, offset, self.type, self.len)
3412 pad_len = self.len - (4 + len_)
3413 msg_pack_into("%dx" % pad_len, buf, offset + 4 + len_)
3415 # XXX old api compat
3416 def serialize_old(self, buf, offset):
3417 len_ = ofproto.OFP_ACTION_SET_FIELD_SIZE + self.field.oxm_len()
3418 self.len = utils.round_up(len_, 8)
3419 pad_len = self.len - len_
3421 msg_pack_into('!HH', buf, offset, self.type, self.len)
3422 self.field.serialize(buf, offset + 4)
3424 msg_pack_into("%dx" % pad_len, buf, offset)
3426 # XXX old api compat
3427 def _composed_with_old_api(self):
3428 return not hasattr(self, 'value')
3430 def to_jsondict(self):
3432 self.__class__.__name__: {
3433 'field': ofproto.oxm_to_jsondict(self.key, self.value),
3440 def from_jsondict(cls, dict_):
3441 k, v = ofproto.oxm_from_jsondict(dict_['field'])
3442 o = OFPActionSetField(**{k: v})
3444 # XXX old api compat
3445 # serialize and parse to fill old attributes
3448 return OFPActionSetField.parser(six.binary_type(buf), 0)
3450 # XXX old api compat
3452 # XXX old api compat
3453 if self._composed_with_old_api():
3454 # copy object first because serialize_old is destructive
3455 o2 = OFPActionSetField(self.field)
3456 # serialize and parse to fill new fields
3458 o2.serialize(buf, 0)
3459 o = OFPActionSetField.parser(six.binary_type(buf), 0)
3462 return super(OFPActionSetField, o).__str__()
3466 def stringify_attrs(self):
3467 yield (self.key, self.value)
3470 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_PBB,
3471 ofproto.OFP_ACTION_PUSH_SIZE)
3472 class OFPActionPushPbb(OFPAction):
3476 This action pushes a new PBB header to the packet.
3478 ================ ======================================================
3479 Attribute Description
3480 ================ ======================================================
3481 ethertype Ether type
3482 ================ ======================================================
3485 def __init__(self, ethertype, type_=None, len_=None):
3486 super(OFPActionPushPbb, self).__init__()
3487 self.ethertype = ethertype
3490 def parser(cls, buf, offset):
3491 (type_, len_, ethertype) = struct.unpack_from(
3492 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
3493 return cls(ethertype)
3495 def serialize(self, buf, offset):
3496 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
3497 self.type, self.len, self.ethertype)
3500 @OFPAction.register_action_type(ofproto.OFPAT_POP_PBB,
3501 ofproto.OFP_ACTION_HEADER_SIZE)
3502 class OFPActionPopPbb(OFPAction):
3506 This action pops the outermost PBB service instance header from
3510 def __init__(self, type_=None, len_=None):
3511 super(OFPActionPopPbb, self).__init__()
3514 def parser(cls, buf, offset):
3515 (type_, len_) = struct.unpack_from(
3516 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
3520 @OFPAction.register_action_type(
3521 ofproto.OFPAT_EXPERIMENTER,
3522 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
3523 class OFPActionExperimenter(OFPAction):
3527 This action is an extensible action for the experimenter.
3529 ================ ======================================================
3530 Attribute Description
3531 ================ ======================================================
3532 experimenter Experimenter ID
3533 ================ ======================================================
3537 For the list of the supported Nicira experimenter actions,
3538 please refer to :ref:`ryu.ofproto.nx_actions <nx_actions_structures>`.
3541 def __init__(self, experimenter):
3542 super(OFPActionExperimenter, self).__init__()
3543 self.type = ofproto.OFPAT_EXPERIMENTER
3544 self.experimenter = experimenter
3548 def parser(cls, buf, offset):
3549 (type_, len_, experimenter) = struct.unpack_from(
3550 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset)
3551 data = buf[(offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE
3553 if experimenter == ofproto_common.NX_EXPERIMENTER_ID:
3554 obj = NXAction.parse(data) # noqa
3556 obj = OFPActionExperimenterUnknown(experimenter, data)
3560 def serialize(self, buf, offset):
3561 msg_pack_into(ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR,
3562 buf, offset, self.type, self.len, self.experimenter)
3565 class OFPActionExperimenterUnknown(OFPActionExperimenter):
3566 def __init__(self, experimenter, data=None, type_=None, len_=None):
3567 super(OFPActionExperimenterUnknown,
3568 self).__init__(experimenter=experimenter)
3571 def serialize(self, buf, offset):
3576 self.len = (utils.round_up(len(data), 8) +
3577 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
3578 super(OFPActionExperimenterUnknown, self).serialize(buf, offset)
3579 msg_pack_into('!%ds' % len(self.data),
3581 offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE,
3585 class OFPBucket(StringifyMixin):
3586 def __init__(self, weight=0, watch_port=ofproto.OFPP_ANY,
3587 watch_group=ofproto.OFPG_ANY, actions=None, len_=None):
3588 super(OFPBucket, self).__init__()
3589 self.weight = weight
3590 self.watch_port = watch_port
3591 self.watch_group = watch_group
3592 self.actions = actions
3595 def parser(cls, buf, offset):
3596 (len_, weight, watch_port, watch_group) = struct.unpack_from(
3597 ofproto.OFP_BUCKET_PACK_STR, buf, offset)
3598 msg = cls(weight, watch_port, watch_group, [])
3601 length = ofproto.OFP_BUCKET_SIZE
3602 offset += ofproto.OFP_BUCKET_SIZE
3603 while length < msg.len:
3604 action = OFPAction.parser(buf, offset)
3605 msg.actions.append(action)
3606 offset += action.len
3607 length += action.len
3611 def serialize(self, buf, offset):
3612 action_offset = offset + ofproto.OFP_BUCKET_SIZE
3614 for a in self.actions:
3615 a.serialize(buf, action_offset)
3616 action_offset += a.len
3619 self.len = utils.round_up(ofproto.OFP_BUCKET_SIZE + action_len, 8)
3620 msg_pack_into(ofproto.OFP_BUCKET_PACK_STR, buf, offset,
3621 self.len, self.weight, self.watch_port,
3625 @_set_msg_type(ofproto.OFPT_GROUP_MOD)
3626 class OFPGroupMod(MsgBase):
3628 Modify group entry message
3630 The controller sends this message to modify the group table.
3632 ================ ======================================================
3633 Attribute Description
3634 ================ ======================================================
3635 command One of the following values.
3640 type One of the following values.
3646 group_id Group identifier
3647 buckets list of ``OFPBucket``
3648 ================ ======================================================
3650 ``type`` attribute corresponds to ``type_`` parameter of __init__.
3654 def send_group_mod(self, datapath):
3655 ofp = datapath.ofproto
3656 ofp_parser = datapath.ofproto_parser
3660 actions = [ofp_parser.OFPActionOutput(port, max_len)]
3665 buckets = [ofp_parser.OFPBucket(weight, watch_port, watch_group,
3669 req = ofp_parser.OFPGroupMod(datapath, ofp.OFPGC_ADD,
3670 ofp.OFPGT_SELECT, group_id, buckets)
3671 datapath.send_msg(req)
3674 def __init__(self, datapath, command=ofproto.OFPGC_ADD,
3675 type_=ofproto.OFPGT_ALL, group_id=0, buckets=None):
3676 buckets = buckets if buckets else []
3677 super(OFPGroupMod, self).__init__(datapath)
3678 self.command = command
3680 self.group_id = group_id
3681 self.buckets = buckets
3683 def _serialize_body(self):
3684 msg_pack_into(ofproto.OFP_GROUP_MOD_PACK_STR, self.buf,
3685 ofproto.OFP_HEADER_SIZE,
3686 self.command, self.type, self.group_id)
3688 offset = ofproto.OFP_GROUP_MOD_SIZE
3689 for b in self.buckets:
3690 b.serialize(self.buf, offset)
3694 @_set_msg_type(ofproto.OFPT_PORT_MOD)
3695 class OFPPortMod(MsgBase):
3697 Port modification message
3699 The controller sneds this message to modify the behavior of the port.
3701 ================ ======================================================
3702 Attribute Description
3703 ================ ======================================================
3704 port_no Port number to modify
3705 hw_addr The hardware address that must be the same as hw_addr
3706 of ``OFPPort`` of ``OFPSwitchFeatures``
3707 config Bitmap of configuration flags.
3712 | OFPPC_NO_PACKET_IN
3713 mask Bitmap of configuration flags above to be changed
3714 advertise Bitmap of the following flags.
3732 ================ ======================================================
3736 def send_port_mod(self, datapath):
3737 ofp = datapath.ofproto
3738 ofp_parser = datapath.ofproto_parser
3741 hw_addr = 'fa:c8:e8:76:1d:7e'
3743 mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
3744 ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
3745 advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
3746 ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
3747 ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
3748 ofp.OFPPF_PAUSE_ASYM)
3749 req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
3751 datapath.send_msg(req)
3760 def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
3761 config=0, mask=0, advertise=0):
3762 super(OFPPortMod, self).__init__(datapath)
3763 self.port_no = port_no
3764 self.hw_addr = hw_addr
3765 self.config = config
3767 self.advertise = advertise
3769 def _serialize_body(self):
3770 msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR, self.buf,
3771 ofproto.OFP_HEADER_SIZE,
3772 self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
3774 self.mask, self.advertise)
3777 @_set_msg_type(ofproto.OFPT_METER_MOD)
3778 class OFPMeterMod(MsgBase):
3780 Meter modification message
3782 The controller sends this message to modify the meter.
3784 ================ ======================================================
3785 Attribute Description
3786 ================ ======================================================
3787 command One of the following values.
3792 flags Bitmap of the following flags.
3798 meter_id Meter instance
3799 bands list of the following class instance.
3802 | OFPMeterBandDscpRemark
3803 | OFPMeterBandExperimenter
3804 ================ ======================================================
3807 def __init__(self, datapath, command=ofproto.OFPMC_ADD,
3808 flags=ofproto.OFPMF_KBPS, meter_id=1, bands=None):
3809 bands = bands if bands else []
3810 super(OFPMeterMod, self).__init__(datapath)
3811 self.command = command
3813 self.meter_id = meter_id
3816 def _serialize_body(self):
3817 msg_pack_into(ofproto.OFP_METER_MOD_PACK_STR, self.buf,
3818 ofproto.OFP_HEADER_SIZE,
3819 self.command, self.flags, self.meter_id)
3821 offset = ofproto.OFP_METER_MOD_SIZE
3822 for b in self.bands:
3823 b.serialize(self.buf, offset)
3827 @_set_msg_type(ofproto.OFPT_TABLE_MOD)
3828 class OFPTableMod(MsgBase):
3830 Flow table configuration message
3832 The controller sends this message to configure table state.
3834 ================ ======================================================
3835 Attribute Description
3836 ================ ======================================================
3837 table_id ID of the table (OFPTT_ALL indicates all tables)
3838 config Bitmap of the following flags.
3839 OFPTC_DEPRECATED_MASK (3)
3840 ================ ======================================================
3844 def send_table_mod(self, datapath):
3845 ofp_parser = datapath.ofproto_parser
3847 req = ofp_parser.OFPTableMod(datapath, 1, 3)
3848 datapath.send_msg(req)
3851 def __init__(self, datapath, table_id, config):
3852 super(OFPTableMod, self).__init__(datapath)
3853 self.table_id = table_id
3854 self.config = config
3856 def _serialize_body(self):
3857 msg_pack_into(ofproto.OFP_TABLE_MOD_PACK_STR, self.buf,
3858 ofproto.OFP_HEADER_SIZE,
3859 self.table_id, self.config)
3862 def _set_stats_type(stats_type, stats_body_cls):
3863 def _set_cls_stats_type(cls):
3864 cls.cls_stats_type = stats_type
3865 cls.cls_stats_body_cls = stats_body_cls
3867 return _set_cls_stats_type
3870 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3871 class OFPMultipartRequest(MsgBase):
3872 def __init__(self, datapath, flags):
3873 super(OFPMultipartRequest, self).__init__(datapath)
3874 self.type = self.__class__.cls_stats_type
3877 def _serialize_stats_body(self):
3880 def _serialize_body(self):
3881 msg_pack_into(ofproto.OFP_MULTIPART_REQUEST_PACK_STR,
3882 self.buf, ofproto.OFP_HEADER_SIZE,
3883 self.type, self.flags)
3884 self._serialize_stats_body()
3888 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3889 class OFPMultipartReply(MsgBase):
3890 _STATS_MSG_TYPES = {}
3893 def register_stats_type(body_single_struct=False):
3894 def _register_stats_type(cls):
3895 assert cls.cls_stats_type is not None
3896 assert cls.cls_stats_type not in OFPMultipartReply._STATS_MSG_TYPES
3897 assert cls.cls_stats_body_cls is not None
3898 cls.cls_body_single_struct = body_single_struct
3899 OFPMultipartReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls
3901 return _register_stats_type
3903 def __init__(self, datapath, body=None, flags=None):
3904 super(OFPMultipartReply, self).__init__(datapath)
3909 def parser_stats_body(cls, buf, msg_len, offset):
3910 body_cls = cls.cls_stats_body_cls
3912 while offset < msg_len:
3913 entry = body_cls.parser(buf, offset)
3915 offset += entry.length
3917 if cls.cls_body_single_struct:
3922 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf):
3923 msg = MsgBase.parser.__func__(
3924 cls, datapath, version, msg_type, msg_len, xid, buf)
3925 msg.body = msg.parser_stats_body(msg.buf, msg.msg_len,
3926 ofproto.OFP_MULTIPART_REPLY_SIZE)
3930 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
3931 type_, flags = struct.unpack_from(
3932 ofproto.OFP_MULTIPART_REPLY_PACK_STR, six.binary_type(buf),
3933 ofproto.OFP_HEADER_SIZE)
3934 stats_type_cls = cls._STATS_MSG_TYPES.get(type_)
3935 msg = super(OFPMultipartReply, stats_type_cls).parser(
3936 datapath, version, msg_type, msg_len, xid, buf)
3940 offset = ofproto.OFP_MULTIPART_REPLY_SIZE
3942 while offset < msg_len:
3943 b = stats_type_cls.cls_stats_body_cls.parser(msg.buf, offset)
3945 offset += b.length if hasattr(b, 'length') else b.len
3947 if stats_type_cls.cls_body_single_struct:
3954 class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
3955 'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
3968 def parser(cls, buf, offset):
3969 desc = struct.unpack_from(ofproto.OFP_DESC_PACK_STR,
3972 desc = [x.rstrip(b'\0') for x in desc]
3974 stats.length = ofproto.OFP_DESC_SIZE
3978 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
3979 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3980 class OFPDescStatsRequest(OFPMultipartRequest):
3982 Description statistics request message
3984 The controller uses this message to query description of the switch.
3986 ================ ======================================================
3987 Attribute Description
3988 ================ ======================================================
3989 flags Zero or ``OFPMPF_REQ_MORE``
3990 ================ ======================================================
3994 def send_desc_stats_request(self, datapath):
3995 ofp_parser = datapath.ofproto_parser
3997 req = ofp_parser.OFPDescStatsRequest(datapath, 0)
3998 datapath.send_msg(req)
4001 def __init__(self, datapath, flags=0, type_=None):
4002 super(OFPDescStatsRequest, self).__init__(datapath, flags)
4005 @OFPMultipartReply.register_stats_type(body_single_struct=True)
4006 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
4007 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4008 class OFPDescStatsReply(OFPMultipartReply):
4010 Description statistics reply message
4012 The switch responds with this message to a description statistics
4015 ================ ======================================================
4016 Attribute Description
4017 ================ ======================================================
4018 body Instance of ``OFPDescStats``
4019 ================ ======================================================
4023 @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
4024 def desc_stats_reply_handler(self, ev):
4027 self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
4028 'serial_num=%s dp_desc=%s',
4029 body.mfr_desc, body.hw_desc, body.sw_desc,
4030 body.serial_num, body.dp_desc)
4033 def __init__(self, datapath, type_=None, **kwargs):
4034 super(OFPDescStatsReply, self).__init__(datapath, **kwargs)
4037 class OFPFlowStats(StringifyMixin):
4038 def __init__(self, table_id=None, duration_sec=None, duration_nsec=None,
4039 priority=None, idle_timeout=None, hard_timeout=None,
4040 flags=None, cookie=None, packet_count=None,
4041 byte_count=None, match=None, instructions=None,
4043 super(OFPFlowStats, self).__init__()
4044 self.table_id = table_id
4045 self.duration_sec = duration_sec
4046 self.duration_nsec = duration_nsec
4047 self.priority = priority
4048 self.idle_timeout = idle_timeout
4049 self.hard_timeout = hard_timeout
4051 self.cookie = cookie
4052 self.packet_count = packet_count
4053 self.byte_count = byte_count
4055 self.instructions = instructions
4056 self.length = length
4059 def parser(cls, buf, offset):
4062 (flow_stats.length, flow_stats.table_id,
4063 flow_stats.duration_sec, flow_stats.duration_nsec,
4064 flow_stats.priority, flow_stats.idle_timeout,
4065 flow_stats.hard_timeout, flow_stats.flags,
4066 flow_stats.cookie, flow_stats.packet_count,
4067 flow_stats.byte_count) = struct.unpack_from(
4068 ofproto.OFP_FLOW_STATS_0_PACK_STR, buf, offset)
4069 offset += ofproto.OFP_FLOW_STATS_0_SIZE
4071 flow_stats.match = OFPMatch.parser(buf, offset)
4072 match_length = utils.round_up(flow_stats.match.length, 8)
4073 inst_length = (flow_stats.length - (ofproto.OFP_FLOW_STATS_SIZE -
4074 ofproto.OFP_MATCH_SIZE +
4076 offset += match_length
4078 while inst_length > 0:
4079 inst = OFPInstruction.parser(buf, offset)
4080 instructions.append(inst)
4082 inst_length -= inst.len
4084 flow_stats.instructions = instructions
4088 class OFPFlowStatsRequestBase(OFPMultipartRequest):
4089 def __init__(self, datapath, flags, table_id, out_port, out_group,
4090 cookie, cookie_mask, match):
4091 super(OFPFlowStatsRequestBase, self).__init__(datapath, flags)
4092 self.table_id = table_id
4093 self.out_port = out_port
4094 self.out_group = out_group
4095 self.cookie = cookie
4096 self.cookie_mask = cookie_mask
4099 def _serialize_stats_body(self):
4100 offset = ofproto.OFP_MULTIPART_REQUEST_SIZE
4101 msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_0_PACK_STR,
4102 self.buf, offset, self.table_id, self.out_port,
4103 self.out_group, self.cookie, self.cookie_mask)
4105 offset += ofproto.OFP_FLOW_STATS_REQUEST_0_SIZE
4106 self.match.serialize(self.buf, offset)
4109 @_set_stats_type(ofproto.OFPMP_FLOW, OFPFlowStats)
4110 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4111 class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
4113 Individual flow statistics request message
4115 The controller uses this message to query individual flow statistics.
4117 ================ ======================================================
4118 Attribute Description
4119 ================ ======================================================
4120 flags Zero or ``OFPMPF_REQ_MORE``
4121 table_id ID of table to read
4122 out_port Require matching entries to include this as an output
4124 out_group Require matching entries to include this as an output
4126 cookie Require matching entries to contain this cookie value
4127 cookie_mask Mask used to restrict the cookie bits that must match
4128 match Instance of ``OFPMatch``
4129 ================ ======================================================
4133 def send_flow_stats_request(self, datapath):
4134 ofp = datapath.ofproto
4135 ofp_parser = datapath.ofproto_parser
4137 cookie = cookie_mask = 0
4138 match = ofp_parser.OFPMatch(in_port=1)
4139 req = ofp_parser.OFPFlowStatsRequest(datapath, 0,
4141 ofp.OFPP_ANY, ofp.OFPG_ANY,
4142 cookie, cookie_mask,
4144 datapath.send_msg(req)
4147 def __init__(self, datapath, flags=0, table_id=ofproto.OFPTT_ALL,
4148 out_port=ofproto.OFPP_ANY,
4149 out_group=ofproto.OFPG_ANY,
4150 cookie=0, cookie_mask=0, match=None, type_=None):
4153 super(OFPFlowStatsRequest, self).__init__(datapath, flags, table_id,
4154 out_port, out_group,
4155 cookie, cookie_mask, match)
4158 @OFPMultipartReply.register_stats_type()
4159 @_set_stats_type(ofproto.OFPMP_FLOW, OFPFlowStats)
4160 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4161 class OFPFlowStatsReply(OFPMultipartReply):
4163 Individual flow statistics reply message
4165 The switch responds with this message to an individual flow statistics
4168 ================ ======================================================
4169 Attribute Description
4170 ================ ======================================================
4171 body List of ``OFPFlowStats`` instance
4172 ================ ======================================================
4176 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
4177 def flow_stats_reply_handler(self, ev):
4179 for stat in ev.msg.body:
4180 flows.append('table_id=%s '
4181 'duration_sec=%d duration_nsec=%d '
4183 'idle_timeout=%d hard_timeout=%d flags=0x%04x '
4184 'cookie=%d packet_count=%d byte_count=%d '
4185 'match=%s instructions=%s' %
4187 stat.duration_sec, stat.duration_nsec,
4189 stat.idle_timeout, stat.hard_timeout, stat.flags,
4190 stat.cookie, stat.packet_count, stat.byte_count,
4191 stat.match, stat.instructions))
4192 self.logger.debug('FlowStats: %s', flows)
4195 def __init__(self, datapath, type_=None, **kwargs):
4196 super(OFPFlowStatsReply, self).__init__(datapath, **kwargs)
4199 class OFPAggregateStats(ofproto_parser.namedtuple('OFPAggregateStats', (
4200 'packet_count', 'byte_count', 'flow_count'))):
4202 def parser(cls, buf, offset):
4203 agg = struct.unpack_from(
4204 ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
4206 stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
4210 @_set_stats_type(ofproto.OFPMP_AGGREGATE, OFPAggregateStats)
4211 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4212 class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
4214 Aggregate flow statistics request message
4216 The controller uses this message to query aggregate flow statictics.
4218 ================ ======================================================
4219 Attribute Description
4220 ================ ======================================================
4221 flags Zero or ``OFPMPF_REQ_MORE``
4222 table_id ID of table to read
4223 out_port Require matching entries to include this as an output
4225 out_group Require matching entries to include this as an output
4227 cookie Require matching entries to contain this cookie value
4228 cookie_mask Mask used to restrict the cookie bits that must match
4229 match Instance of ``OFPMatch``
4230 ================ ======================================================
4234 def send_aggregate_stats_request(self, datapath):
4235 ofp = datapath.ofproto
4236 ofp_parser = datapath.ofproto_parser
4238 cookie = cookie_mask = 0
4239 match = ofp_parser.OFPMatch(in_port=1)
4240 req = ofp_parser.OFPAggregateStatsRequest(datapath, 0,
4244 cookie, cookie_mask,
4246 datapath.send_msg(req)
4249 def __init__(self, datapath, flags, table_id, out_port, out_group,
4250 cookie, cookie_mask, match, type_=None):
4251 super(OFPAggregateStatsRequest, self).__init__(datapath,
4261 @OFPMultipartReply.register_stats_type(body_single_struct=True)
4262 @_set_stats_type(ofproto.OFPMP_AGGREGATE, OFPAggregateStats)
4263 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4264 class OFPAggregateStatsReply(OFPMultipartReply):
4266 Aggregate flow statistics reply message
4268 The switch responds with this message to an aggregate flow statistics
4271 ================ ======================================================
4272 Attribute Description
4273 ================ ======================================================
4274 body Instance of ``OFPAggregateStats``
4275 ================ ======================================================
4279 @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
4280 def aggregate_stats_reply_handler(self, ev):
4283 self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
4285 body.packet_count, body.byte_count,
4289 def __init__(self, datapath, type_=None, **kwargs):
4290 super(OFPAggregateStatsReply, self).__init__(datapath, **kwargs)
4293 class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', (
4294 'table_id', 'active_count', 'lookup_count',
4297 def parser(cls, buf, offset):
4298 tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR,
4301 stats.length = ofproto.OFP_TABLE_STATS_SIZE
4305 @_set_stats_type(ofproto.OFPMP_TABLE, OFPTableStats)
4306 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4307 class OFPTableStatsRequest(OFPMultipartRequest):
4309 Table statistics request message
4311 The controller uses this message to query flow table statictics.
4313 ================ ======================================================
4314 Attribute Description
4315 ================ ======================================================
4316 flags Zero or ``OFPMPF_REQ_MORE``
4317 ================ ======================================================
4321 def send_table_stats_request(self, datapath):
4322 ofp_parser = datapath.ofproto_parser
4324 req = ofp_parser.OFPTableStatsRequest(datapath, 0)
4325 datapath.send_msg(req)
4328 def __init__(self, datapath, flags=0, type_=None):
4329 super(OFPTableStatsRequest, self).__init__(datapath, flags)
4332 @OFPMultipartReply.register_stats_type()
4333 @_set_stats_type(ofproto.OFPMP_TABLE, OFPTableStats)
4334 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4335 class OFPTableStatsReply(OFPMultipartReply):
4337 Table statistics reply message
4339 The switch responds with this message to a table statistics request.
4341 ================ ======================================================
4342 Attribute Description
4343 ================ ======================================================
4344 body List of ``OFPTableStats`` instance
4345 ================ ======================================================
4349 @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
4350 def table_stats_reply_handler(self, ev):
4352 for stat in ev.msg.body:
4353 tables.append('table_id=%d active_count=%d lookup_count=%d '
4354 ' matched_count=%d' %
4355 (stat.table_id, stat.active_count,
4356 stat.lookup_count, stat.matched_count))
4357 self.logger.debug('TableStats: %s', tables)
4360 def __init__(self, datapath, type_=None, **kwargs):
4361 super(OFPTableStatsReply, self).__init__(datapath, **kwargs)
4364 class OFPPortStats(ofproto_parser.namedtuple('OFPPortStats', (
4365 'port_no', 'rx_packets', 'tx_packets', 'rx_bytes', 'tx_bytes',
4366 'rx_dropped', 'tx_dropped', 'rx_errors', 'tx_errors',
4367 'rx_frame_err', 'rx_over_err', 'rx_crc_err', 'collisions',
4368 'duration_sec', 'duration_nsec'))):
4370 def parser(cls, buf, offset):
4371 port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR,
4374 stats.length = ofproto.OFP_PORT_STATS_SIZE
4378 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
4379 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4380 class OFPPortStatsRequest(OFPMultipartRequest):
4382 Port statistics request message
4384 The controller uses this message to query information about ports
4387 ================ ======================================================
4388 Attribute Description
4389 ================ ======================================================
4390 flags Zero or ``OFPMPF_REQ_MORE``
4391 port_no Port number to read (OFPP_ANY to all ports)
4392 ================ ======================================================
4396 def send_port_stats_request(self, datapath):
4397 ofp = datapath.ofproto
4398 ofp_parser = datapath.ofproto_parser
4400 req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY)
4401 datapath.send_msg(req)
4404 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
4406 super(OFPPortStatsRequest, self).__init__(datapath, flags)
4407 self.port_no = port_no
4409 def _serialize_stats_body(self):
4410 msg_pack_into(ofproto.OFP_PORT_STATS_REQUEST_PACK_STR,
4412 ofproto.OFP_MULTIPART_REQUEST_SIZE,
4416 @OFPMultipartReply.register_stats_type()
4417 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
4418 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4419 class OFPPortStatsReply(OFPMultipartReply):
4421 Port statistics reply message
4423 The switch responds with this message to a port statistics request.
4425 ================ ======================================================
4426 Attribute Description
4427 ================ ======================================================
4428 body List of ``OFPPortStats`` instance
4429 ================ ======================================================
4433 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
4434 def port_stats_reply_handler(self, ev):
4436 for stat in ev.msg.body:
4437 ports.append('port_no=%d '
4438 'rx_packets=%d tx_packets=%d '
4439 'rx_bytes=%d tx_bytes=%d '
4440 'rx_dropped=%d tx_dropped=%d '
4441 'rx_errors=%d tx_errors=%d '
4442 'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
4443 'collisions=%d duration_sec=%d duration_nsec=%d' %
4445 stat.rx_packets, stat.tx_packets,
4446 stat.rx_bytes, stat.tx_bytes,
4447 stat.rx_dropped, stat.tx_dropped,
4448 stat.rx_errors, stat.tx_errors,
4449 stat.rx_frame_err, stat.rx_over_err,
4450 stat.rx_crc_err, stat.collisions,
4451 stat.duration_sec, stat.duration_nsec))
4452 self.logger.debug('PortStats: %s', ports)
4455 def __init__(self, datapath, type_=None, **kwargs):
4456 super(OFPPortStatsReply, self).__init__(datapath, **kwargs)
4459 class OFPQueueStats(ofproto_parser.namedtuple('OFPQueueStats', (
4460 'port_no', 'queue_id', 'tx_bytes', 'tx_packets', 'tx_errors',
4461 'duration_sec', 'duration_nsec'))):
4463 def parser(cls, buf, offset):
4464 queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR,
4467 stats.length = ofproto.OFP_QUEUE_STATS_SIZE
4471 @_set_stats_type(ofproto.OFPMP_QUEUE, OFPQueueStats)
4472 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4473 class OFPQueueStatsRequest(OFPMultipartRequest):
4475 Queue statistics request message
4477 The controller uses this message to query queue statictics.
4479 ================ ======================================================
4480 Attribute Description
4481 ================ ======================================================
4482 flags Zero or ``OFPMPF_REQ_MORE``
4483 port_no Port number to read
4484 queue_id ID of queue to read
4485 ================ ======================================================
4489 def send_queue_stats_request(self, datapath):
4490 ofp = datapath.ofproto
4491 ofp_parser = datapath.ofproto_parser
4493 req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPP_ANY,
4495 datapath.send_msg(req)
4498 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
4499 queue_id=ofproto.OFPQ_ALL, type_=None):
4500 super(OFPQueueStatsRequest, self).__init__(datapath, flags)
4501 self.port_no = port_no
4502 self.queue_id = queue_id
4504 def _serialize_stats_body(self):
4505 msg_pack_into(ofproto.OFP_QUEUE_STATS_REQUEST_PACK_STR,
4507 ofproto.OFP_MULTIPART_REQUEST_SIZE,
4508 self.port_no, self.queue_id)
4511 @OFPMultipartReply.register_stats_type()
4512 @_set_stats_type(ofproto.OFPMP_QUEUE, OFPQueueStats)
4513 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4514 class OFPQueueStatsReply(OFPMultipartReply):
4516 Queue statistics reply message
4518 The switch responds with this message to an aggregate flow statistics
4521 ================ ======================================================
4522 Attribute Description
4523 ================ ======================================================
4524 body List of ``OFPQueueStats`` instance
4525 ================ ======================================================
4529 @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
4530 def queue_stats_reply_handler(self, ev):
4532 for stat in ev.msg.body:
4533 queues.append('port_no=%d queue_id=%d '
4534 'tx_bytes=%d tx_packets=%d tx_errors=%d '
4535 'duration_sec=%d duration_nsec=%d' %
4536 (stat.port_no, stat.queue_id,
4537 stat.tx_bytes, stat.tx_packets, stat.tx_errors,
4538 stat.duration_sec, stat.duration_nsec))
4539 self.logger.debug('QueueStats: %s', queues)
4542 def __init__(self, datapath, type_=None, **kwargs):
4543 super(OFPQueueStatsReply, self).__init__(datapath, **kwargs)
4546 class OFPBucketCounter(StringifyMixin):
4547 def __init__(self, packet_count, byte_count):
4548 super(OFPBucketCounter, self).__init__()
4549 self.packet_count = packet_count
4550 self.byte_count = byte_count
4553 def parser(cls, buf, offset):
4554 packet_count, byte_count = struct.unpack_from(
4555 ofproto.OFP_BUCKET_COUNTER_PACK_STR, buf, offset)
4556 return cls(packet_count, byte_count)
4559 class OFPGroupStats(StringifyMixin):
4560 def __init__(self, length=None, group_id=None, ref_count=None,
4561 packet_count=None, byte_count=None, duration_sec=None,
4562 duration_nsec=None, bucket_stats=None):
4563 super(OFPGroupStats, self).__init__()
4564 self.length = length
4565 self.group_id = group_id
4566 self.ref_count = ref_count
4567 self.packet_count = packet_count
4568 self.byte_count = byte_count
4569 self.duration_sec = duration_sec
4570 self.duration_nsec = duration_nsec
4571 self.bucket_stats = bucket_stats
4574 def parser(cls, buf, offset):
4575 group = struct.unpack_from(ofproto.OFP_GROUP_STATS_PACK_STR,
4577 group_stats = cls(*group)
4579 group_stats.bucket_stats = []
4580 total_len = group_stats.length + offset
4581 offset += ofproto.OFP_GROUP_STATS_SIZE
4582 while total_len > offset:
4583 b = OFPBucketCounter.parser(buf, offset)
4584 group_stats.bucket_stats.append(b)
4585 offset += ofproto.OFP_BUCKET_COUNTER_SIZE
4590 @_set_stats_type(ofproto.OFPMP_GROUP, OFPGroupStats)
4591 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4592 class OFPGroupStatsRequest(OFPMultipartRequest):
4594 Group statistics request message
4596 The controller uses this message to query statistics of one or more
4599 ================ ======================================================
4600 Attribute Description
4601 ================ ======================================================
4602 flags Zero or ``OFPMPF_REQ_MORE``
4603 group_id ID of group to read (OFPG_ALL to all groups)
4604 ================ ======================================================
4608 def send_group_stats_request(self, datapath):
4609 ofp = datapath.ofproto
4610 ofp_parser = datapath.ofproto_parser
4612 req = ofp_parser.OFPGroupStatsRequest(datapath, 0, ofp.OFPG_ALL)
4613 datapath.send_msg(req)
4616 def __init__(self, datapath, flags=0, group_id=ofproto.OFPG_ALL,
4618 super(OFPGroupStatsRequest, self).__init__(datapath, flags)
4619 self.group_id = group_id
4621 def _serialize_stats_body(self):
4622 msg_pack_into(ofproto.OFP_GROUP_STATS_REQUEST_PACK_STR,
4624 ofproto.OFP_MULTIPART_REQUEST_SIZE,
4628 @OFPMultipartReply.register_stats_type()
4629 @_set_stats_type(ofproto.OFPMP_GROUP, OFPGroupStats)
4630 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4631 class OFPGroupStatsReply(OFPMultipartReply):
4633 Group statistics reply message
4635 The switch responds with this message to a group statistics request.
4637 ================ ======================================================
4638 Attribute Description
4639 ================ ======================================================
4640 body List of ``OFPGroupStats`` instance
4641 ================ ======================================================
4645 @set_ev_cls(ofp_event.EventOFPGroupStatsReply, MAIN_DISPATCHER)
4646 def group_stats_reply_handler(self, ev):
4648 for stat in ev.msg.body:
4649 groups.append('length=%d group_id=%d '
4650 'ref_count=%d packet_count=%d byte_count=%d '
4651 'duration_sec=%d duration_nsec=%d' %
4652 (stat.length, stat.group_id,
4653 stat.ref_count, stat.packet_count,
4654 stat.byte_count, stat.duration_sec,
4655 stat.duration_nsec))
4656 self.logger.debug('GroupStats: %s', groups)
4659 def __init__(self, datapath, type_=None, **kwargs):
4660 super(OFPGroupStatsReply, self).__init__(datapath, **kwargs)
4663 class OFPGroupDescStats(StringifyMixin):
4664 def __init__(self, type_=None, group_id=None, buckets=None, length=None):
4665 super(OFPGroupDescStats, self).__init__()
4667 self.group_id = group_id
4668 self.buckets = buckets
4671 def parser(cls, buf, offset):
4674 (stats.length, stats.type, stats.group_id) = struct.unpack_from(
4675 ofproto.OFP_GROUP_DESC_STATS_PACK_STR, buf, offset)
4676 offset += ofproto.OFP_GROUP_DESC_STATS_SIZE
4679 length = ofproto.OFP_GROUP_DESC_STATS_SIZE
4680 while length < stats.length:
4681 bucket = OFPBucket.parser(buf, offset)
4682 stats.buckets.append(bucket)
4684 offset += bucket.len
4685 length += bucket.len
4690 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
4691 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4692 class OFPGroupDescStatsRequest(OFPMultipartRequest):
4694 Group description request message
4696 The controller uses this message to list the set of groups on a switch.
4698 ================ ======================================================
4699 Attribute Description
4700 ================ ======================================================
4701 flags Zero or ``OFPMPF_REQ_MORE``
4702 ================ ======================================================
4706 def send_group_desc_stats_request(self, datapath):
4707 ofp_parser = datapath.ofproto_parser
4709 req = ofp_parser.OFPGroupDescStatsRequest(datapath, 0)
4710 datapath.send_msg(req)
4713 def __init__(self, datapath, flags=0, type_=None):
4714 super(OFPGroupDescStatsRequest, self).__init__(datapath, flags)
4717 @OFPMultipartReply.register_stats_type()
4718 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
4719 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4720 class OFPGroupDescStatsReply(OFPMultipartReply):
4722 Group description reply message
4724 The switch responds with this message to a group description request.
4726 ================ ======================================================
4727 Attribute Description
4728 ================ ======================================================
4729 body List of ``OFPGroupDescStats`` instance
4730 ================ ======================================================
4734 @set_ev_cls(ofp_event.EventOFPGroupDescStatsReply, MAIN_DISPATCHER)
4735 def group_desc_stats_reply_handler(self, ev):
4737 for stat in ev.msg.body:
4738 descs.append('length=%d type=%d group_id=%d '
4740 (stat.length, stat.type, stat.group_id,
4742 self.logger.debug('GroupDescStats: %s', descs)
4745 def __init__(self, datapath, type_=None, **kwargs):
4746 super(OFPGroupDescStatsReply, self).__init__(datapath, **kwargs)
4749 class OFPGroupFeaturesStats(ofproto_parser.namedtuple('OFPGroupFeaturesStats',
4750 ('types', 'capabilities', 'max_groups',
4753 def parser(cls, buf, offset):
4754 group_features = struct.unpack_from(
4755 ofproto.OFP_GROUP_FEATURES_PACK_STR, buf, offset)
4756 types = group_features[0]
4757 capabilities = group_features[1]
4758 max_groups = list(group_features[2:6])
4759 actions = list(group_features[6:10])
4760 stats = cls(types, capabilities, max_groups, actions)
4761 stats.length = ofproto.OFP_GROUP_FEATURES_SIZE
4765 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
4766 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4767 class OFPGroupFeaturesStatsRequest(OFPMultipartRequest):
4769 Group features request message
4771 The controller uses this message to list the capabilities of groups on
4774 ================ ======================================================
4775 Attribute Description
4776 ================ ======================================================
4777 flags Zero or ``OFPMPF_REQ_MORE``
4778 ================ ======================================================
4782 def send_group_features_stats_request(self, datapath):
4783 ofp_parser = datapath.ofproto_parser
4785 req = ofp_parser.OFPGroupFeaturesStatsRequest(datapath, 0)
4786 datapath.send_msg(req)
4789 def __init__(self, datapath, flags=0, type_=None):
4790 super(OFPGroupFeaturesStatsRequest, self).__init__(datapath, flags)
4793 @OFPMultipartReply.register_stats_type(body_single_struct=True)
4794 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
4795 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4796 class OFPGroupFeaturesStatsReply(OFPMultipartReply):
4798 Group features reply message
4800 The switch responds with this message to a group features request.
4802 ================ ======================================================
4803 Attribute Description
4804 ================ ======================================================
4805 body Instance of ``OFPGroupFeaturesStats``
4806 ================ ======================================================
4810 @set_ev_cls(ofp_event.EventOFPGroupFeaturesStatsReply, MAIN_DISPATCHER)
4811 def group_features_stats_reply_handler(self, ev):
4814 self.logger.debug('GroupFeaturesStats: types=%d '
4815 'capabilities=0x%08x max_groups=%s '
4817 body.types, body.capabilities,
4818 body.max_groups, body.actions)
4821 def __init__(self, datapath, type_=None, **kwargs):
4822 super(OFPGroupFeaturesStatsReply, self).__init__(datapath, **kwargs)
4825 class OFPMeterBandStats(StringifyMixin):
4826 def __init__(self, packet_band_count, byte_band_count):
4827 super(OFPMeterBandStats, self).__init__()
4828 self.packet_band_count = packet_band_count
4829 self.byte_band_count = byte_band_count
4832 def parser(cls, buf, offset):
4833 band_stats = struct.unpack_from(
4834 ofproto.OFP_METER_BAND_STATS_PACK_STR, buf, offset)
4835 return cls(*band_stats)
4838 class OFPMeterStats(StringifyMixin):
4839 def __init__(self, meter_id=None, flow_count=None, packet_in_count=None,
4840 byte_in_count=None, duration_sec=None, duration_nsec=None,
4841 band_stats=None, len_=None):
4842 super(OFPMeterStats, self).__init__()
4843 self.meter_id = meter_id
4845 self.flow_count = flow_count
4846 self.packet_in_count = packet_in_count
4847 self.byte_in_count = byte_in_count
4848 self.duration_sec = duration_sec
4849 self.duration_nsec = duration_nsec
4850 self.band_stats = band_stats
4853 def parser(cls, buf, offset):
4856 (meter_stats.meter_id, meter_stats.len,
4857 meter_stats.flow_count, meter_stats.packet_in_count,
4858 meter_stats.byte_in_count, meter_stats.duration_sec,
4859 meter_stats.duration_nsec) = struct.unpack_from(
4860 ofproto.OFP_METER_STATS_PACK_STR, buf, offset)
4861 offset += ofproto.OFP_METER_STATS_SIZE
4863 meter_stats.band_stats = []
4864 length = ofproto.OFP_METER_STATS_SIZE
4865 while length < meter_stats.len:
4866 band_stats = OFPMeterBandStats.parser(buf, offset)
4867 meter_stats.band_stats.append(band_stats)
4868 offset += ofproto.OFP_METER_BAND_STATS_SIZE
4869 length += ofproto.OFP_METER_BAND_STATS_SIZE
4874 @_set_stats_type(ofproto.OFPMP_METER, OFPMeterStats)
4875 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4876 class OFPMeterStatsRequest(OFPMultipartRequest):
4878 Meter statistics request message
4880 The controller uses this message to query statistics for one or more
4883 ================ ======================================================
4884 Attribute Description
4885 ================ ======================================================
4886 flags Zero or ``OFPMPF_REQ_MORE``
4887 meter_id ID of meter to read (OFPM_ALL to all meters)
4888 ================ ======================================================
4892 def send_meter_stats_request(self, datapath):
4893 ofp = datapath.ofproto
4894 ofp_parser = datapath.ofproto_parser
4896 req = ofp_parser.OFPMeterStatsRequest(datapath, 0, ofp.OFPM_ALL)
4897 datapath.send_msg(req)
4900 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
4902 super(OFPMeterStatsRequest, self).__init__(datapath, flags)
4903 self.meter_id = meter_id
4905 def _serialize_stats_body(self):
4906 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
4908 ofproto.OFP_MULTIPART_REQUEST_SIZE,
4912 @OFPMultipartReply.register_stats_type()
4913 @_set_stats_type(ofproto.OFPMP_METER, OFPMeterStats)
4914 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4915 class OFPMeterStatsReply(OFPMultipartReply):
4917 Meter statistics reply message
4919 The switch responds with this message to a meter statistics request.
4921 ================ ======================================================
4922 Attribute Description
4923 ================ ======================================================
4924 body List of ``OFPMeterStats`` instance
4925 ================ ======================================================
4929 @set_ev_cls(ofp_event.EventOFPMeterStatsReply, MAIN_DISPATCHER)
4930 def meter_stats_reply_handler(self, ev):
4932 for stat in ev.msg.body:
4933 meters.append('meter_id=0x%08x len=%d flow_count=%d '
4934 'packet_in_count=%d byte_in_count=%d '
4935 'duration_sec=%d duration_nsec=%d '
4937 (stat.meter_id, stat.len, stat.flow_count,
4938 stat.packet_in_count, stat.byte_in_count,
4939 stat.duration_sec, stat.duration_nsec,
4941 self.logger.debug('MeterStats: %s', meters)
4944 def __init__(self, datapath, type_=None, **kwargs):
4945 super(OFPMeterStatsReply, self).__init__(datapath, **kwargs)
4948 class OFPMeterBand(StringifyMixin):
4949 def __init__(self, type_, len_):
4950 super(OFPMeterBand, self).__init__()
4955 class OFPMeterBandHeader(OFPMeterBand):
4959 def register_meter_band_type(type_, len_):
4960 def _register_meter_band_type(cls):
4961 OFPMeterBandHeader._METER_BAND[type_] = cls
4962 cls.cls_meter_band_type = type_
4963 cls.cls_meter_band_len = len_
4965 return _register_meter_band_type
4968 cls = self.__class__
4969 super(OFPMeterBandHeader, self).__init__(cls.cls_meter_band_type,
4970 cls.cls_meter_band_len)
4973 def parser(cls, buf, offset):
4974 type_, len_, _rate, _burst_size = struct.unpack_from(
4975 ofproto.OFP_METER_BAND_HEADER_PACK_STR, buf, offset)
4976 cls_ = cls._METER_BAND[type_]
4977 assert cls_.cls_meter_band_len == len_
4978 return cls_.parser(buf, offset)
4981 @OFPMeterBandHeader.register_meter_band_type(
4982 ofproto.OFPMBT_DROP, ofproto.OFP_METER_BAND_DROP_SIZE)
4983 class OFPMeterBandDrop(OFPMeterBandHeader):
4984 def __init__(self, rate=0, burst_size=0, type_=None, len_=None):
4985 super(OFPMeterBandDrop, self).__init__()
4987 self.burst_size = burst_size
4989 def serialize(self, buf, offset):
4990 msg_pack_into(ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset,
4991 self.type, self.len, self.rate, self.burst_size)
4994 def parser(cls, buf, offset):
4995 type_, len_, rate, burst_size = struct.unpack_from(
4996 ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset)
4997 assert cls.cls_meter_band_type == type_
4998 assert cls.cls_meter_band_len == len_
4999 return cls(rate, burst_size)
5002 @OFPMeterBandHeader.register_meter_band_type(
5003 ofproto.OFPMBT_DSCP_REMARK,
5004 ofproto.OFP_METER_BAND_DSCP_REMARK_SIZE)
5005 class OFPMeterBandDscpRemark(OFPMeterBandHeader):
5006 def __init__(self, rate=0, burst_size=0, prec_level=0,
5007 type_=None, len_=None):
5008 super(OFPMeterBandDscpRemark, self).__init__()
5010 self.burst_size = burst_size
5011 self.prec_level = prec_level
5013 def serialize(self, buf, offset):
5014 msg_pack_into(ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf,
5015 offset, self.type, self.len, self.rate,
5016 self.burst_size, self.prec_level)
5019 def parser(cls, buf, offset):
5020 type_, len_, rate, burst_size, prec_level = struct.unpack_from(
5021 ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf, offset)
5022 assert cls.cls_meter_band_type == type_
5023 assert cls.cls_meter_band_len == len_
5024 return cls(rate, burst_size, prec_level)
5027 @OFPMeterBandHeader.register_meter_band_type(
5028 ofproto.OFPMBT_EXPERIMENTER,
5029 ofproto.OFP_METER_BAND_EXPERIMENTER_SIZE)
5030 class OFPMeterBandExperimenter(OFPMeterBandHeader):
5031 def __init__(self, rate=0, burst_size=0, experimenter=None,
5032 type_=None, len_=None):
5033 super(OFPMeterBandExperimenter, self).__init__()
5035 self.burst_size = burst_size
5036 self.experimenter = experimenter
5038 def serialize(self, buf, offset):
5039 msg_pack_into(ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf,
5040 offset, self.type, self.len, self.rate,
5041 self.burst_size, self.experimenter)
5044 def parser(cls, buf, offset):
5045 type_, len_, rate, burst_size, experimenter = struct.unpack_from(
5046 ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf, offset)
5047 assert cls.cls_meter_band_type == type_
5048 assert cls.cls_meter_band_len == len_
5049 return cls(rate, burst_size, experimenter)
5052 class OFPMeterConfigStats(StringifyMixin):
5053 def __init__(self, flags=None, meter_id=None, bands=None, length=None):
5054 super(OFPMeterConfigStats, self).__init__()
5057 self.meter_id = meter_id
5061 def parser(cls, buf, offset):
5062 meter_config = cls()
5064 (meter_config.length, meter_config.flags,
5065 meter_config.meter_id) = struct.unpack_from(
5066 ofproto.OFP_METER_CONFIG_PACK_STR, buf, offset)
5067 offset += ofproto.OFP_METER_CONFIG_SIZE
5069 meter_config.bands = []
5070 length = ofproto.OFP_METER_CONFIG_SIZE
5071 while length < meter_config.length:
5072 band = OFPMeterBandHeader.parser(buf, offset)
5073 meter_config.bands.append(band)
5080 @_set_stats_type(ofproto.OFPMP_METER_CONFIG, OFPMeterConfigStats)
5081 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5082 class OFPMeterConfigStatsRequest(OFPMultipartRequest):
5084 Meter configuration statistics request message
5086 The controller uses this message to query configuration for one or more
5089 ================ ======================================================
5090 Attribute Description
5091 ================ ======================================================
5092 flags Zero or ``OFPMPF_REQ_MORE``
5093 meter_id ID of meter to read (OFPM_ALL to all meters)
5094 ================ ======================================================
5098 def send_meter_config_stats_request(self, datapath):
5099 ofp = datapath.ofproto
5100 ofp_parser = datapath.ofproto_parser
5102 req = ofp_parser.OFPMeterConfigStatsRequest(datapath, 0,
5104 datapath.send_msg(req)
5107 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
5109 super(OFPMeterConfigStatsRequest, self).__init__(datapath, flags)
5110 self.meter_id = meter_id
5112 def _serialize_stats_body(self):
5113 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
5115 ofproto.OFP_MULTIPART_REQUEST_SIZE,
5119 @OFPMultipartReply.register_stats_type()
5120 @_set_stats_type(ofproto.OFPMP_METER_CONFIG, OFPMeterConfigStats)
5121 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
5122 class OFPMeterConfigStatsReply(OFPMultipartReply):
5124 Meter configuration statistics reply message
5126 The switch responds with this message to a meter configuration
5129 ================ ======================================================
5130 Attribute Description
5131 ================ ======================================================
5132 body List of ``OFPMeterConfigStats`` instance
5133 ================ ======================================================
5137 @set_ev_cls(ofp_event.EventOFPMeterConfigStatsReply, MAIN_DISPATCHER)
5138 def meter_config_stats_reply_handler(self, ev):
5140 for stat in ev.msg.body:
5141 configs.append('length=%d flags=0x%04x meter_id=0x%08x '
5143 (stat.length, stat.flags, stat.meter_id,
5145 self.logger.debug('MeterConfigStats: %s', configs)
5148 def __init__(self, datapath, type_=None, **kwargs):
5149 super(OFPMeterConfigStatsReply, self).__init__(datapath, **kwargs)
5152 class OFPMeterFeaturesStats(ofproto_parser.namedtuple('OFPMeterFeaturesStats',
5153 ('max_meter', 'band_types', 'capabilities',
5154 'max_bands', 'max_color'))):
5156 def parser(cls, buf, offset):
5157 meter_features = struct.unpack_from(
5158 ofproto.OFP_METER_FEATURES_PACK_STR, buf, offset)
5159 stats = cls(*meter_features)
5160 stats.length = ofproto.OFP_METER_FEATURES_SIZE
5164 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
5165 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5166 class OFPMeterFeaturesStatsRequest(OFPMultipartRequest):
5168 Meter features statistics request message
5170 The controller uses this message to query the set of features of the
5173 ================ ======================================================
5174 Attribute Description
5175 ================ ======================================================
5176 flags Zero or ``OFPMPF_REQ_MORE``
5177 ================ ======================================================
5181 def send_meter_features_stats_request(self, datapath):
5182 ofp_parser = datapath.ofproto_parser
5184 req = ofp_parser.OFPMeterFeaturesStatsRequest(datapath, 0)
5185 datapath.send_msg(req)
5188 def __init__(self, datapath, flags=0, type_=None):
5189 super(OFPMeterFeaturesStatsRequest, self).__init__(datapath, flags)
5192 @OFPMultipartReply.register_stats_type()
5193 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
5194 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
5195 class OFPMeterFeaturesStatsReply(OFPMultipartReply):
5197 Meter features statistics reply message
5199 The switch responds with this message to a meter features statistics
5202 ================ ======================================================
5203 Attribute Description
5204 ================ ======================================================
5205 body List of ``OFPMeterFeaturesStats`` instance
5206 ================ ======================================================
5210 @set_ev_cls(ofp_event.EventOFPMeterFeaturesStatsReply, MAIN_DISPATCHER)
5211 def meter_features_stats_reply_handler(self, ev):
5213 for stat in ev.msg.body:
5214 features.append('max_meter=%d band_types=0x%08x '
5215 'capabilities=0x%08x max_bands=%d '
5217 (stat.max_meter, stat.band_types,
5218 stat.capabilities, stat.max_bands,
5220 self.logger.debug('MeterFeaturesStats: %s', features)
5223 def __init__(self, datapath, type_=None, **kwargs):
5224 super(OFPMeterFeaturesStatsReply, self).__init__(datapath, **kwargs)
5227 class OFPTableFeaturesStats(StringifyMixin):
5231 # OF spec is unclear about the encoding of name.
5237 def __init__(self, table_id=None, name=None, metadata_match=None,
5238 metadata_write=None, config=None, max_entries=None,
5239 properties=None, length=None):
5240 super(OFPTableFeaturesStats, self).__init__()
5242 self.table_id = table_id
5244 self.metadata_match = metadata_match
5245 self.metadata_write = metadata_write
5246 self.config = config
5247 self.max_entries = max_entries
5248 self.properties = properties
5251 def parser(cls, buf, offset):
5252 table_features = cls()
5253 (table_features.length, table_features.table_id,
5254 name, table_features.metadata_match,
5255 table_features.metadata_write, table_features.config,
5256 table_features.max_entries
5257 ) = struct.unpack_from(ofproto.OFP_TABLE_FEATURES_PACK_STR,
5259 table_features.name = name.rstrip(b'\0')
5262 rest = buf[offset + ofproto.OFP_TABLE_FEATURES_SIZE:
5263 offset + table_features.length]
5265 p, rest = OFPTableFeatureProp.parse(rest)
5267 table_features.properties = props
5269 return table_features
5271 def serialize(self):
5273 bin_props = bytearray()
5274 for p in self.properties:
5275 bin_props += p.serialize()
5276 self.length = ofproto.OFP_TABLE_FEATURES_SIZE + len(bin_props)
5279 msg_pack_into(ofproto.OFP_TABLE_FEATURES_PACK_STR, buf, 0,
5280 self.length, self.table_id, self.name,
5281 self.metadata_match, self.metadata_write,
5282 self.config, self.max_entries)
5283 return buf + bin_props
5286 class OFPTableFeatureProp(OFPPropBase):
5290 class OFPTableFeaturePropUnknown(OFPTableFeatureProp):
5291 def __init__(self, type_, length=None, data=None):
5292 super(OFPTableFeaturePropUnknown, self).__init__(type_, length)
5296 def _parse_prop(cls, buf):
5297 return {'data': buf}
5299 def _serialize_prop(self):
5303 # Implementation note: While OpenFlow 1.3.2 shares the same ofp_instruction
5304 # for flow_mod and table_features, we have separate classes. We named this
5305 # class to match with OpenFlow 1.4's name. (ofp_instruction_id)
5306 class OFPInstructionId(StringifyMixin):
5307 _PACK_STR = '!HH' # type, len
5309 def __init__(self, type_, len_=None):
5315 def parse(cls, buf):
5316 (type_, len_,) = struct.unpack_from(cls._PACK_STR,
5317 six.binary_type(buf), 0)
5319 return cls(type_=type_, len_=len_), rest
5321 def serialize(self):
5323 self.len = struct.calcsize(self._PACK_STR)
5326 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
5330 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS)
5331 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS_MISS)
5332 class OFPTableFeaturePropInstructions(OFPTableFeatureProp):
5333 def __init__(self, type_=None, length=None, instruction_ids=None):
5334 instruction_ids = instruction_ids if instruction_ids else []
5335 super(OFPTableFeaturePropInstructions, self).__init__(type_, length)
5336 self.instruction_ids = instruction_ids
5339 def parser(cls, buf):
5340 rest = cls.get_rest(buf)
5343 i, rest = OFPInstructionId.parse(rest)
5345 return cls(instruction_ids=ids)
5347 def serialize_body(self):
5348 bin_ids = bytearray()
5349 for i in self.instruction_ids:
5350 bin_ids += i.serialize()
5355 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES)
5356 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES_MISS)
5357 class OFPTableFeaturePropNextTables(OFPTableFeatureProp):
5358 _TABLE_ID_PACK_STR = '!B'
5360 def __init__(self, type_=None, length=None, table_ids=None):
5361 table_ids = table_ids if table_ids else []
5362 super(OFPTableFeaturePropNextTables, self).__init__(type_, length)
5363 self.table_ids = table_ids
5366 def parser(cls, buf):
5367 rest = cls.get_rest(buf)
5370 (i,) = struct.unpack_from(cls._TABLE_ID_PACK_STR,
5371 six.binary_type(rest), 0)
5372 rest = rest[struct.calcsize(cls._TABLE_ID_PACK_STR):]
5374 return cls(table_ids=ids)
5376 def serialize_body(self):
5377 bin_ids = bytearray()
5378 for i in self.table_ids:
5379 bin_id = bytearray()
5380 msg_pack_into(self._TABLE_ID_PACK_STR, bin_id, 0, i)
5385 # Implementation note: While OpenFlow 1.3.2 shares the same ofp_action_header
5386 # for flow_mod and table_features, we have separate classes. We named this
5387 # class to match with OpenFlow 1.4's name. (ofp_action_id)
5388 class OFPActionId(StringifyMixin):
5390 # ofp_action_header should have trailing pad bytes.
5391 # however, i guess it's a specification bug as:
5392 # - the spec explicitly says non-experimenter actions are 4 bytes
5393 # - linc/of_protocol doesn't use them
5394 # - OpenFlow 1.4 changed to use a separate structure
5395 _PACK_STR = '!HH' # type, len
5397 def __init__(self, type_, len_=None):
5403 def parse(cls, buf):
5404 (type_, len_,) = struct.unpack_from(cls._PACK_STR,
5405 six.binary_type(buf), 0)
5407 return cls(type_=type_, len_=len_), rest
5409 def serialize(self):
5411 self.len = struct.calcsize(self._PACK_STR)
5414 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
5418 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS)
5419 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS_MISS)
5420 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS)
5421 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS_MISS)
5422 class OFPTableFeaturePropActions(OFPTableFeatureProp):
5423 def __init__(self, type_=None, length=None, action_ids=None):
5424 action_ids = action_ids if action_ids else []
5425 super(OFPTableFeaturePropActions, self).__init__(type_, length)
5426 self.action_ids = action_ids
5429 def parser(cls, buf):
5430 rest = cls.get_rest(buf)
5433 i, rest = OFPActionId.parse(rest)
5435 return cls(action_ids=ids)
5437 def serialize_body(self):
5438 bin_ids = bytearray()
5439 for i in self.action_ids:
5440 bin_ids += i.serialize()
5444 # Implementation note: OFPOxmId is specific to this implementation.
5445 # It does not have a corresponding structure in the specification.
5446 # (the specification uses plain uint32_t for non-experimenter OXMs
5447 # and uint64_t for experimenter OXMs.)
5449 # i have taken a look at some of software switch implementations
5450 # but they all look broken or incomplete. according to the spec,
5451 # oxm_hasmask should be 1 if a switch supports masking for the type.
5452 # the right value for oxm_length is not clear from the spec.
5453 # update: OpenFlow 1.3.3 "clarified" that oxm_length here is the payload
5454 # length. it's still unclear if it should be doubled for hasmask or not,
5457 # oxm_hasmask always 0
5458 # oxm_length same as ofp_match etc (as without mask)
5460 # oxm_hasmask always 0
5461 # oxm_length always 0
5463 # seems in flux as of writing this [20141003]
5464 class OFPOxmId(StringifyMixin):
5465 _PACK_STR = '!I' # oxm header
5466 _EXPERIMENTER_ID_PACK_STR = '!I'
5474 def __init__(self, type_, hasmask=False, length=None):
5476 self.hasmask = hasmask
5477 self.length = length
5480 def parse(cls, buf):
5481 (oxm,) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf), 0)
5482 # oxm (32 bit) == class (16) | field (7) | hasmask (1) | length (8)
5483 # in case of experimenter OXMs, another 32 bit value
5484 # (experimenter id) follows.
5485 (type_, _v) = ofproto.oxm_to_user(oxm >> (1 + 8), None, None)
5486 rest = buf[struct.calcsize(cls._PACK_STR):]
5487 hasmask = ofproto.oxm_tlv_header_extract_hasmask(oxm)
5488 length = oxm & 0xff # XXX see the comment on OFPOxmId
5489 class_ = oxm >> (7 + 1 + 8)
5490 if class_ == ofproto.OFPXMC_EXPERIMENTER:
5491 (exp_id,) = struct.unpack_from(cls._EXPERIMENTER_ID_PACK_STR,
5492 six.binary_type(rest), 0)
5493 rest = rest[struct.calcsize(cls._EXPERIMENTER_ID_PACK_STR):]
5494 subcls = OFPExperimenterOxmId
5495 return subcls(type_=type_, exp_id=exp_id, hasmask=hasmask,
5496 length=length), rest
5498 return cls(type_=type_, hasmask=hasmask, length=length), rest
5500 def serialize(self):
5502 self.length = 0 # XXX see the comment on OFPOxmId
5504 (n, _v, _m) = ofproto.oxm_from_user(self.type, None)
5505 oxm = (n << (1 + 8)) | (self.hasmask << 8) | self.length
5507 msg_pack_into(self._PACK_STR, buf, 0, oxm)
5508 assert n >> 7 != ofproto.OFPXMC_EXPERIMENTER
5512 class OFPExperimenterOxmId(OFPOxmId):
5513 def __init__(self, type_, exp_id, hasmask=False, length=None):
5514 super(OFPExperimenterOxmId, self).__init__(type_=type_,
5517 self.exp_id = exp_id
5519 def serialize(self):
5520 buf = super(OFPExperimenterOxmId, self).serialize()
5521 msg_pack_into(self._EXPERIMENTER_ID_PACK_STR, buf,
5522 struct.calcsize(self._PACK_STR), self.exp_id)
5525 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_MATCH)
5526 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WILDCARDS)
5527 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD)
5528 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD_MISS)
5529 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD)
5530 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD_MISS)
5531 class OFPTableFeaturePropOxm(OFPTableFeatureProp):
5532 def __init__(self, type_=None, length=None, oxm_ids=None):
5533 oxm_ids = oxm_ids if oxm_ids else []
5534 super(OFPTableFeaturePropOxm, self).__init__(type_, length)
5535 self.oxm_ids = oxm_ids
5538 def parser(cls, buf):
5539 rest = cls.get_rest(buf)
5542 i, rest = OFPOxmId.parse(rest)
5544 return cls(oxm_ids=ids)
5546 def serialize_body(self):
5547 bin_ids = bytearray()
5548 for i in self.oxm_ids:
5549 bin_ids += i.serialize()
5553 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER)
5554 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER_MISS)
5555 class OFPTableFeaturePropExperimenter(OFPPropCommonExperimenter4ByteData):
5559 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
5560 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5561 class OFPTableFeaturesStatsRequest(OFPMultipartRequest):
5563 Table features statistics request message
5565 The controller uses this message to query table features.
5567 ================ ======================================================
5568 Attribute Description
5569 ================ ======================================================
5570 body List of ``OFPTableFeaturesStats`` instances.
5572 ================ ======================================================
5575 def __init__(self, datapath, flags=0,
5578 body = body if body else []
5579 super(OFPTableFeaturesStatsRequest, self).__init__(datapath, flags)
5582 def _serialize_stats_body(self):
5583 bin_body = bytearray()
5585 bin_body += p.serialize()
5586 self.buf += bin_body
5589 @OFPMultipartReply.register_stats_type()
5590 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
5591 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
5592 class OFPTableFeaturesStatsReply(OFPMultipartReply):
5594 Table features statistics reply message
5596 The switch responds with this message to a table features statistics
5599 ================ ======================================================
5600 Attribute Description
5601 ================ ======================================================
5602 body List of ``OFPTableFeaturesStats`` instance
5603 ================ ======================================================
5606 def __init__(self, datapath, type_=None, **kwargs):
5607 super(OFPTableFeaturesStatsReply, self).__init__(datapath, **kwargs)
5610 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
5611 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5612 class OFPPortDescStatsRequest(OFPMultipartRequest):
5614 Port description request message
5616 The controller uses this message to query description of all the ports.
5618 ================ ======================================================
5619 Attribute Description
5620 ================ ======================================================
5621 flags Zero or ``OFPMPF_REQ_MORE``
5622 ================ ======================================================
5626 def send_port_desc_stats_request(self, datapath):
5627 ofp_parser = datapath.ofproto_parser
5629 req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
5630 datapath.send_msg(req)
5633 def __init__(self, datapath, flags=0, type_=None):
5634 super(OFPPortDescStatsRequest, self).__init__(datapath, flags)
5637 @OFPMultipartReply.register_stats_type()
5638 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
5639 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
5640 class OFPPortDescStatsReply(OFPMultipartReply):
5642 Port description reply message
5644 The switch responds with this message to a port description request.
5646 ================ ======================================================
5647 Attribute Description
5648 ================ ======================================================
5649 body List of ``OFPPort`` instance
5650 ================ ======================================================
5654 @set_ev_cls(ofp_event.EventOFPPortDescStatsReply, MAIN_DISPATCHER)
5655 def port_desc_stats_reply_handler(self, ev):
5657 for p in ev.msg.body:
5658 ports.append('port_no=%d hw_addr=%s name=%s config=0x%08x '
5659 'state=0x%08x curr=0x%08x advertised=0x%08x '
5660 'supported=0x%08x peer=0x%08x curr_speed=%d '
5662 (p.port_no, p.hw_addr,
5664 p.state, p.curr, p.advertised,
5665 p.supported, p.peer, p.curr_speed,
5667 self.logger.debug('OFPPortDescStatsReply received: %s', ports)
5670 def __init__(self, datapath, type_=None, **kwargs):
5671 super(OFPPortDescStatsReply, self).__init__(datapath, **kwargs)
5674 class OFPExperimenterMultipart(ofproto_parser.namedtuple(
5675 'OFPExperimenterMultipart',
5676 ('experimenter', 'exp_type', 'data'))):
5678 The body of OFPExperimenterStatsReply multipart messages.
5680 ================ ======================================================
5681 Attribute Description
5682 ================ ======================================================
5683 experimenter Experimenter ID
5684 exp_type Experimenter defined
5685 data Experimenter defined additional data
5686 ================ ======================================================
5690 def parser(cls, buf, offset):
5691 args = struct.unpack_from(
5692 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR, buf,
5695 args.append(buf[offset +
5696 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_SIZE:])
5698 stats.length = ofproto.OFP_METER_FEATURES_SIZE
5701 def serialize(self):
5703 msg_pack_into(ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR,
5705 self.experimenter, self.exp_type)
5706 return buf + self.data
5709 class OFPExperimenterStatsRequestBase(OFPMultipartRequest):
5710 def __init__(self, datapath, flags,
5711 experimenter, exp_type,
5713 super(OFPExperimenterStatsRequestBase, self).__init__(datapath, flags)
5714 self.experimenter = experimenter
5715 self.exp_type = exp_type
5718 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
5719 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5720 class OFPExperimenterStatsRequest(OFPExperimenterStatsRequestBase):
5722 Experimenter multipart request message
5724 ================ ======================================================
5725 Attribute Description
5726 ================ ======================================================
5727 flags Zero or ``OFPMPF_REQ_MORE``
5728 experimenter Experimenter ID
5729 exp_type Experimenter defined
5730 data Experimenter defined additional data
5731 ================ ======================================================
5734 def __init__(self, datapath, flags,
5735 experimenter, exp_type, data,
5737 super(OFPExperimenterStatsRequest, self).__init__(datapath, flags,
5742 def _serialize_stats_body(self):
5743 body = OFPExperimenterMultipart(experimenter=self.experimenter,
5744 exp_type=self.exp_type,
5746 self.buf += body.serialize()
5749 # NOTE: we use OFPMatch while on-wire does not ofp_match.
5750 # (OF1.4 version uses ofp_match.)
5751 class ONFFlowMonitorRequest(StringifyMixin):
5752 def __init__(self, id_, flags,
5754 out_port=ofproto.OFPP_ANY,
5755 table_id=ofproto.OFPTT_ALL,
5759 self.match_len = match_len
5760 self.out_port = out_port
5761 self.table_id = table_id
5764 def serialize(self):
5767 bin_match = bytearray()
5768 ofp_match_len = match.serialize(bin_match, 0)
5769 assert len(bin_match) == ofp_match_len
5770 match_len = match.length
5771 match_hdr_len = ofproto.OFP_MATCH_SIZE - 4 # exclude pad[4]
5772 # strip ofp_match header and trailing padding
5773 bin_match = bytes(bin_match)[match_hdr_len:match_len]
5774 self.match_len = len(bin_match)
5777 msg_pack_into(ofproto.ONF_FLOW_MONITOR_REQUEST_PACK_STR,
5779 self.id, self.flags, self.match_len,
5780 self.out_port, self.table_id)
5782 pad_len = utils.round_up(self.match_len, 8) - self.match_len
5783 buf += pad_len * b'\0'
5787 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
5788 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
5789 class ONFFlowMonitorStatsRequest(OFPExperimenterStatsRequestBase):
5791 ================ ======================================================
5792 Attribute Description
5793 ================ ======================================================
5794 flags Zero or ``OFPMPF_REQ_MORE``
5795 body List of ONFFlowMonitorRequest instances
5796 ================ ======================================================
5799 def __init__(self, datapath, flags, body=None,
5800 type_=None, experimenter=None, exp_type=None):
5801 body = body if body else []
5802 super(ONFFlowMonitorStatsRequest,
5803 self).__init__(datapath, flags,
5804 experimenter=ofproto_common.ONF_EXPERIMENTER_ID,
5805 exp_type=ofproto.ONFMP_FLOW_MONITOR)
5808 def _serialize_stats_body(self):
5811 data += i.serialize()
5812 body = OFPExperimenterMultipart(experimenter=self.experimenter,
5813 exp_type=self.exp_type,
5815 self.buf += body.serialize()
5818 @OFPMultipartReply.register_stats_type(body_single_struct=True)
5819 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
5820 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
5821 class OFPExperimenterStatsReply(OFPMultipartReply):
5823 Experimenter multipart reply message
5825 ================ ======================================================
5826 Attribute Description
5827 ================ ======================================================
5828 body An ``OFPExperimenterMultipart`` instance
5829 ================ ======================================================
5832 def __init__(self, datapath, type_=None, **kwargs):
5833 super(OFPExperimenterStatsReply, self).__init__(datapath, **kwargs)
5836 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
5837 class OFPBarrierRequest(MsgBase):
5839 Barrier request message
5841 The controller sends this message to ensure message dependencies have
5842 been met or receive notifications for completed operations.
5846 def send_barrier_request(self, datapath):
5847 ofp_parser = datapath.ofproto_parser
5849 req = ofp_parser.OFPBarrierRequest(datapath)
5850 datapath.send_msg(req)
5853 def __init__(self, datapath):
5854 super(OFPBarrierRequest, self).__init__(datapath)
5858 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
5859 class OFPBarrierReply(MsgBase):
5861 Barrier reply message
5863 The switch responds with this message to a barrier request.
5867 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
5868 def barrier_reply_handler(self, ev):
5869 self.logger.debug('OFPBarrierReply received')
5872 def __init__(self, datapath):
5873 super(OFPBarrierReply, self).__init__(datapath)
5876 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST)
5877 class OFPQueueGetConfigRequest(MsgBase):
5879 Queue configuration request message
5881 ================ ======================================================
5882 Attribute Description
5883 ================ ======================================================
5884 port Port to be queried (OFPP_ANY to all configured queues)
5885 ================ ======================================================
5889 def send_queue_get_config_request(self, datapath):
5890 ofp = datapath.ofproto
5891 ofp_parser = datapath.ofproto_parser
5893 req = ofp_parser.OFPQueueGetConfigRequest(datapath, ofp.OFPP_ANY)
5894 datapath.send_msg(req)
5897 def __init__(self, datapath, port):
5898 super(OFPQueueGetConfigRequest, self).__init__(datapath)
5901 def _serialize_body(self):
5902 msg_pack_into(ofproto.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR,
5903 self.buf, ofproto.OFP_HEADER_SIZE, self.port)
5906 class OFPQueuePropHeader(StringifyMixin):
5907 def __init__(self, property_, len_):
5908 self.property = property_
5911 def serialize(self, buf, offset):
5912 msg_pack_into(ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
5913 buf, offset, self.property, self.len)
5916 class OFPQueueProp(OFPQueuePropHeader):
5917 _QUEUE_PROP_PROPERTIES = {}
5920 def register_property(property_, len_=None):
5921 def _register_property(cls):
5922 cls.cls_property = property_
5924 OFPQueueProp._QUEUE_PROP_PROPERTIES[property_] = cls
5926 return _register_property
5929 cls = self.__class__
5930 super(OFPQueueProp, self).__init__(cls.cls_property,
5934 def parser(cls, buf, offset):
5935 (property_, len_) = struct.unpack_from(
5936 ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR,
5938 cls_ = cls._QUEUE_PROP_PROPERTIES.get(property_)
5939 p = cls_.parser(buf, offset + ofproto.OFP_QUEUE_PROP_HEADER_SIZE)
5940 p.property = property_
5942 if property_ == ofproto.OFPQT_EXPERIMENTER:
5943 rest = buf[offset + ofproto.OFP_QUEUE_PROP_EXPERIMENTER_SIZE:
5945 p.parse_experimenter_data(rest)
5949 @OFPQueueProp.register_property(ofproto.OFPQT_MIN_RATE,
5950 ofproto.OFP_QUEUE_PROP_MIN_RATE_SIZE)
5951 class OFPQueuePropMinRate(OFPQueueProp):
5952 def __init__(self, rate, property_=None, len_=None):
5953 super(OFPQueuePropMinRate, self).__init__()
5957 def parser(cls, buf, offset):
5958 (rate,) = struct.unpack_from(
5959 ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, buf, offset)
5963 @OFPQueueProp.register_property(ofproto.OFPQT_MAX_RATE,
5964 ofproto.OFP_QUEUE_PROP_MAX_RATE_SIZE)
5965 class OFPQueuePropMaxRate(OFPQueueProp):
5966 def __init__(self, rate, property_=None, len_=None):
5967 super(OFPQueuePropMaxRate, self).__init__()
5971 def parser(cls, buf, offset):
5972 (rate,) = struct.unpack_from(
5973 ofproto.OFP_QUEUE_PROP_MAX_RATE_PACK_STR, buf, offset)
5977 @OFPQueueProp.register_property(ofproto.OFPQT_EXPERIMENTER)
5978 class OFPQueuePropExperimenter(OFPQueueProp):
5979 _EXPERIMENTER_DATA_PACK_STR = '!B'
5980 _EXPERIMENTER_DATA_SIZE = 1
5982 def __init__(self, experimenter, data=None, property_=None, len_=None):
5983 super(OFPQueuePropExperimenter, self).__init__()
5984 self.experimenter = experimenter
5988 def parser(cls, buf, offset):
5989 (experimenter,) = struct.unpack_from(
5990 ofproto.OFP_QUEUE_PROP_EXPERIMENTER_PACK_STR, buf, offset)
5991 return cls(experimenter)
5993 def parse_experimenter_data(self, rest):
5996 (d,) = struct.unpack_from(
5997 self._EXPERIMENTER_DATA_PACK_STR, rest, 0)
5999 rest = rest[self._EXPERIMENTER_DATA_SIZE:]
6003 class OFPPacketQueue(StringifyMixin):
6004 def __init__(self, queue_id, port, properties, len_=None):
6005 super(OFPPacketQueue, self).__init__()
6006 self.queue_id = queue_id
6009 self.properties = properties
6012 def parser(cls, buf, offset):
6013 (queue_id, port, len_) = struct.unpack_from(
6014 ofproto.OFP_PACKET_QUEUE_PACK_STR, buf, offset)
6015 length = ofproto.OFP_PACKET_QUEUE_SIZE
6016 offset += ofproto.OFP_PACKET_QUEUE_SIZE
6018 while length < len_:
6019 queue_prop = OFPQueueProp.parser(buf, offset)
6020 properties.append(queue_prop)
6021 offset += queue_prop.len
6022 length += queue_prop.len
6023 o = cls(queue_id, port, properties)
6029 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY)
6030 class OFPQueueGetConfigReply(MsgBase):
6032 Queue configuration reply message
6034 The switch responds with this message to a queue configuration request.
6036 ================ ======================================================
6037 Attribute Description
6038 ================ ======================================================
6039 queues list of ``OFPPacketQueue`` instance
6040 port Port which was queried
6041 ================ ======================================================
6045 @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
6046 def queue_get_config_reply_handler(self, ev):
6049 self.logger.debug('OFPQueueGetConfigReply received: '
6050 'port=%s queues=%s',
6051 msg.port, msg.queues)
6054 def __init__(self, datapath, queues=None, port=None):
6055 super(OFPQueueGetConfigReply, self).__init__(datapath)
6056 self.queues = queues
6060 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6061 msg = super(OFPQueueGetConfigReply, cls).parser(datapath, version,
6064 (msg.port,) = struct.unpack_from(
6065 ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf,
6066 ofproto.OFP_HEADER_SIZE)
6069 offset = ofproto.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
6070 while offset < msg_len:
6071 queue = OFPPacketQueue.parser(msg.buf, offset)
6072 msg.queues.append(queue)
6078 @_set_msg_type(ofproto.OFPT_ROLE_REQUEST)
6079 class OFPRoleRequest(MsgBase):
6081 Role request message
6083 The controller uses this message to change its role.
6085 ================ ======================================================
6086 Attribute Description
6087 ================ ======================================================
6088 role One of the following values.
6090 | OFPCR_ROLE_NOCHANGE
6094 generation_id Master Election Generation ID
6095 ================ ======================================================
6099 def send_role_request(self, datapath):
6100 ofp = datapath.ofproto
6101 ofp_parser = datapath.ofproto_parser
6103 req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
6104 datapath.send_msg(req)
6107 def __init__(self, datapath, role=None, generation_id=None):
6108 super(OFPRoleRequest, self).__init__(datapath)
6110 self.generation_id = generation_id
6112 def _serialize_body(self):
6113 assert self.role is not None
6114 assert self.generation_id is not None
6115 msg_pack_into(ofproto.OFP_ROLE_REQUEST_PACK_STR,
6116 self.buf, ofproto.OFP_HEADER_SIZE,
6117 self.role, self.generation_id)
6121 @_set_msg_type(ofproto.OFPT_ROLE_REPLY)
6122 class OFPRoleReply(MsgBase):
6126 The switch responds with this message to a role request.
6128 ================ ======================================================
6129 Attribute Description
6130 ================ ======================================================
6131 role One of the following values.
6133 | OFPCR_ROLE_NOCHANGE
6137 generation_id Master Election Generation ID
6138 ================ ======================================================
6142 @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
6143 def role_reply_handler(self, ev):
6148 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
6150 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
6152 elif msg.role == ofp.OFPCR_ROLE_MASTER:
6154 elif msg.role == ofp.OFPCR_ROLE_SLAVE:
6159 self.logger.debug('OFPRoleReply received: '
6160 'role=%s generation_id=%d',
6161 role, msg.generation_id)
6164 def __init__(self, datapath, role=None, generation_id=None):
6165 super(OFPRoleReply, self).__init__(datapath)
6167 self.generation_id = generation_id
6170 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6171 msg = super(OFPRoleReply, cls).parser(datapath, version,
6172 msg_type, msg_len, xid,
6174 (msg.role, msg.generation_id) = struct.unpack_from(
6175 ofproto.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
6176 ofproto.OFP_HEADER_SIZE)
6180 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REQUEST)
6181 class OFPGetAsyncRequest(MsgBase):
6183 Get asynchronous configuration request message
6185 The controller uses this message to query the asynchronous message.
6189 def send_get_async_request(self, datapath):
6190 ofp_parser = datapath.ofproto_parser
6192 req = ofp_parser.OFPGetAsyncRequest(datapath)
6193 datapath.send_msg(req)
6196 def __init__(self, datapath):
6197 super(OFPGetAsyncRequest, self).__init__(datapath)
6201 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REPLY)
6202 class OFPGetAsyncReply(MsgBase):
6204 Get asynchronous configuration reply message
6206 The switch responds with this message to a get asynchronous configuration
6209 ================== ====================================================
6210 Attribute Description
6211 ================== ====================================================
6212 packet_in_mask 2-element array: element 0, when the controller has a
6213 OFPCR_ROLE_EQUAL or OFPCR_ROLE_MASTER role. element 1,
6214 OFPCR_ROLE_SLAVE role controller.
6215 Bitmasks of following values.
6220 port_status_mask 2-element array.
6221 Bitmasks of following values.
6226 flow_removed_mask 2-element array.
6227 Bitmasks of following values.
6229 | OFPRR_IDLE_TIMEOUT
6230 | OFPRR_HARD_TIMEOUT
6232 | OFPRR_GROUP_DELETE
6233 ================== ====================================================
6237 @set_ev_cls(ofp_event.EventOFPGetAsyncReply, MAIN_DISPATCHER)
6238 def get_async_reply_handler(self, ev):
6241 self.logger.debug('OFPGetAsyncReply received: '
6242 'packet_in_mask=0x%08x:0x%08x '
6243 'port_status_mask=0x%08x:0x%08x '
6244 'flow_removed_mask=0x%08x:0x%08x',
6245 msg.packet_in_mask[0],
6246 msg.packet_in_mask[1],
6247 msg.port_status_mask[0],
6248 msg.port_status_mask[1],
6249 msg.flow_removed_mask[0],
6250 msg.flow_removed_mask[1])
6253 def __init__(self, datapath, packet_in_mask=None, port_status_mask=None,
6254 flow_removed_mask=None):
6255 super(OFPGetAsyncReply, self).__init__(datapath)
6256 self.packet_in_mask = packet_in_mask
6257 self.port_status_mask = port_status_mask
6258 self.flow_removed_mask = flow_removed_mask
6261 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6262 msg = super(OFPGetAsyncReply, cls).parser(datapath, version,
6265 (packet_in_mask_m, packet_in_mask_s,
6266 port_status_mask_m, port_status_mask_s,
6267 flow_removed_mask_m, flow_removed_mask_s) = struct.unpack_from(
6268 ofproto.OFP_ASYNC_CONFIG_PACK_STR, msg.buf,
6269 ofproto.OFP_HEADER_SIZE)
6270 msg.packet_in_mask = [packet_in_mask_m, packet_in_mask_s]
6271 msg.port_status_mask = [port_status_mask_m, port_status_mask_s]
6272 msg.flow_removed_mask = [flow_removed_mask_m, flow_removed_mask_s]
6276 @_set_msg_type(ofproto.OFPT_SET_ASYNC)
6277 class OFPSetAsync(MsgBase):
6279 Set asynchronous configuration message
6281 The controller sends this message to set the asynchronous messages that
6282 it wants to receive on a given OpneFlow channel.
6284 ================== ====================================================
6285 Attribute Description
6286 ================== ====================================================
6287 packet_in_mask 2-element array: element 0, when the controller has a
6288 OFPCR_ROLE_EQUAL or OFPCR_ROLE_MASTER role. element 1,
6289 OFPCR_ROLE_SLAVE role controller.
6290 Bitmasks of following values.
6295 port_status_mask 2-element array.
6296 Bitmasks of following values.
6301 flow_removed_mask 2-element array.
6302 Bitmasks of following values.
6304 | OFPRR_IDLE_TIMEOUT
6305 | OFPRR_HARD_TIMEOUT
6307 | OFPRR_GROUP_DELETE
6308 ================== ====================================================
6312 def send_set_async(self, datapath):
6313 ofp = datapath.ofproto
6314 ofp_parser = datapath.ofproto_parser
6316 packet_in_mask = 1 << ofp.OFPR_ACTION | 1 << ofp.OFPR_INVALID_TTL
6317 port_status_mask = (1 << ofp.OFPPR_ADD
6318 | 1 << ofp.OFPPR_DELETE
6319 | 1 << ofp.OFPPR_MODIFY)
6320 flow_removed_mask = (1 << ofp.OFPRR_IDLE_TIMEOUT
6321 | 1 << ofp.OFPRR_HARD_TIMEOUT
6322 | 1 << ofp.OFPRR_DELETE)
6323 req = ofp_parser.OFPSetAsync(datapath,
6324 [packet_in_mask, 0],
6325 [port_status_mask, 0],
6326 [flow_removed_mask, 0])
6327 datapath.send_msg(req)
6330 def __init__(self, datapath,
6331 packet_in_mask, port_status_mask, flow_removed_mask):
6332 super(OFPSetAsync, self).__init__(datapath)
6333 self.packet_in_mask = packet_in_mask
6334 self.port_status_mask = port_status_mask
6335 self.flow_removed_mask = flow_removed_mask
6337 def _serialize_body(self):
6338 msg_pack_into(ofproto.OFP_ASYNC_CONFIG_PACK_STR, self.buf,
6339 ofproto.OFP_HEADER_SIZE,
6340 self.packet_in_mask[0], self.packet_in_mask[1],
6341 self.port_status_mask[0], self.port_status_mask[1],
6342 self.flow_removed_mask[0], self.flow_removed_mask[1])
6345 @_register_exp_type(ofproto_common.ONF_EXPERIMENTER_ID,
6346 ofproto.ONF_ET_BUNDLE_CONTROL)
6347 class ONFBundleCtrlMsg(OFPExperimenter):
6349 Bundle control message
6351 The controller uses this message to create, destroy and commit bundles
6353 ================ ======================================================
6354 Attribute Description
6355 ================ ======================================================
6356 bundle_id Id of the bundle
6357 type One of the following values.
6359 | ONF_BCT_OPEN_REQUEST
6360 | ONF_BCT_OPEN_REPLY
6361 | ONF_BCT_CLOSE_REQUEST
6362 | ONF_BCT_CLOSE_REPLY
6363 | ONF_BCT_COMMIT_REQUEST
6364 | ONF_BCT_COMMIT_REPLY
6365 | ONF_BCT_DISCARD_REQUEST
6366 | ONF_BCT_DISCARD_REPLY
6367 flags Bitmap of the following flags.
6371 properties List of ``OFPBundleProp`` subclass instance
6372 ================ ======================================================
6376 def send_bundle_control(self, datapath):
6377 ofp = datapath.ofproto
6378 ofp_parser = datapath.ofproto_parser
6380 req = ofp_parser.ONFBundleCtrlMsg(datapath, 7,
6381 ofp.ONF_BCT_OPEN_REQUEST,
6382 ofp.ONF_BF_ATOMIC, [])
6383 datapath.send_msg(req)
6386 def __init__(self, datapath, bundle_id=None, type_=None, flags=None,
6388 super(ONFBundleCtrlMsg, self).__init__(
6389 datapath, ofproto_common.ONF_EXPERIMENTER_ID,
6390 ofproto.ONF_ET_BUNDLE_CONTROL)
6391 self.bundle_id = bundle_id
6394 self.properties = properties
6396 def _serialize_body(self):
6397 bin_props = bytearray()
6398 for p in self.properties:
6399 bin_props += p.serialize()
6401 msg_pack_into(ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR,
6402 self.buf, ofproto.OFP_HEADER_SIZE,
6403 self.experimenter, self.exp_type)
6404 msg_pack_into(ofproto.ONF_BUNDLE_CTRL_PACK_STR,
6405 self.buf, ofproto.OFP_EXPERIMENTER_HEADER_SIZE,
6406 self.bundle_id, self.type, self.flags)
6407 self.buf += bin_props
6410 def parser_subtype(cls, super_msg):
6411 (bundle_id, type_, flags) = struct.unpack_from(
6412 ofproto.ONF_BUNDLE_CTRL_PACK_STR, super_msg.data)
6413 msg = cls(super_msg.datapath, bundle_id, type_, flags)
6415 rest = super_msg.data[ofproto.ONF_BUNDLE_CTRL_SIZE:]
6417 p, rest = OFPBundleProp.parse(rest)
6418 msg.properties.append(p)
6423 class ONFBundleAddMsg(OFPExperimenter):
6427 The controller uses this message to add a message to a bundle
6429 ================ ======================================================
6430 Attribute Description
6431 ================ ======================================================
6432 bundle_id Id of the bundle
6433 flags Bitmap of the following flags.
6437 message ``MsgBase`` subclass instance
6438 properties List of ``OFPBundleProp`` subclass instance
6439 ================ ======================================================
6443 def send_bundle_add_message(self, datapath):
6444 ofp = datapath.ofproto
6445 ofp_parser = datapath.ofproto_parser
6447 msg = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
6449 req = ofp_parser.OFPBundleAddMsg(datapath, 7, ofp.ONF_BF_ATOMIC,
6451 datapath.send_msg(req)
6454 def __init__(self, datapath, bundle_id, flags, message, properties):
6455 super(ONFBundleAddMsg, self).__init__(
6456 datapath, ofproto_common.ONF_EXPERIMENTER_ID,
6457 ofproto.ONF_ET_BUNDLE_ADD_MESSAGE)
6458 self.bundle_id = bundle_id
6460 self.message = message
6461 self.properties = properties
6463 def _serialize_body(self):
6464 # The xid of the inner message must be the same as
6465 # that of the outer message (OF1.3 Bundle Extension 3.3)
6466 if self.message.xid != self.xid:
6467 self.message.set_xid(self.xid)
6470 self.message.serialize()
6471 tail_buf = self.message.buf
6474 if len(self.properties) > 0:
6475 message_len = len(tail_buf)
6476 pad_len = utils.round_up(message_len, 8) - message_len
6477 msg_pack_into("%dx" % pad_len, tail_buf, message_len)
6480 for p in self.properties:
6481 tail_buf += p.serialize()
6484 msg_pack_into(ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR,
6485 self.buf, ofproto.OFP_HEADER_SIZE,
6486 self.experimenter, self.exp_type)
6487 msg_pack_into(ofproto.ONF_BUNDLE_ADD_MSG_PACK_STR,
6488 self.buf, ofproto.OFP_EXPERIMENTER_HEADER_SIZE,
6489 self.bundle_id, self.flags)
6492 self.buf += tail_buf
6495 nx_actions.generate(
6496 'ryu.ofproto.ofproto_v1_3',
6497 'ryu.ofproto.ofproto_v1_3_parser'