1 # Copyright (C) 2012, 2013, 2014 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 Decoder/Encoder implementations of OpenFlow 1.5.
26 from ryu.lib import addrconv
27 from ryu.lib.pack_utils import msg_pack_into
28 from ryu.lib.packet import packet
29 from ryu import exception
31 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase, MsgInMsgBase
32 from ryu.ofproto import ether
33 from ryu.ofproto import nx_actions
34 from ryu.ofproto import ofproto_parser
35 from ryu.ofproto import ofproto_common
36 from ryu.ofproto import ofproto_v1_5 as ofproto
41 def _set_msg_type(msg_type):
42 def _set_cls_msg_type(cls):
43 cls.cls_msg_type = msg_type
45 return _set_cls_msg_type
48 def _register_parser(cls):
49 '''class decorator to register msg parser'''
50 assert cls.cls_msg_type is not None
51 assert cls.cls_msg_type not in _MSG_PARSERS
52 _MSG_PARSERS[cls.cls_msg_type] = cls.parser
56 @ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
57 def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
58 parser = _MSG_PARSERS.get(msg_type)
59 return parser(datapath, version, msg_type, msg_len, xid, buf)
63 @_set_msg_type(ofproto.OFPT_HELLO)
64 class OFPHello(MsgBase):
68 When connection is started, the hello message is exchanged between a
69 switch and a controller.
71 This message is handled by the Ryu framework, so the Ryu application
72 do not need to process this typically.
74 ========== =========================================================
76 ========== =========================================================
77 elements list of ``OFPHelloElemVersionBitmap`` instance
78 ========== =========================================================
81 def __init__(self, datapath, elements=None):
82 elements = elements if elements else []
83 super(OFPHello, self).__init__(datapath)
84 self.elements = elements
87 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
88 msg = super(OFPHello, cls).parser(datapath, version, msg_type,
91 offset = ofproto.OFP_HELLO_HEADER_SIZE
93 while offset < msg.msg_len:
94 type_, length = struct.unpack_from(
95 ofproto.OFP_HELLO_ELEM_HEADER_PACK_STR, msg.buf, offset)
97 # better to register Hello Element classes but currently
98 # Only VerisonBitmap is supported so let's be simple.
100 if type_ == ofproto.OFPHET_VERSIONBITMAP:
101 elem = OFPHelloElemVersionBitmap.parser(msg.buf, offset)
109 class OFPHelloElemVersionBitmap(StringifyMixin):
111 Version bitmap Hello Element
113 ========== =========================================================
114 Attribute Description
115 ========== =========================================================
116 versions list of versions of OpenFlow protocol a device supports
117 ========== =========================================================
120 def __init__(self, versions, type_=None, length=None):
121 super(OFPHelloElemVersionBitmap, self).__init__()
122 self.type = ofproto.OFPHET_VERSIONBITMAP
125 self.versions = versions
128 def parser(cls, buf, offset):
129 type_, length = struct.unpack_from(
130 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_PACK_STR,
132 assert type_ == ofproto.OFPHET_VERSIONBITMAP
134 bitmaps_len = (length -
135 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE)
136 offset += ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE
138 while bitmaps_len >= 4:
139 bitmap = struct.unpack_from('!I', buf, offset)
140 bitmaps.append(bitmap[0])
144 versions = [i * 32 + shift
145 for i, bitmap in enumerate(bitmaps)
146 for shift in range(31) if bitmap & (1 << shift)]
149 elem._bitmaps = bitmaps
154 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
155 class OFPEchoRequest(MsgBase):
159 This message is handled by the Ryu framework, so the Ryu application
160 do not need to process this typically.
162 ========== =========================================================
163 Attribute Description
164 ========== =========================================================
165 data An arbitrary length data
166 ========== =========================================================
170 def send_echo_request(self, datapath, data):
171 ofp_parser = datapath.ofproto_parser
173 req = ofp_parser.OFPEchoRequest(datapath, data)
174 datapath.send_msg(req)
176 @set_ev_cls(ofp_event.EventOFPEchoRequest,
177 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
178 def echo_request_handler(self, ev):
179 self.logger.debug('OFPEchoRequest received: data=%s',
180 utils.hex_array(ev.msg.data))
183 def __init__(self, datapath, data=None):
184 super(OFPEchoRequest, self).__init__(datapath)
188 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
189 msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
191 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
194 def _serialize_body(self):
195 if self.data is not None:
196 self.buf += self.data
200 @_set_msg_type(ofproto.OFPT_ERROR)
201 class OFPErrorMsg(MsgBase):
205 The switch notifies controller of problems by this message.
207 ========== =========================================================
208 Attribute Description
209 ========== =========================================================
210 type High level type of error
211 code Details depending on the type
212 data Variable length data depending on the type and code
213 ========== =========================================================
215 ``type`` attribute corresponds to ``type_`` parameter of __init__.
217 Types and codes are defined in ``ryu.ofproto.ofproto``.
219 ============================= ===========
221 ============================= ===========
222 OFPET_HELLO_FAILED OFPHFC_*
223 OFPET_BAD_REQUEST OFPBRC_*
224 OFPET_BAD_ACTION OFPBAC_*
225 OFPET_BAD_INSTRUCTION OFPBIC_*
226 OFPET_BAD_MATCH OFPBMC_*
227 OFPET_FLOW_MOD_FAILED OFPFMFC_*
228 OFPET_GROUP_MOD_FAILED OFPGMFC_*
229 OFPET_PORT_MOD_FAILED OFPPMFC_*
230 OFPET_TABLE_MOD_FAILED OFPTMFC_*
231 OFPET_QUEUE_OP_FAILED OFPQOFC_*
232 OFPET_SWITCH_CONFIG_FAILED OFPSCFC_*
233 OFPET_ROLE_REQUEST_FAILED OFPRRFC_*
234 OFPET_METER_MOD_FAILED OFPMMFC_*
235 OFPET_TABLE_FEATURES_FAILED OFPTFFC_*
236 OFPET_EXPERIMENTER N/A
237 ============================= ===========
239 If ``type == OFPET_EXPERIMENTER``, this message has also the following
242 ============= ======================================================
243 Attribute Description
244 ============= ======================================================
245 exp_type Experimenter defined type
246 experimenter Experimenter ID
247 ============= ======================================================
251 @set_ev_cls(ofp_event.EventOFPErrorMsg,
252 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
253 def error_msg_handler(self, ev):
256 self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
258 msg.type, msg.code, utils.hex_array(msg.data))
261 def __init__(self, datapath, type_=None, code=None, data=None, **kwargs):
262 super(OFPErrorMsg, self).__init__(datapath)
265 if isinstance(data, six.string_types):
266 data = data.encode('ascii')
268 if self.type == ofproto.OFPET_EXPERIMENTER:
269 self.exp_type = kwargs.get('exp_type', None)
270 self.experimenter = kwargs.get('experimenter', None)
273 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
274 type_, = struct.unpack_from('!H', six.binary_type(buf),
275 ofproto.OFP_HEADER_SIZE)
276 msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
278 if type_ == ofproto.OFPET_EXPERIMENTER:
279 (msg.type, msg.exp_type, msg.experimenter,
280 msg.data) = cls.parse_experimenter_body(buf)
283 msg.data) = cls.parse_body(buf)
287 def parse_body(cls, buf):
288 type_, code = struct.unpack_from(
289 ofproto.OFP_ERROR_MSG_PACK_STR, buf,
290 ofproto.OFP_HEADER_SIZE)
291 data = buf[ofproto.OFP_ERROR_MSG_SIZE:]
292 return type_, code, data
295 def parse_experimenter_body(cls, buf):
296 type_, exp_type, experimenter = struct.unpack_from(
297 ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR, buf,
298 ofproto.OFP_HEADER_SIZE)
299 data = buf[ofproto.OFP_ERROR_EXPERIMENTER_MSG_SIZE:]
300 return type_, exp_type, experimenter, data
302 def _serialize_body(self):
303 assert self.data is not None
304 if self.type == ofproto.OFPET_EXPERIMENTER:
305 msg_pack_into(ofproto.OFP_ERROR_EXPERIMENTER_MSG_PACK_STR,
306 self.buf, ofproto.OFP_HEADER_SIZE,
307 self.type, self.exp_type, self.experimenter)
308 self.buf += self.data
310 msg_pack_into(ofproto.OFP_ERROR_MSG_PACK_STR,
311 self.buf, ofproto.OFP_HEADER_SIZE,
312 self.type, self.code)
313 self.buf += self.data
316 # For the backward compatibility
317 def OFPErrorExperimenterMsg(datapath, type_=None, exp_type=None,
318 experimenter=None, data=None):
319 msg = OFPErrorMsg(datapath, data=data)
320 msg.type = ofproto.OFPET_EXPERIMENTER
321 msg.exp_type = exp_type
322 msg.experimenter = experimenter
327 @_set_msg_type(ofproto.OFPT_ECHO_REPLY)
328 class OFPEchoReply(MsgBase):
332 This message is handled by the Ryu framework, so the Ryu application
333 do not need to process this typically.
335 ========== =========================================================
336 Attribute Description
337 ========== =========================================================
338 data An arbitrary length data
339 ========== =========================================================
343 def send_echo_reply(self, datapath, data):
344 ofp_parser = datapath.ofproto_parser
346 reply = ofp_parser.OFPEchoReply(datapath, data)
347 datapath.send_msg(reply)
349 @set_ev_cls(ofp_event.EventOFPEchoReply,
350 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
351 def echo_reply_handler(self, ev):
352 self.logger.debug('OFPEchoReply received: data=%s',
353 utils.hex_array(ev.msg.data))
356 def __init__(self, datapath, data=None):
357 super(OFPEchoReply, self).__init__(datapath)
361 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
362 msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
364 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
367 def _serialize_body(self):
368 assert self.data is not None
369 self.buf += self.data
372 @_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
373 class OFPFeaturesRequest(MsgBase):
375 Features request message
377 The controller sends a feature request to the switch upon session
380 This message is handled by the Ryu framework, so the Ryu application
381 do not need to process this typically.
385 def send_features_request(self, datapath):
386 ofp_parser = datapath.ofproto_parser
388 req = ofp_parser.OFPFeaturesRequest(datapath)
389 datapath.send_msg(req)
392 def __init__(self, datapath):
393 super(OFPFeaturesRequest, self).__init__(datapath)
397 @_set_msg_type(ofproto.OFPT_EXPERIMENTER)
398 class OFPExperimenter(MsgBase):
400 Experimenter extension message
402 ============= =========================================================
403 Attribute Description
404 ============= =========================================================
405 experimenter Experimenter ID
406 exp_type Experimenter defined
407 data Experimenter defined arbitrary additional data
408 ============= =========================================================
411 def __init__(self, datapath, experimenter=None, exp_type=None, data=None):
412 super(OFPExperimenter, self).__init__(datapath)
413 self.experimenter = experimenter
414 self.exp_type = exp_type
418 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
419 msg = super(OFPExperimenter, cls).parser(datapath, version,
422 (msg.experimenter, msg.exp_type) = struct.unpack_from(
423 ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR, msg.buf,
424 ofproto.OFP_HEADER_SIZE)
425 msg.data = msg.buf[ofproto.OFP_EXPERIMENTER_HEADER_SIZE:]
429 def _serialize_body(self):
430 assert self.data is not None
431 msg_pack_into(ofproto.OFP_EXPERIMENTER_HEADER_PACK_STR,
432 self.buf, ofproto.OFP_HEADER_SIZE,
433 self.experimenter, self.exp_type)
434 self.buf += self.data
438 @_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
439 class OFPSwitchFeatures(MsgBase):
441 Features reply message
443 The switch responds with a features reply message to a features
446 This message is handled by the Ryu framework, so the Ryu application
447 do not need to process this typically.
451 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
452 def switch_features_handler(self, ev):
455 self.logger.debug('OFPSwitchFeatures received: '
456 'datapath_id=0x%016x n_buffers=%d '
457 'n_tables=%d auxiliary_id=%d '
458 'capabilities=0x%08x',
459 msg.datapath_id, msg.n_buffers, msg.n_tables,
460 msg.auxiliary_id, msg.capabilities)
463 def __init__(self, datapath, datapath_id=None, n_buffers=None,
464 n_tables=None, auxiliary_id=None, capabilities=None):
465 super(OFPSwitchFeatures, self).__init__(datapath)
466 self.datapath_id = datapath_id
467 self.n_buffers = n_buffers
468 self.n_tables = n_tables
469 self.auxiliary_id = auxiliary_id
470 self.capabilities = capabilities
473 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
474 msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
481 msg._reserved) = struct.unpack_from(
482 ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
483 ofproto.OFP_HEADER_SIZE)
487 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
488 class OFPGetConfigRequest(MsgBase):
490 Get config request message
492 The controller sends a get config request to query configuration
493 parameters in the switch.
497 def send_get_config_request(self, datapath):
498 ofp_parser = datapath.ofproto_parser
500 req = ofp_parser.OFPGetConfigRequest(datapath)
501 datapath.send_msg(req)
504 def __init__(self, datapath):
505 super(OFPGetConfigRequest, self).__init__(datapath)
509 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
510 class OFPGetConfigReply(MsgBase):
512 Get config reply message
514 The switch responds to a configuration request with a get config reply
517 ============= =========================================================
518 Attribute Description
519 ============= =========================================================
520 flags Bitmap of the following flags.
525 miss_send_len Max bytes of new flow that datapath should send to the
527 ============= =========================================================
531 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
532 def get_config_reply_handler(self, ev):
538 if msg.flags & ofp.OFPC_FRAG_NORMAL:
539 flags.append('NORMAL')
540 if msg.flags & ofp.OFPC_FRAG_DROP:
542 if msg.flags & ofp.OFPC_FRAG_REASM:
543 flags.append('REASM')
544 self.logger.debug('OFPGetConfigReply received: '
545 'flags=%s miss_send_len=%d',
546 ','.join(flags), msg.miss_send_len)
549 def __init__(self, datapath, flags=None, miss_send_len=None):
550 super(OFPGetConfigReply, self).__init__(datapath)
552 self.miss_send_len = miss_send_len
555 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
556 msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
558 msg.flags, msg.miss_send_len = struct.unpack_from(
559 ofproto.OFP_SWITCH_CONFIG_PACK_STR, msg.buf,
560 ofproto.OFP_HEADER_SIZE)
564 @_set_msg_type(ofproto.OFPT_SET_CONFIG)
565 class OFPSetConfig(MsgBase):
567 Set config request message
569 The controller sends a set config request message to set configuraion
572 ============= =========================================================
573 Attribute Description
574 ============= =========================================================
575 flags Bitmap of the following flags.
580 miss_send_len Max bytes of new flow that datapath should send to the
582 ============= =========================================================
586 def send_set_config(self, datapath):
587 ofp = datapath.ofproto
588 ofp_parser = datapath.ofproto_parser
590 req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
591 datapath.send_msg(req)
594 def __init__(self, datapath, flags=0, miss_send_len=0):
595 super(OFPSetConfig, self).__init__(datapath)
597 self.miss_send_len = miss_send_len
599 def _serialize_body(self):
600 assert self.flags is not None
601 assert self.miss_send_len is not None
602 msg_pack_into(ofproto.OFP_SWITCH_CONFIG_PACK_STR,
603 self.buf, ofproto.OFP_HEADER_SIZE,
604 self.flags, self.miss_send_len)
607 class OFPMatch(StringifyMixin):
611 This class is implementation of the flow match structure having
614 You can define the flow match by the keyword arguments.
615 The following arguments are available.
617 ================ =============== ==================================
618 Argument Value Description
619 ================ =============== ==================================
620 in_port Integer 32bit Switch input port
621 in_phy_port Integer 32bit Switch physical input port
622 metadata Integer 64bit Metadata passed between tables
623 eth_dst MAC address Ethernet destination address
624 eth_src MAC address Ethernet source address
625 eth_type Integer 16bit Ethernet frame type
626 vlan_vid Integer 16bit VLAN id
627 vlan_pcp Integer 8bit VLAN priority
628 ip_dscp Integer 8bit IP DSCP (6 bits in ToS field)
629 ip_ecn Integer 8bit IP ECN (2 bits in ToS field)
630 ip_proto Integer 8bit IP protocol
631 ipv4_src IPv4 address IPv4 source address
632 ipv4_dst IPv4 address IPv4 destination address
633 tcp_src Integer 16bit TCP source port
634 tcp_dst Integer 16bit TCP destination port
635 udp_src Integer 16bit UDP source port
636 udp_dst Integer 16bit UDP destination port
637 sctp_src Integer 16bit SCTP source port
638 sctp_dst Integer 16bit SCTP destination port
639 icmpv4_type Integer 8bit ICMP type
640 icmpv4_code Integer 8bit ICMP code
641 arp_op Integer 16bit ARP opcode
642 arp_spa IPv4 address ARP source IPv4 address
643 arp_tpa IPv4 address ARP target IPv4 address
644 arp_sha MAC address ARP source hardware address
645 arp_tha MAC address ARP target hardware address
646 ipv6_src IPv6 address IPv6 source address
647 ipv6_dst IPv6 address IPv6 destination address
648 ipv6_flabel Integer 32bit IPv6 Flow Label
649 icmpv6_type Integer 8bit ICMPv6 type
650 icmpv6_code Integer 8bit ICMPv6 code
651 ipv6_nd_target IPv6 address Target address for ND
652 ipv6_nd_sll MAC address Source link-layer for ND
653 ipv6_nd_tll MAC address Target link-layer for ND
654 mpls_label Integer 32bit MPLS label
655 mpls_tc Integer 8bit MPLS TC
656 mpls_bos Integer 8bit MPLS BoS bit
657 pbb_isid Integer 24bit PBB I-SID
658 tunnel_id Integer 64bit Logical Port Metadata
659 ipv6_exthdr Integer 16bit IPv6 Extension Header pseudo-field
660 pbb_uca Integer 8bit PBB UCA header field
661 tcp_flags Integer 16bit TCP flags
662 actset_output Integer 32bit Output port from action set metadata
663 packet_type Integer 32bit Packet type value
664 ================ =============== ==================================
669 >>> match = parser.OFPMatch(
672 ... ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
673 ... 'ffff:ffff:ffff:ffff::'),
674 ... ipv6_dst='2001:db8:bd05:1d2:288a:1fc0:1:10ee')
676 >>> if 'ipv6_src' in match:
677 ... print match['ipv6_src']
679 ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::')
683 For the list of the supported Nicira experimenter matches,
684 please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`.
688 For VLAN id match field, special values are defined in OpenFlow Spec.
690 1) Packets with and without a VLAN tag
694 match = parser.OFPMatch()
698 ====================== =====
699 non-VLAN-tagged MATCH
700 VLAN-tagged(vlan_id=3) MATCH
701 VLAN-tagged(vlan_id=5) MATCH
702 ====================== =====
704 2) Only packets without a VLAN tag
708 match = parser.OFPMatch(vlan_vid=0x0000)
712 ====================== =====
713 non-VLAN-tagged MATCH
714 VLAN-tagged(vlan_id=3) x
715 VLAN-tagged(vlan_id=5) x
716 ====================== =====
718 3) Only packets with a VLAN tag regardless of its value
722 match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000))
726 ====================== =====
728 VLAN-tagged(vlan_id=3) MATCH
729 VLAN-tagged(vlan_id=5) MATCH
730 ====================== =====
732 4) Only packets with VLAN tag and VID equal
736 match = parser.OFPMatch(vlan_vid=(0x1000 | 3))
740 ====================== =====
742 VLAN-tagged(vlan_id=3) MATCH
743 VLAN-tagged(vlan_id=5) x
744 ====================== =====
747 def __init__(self, type_=None, length=None, _ordered_fields=None,
749 super(OFPMatch, self).__init__()
750 self.type = ofproto.OFPMT_OXM
753 if _ordered_fields is not None:
755 self._fields2 = _ordered_fields
757 kwargs = dict(ofproto.oxm_normalize_user(k, v) for
758 (k, v) in kwargs.items())
759 fields = [ofproto.oxm_from_user(k, v) for (k, v)
761 # assumption: sorting by OXM type values makes fields
762 # meet ordering requirements (eg. eth_type before ipv4_src)
764 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
765 self._fields2 = [ofproto.oxm_to_user(n, v, m) for (n, v, m)
769 def parser(cls, buf, offset):
771 Returns an object which is generated from a buffer including the
772 expression of the wire protocol of the flow match.
775 type_, length = struct.unpack_from('!HH', buf, offset)
778 match.length = length
780 # ofp_match adjustment
786 n, value, mask, field_len = ofproto.oxm_parse(buf, offset)
787 k, uv = ofproto.oxm_to_user(n, value, mask)
788 fields.append((k, uv))
791 match._fields2 = fields
794 def serialize(self, buf, offset):
796 Outputs the expression of the wire protocol of the flow match into
798 Returns the output length.
800 fields = [ofproto.oxm_from_user(k, uv) for (k, uv)
804 field_offset = offset + struct.calcsize(hdr_pack_str)
805 for (n, value, mask) in fields:
806 field_offset += ofproto.oxm_serialize(n, value, mask, buf,
809 length = field_offset - offset
810 msg_pack_into(hdr_pack_str, buf, offset, ofproto.OFPMT_OXM, length)
813 pad_len = utils.round_up(length, 8) - length
814 msg_pack_into("%dx" % pad_len, buf, field_offset)
816 return length + pad_len
818 def __getitem__(self, key):
819 return dict(self._fields2)[key]
821 def __contains__(self, key):
822 return key in dict(self._fields2)
825 return iter(dict(self._fields2).items())
830 def get(self, key, default=None):
831 return dict(self._fields2).get(key, default)
833 def stringify_attrs(self):
834 yield "oxm_fields", dict(self._fields2)
836 def to_jsondict(self):
838 Returns a dict expressing the flow match.
840 body = {"oxm_fields": [ofproto.oxm_to_jsondict(k, uv) for k, uv
842 "length": self.length,
844 return {self.__class__.__name__: body}
847 def from_jsondict(cls, dict_):
849 Returns an object which is generated from a dict.
852 KeyError -- Unknown match field is defined in dict
854 fields = [ofproto.oxm_from_jsondict(f) for f
855 in dict_['oxm_fields']]
856 return OFPMatch(_ordered_fields=fields)
859 class OFPStats(StringifyMixin):
863 This class is implementation of the flow stats structure having
866 You can define the flow stats by the keyword arguments.
867 The following arguments are available.
869 ============= ================ ============================================
870 Argument Value Description
871 ============= ================ ============================================
872 duration Integer 32bit*2 Time flow entry has been alive. This field
873 is a tuple of two Integer 32bit. The first
874 value is duration_sec and the second is
876 idle_time Integer 32bit*2 Time flow entry has been idle.
877 flow_count Integer 32bit Number of aggregated flow entries.
878 packet_count Integer 64bit Number of packets matched by a flow entry.
879 byte_count Integer 64bit Number of bytes matched by a flow entry.
880 ============= ================ ============================================
885 >>> stats = parser.OFPStats(
886 ... packet_count=100,
887 ... duration=(100, 200)
889 >>> if 'duration' in stats:
890 ... print stats['duration']
895 def __init__(self, length=None, _ordered_fields=None, **kwargs):
896 super(OFPStats, self).__init__()
899 if _ordered_fields is not None:
901 self.fields = _ordered_fields
903 fields = [ofproto.oxs_from_user(k, v) for (k, v)
905 # sort by OXS type values
907 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
909 self.fields = [ofproto.oxs_to_user(n, v, None) for (n, v, _)
913 def parser(cls, buf, offset):
915 Returns an object which is generated from a buffer including the
916 expression of the wire protocol of the flow stats.
919 reserved, length = struct.unpack_from('!HH', buf, offset)
921 stats.length = length
923 # ofp_stats adjustment
929 n, value, _, field_len = ofproto.oxs_parse(buf, offset)
930 k, uv = ofproto.oxs_to_user(n, value, None) # No mask
931 fields.append((k, uv))
934 stats.fields = fields
937 def serialize(self, buf, offset):
939 Outputs the expression of the wire protocol of the flow stats into
941 Returns the output length.
943 fields = [ofproto.oxs_from_user(k, uv) for (k, uv)
947 field_offset = offset + struct.calcsize(hdr_pack_str)
948 for (n, value, _) in fields:
950 field_offset += ofproto.oxs_serialize(n, value, None, buf,
954 length = field_offset - offset
955 msg_pack_into(hdr_pack_str, buf, offset, reserved, length)
958 pad_len = utils.round_up(length, 8) - length
959 msg_pack_into("%dx" % pad_len, buf, field_offset)
961 return length + pad_len
963 def __getitem__(self, key):
964 return dict(self.fields)[key]
966 def __contains__(self, key):
967 return key in dict(self.fields)
970 return dict(self.fields).items()
975 def get(self, key, default=None):
976 return dict(self.fields).get(key, default)
978 def stringify_attrs(self):
979 yield "oxs_fields", dict(self.fields)
981 def to_jsondict(self):
983 Returns a dict expressing the flow stats.
985 body = {"oxs_fields": [ofproto.oxs_to_jsondict(k, uv) for k, uv
987 "length": self.length}
988 return {self.__class__.__name__: body}
991 def from_jsondict(cls, dict_):
993 Returns an object which is generated from a dict.
996 KeyError -- Unknown stats field is defined in dict
998 fields = [ofproto.oxs_from_jsondict(f) for f
999 in dict_['oxs_fields']]
1000 return OFPStats(_ordered_fields=fields)
1003 class OFPPropUnknown(StringifyMixin):
1004 def __init__(self, type_=None, length=None, buf=None):
1008 def parser(cls, buf):
1012 class OFPPropBase(StringifyMixin):
1014 # _TYPES = {} must be an attribute of subclass
1016 def __init__(self, type_, length=None):
1018 self.length = length
1021 def register_type(cls, type_):
1022 def _register_type(subcls):
1023 cls._TYPES[type_] = subcls
1025 return _register_type
1028 def parse(cls, buf):
1029 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
1030 rest = buf[utils.round_up(length, 8):]
1032 subcls = cls._TYPES[type_]
1034 subcls = OFPPropUnknown
1035 prop = subcls.parser(buf)
1037 prop.length = length
1041 def get_rest(cls, buf):
1042 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
1043 offset = struct.calcsize(cls._PACK_STR)
1044 return buf[offset:length]
1046 def serialize(self):
1048 # serialize_body should be implemented by subclass
1050 body += self.serialize_body()
1053 self.length = len(body) + struct.calcsize(self._PACK_STR)
1057 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.length)
1061 pad_len = utils.round_up(self.length, 8) - self.length
1062 msg_pack_into("%dx" % pad_len, buf, len(buf))
1067 class OFPPropCommonExperimenter4ByteData(StringifyMixin):
1069 _EXPERIMENTER_DATA_PACK_STR = '!I'
1070 _EXPERIMENTER_DATA_SIZE = 4
1072 def __init__(self, type_=None, length=None, experimenter=None,
1073 exp_type=None, data=bytearray()):
1075 self.length = length
1076 self.experimenter = experimenter
1077 self.exp_type = exp_type
1081 def parser(cls, buf):
1082 (type_, length, experimenter, exp_type) = struct.unpack_from(
1083 ofproto.OFP_PROP_EXPERIMENTER_PACK_STR, buf, 0)
1085 rest = buf[ofproto.OFP_PROP_EXPERIMENTER_SIZE:length]
1088 (d,) = struct.unpack_from(
1089 cls._EXPERIMENTER_DATA_PACK_STR, rest, 0)
1091 rest = rest[cls._EXPERIMENTER_DATA_SIZE:]
1093 return cls(type_, length, experimenter, exp_type, data)
1095 def serialize(self):
1097 bin_data = bytearray()
1099 msg_pack_into(self._EXPERIMENTER_DATA_PACK_STR,
1100 bin_data, offset, d)
1101 offset += self._EXPERIMENTER_DATA_SIZE
1104 self.length = struct.calcsize(self._PACK_STR)
1105 self.length += len(bin_data)
1108 msg_pack_into(self._PACK_STR, buf,
1109 0, self.type, self.length, self.experimenter,
1114 pad_len = utils.round_up(self.length, 8) - self.length
1115 msg_pack_into("%dx" % pad_len, buf, len(buf))
1120 class OFPPortDescProp(OFPPropBase):
1124 @OFPPortDescProp.register_type(ofproto.OFPPDPT_ETHERNET)
1125 class OFPPortDescPropEthernet(OFPPortDescProp):
1126 def __init__(self, type_=None, length=None, curr=None, advertised=None,
1127 supported=None, peer=None, curr_speed=None, max_speed=None):
1129 self.length = length
1131 self.advertised = advertised
1132 self.supported = supported
1134 self.curr_speed = curr_speed
1135 self.max_speed = max_speed
1138 def parser(cls, buf):
1140 (ether.type, ether.length, ether.curr,
1141 ether.advertised, ether.supported,
1142 ether.peer, ether.curr_speed, ether.max_speed) = struct.unpack_from(
1143 ofproto.OFP_PORT_DESC_PROP_ETHERNET_PACK_STR, buf, 0)
1147 @OFPPortDescProp.register_type(ofproto.OFPPDPT_OPTICAL)
1148 class OFPPortDescPropOptical(OFPPortDescProp):
1149 def __init__(self, type_=None, length=None, supported=None,
1150 tx_min_freq_lmda=None, tx_max_freq_lmda=None,
1151 tx_grid_freq_lmda=None, rx_min_freq_lmda=None,
1152 rx_max_freq_lmda=None, rx_grid_freq_lmda=None,
1153 tx_pwr_min=None, tx_pwr_max=None):
1155 self.length = length
1156 self.supported = supported
1157 self.tx_min_freq_lmda = tx_min_freq_lmda
1158 self.tx_max_freq_lmda = tx_max_freq_lmda
1159 self.tx_grid_freq_lmda = tx_grid_freq_lmda
1160 self.rx_min_freq_lmda = rx_min_freq_lmda
1161 self.rx_max_freq_lmda = rx_max_freq_lmda
1162 self.rx_grid_freq_lmda = rx_grid_freq_lmda
1163 self.tx_pwr_min = tx_pwr_min
1164 self.tx_pwr_max = tx_pwr_max
1167 def parser(cls, buf):
1169 (optical.type, optical.length, optical.supported,
1170 optical.tx_min_freq_lmda, optical.tx_max_freq_lmda,
1171 optical.tx_grid_freq_lmda, optical.rx_min_freq_lmda,
1172 optical.rx_max_freq_lmda, optical.rx_grid_freq_lmda,
1173 optical.tx_pwr_min, optical.tx_pwr_max) = struct.unpack_from(
1174 ofproto.OFP_PORT_DESC_PROP_OPTICAL_PACK_STR, buf, 0)
1178 @OFPPortDescProp.register_type(ofproto.OFPPDPT_PIPELINE_INPUT)
1179 @OFPPortDescProp.register_type(ofproto.OFPPDPT_PIPELINE_OUTPUT)
1180 class OFPPortDescPropOxm(OFPPortDescProp):
1181 def __init__(self, type_=None, length=None, oxm_ids=None):
1182 oxm_ids = oxm_ids if oxm_ids else []
1183 super(OFPPortDescPropOxm, self).__init__(type_, length)
1184 self.oxm_ids = oxm_ids
1187 def parser(cls, buf):
1188 rest = cls.get_rest(buf)
1191 i, rest = OFPOxmId.parse(rest)
1193 return cls(oxm_ids=ids)
1195 def serialize_body(self):
1196 bin_ids = bytearray()
1197 for i in self.oxm_ids:
1198 bin_ids += i.serialize()
1202 @OFPPortDescProp.register_type(ofproto.OFPPDPT_RECIRCULATE)
1203 class OFPPortDescPropRecirculate(OFPPortDescProp):
1204 _PORT_NO_PACK_STR = '!I'
1206 def __init__(self, type_=None, length=None, port_nos=None):
1207 port_nos = port_nos if port_nos else []
1208 super(OFPPortDescPropRecirculate, self).__init__(type_, length)
1209 self.port_nos = port_nos
1212 def parser(cls, buf):
1213 rest = cls.get_rest(buf)
1216 (n,) = struct.unpack_from(cls._PORT_NO_PACK_STR,
1217 six.binary_type(rest), 0)
1218 rest = rest[struct.calcsize(cls._PORT_NO_PACK_STR):]
1220 return cls(port_nos=nos)
1222 def serialize_body(self):
1223 bin_nos = bytearray()
1224 for n in self.port_nos:
1225 bin_no = bytearray()
1226 msg_pack_into(self._PORT_NO_PACK_STR, bin_no, 0, n)
1231 @OFPPortDescProp.register_type(ofproto.OFPPDPT_EXPERIMENTER)
1232 class OFPPortDescPropExperimenter(OFPPropCommonExperimenter4ByteData):
1236 class OFPTableModProp(OFPPropBase):
1240 @OFPTableModProp.register_type(ofproto.OFPTMPT_EVICTION)
1241 class OFPTableModPropEviction(OFPTableModProp):
1242 def __init__(self, type_=None, length=None, flags=None):
1244 self.length = length
1248 def parser(cls, buf):
1250 (eviction.type, eviction.length, eviction.flags) = struct.unpack_from(
1251 ofproto.OFP_TABLE_MOD_PROP_EVICTION_PACK_STR, buf, 0)
1254 def serialize(self):
1256 self.length = ofproto.OFP_TABLE_MOD_PROP_EVICTION_SIZE
1259 msg_pack_into(ofproto.OFP_TABLE_MOD_PROP_EVICTION_PACK_STR, buf, 0,
1260 self.type, self.length, self.flags)
1264 @OFPTableModProp.register_type(ofproto.OFPTMPT_VACANCY)
1265 class OFPTableModPropVacancy(OFPTableModProp):
1266 def __init__(self, type_=None, length=None, vacancy_down=None,
1267 vacancy_up=None, vacancy=None):
1269 self.length = length
1270 self.vacancy_down = vacancy_down
1271 self.vacancy_up = vacancy_up
1272 self.vacancy = vacancy
1275 def parser(cls, buf):
1277 (vacancy.type, vacancy.length, vacancy.vacancy_down,
1278 vacancy.vacancy_up, vacancy.vacancy) = struct.unpack_from(
1279 ofproto.OFP_TABLE_MOD_PROP_VACANCY_PACK_STR, buf, 0)
1282 def serialize(self):
1284 self.length = ofproto.OFP_TABLE_MOD_PROP_VACANCY_SIZE
1287 msg_pack_into(ofproto.OFP_TABLE_MOD_PROP_VACANCY_PACK_STR, buf, 0,
1288 self.type, self.length, self.vacancy_down,
1289 self.vacancy_up, self.vacancy)
1293 @OFPTableModProp.register_type(ofproto.OFPTMPT_EXPERIMENTER)
1294 class OFPTableModPropExperimenter(OFPPropCommonExperimenter4ByteData):
1298 class OFPQueueDescProp(OFPPropBase):
1302 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_MIN_RATE)
1303 class OFPQueueDescPropMinRate(OFPQueueDescProp):
1304 def __init__(self, type_=None, length=None, rate=None):
1306 self.length = length
1310 def parser(cls, buf):
1312 (minrate.type, minrate.length, minrate.rate) = struct.unpack_from(
1313 ofproto.OFP_QUEUE_DESC_PROP_MIN_RATE_PACK_STR, buf, 0)
1317 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_MAX_RATE)
1318 class OFPQueueDescPropMaxRate(OFPQueueDescProp):
1319 def __init__(self, type_=None, length=None, rate=None):
1321 self.length = length
1325 def parser(cls, buf):
1327 (maxrate.type, maxrate.length, maxrate.rate) = struct.unpack_from(
1328 ofproto.OFP_QUEUE_DESC_PROP_MAX_RATE_PACK_STR, buf, 0)
1332 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_EXPERIMENTER)
1333 class OFPQueueDescPropExperimenter(OFPPropCommonExperimenter4ByteData):
1337 class OFPRoleProp(OFPPropBase):
1341 @OFPRoleProp.register_type(ofproto.OFPRPT_EXPERIMENTER)
1342 class OFPRolePropExperimenter(OFPPropCommonExperimenter4ByteData):
1346 class OFPTime(StringifyMixin):
1347 def __init__(self, seconds=None, nanoseconds=None):
1348 self.seconds = seconds
1349 self.nanoseconds = nanoseconds
1352 def parser(cls, buf, offset):
1354 (cls_.seconds, cls_.nanoseconds) = struct.unpack_from(
1355 ofproto.OFP_TIME_PACK_STR, buf, offset)
1358 def serialize(self, buf, offset):
1359 msg_pack_into(ofproto.OFP_TIME_PACK_STR, buf, offset,
1360 self.seconds, self.nanoseconds)
1361 return ofproto.OFP_TIME_SIZE
1364 class OFPBundleProp(OFPPropBase):
1368 @OFPBundleProp.register_type(ofproto.OFPBPT_TIME)
1369 class OFPBundlePropTime(OFPBundleProp):
1370 def __init__(self, type_=None, length=None, scheduled_time=None):
1371 super(OFPBundlePropTime, self).__init__(type_, length)
1372 self.scheduled_time = scheduled_time
1375 def parser(cls, buf):
1377 offset = ofproto.OFP_BUNDLE_PROP_TIME_PACK_STR0_SIZE
1378 prop.scheduled_time = OFPTime.parser(buf, offset)
1381 def serialize(self):
1383 self.length = ofproto.OFP_BUNDLE_PROP_TIME_PACK_STR_SIZE
1386 msg_pack_into(ofproto.OFP_BUNDLE_PROP_TIME_PACK_STR0, buf, 0,
1387 self.type, self.length)
1388 offset = ofproto.OFP_BUNDLE_PROP_TIME_PACK_STR0_SIZE
1389 self.scheduled_time.serialize(buf, offset)
1393 @OFPBundleProp.register_type(ofproto.OFPRPT_EXPERIMENTER)
1394 class OFPBundlePropExperimenter(OFPPropCommonExperimenter4ByteData):
1399 @_set_msg_type(ofproto.OFPT_PACKET_IN)
1400 class OFPPacketIn(MsgBase):
1404 The switch sends the packet that received to the controller by this
1407 ============= =========================================================
1408 Attribute Description
1409 ============= =========================================================
1410 buffer_id ID assigned by datapath
1411 total_len Full length of frame
1412 reason Reason packet is being sent.
1420 table_id ID of the table that was looked up
1421 cookie Cookie of the flow entry that was looked up
1422 match Instance of ``OFPMatch``
1424 ============= =========================================================
1428 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
1429 def packet_in_handler(self, ev):
1434 if msg.reason == ofp.TABLE_MISS:
1435 reason = 'TABLE MISS'
1436 elif msg.reason == ofp.OFPR_APPLY_ACTION:
1437 reason = 'APPLY ACTION'
1438 elif msg.reason == ofp.OFPR_INVALID_TTL:
1439 reason = 'INVALID TTL'
1440 elif msg.reason == ofp.OFPR_ACTION_SET:
1441 reason = 'ACTION SET'
1442 elif msg.reason == ofp.OFPR_GROUP:
1444 elif msg.reason == ofp.OFPR_PACKET_OUT:
1445 reason = 'PACKET OUT'
1449 self.logger.debug('OFPPacketIn received: '
1450 'buffer_id=%x total_len=%d reason=%s '
1451 'table_id=%d cookie=%d match=%s data=%s',
1452 msg.buffer_id, msg.total_len, reason,
1453 msg.table_id, msg.cookie, msg.match,
1454 utils.hex_array(msg.data))
1457 def __init__(self, datapath, buffer_id=None, total_len=None, reason=None,
1458 table_id=None, cookie=None, match=None, data=None):
1459 super(OFPPacketIn, self).__init__(datapath)
1460 self.buffer_id = buffer_id
1461 self.total_len = total_len
1462 self.reason = reason
1463 self.table_id = table_id
1464 self.cookie = cookie
1469 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1470 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
1472 (msg.buffer_id, msg.total_len, msg.reason,
1473 msg.table_id, msg.cookie) = struct.unpack_from(
1474 ofproto.OFP_PACKET_IN_PACK_STR,
1475 msg.buf, ofproto.OFP_HEADER_SIZE)
1477 msg.match = OFPMatch.parser(msg.buf, ofproto.OFP_PACKET_IN_SIZE -
1478 ofproto.OFP_MATCH_SIZE)
1480 match_len = utils.round_up(msg.match.length, 8)
1481 msg.data = msg.buf[(ofproto.OFP_PACKET_IN_SIZE -
1482 ofproto.OFP_MATCH_SIZE + match_len + 2):]
1484 if msg.total_len < len(msg.data):
1485 # discard padding for 8-byte alignment of OFP packet
1486 msg.data = msg.data[:msg.total_len]
1492 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
1493 class OFPFlowRemoved(MsgBase):
1495 Flow removed message
1497 When flow entries time out or are deleted, the switch notifies controller
1500 ================ ======================================================
1501 Attribute Description
1502 ================ ======================================================
1503 table_id ID of the table
1504 reason One of the following values.
1506 | OFPRR_IDLE_TIMEOUT
1507 | OFPRR_HARD_TIMEOUT
1509 | OFPRR_GROUP_DELETE
1510 | OFPRR_METER_DELETE
1512 priority Priority level of flow entry
1513 idle_timeout Idle timeout from original flow mod
1514 hard_timeout Hard timeout from original flow mod
1515 cookie Opaque controller-issued identifier
1516 match Instance of ``OFPMatch``
1517 stats Instance of ``OFPStats``
1518 ================ ======================================================
1522 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
1523 def flow_removed_handler(self, ev):
1528 if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
1529 reason = 'IDLE TIMEOUT'
1530 elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
1531 reason = 'HARD TIMEOUT'
1532 elif msg.reason == ofp.OFPRR_DELETE:
1534 elif msg.reason == ofp.OFPRR_GROUP_DELETE:
1535 reason = 'GROUP DELETE'
1536 elif msg.reason == ofp.OFPRR_METER_DELETE:
1537 reason = 'METER DELETE'
1538 elif msg.reason == ofp.OFPRR_EVICTION:
1543 self.logger.debug('OFPFlowRemoved received: '
1544 'table_id=%d reason=%s priority=%d '
1545 'idle_timeout=%d hard_timeout=%d cookie=%d '
1546 'match=%s stats=%s',
1547 msg.table_id, reason, msg.priority,
1548 msg.idle_timeout, msg.hard_timeout, msg.cookie,
1549 msg.match, msg.stats)
1552 def __init__(self, datapath, table_id=None, reason=None, priority=None,
1553 idle_timeout=None, hard_timeout=None, cookie=None,
1554 match=None, stats=None):
1555 super(OFPFlowRemoved, self).__init__(datapath)
1556 self.table_id = table_id
1557 self.reason = reason
1558 self.priority = priority
1559 self.idle_timeout = idle_timeout
1560 self.hard_timeout = hard_timeout
1561 self.cookie = cookie
1566 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1567 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
1570 (msg.table_id, msg.reason, msg.priority, msg.idle_timeout,
1571 msg.hard_timeout, msg.cookie) = struct.unpack_from(
1572 ofproto.OFP_FLOW_REMOVED_PACK_STR0,
1573 msg.buf, ofproto.OFP_HEADER_SIZE)
1574 offset = (ofproto.OFP_FLOW_REMOVED_SIZE - ofproto.OFP_MATCH_SIZE)
1576 msg.match = OFPMatch.parser(msg.buf, offset)
1577 offset += utils.round_up(msg.match.length, 8)
1579 stats_length = msg.msg_len - offset
1580 if stats_length > 0:
1581 msg.stats = OFPStats.parser(buf, offset)
1586 class OFPPort(StringifyMixin):
1589 Description of a port
1591 ========== =========================================================
1592 Attribute Description
1593 ========== =========================================================
1594 port_no Port number and it uniquely identifies a port within
1596 length Length of ofp_port (excluding padding).
1597 hw_addr MAC address for the port.
1598 name Null-terminated string containing a human-readable name
1600 config Bitmap of port configration flags.
1605 | OFPPC_NO_PACKET_IN
1606 state Bitmap of port state flags.
1611 properties List of ``OFPPortDescProp`` subclass instance
1612 ========== =========================================================
1620 # OF spec is unclear about the encoding of name.
1621 # we assumes UTF-8, which is used by OVS.
1626 def __init__(self, port_no=None, length=None, hw_addr=None, name=None,
1627 config=None, state=None, properties=None):
1628 super(OFPPort, self).__init__()
1629 self.port_no = port_no
1630 self.length = length
1631 self.hw_addr = hw_addr
1633 self.config = config
1635 self.properties = properties
1638 def parser(cls, buf, offset):
1639 (port_no, length, hw_addr, name, config, state) = struct.unpack_from(
1640 ofproto.OFP_PORT_PACK_STR, buf, offset)
1641 hw_addr = addrconv.mac.bin_to_text(hw_addr)
1642 name = name.rstrip(b'\0')
1644 rest = buf[offset + ofproto.OFP_PORT_SIZE:offset + length]
1646 p, rest = OFPPortDescProp.parse(rest)
1648 ofpport = cls(port_no, length, hw_addr, name, config, state, props)
1652 class OFPTableDesc(StringifyMixin):
1653 def __init__(self, length=None, table_id=None, config=None,
1655 super(OFPTableDesc, self).__init__()
1656 self.table_id = table_id
1657 self.length = length
1658 self.config = config
1659 self.properties = properties
1662 def parser(cls, buf, offset):
1663 (length, table_id, config) = struct.unpack_from(
1664 ofproto.OFP_TABLE_DESC_PACK_STR, buf, offset)
1666 rest = buf[offset + ofproto.OFP_TABLE_DESC_SIZE:offset + length]
1668 p, rest = OFPTableModProp.parse(rest)
1670 ofptabledesc = cls(length, table_id, config, props)
1674 class OFPQueueDesc(StringifyMixin):
1675 def __init__(self, port_no=None, queue_id=None, len_=None,
1677 super(OFPQueueDesc, self).__init__()
1678 self.port_no = port_no
1679 self.queue_id = queue_id
1681 self.properties = properties
1684 def parser(cls, buf, offset):
1685 (port_no, queue_id, len_) = struct.unpack_from(
1686 ofproto.OFP_QUEUE_DESC_PACK_STR, buf, offset)
1688 rest = buf[offset + ofproto.OFP_QUEUE_DESC_SIZE:offset + len_]
1690 p, rest = OFPQueueDescProp.parse(rest)
1692 ofpqueuedesc = cls(port_no, queue_id, len_, props)
1696 def _set_stats_type(stats_type, stats_body_cls):
1697 def _set_cls_stats_type(cls):
1698 cls.cls_stats_type = stats_type
1699 cls.cls_stats_body_cls = stats_body_cls
1701 return _set_cls_stats_type
1704 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
1705 class OFPMultipartRequest(MsgBase):
1706 def __init__(self, datapath, flags):
1707 super(OFPMultipartRequest, self).__init__(datapath)
1708 self.type = self.__class__.cls_stats_type
1711 def _serialize_stats_body(self):
1714 def _serialize_body(self):
1715 msg_pack_into(ofproto.OFP_MULTIPART_REQUEST_PACK_STR,
1716 self.buf, ofproto.OFP_HEADER_SIZE,
1717 self.type, self.flags)
1718 self._serialize_stats_body()
1722 @_set_msg_type(ofproto.OFPT_METER_MOD)
1723 class OFPMeterMod(MsgBase):
1725 Meter modification message
1727 The controller sends this message to modify the meter.
1729 ================ ======================================================
1730 Attribute Description
1731 ================ ======================================================
1732 command One of the following values.
1737 flags Bitmap of the following flags.
1743 meter_id Meter instance
1744 bands list of the following class instance.
1747 | OFPMeterBandDscpRemark
1748 | OFPMeterBandExperimenter
1749 ================ ======================================================
1752 def __init__(self, datapath, command=ofproto.OFPMC_ADD,
1753 flags=ofproto.OFPMF_KBPS, meter_id=1, bands=None):
1754 bands = bands if bands else []
1755 super(OFPMeterMod, self).__init__(datapath)
1756 self.command = command
1758 self.meter_id = meter_id
1762 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1763 msg = super(OFPMeterMod, cls).parser(
1764 datapath, version, msg_type, msg_len, xid, buf)
1766 (msg.command, msg.flags, msg.meter_id) = struct.unpack_from(
1767 ofproto.OFP_METER_MOD_PACK_STR, buf, ofproto.OFP_HEADER_SIZE)
1768 offset = ofproto.OFP_METER_MOD_SIZE
1771 while offset < msg.msg_len:
1772 band = OFPMeterBandHeader.parser(buf, offset)
1773 msg.bands.append(band)
1778 def _serialize_body(self):
1779 msg_pack_into(ofproto.OFP_METER_MOD_PACK_STR, self.buf,
1780 ofproto.OFP_HEADER_SIZE,
1781 self.command, self.flags, self.meter_id)
1783 offset = ofproto.OFP_METER_MOD_SIZE
1784 for b in self.bands:
1785 b.serialize(self.buf, offset)
1789 @_set_msg_type(ofproto.OFPT_TABLE_MOD)
1790 class OFPTableMod(MsgBase):
1792 Flow table configuration message
1794 The controller sends this message to configure table state.
1796 ================ ======================================================
1797 Attribute Description
1798 ================ ======================================================
1799 table_id ID of the table (OFPTT_ALL indicates all tables)
1800 config Bitmap of configuration flags.
1803 | OFPTC_VACANCY_EVENTS
1804 properties List of ``OFPTableModProp`` subclass instance
1805 ================ ======================================================
1809 def send_table_mod(self, datapath):
1810 ofp = datapath.ofproto
1811 ofp_parser = datapath.ofproto_parser
1813 req = ofp_parser.OFPTableMod(datapath, 1, 3)
1814 flags = ofp.OFPTC_VACANCY_EVENTS
1815 properties = [ofp_parser.OFPTableModPropEviction(flags)]
1816 req = ofp_parser.OFPTableMod(datapath, 1, 3, properties)
1817 datapath.send_msg(req)
1820 def __init__(self, datapath, table_id, config, properties):
1821 super(OFPTableMod, self).__init__(datapath)
1822 self.table_id = table_id
1823 self.config = config
1824 self.properties = properties
1826 def _serialize_body(self):
1827 props_buf = bytearray()
1828 for p in self.properties:
1829 props_buf += p.serialize()
1831 msg_pack_into(ofproto.OFP_TABLE_MOD_PACK_STR, self.buf,
1832 ofproto.OFP_HEADER_SIZE,
1833 self.table_id, self.config)
1835 self.buf += props_buf
1839 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
1840 class OFPMultipartReply(MsgBase):
1841 _STATS_MSG_TYPES = {}
1844 def register_stats_type(body_single_struct=False):
1845 def _register_stats_type(cls):
1846 assert cls.cls_stats_type is not None
1847 assert cls.cls_stats_type not in OFPMultipartReply._STATS_MSG_TYPES
1848 assert cls.cls_stats_body_cls is not None
1849 cls.cls_body_single_struct = body_single_struct
1850 OFPMultipartReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls
1852 return _register_stats_type
1854 def __init__(self, datapath, body=None, flags=None):
1855 super(OFPMultipartReply, self).__init__(datapath)
1860 def parser_stats_body(cls, buf, msg_len, offset):
1861 body_cls = cls.cls_stats_body_cls
1863 while offset < msg_len:
1864 entry = body_cls.parser(buf, offset)
1866 offset += entry.length
1868 if cls.cls_body_single_struct:
1873 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf):
1874 msg = MsgBase.parser.__func__(
1875 cls, datapath, version, msg_type, msg_len, xid, buf)
1876 msg.body = msg.parser_stats_body(msg.buf, msg.msg_len,
1877 ofproto.OFP_MULTIPART_REPLY_SIZE)
1881 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1882 type_, flags = struct.unpack_from(
1883 ofproto.OFP_MULTIPART_REPLY_PACK_STR, six.binary_type(buf),
1884 ofproto.OFP_HEADER_SIZE)
1885 stats_type_cls = cls._STATS_MSG_TYPES.get(type_)
1886 msg = super(OFPMultipartReply, stats_type_cls).parser(
1887 datapath, version, msg_type, msg_len, xid, buf)
1891 offset = ofproto.OFP_MULTIPART_REPLY_SIZE
1893 while offset < msg_len:
1894 b = stats_type_cls.cls_stats_body_cls.parser(msg.buf, offset)
1895 offset_step = b.length if hasattr(b, 'length') else b.len
1897 raise exception.OFPMalformedMessage()
1899 offset += offset_step
1901 if stats_type_cls.cls_body_single_struct:
1908 class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
1909 'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
1922 def parser(cls, buf, offset):
1923 desc = struct.unpack_from(ofproto.OFP_DESC_PACK_STR,
1926 desc = [x.rstrip(b'\0') for x in desc]
1928 stats.length = ofproto.OFP_DESC_SIZE
1932 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
1933 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
1934 class OFPDescStatsRequest(OFPMultipartRequest):
1936 Description statistics request message
1938 The controller uses this message to query description of the switch.
1940 ================ ======================================================
1941 Attribute Description
1942 ================ ======================================================
1943 flags Zero or ``OFPMPF_REQ_MORE``
1944 ================ ======================================================
1948 def send_desc_stats_request(self, datapath):
1949 ofp_parser = datapath.ofproto_parser
1951 req = ofp_parser.OFPDescStatsRequest(datapath, 0)
1952 datapath.send_msg(req)
1955 def __init__(self, datapath, flags=0, type_=None):
1956 super(OFPDescStatsRequest, self).__init__(datapath, flags)
1959 @OFPMultipartReply.register_stats_type(body_single_struct=True)
1960 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
1961 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
1962 class OFPDescStatsReply(OFPMultipartReply):
1964 Description statistics reply message
1966 The switch responds with this message to a description statistics
1969 ================ ======================================================
1970 Attribute Description
1971 ================ ======================================================
1972 body Instance of ``OFPDescStats``
1973 ================ ======================================================
1977 @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
1978 def desc_stats_reply_handler(self, ev):
1981 self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
1982 'serial_num=%s dp_desc=%s',
1983 body.mfr_desc, body.hw_desc, body.sw_desc,
1984 body.serial_num, body.dp_desc)
1987 def __init__(self, datapath, type_=None, **kwargs):
1988 super(OFPDescStatsReply, self).__init__(datapath, **kwargs)
1991 class OFPTableFeaturesStats(StringifyMixin):
1995 # OF spec is unclear about the encoding of name.
2001 def __init__(self, table_id=None, command=None, features=None, name=None,
2002 metadata_match=None, metadata_write=None, capabilities=None,
2003 max_entries=None, properties=None, length=None):
2004 super(OFPTableFeaturesStats, self).__init__()
2005 self.length = length
2006 self.table_id = table_id
2007 self.command = command
2008 self.features = features
2010 self.metadata_match = metadata_match
2011 self.metadata_write = metadata_write
2012 self.capabilities = capabilities
2013 self.max_entries = max_entries
2014 self.properties = properties
2017 def parser(cls, buf, offset):
2019 (tbl.length, tbl.table_id, tbl.command, tbl.features,
2020 name, tbl.metadata_match, tbl.metadata_write,
2021 tbl.capabilities, tbl.max_entries
2022 ) = struct.unpack_from(ofproto.OFP_TABLE_FEATURES_PACK_STR,
2024 tbl.name = name.rstrip(b'\0')
2027 rest = buf[offset + ofproto.OFP_TABLE_FEATURES_SIZE:
2028 offset + tbl.length]
2030 p, rest = OFPTableFeatureProp.parse(rest)
2032 tbl.properties = props
2036 def serialize(self):
2038 bin_props = bytearray()
2039 for p in self.properties:
2040 bin_props += p.serialize()
2041 self.length = ofproto.OFP_TABLE_FEATURES_SIZE + len(bin_props)
2044 msg_pack_into(ofproto.OFP_TABLE_FEATURES_PACK_STR, buf, 0,
2045 self.length, self.table_id, self.command, self.features,
2046 self.name, self.metadata_match, self.metadata_write,
2047 self.capabilities, self.max_entries)
2048 return buf + bin_props
2051 class OFPTableFeatureProp(OFPPropBase):
2055 class OFPInstructionId(StringifyMixin):
2056 _PACK_STR = '!HH' # type, len
2058 def __init__(self, type_, len_=None):
2064 def parse(cls, buf):
2065 (type_, len_,) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf), 0)
2067 return cls(type_=type_, len_=len_), rest
2069 def serialize(self):
2071 self.len = struct.calcsize(self._PACK_STR)
2074 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
2078 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS)
2079 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS_MISS)
2080 class OFPTableFeaturePropInstructions(OFPTableFeatureProp):
2081 def __init__(self, type_=None, length=None, instruction_ids=None):
2082 instruction_ids = instruction_ids if instruction_ids else []
2083 super(OFPTableFeaturePropInstructions, self).__init__(type_, length)
2084 self.instruction_ids = instruction_ids
2087 def parser(cls, buf):
2088 rest = cls.get_rest(buf)
2091 i, rest = OFPInstructionId.parse(rest)
2093 return cls(instruction_ids=ids)
2095 def serialize_body(self):
2096 bin_ids = bytearray()
2097 for i in self.instruction_ids:
2098 bin_ids += i.serialize()
2103 # Implementation note: While OpenFlow 1.3.2 shares the same ofp_action_header
2104 # for flow_mod and table_features, we have separate classes. We named this
2105 # class to match with OpenFlow 1.4's name. (ofp_action_id)
2106 class OFPActionId(StringifyMixin):
2107 _PACK_STR = '!HH' # type, len
2109 def __init__(self, type_, len_=None):
2115 def parse(cls, buf):
2116 (type_, len_,) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf), 0)
2118 return cls(type_=type_, len_=len_), rest
2120 def serialize(self):
2122 self.len = struct.calcsize(self._PACK_STR)
2125 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
2129 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS)
2130 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS_MISS)
2131 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS)
2132 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS_MISS)
2133 class OFPTableFeaturePropActions(OFPTableFeatureProp):
2134 def __init__(self, type_=None, length=None, action_ids=None):
2135 action_ids = action_ids if action_ids else []
2136 super(OFPTableFeaturePropActions, self).__init__(type_, length)
2137 self.action_ids = action_ids
2140 def parser(cls, buf):
2141 rest = cls.get_rest(buf)
2144 i, rest = OFPActionId.parse(rest)
2146 return cls(action_ids=ids)
2148 def serialize_body(self):
2149 bin_ids = bytearray()
2150 for i in self.action_ids:
2151 bin_ids += i.serialize()
2155 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES)
2156 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES_MISS)
2157 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_TABLE_SYNC_FROM)
2158 class OFPTableFeaturePropNextTables(OFPTableFeatureProp):
2159 _TABLE_ID_PACK_STR = '!B'
2161 def __init__(self, type_=None, length=None, table_ids=None):
2162 table_ids = table_ids if table_ids else []
2163 super(OFPTableFeaturePropNextTables, self).__init__(type_, length)
2164 self.table_ids = table_ids
2167 def parser(cls, buf):
2168 rest = cls.get_rest(buf)
2171 (i,) = struct.unpack_from(cls._TABLE_ID_PACK_STR, six.binary_type(rest), 0)
2172 rest = rest[struct.calcsize(cls._TABLE_ID_PACK_STR):]
2174 return cls(table_ids=ids)
2176 def serialize_body(self):
2177 bin_ids = bytearray()
2178 for i in self.table_ids:
2179 bin_id = bytearray()
2180 msg_pack_into(self._TABLE_ID_PACK_STR, bin_id, 0, i)
2185 # Implementation note: OFPOxmId is specific to this implementation.
2186 # It does not have a corresponding structure in the specification.
2187 # (the specification uses plain uint32_t for non-experimenter OXMs
2188 # and uint64_t for experimenter OXMs.)
2190 # i have taken a look at some of software switch implementations
2191 # but they all look broken or incomplete. according to the spec,
2192 # oxm_hasmask should be 1 if a switch supports masking for the type.
2193 # the right value for oxm_length is not clear from the spec.
2194 # update: OpenFlow 1.3.3 "clarified" that oxm_length here is the payload
2195 # length. it's still unclear if it should be doubled for hasmask or not,
2198 # oxm_hasmask always 0
2199 # oxm_length same as ofp_match etc (as without mask)
2201 # oxm_hasmask always 0
2202 # oxm_length always 0
2204 # seems in flux as of writing this [20141003]
2205 # updtate: OVS checks the oxm_length strictly which contained in
2206 # the OFPAT_COPY_FIELD action when using OpenFlow 1.5, so here composes the
2207 # payload length as the oxm_length (if has mask, it will be doubled, still
2209 class OFPOxmId(StringifyMixin):
2210 _PACK_STR = '!I' # oxm header
2211 _EXPERIMENTER_ID_PACK_STR = '!I'
2219 def __init__(self, type_, hasmask=False, length=None):
2221 self.hasmask = hasmask
2222 self.length = length
2225 def parse(cls, buf):
2226 (oxm,) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf), 0)
2227 # oxm (32 bit) == class (16) | field (7) | hasmask (1) | length (8)
2228 # in case of experimenter OXMs, another 32 bit value
2229 # (experimenter id) follows.
2230 (type_, _v) = ofproto.oxm_to_user(oxm >> (1 + 8), None, None)
2231 rest = buf[struct.calcsize(cls._PACK_STR):]
2232 hasmask = ofproto.oxm_tlv_header_extract_hasmask(oxm)
2233 length = oxm & 0xff # XXX see the comment on OFPOxmId
2234 class_ = oxm >> (7 + 1 + 8)
2235 if class_ == ofproto.OFPXMC_EXPERIMENTER:
2236 (exp_id,) = struct.unpack_from(cls._EXPERIMENTER_ID_PACK_STR,
2237 six.binary_type(rest), 0)
2238 rest = rest[struct.calcsize(cls._EXPERIMENTER_ID_PACK_STR):]
2239 subcls = OFPExperimenterOxmId
2240 return subcls(type_=type_, exp_id=exp_id, hasmask=hasmask,
2241 length=length), rest
2243 return cls(type_=type_, hasmask=hasmask, length=length), rest
2245 def serialize(self):
2246 n, t = ofproto.oxm_get_field_info_by_name(self.type)
2248 # XXX see the comment on OFPOxmId
2249 self.length = t.size * 2 if self.hasmask else t.size
2250 oxm = (n << (1 + 8)) | (self.hasmask << 8) | self.length
2252 msg_pack_into(self._PACK_STR, buf, 0, oxm)
2253 assert n >> 7 != ofproto.OFPXMC_EXPERIMENTER
2257 class OFPExperimenterOxmId(OFPOxmId):
2258 def __init__(self, type_, exp_id, hasmask=False, length=None):
2259 super(OFPExperimenterOxmId, self).__init__(type_=type_,
2262 self.exp_id = exp_id
2264 def serialize(self):
2265 buf = super(OFPExperimenterOxmId, self).serialize()
2266 msg_pack_into(self._EXPERIMENTER_ID_PACK_STR, buf,
2267 struct.calcsize(self._PACK_STR), self.exp_id)
2270 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_MATCH)
2271 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WILDCARDS)
2272 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD)
2273 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD_MISS)
2274 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD)
2275 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD_MISS)
2276 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_COPYFIELD)
2277 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_COPYFIELD_MISS)
2278 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_COPYFIELD)
2279 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_COPYFIELD_MISS)
2280 class OFPTableFeaturePropOxm(OFPTableFeatureProp):
2281 def __init__(self, type_=None, length=None, oxm_ids=None):
2282 oxm_ids = oxm_ids if oxm_ids else []
2283 super(OFPTableFeaturePropOxm, self).__init__(type_, length)
2284 self.oxm_ids = oxm_ids
2287 def parser(cls, buf):
2288 rest = cls.get_rest(buf)
2291 i, rest = OFPOxmId.parse(rest)
2293 return cls(oxm_ids=ids)
2295 def serialize_body(self):
2296 bin_ids = bytearray()
2297 for i in self.oxm_ids:
2298 bin_ids += i.serialize()
2302 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_PACKET_TYPES)
2303 class OFPTableFeaturePropOxmValues(OFPTableFeatureProp):
2304 def __init__(self, type_=None, length=None, _ordered_values=None,
2306 super(OFPTableFeaturePropOxmValues, self).__init__(type_, length)
2307 if _ordered_values is not None:
2309 self.oxm_values = _ordered_values
2311 kwargs = dict(ofproto.oxm_normalize_user(k, v) for
2312 (k, v) in kwargs.items())
2313 values = [ofproto.oxm_from_user(k, v) for (k, v)
2315 # assumption: sorting by OXM type values makes fields
2316 # meet ordering requirements (eg. eth_type before ipv4_src)
2318 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
2319 self.oxm_values = [ofproto.oxm_to_user(n, v, m) for (n, v, m)
2323 def parser(cls, buf):
2324 rest = cls.get_rest(buf)
2327 n, value, mask, field_len = ofproto.oxm_parse(rest, 0)
2328 k, uv = ofproto.oxm_to_user(n, value, mask)
2329 values.append((k, uv))
2330 rest = rest[field_len:]
2331 return cls(_ordered_values=values)
2333 def serialize_body(self):
2334 values = [ofproto.oxm_from_user(k, uv) for (k, uv)
2338 for (n, value, mask) in values:
2339 offset += ofproto.oxm_serialize(n, value, mask, buf, offset)
2342 def __getitem__(self, key):
2343 return dict(self.oxm_values)[key]
2345 def __contains__(self, key):
2346 return key in dict(self.oxm_values)
2348 def iteritems(self):
2349 return iter(dict(self.oxm_values).items())
2352 return self.oxm_values
2354 def get(self, key, default=None):
2355 return dict(self.oxm_values).get(key, default)
2357 def stringify_attrs(self):
2358 yield "oxm_values", dict(self.oxm_values)
2360 def to_jsondict(self):
2362 Returns a dict expressing the OXM values.
2364 body = {"oxm_values": [ofproto.oxm_to_jsondict(k, uv) for k, uv
2365 in self.oxm_values],
2366 "length": self.length,
2368 return {self.__class__.__name__: body}
2371 def from_jsondict(cls, dict_):
2373 Returns an object which is generated from a dict.
2375 KeyError -- Unknown OXM value is defined in dict
2377 type_ = dict_['type']
2378 values = [ofproto.oxm_from_jsondict(f) for f
2379 in dict_['oxm_values']]
2380 return cls(type_=type_, _ordered_values=values)
2383 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER)
2384 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER_MISS)
2385 class OFPTableFeaturePropExperimenter(OFPPropCommonExperimenter4ByteData):
2389 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
2390 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2391 class OFPTableFeaturesStatsRequest(OFPMultipartRequest):
2393 Table features statistics request message
2395 The controller uses this message to query table features.
2397 ================ ======================================================
2398 Attribute Description
2399 ================ ======================================================
2400 body List of ``OFPTableFeaturesStats`` instances.
2402 ================ ======================================================
2405 def __init__(self, datapath, flags=0, body=None, type_=None):
2406 body = body if body else []
2407 super(OFPTableFeaturesStatsRequest, self).__init__(datapath, flags)
2410 def _serialize_stats_body(self):
2411 bin_body = bytearray()
2413 bin_body += p.serialize()
2414 self.buf += bin_body
2417 @OFPMultipartReply.register_stats_type()
2418 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
2419 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2420 class OFPTableFeaturesStatsReply(OFPMultipartReply):
2422 Table features statistics reply message
2424 The switch responds with this message to a table features statistics
2427 ================ ======================================================
2428 Attribute Description
2429 ================ ======================================================
2430 body List of ``OFPTableFeaturesStats`` instance
2431 ================ ======================================================
2434 def __init__(self, datapath, type_=None, **kwargs):
2435 super(OFPTableFeaturesStatsReply, self).__init__(datapath, **kwargs)
2438 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
2439 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2440 class OFPPortDescStatsRequest(OFPMultipartRequest):
2442 Port description request message
2444 The controller uses this message to query description of one or all the ports.
2446 ================ ======================================================
2447 Attribute Description
2448 ================ ======================================================
2449 flags Zero or ``OFPMPF_REQ_MORE``
2450 port_no Port number to read (OFPP_ANY to all ports)
2451 ================ ======================================================
2455 def send_port_desc_stats_request(self, datapath):
2456 ofp = datapath.ofproto
2457 ofp_parser = datapath.ofproto_parser
2459 req = ofp_parser.OFPPortDescStatsRequest(datapath, 0, ofp.OFPP_ANY)
2460 datapath.send_msg(req)
2463 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY, type_=None):
2464 super(OFPPortDescStatsRequest, self).__init__(datapath, flags)
2465 self.port_no = port_no
2467 def _serialize_stats_body(self):
2468 msg_pack_into(ofproto.OFP_PORT_MULTIPART_REQUEST_PACK_STR,
2470 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2474 @OFPMultipartReply.register_stats_type()
2475 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
2476 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2477 class OFPPortDescStatsReply(OFPMultipartReply):
2479 Port description reply message
2481 The switch responds with this message to a port description request.
2483 ================ ======================================================
2484 Attribute Description
2485 ================ ======================================================
2486 body List of ``OFPPort`` instance
2487 ================ ======================================================
2491 @set_ev_cls(ofp_event.EventOFPPortDescStatsReply, MAIN_DISPATCHER)
2492 def port_desc_stats_reply_handler(self, ev):
2494 for p in ev.msg.body:
2495 ports.append('port_no=%d hw_addr=%s name=%s config=0x%08x '
2496 'state=0x%08x properties=%s' %
2497 (p.port_no, p.hw_addr,
2498 p.name, p.config, p.state, repr(p.properties)))
2499 self.logger.debug('OFPPortDescStatsReply received: %s', ports)
2502 def __init__(self, datapath, type_=None, **kwargs):
2503 super(OFPPortDescStatsReply, self).__init__(datapath, **kwargs)
2506 @_set_stats_type(ofproto.OFPMP_TABLE_DESC, OFPTableDesc)
2507 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2508 class OFPTableDescStatsRequest(OFPMultipartRequest):
2510 Table description request message
2512 The controller uses this message to query description of all the tables.
2514 ================ ======================================================
2515 Attribute Description
2516 ================ ======================================================
2517 flags Zero or ``OFPMPF_REQ_MORE``
2518 ================ ======================================================
2522 def send_table_desc_stats_request(self, datapath):
2523 ofp_parser = datapath.ofproto_parser
2525 req = ofp_parser.OFPTableDescStatsRequest(datapath, 0)
2526 datapath.send_msg(req)
2529 def __init__(self, datapath, flags=0, type_=None):
2530 super(OFPTableDescStatsRequest, self).__init__(datapath, flags)
2533 @OFPMultipartReply.register_stats_type()
2534 @_set_stats_type(ofproto.OFPMP_TABLE_DESC, OFPTableDesc)
2535 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2536 class OFPTableDescStatsReply(OFPMultipartReply):
2538 Table description reply message
2540 The switch responds with this message to a table description request.
2542 ================ ======================================================
2543 Attribute Description
2544 ================ ======================================================
2545 body List of ``OFPTableDesc`` instance
2546 ================ ======================================================
2550 @set_ev_cls(ofp_event.EventOFPTableDescStatsReply, MAIN_DISPATCHER)
2551 def table_desc_stats_reply_handler(self, ev):
2553 for p in ev.msg.body:
2554 tables.append('table_id=%d config=0x%08x properties=%s' %
2555 (p.table_id, p.config, repr(p.properties)))
2556 self.logger.debug('OFPTableDescStatsReply received: %s', tables)
2559 def __init__(self, datapath, type_=None, **kwargs):
2560 super(OFPTableDescStatsReply, self).__init__(datapath, **kwargs)
2563 @_set_stats_type(ofproto.OFPMP_QUEUE_DESC, OFPQueueDesc)
2564 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2565 class OFPQueueDescStatsRequest(OFPMultipartRequest):
2567 Queue description request message
2569 The controller uses this message to query description of all the queues.
2571 ================ ======================================================
2572 Attribute Description
2573 ================ ======================================================
2574 flags Zero or ``OFPMPF_REQ_MORE``
2575 port_no Port number to read (OFPP_ANY for all ports)
2576 queue_id ID of queue to read (OFPQ_ALL for all queues)
2577 ================ ======================================================
2581 def send_queue_desc_stats_request(self, datapath):
2582 ofp = datapath.ofproto
2583 ofp_parser = datapath.ofproto_parser
2585 req = ofp_parser.OFPQueueDescStatsRequest(datapath, 0,
2588 datapath.send_msg(req)
2591 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
2592 queue_id=ofproto.OFPQ_ALL, type_=None):
2593 super(OFPQueueDescStatsRequest, self).__init__(datapath, flags)
2594 self.port_no = port_no
2595 self.queue_id = queue_id
2597 def _serialize_stats_body(self):
2598 msg_pack_into(ofproto.OFP_QUEUE_MULTIPART_REQUEST_PACK_STR,
2600 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2601 self.port_no, self.queue_id)
2604 @OFPMultipartReply.register_stats_type()
2605 @_set_stats_type(ofproto.OFPMP_QUEUE_DESC, OFPQueueDesc)
2606 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2607 class OFPQueueDescStatsReply(OFPMultipartReply):
2609 Queue description reply message
2611 The switch responds with this message to a queue description request.
2613 ================ ======================================================
2614 Attribute Description
2615 ================ ======================================================
2616 body List of ``OFPQueueDesc`` instance
2617 ================ ======================================================
2621 @set_ev_cls(ofp_event.EventOFPQueueDescStatsReply, MAIN_DISPATCHER)
2622 def queue_desc_stats_reply_handler(self, ev):
2624 for q in ev.msg.body:
2625 queues.append('port_no=%d queue_id=0x%08x properties=%s' %
2626 (q.port_no, q.queue_id, repr(q.properties)))
2627 self.logger.debug('OFPQueueDescStatsReply received: %s', queues)
2630 def __init__(self, datapath, type_=None, **kwargs):
2631 super(OFPQueueDescStatsReply, self).__init__(datapath, **kwargs)
2634 class OFPQueueStatsProp(OFPPropBase):
2638 @OFPQueueStatsProp.register_type(ofproto.OFPQSPT_EXPERIMENTER)
2639 class OFPQueueStatsPropExperimenter(OFPPropCommonExperimenter4ByteData):
2643 class OFPQueueStats(StringifyMixin):
2644 def __init__(self, length=None, port_no=None, queue_id=None,
2645 tx_bytes=None, tx_packets=None, tx_errors=None,
2646 duration_sec=None, duration_nsec=None, properties=None):
2647 super(OFPQueueStats, self).__init__()
2648 self.length = length
2649 self.port_no = port_no
2650 self.queue_id = queue_id
2651 self.tx_bytes = tx_bytes
2652 self.tx_packets = tx_packets
2653 self.tx_errors = tx_errors
2654 self.duration_sec = duration_sec
2655 self.duration_nsec = duration_nsec
2656 self.properties = properties
2659 def parser(cls, buf, offset):
2660 (length, port_no, queue_id, tx_bytes, tx_packets, tx_errors,
2661 duration_sec, duration_nsec) = struct.unpack_from(
2662 ofproto.OFP_QUEUE_STATS_PACK_STR, buf, offset)
2664 rest = buf[offset + ofproto.OFP_QUEUE_STATS_SIZE:offset + length]
2666 p, rest = OFPQueueStatsProp.parse(rest)
2668 stats = cls(length, port_no, queue_id, tx_bytes, tx_packets, tx_errors,
2669 duration_sec, duration_nsec, props)
2673 @_set_stats_type(ofproto.OFPMP_QUEUE_STATS, OFPQueueStats)
2674 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2675 class OFPQueueStatsRequest(OFPMultipartRequest):
2677 Queue statistics request message
2679 The controller uses this message to query queue statictics.
2681 ================ ======================================================
2682 Attribute Description
2683 ================ ======================================================
2684 flags Zero or ``OFPMPF_REQ_MORE``
2685 port_no Port number to read
2686 queue_id ID of queue to read
2687 ================ ======================================================
2691 def send_queue_stats_request(self, datapath):
2692 ofp = datapath.ofproto
2693 ofp_parser = datapath.ofproto_parser
2695 req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPP_ANY,
2697 datapath.send_msg(req)
2700 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
2701 queue_id=ofproto.OFPQ_ALL, type_=None):
2702 super(OFPQueueStatsRequest, self).__init__(datapath, flags)
2703 self.port_no = port_no
2704 self.queue_id = queue_id
2706 def _serialize_stats_body(self):
2707 msg_pack_into(ofproto.OFP_QUEUE_MULTIPART_REQUEST_PACK_STR,
2709 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2710 self.port_no, self.queue_id)
2713 @OFPMultipartReply.register_stats_type()
2714 @_set_stats_type(ofproto.OFPMP_QUEUE_STATS, OFPQueueStats)
2715 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2716 class OFPQueueStatsReply(OFPMultipartReply):
2718 Queue statistics reply message
2720 The switch responds with this message to an aggregate flow statistics
2723 ================ ======================================================
2724 Attribute Description
2725 ================ ======================================================
2726 body List of ``OFPQueueStats`` instance
2727 ================ ======================================================
2731 @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
2732 def queue_stats_reply_handler(self, ev):
2734 for stat in ev.msg.body:
2735 queues.append('port_no=%d queue_id=%d '
2736 'tx_bytes=%d tx_packets=%d tx_errors=%d '
2737 'duration_sec=%d duration_nsec=%d'
2739 (stat.port_no, stat.queue_id,
2740 stat.tx_bytes, stat.tx_packets, stat.tx_errors,
2741 stat.duration_sec, stat.duration_nsec,
2742 repr(stat.properties)))
2743 self.logger.debug('QueueStats: %s', queues)
2746 def __init__(self, datapath, type_=None, **kwargs):
2747 super(OFPQueueStatsReply, self).__init__(datapath, **kwargs)
2750 class OFPBucketCounter(StringifyMixin):
2751 def __init__(self, packet_count, byte_count):
2752 super(OFPBucketCounter, self).__init__()
2753 self.packet_count = packet_count
2754 self.byte_count = byte_count
2757 def parser(cls, buf, offset):
2758 packet_count, byte_count = struct.unpack_from(
2759 ofproto.OFP_BUCKET_COUNTER_PACK_STR, buf, offset)
2760 return cls(packet_count, byte_count)
2763 class OFPGroupStats(StringifyMixin):
2764 def __init__(self, length=None, group_id=None, ref_count=None,
2765 packet_count=None, byte_count=None, duration_sec=None,
2766 duration_nsec=None, bucket_stats=None):
2767 super(OFPGroupStats, self).__init__()
2768 self.length = length
2769 self.group_id = group_id
2770 self.ref_count = ref_count
2771 self.packet_count = packet_count
2772 self.byte_count = byte_count
2773 self.duration_sec = duration_sec
2774 self.duration_nsec = duration_nsec
2775 self.bucket_stats = bucket_stats
2778 def parser(cls, buf, offset):
2779 group = struct.unpack_from(ofproto.OFP_GROUP_STATS_PACK_STR,
2781 group_stats = cls(*group)
2783 group_stats.bucket_stats = []
2784 total_len = group_stats.length + offset
2785 offset += ofproto.OFP_GROUP_STATS_SIZE
2786 while total_len > offset:
2787 b = OFPBucketCounter.parser(buf, offset)
2788 group_stats.bucket_stats.append(b)
2789 offset += ofproto.OFP_BUCKET_COUNTER_SIZE
2794 @_set_stats_type(ofproto.OFPMP_GROUP_STATS, OFPGroupStats)
2795 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2796 class OFPGroupStatsRequest(OFPMultipartRequest):
2798 Group statistics request message
2800 The controller uses this message to query statistics of one or more
2803 ================ ======================================================
2804 Attribute Description
2805 ================ ======================================================
2806 flags Zero or ``OFPMPF_REQ_MORE``
2807 group_id ID of group to read (OFPG_ALL to all groups)
2808 ================ ======================================================
2812 def send_group_stats_request(self, datapath):
2813 ofp = datapath.ofproto
2814 ofp_parser = datapath.ofproto_parser
2816 req = ofp_parser.OFPGroupStatsRequest(datapath, 0, ofp.OFPG_ALL)
2817 datapath.send_msg(req)
2820 def __init__(self, datapath, flags=0, group_id=ofproto.OFPG_ALL,
2822 super(OFPGroupStatsRequest, self).__init__(datapath, flags)
2823 self.group_id = group_id
2825 def _serialize_stats_body(self):
2826 msg_pack_into(ofproto.OFP_GROUP_MULTIPART_REQUEST_PACK_STR,
2828 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2832 @OFPMultipartReply.register_stats_type()
2833 @_set_stats_type(ofproto.OFPMP_GROUP_STATS, OFPGroupStats)
2834 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2835 class OFPGroupStatsReply(OFPMultipartReply):
2837 Group statistics reply message
2839 The switch responds with this message to a group statistics request.
2841 ================ ======================================================
2842 Attribute Description
2843 ================ ======================================================
2844 body List of ``OFPGroupStats`` instance
2845 ================ ======================================================
2849 @set_ev_cls(ofp_event.EventOFPGroupStatsReply, MAIN_DISPATCHER)
2850 def group_stats_reply_handler(self, ev):
2852 for stat in ev.msg.body:
2853 groups.append('length=%d group_id=%d '
2854 'ref_count=%d packet_count=%d byte_count=%d '
2855 'duration_sec=%d duration_nsec=%d' %
2856 (stat.length, stat.group_id,
2857 stat.ref_count, stat.packet_count,
2858 stat.byte_count, stat.duration_sec,
2859 stat.duration_nsec))
2860 self.logger.debug('GroupStats: %s', groups)
2863 def __init__(self, datapath, type_=None, **kwargs):
2864 super(OFPGroupStatsReply, self).__init__(datapath, **kwargs)
2867 class OFPGroupDescStats(StringifyMixin):
2868 def __init__(self, type_=None, group_id=None, buckets=None, properties=None,
2869 length=None, bucket_array_len=None):
2870 buckets = buckets if buckets else []
2871 properties = properties if properties else []
2872 super(OFPGroupDescStats, self).__init__()
2873 self.length = length
2875 self.group_id = group_id
2876 self.buckets = buckets
2877 self.properties = properties
2880 def parser(cls, buf, offset):
2883 (stats.length, stats.type, stats.group_id,
2884 stats.bucket_array_len) = struct.unpack_from(
2885 ofproto.OFP_GROUP_DESC_STATS_PACK_STR, buf, offset)
2886 offset += ofproto.OFP_GROUP_DESC_STATS_SIZE
2888 bucket_buf = buf[offset:offset + stats.bucket_array_len]
2891 bucket = OFPBucket.parser(bucket_buf, 0)
2892 stats.buckets.append(bucket)
2893 bucket_buf = bucket_buf[bucket.len:]
2894 offset += stats.bucket_array_len
2896 rest = buf[offset:offset + stats.length]
2898 p, rest = OFPGroupProp.parse(rest)
2899 stats.properties.append(p)
2904 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
2905 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2906 class OFPGroupDescStatsRequest(OFPMultipartRequest):
2908 Group description request message
2910 The controller uses this message to list the set of groups on a switch.
2912 ================ ======================================================
2913 Attribute Description
2914 ================ ======================================================
2915 flags Zero or ``OFPMPF_REQ_MORE``
2916 group_id ID of group to read (OFPG_ALL to all groups)
2917 ================ ======================================================
2921 def send_group_desc_stats_request(self, datapath):
2922 ofp = datapath.ofproto
2923 ofp_parser = datapath.ofproto_parser
2925 req = ofp_parser.OFPGroupDescStatsRequest(datapath, 0, ofp.OFPG_ALL)
2926 datapath.send_msg(req)
2929 def __init__(self, datapath, flags=0, group_id=ofproto.OFPG_ALL,
2931 super(OFPGroupDescStatsRequest, self).__init__(datapath, flags)
2932 self.group_id = group_id
2934 def _serialize_stats_body(self):
2935 msg_pack_into(ofproto.OFP_GROUP_MULTIPART_REQUEST_PACK_STR,
2937 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2941 @OFPMultipartReply.register_stats_type()
2942 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
2943 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2944 class OFPGroupDescStatsReply(OFPMultipartReply):
2946 Group description reply message
2948 The switch responds with this message to a group description request.
2950 ================ ======================================================
2951 Attribute Description
2952 ================ ======================================================
2953 body List of ``OFPGroupDescStats`` instance
2954 ================ ======================================================
2958 @set_ev_cls(ofp_event.EventOFPGroupDescStatsReply, MAIN_DISPATCHER)
2959 def group_desc_stats_reply_handler(self, ev):
2961 for stat in ev.msg.body:
2962 descs.append('length=%d type=%d group_id=%d '
2963 'buckets=%s properties=%s' %
2964 (stat.length, stat.type, stat.group_id,
2965 stat.bucket, repr(stat.properties)))
2966 self.logger.debug('GroupDescStats: %s', descs)
2969 def __init__(self, datapath, type_=None, **kwargs):
2970 super(OFPGroupDescStatsReply, self).__init__(datapath, **kwargs)
2973 class OFPGroupFeaturesStats(ofproto_parser.namedtuple('OFPGroupFeaturesStats',
2974 ('types', 'capabilities', 'max_groups',
2977 def parser(cls, buf, offset):
2978 group_features = struct.unpack_from(
2979 ofproto.OFP_GROUP_FEATURES_PACK_STR, buf, offset)
2980 types = group_features[0]
2981 capabilities = group_features[1]
2982 max_groups = list(group_features[2:6])
2983 actions = list(group_features[6:10])
2984 stats = cls(types, capabilities, max_groups, actions)
2985 stats.length = ofproto.OFP_GROUP_FEATURES_SIZE
2989 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
2990 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2991 class OFPGroupFeaturesStatsRequest(OFPMultipartRequest):
2993 Group features request message
2995 The controller uses this message to list the capabilities of groups on
2998 ================ ======================================================
2999 Attribute Description
3000 ================ ======================================================
3001 flags Zero or ``OFPMPF_REQ_MORE``
3002 ================ ======================================================
3006 def send_group_features_stats_request(self, datapath):
3007 ofp_parser = datapath.ofproto_parser
3009 req = ofp_parser.OFPGroupFeaturesStatsRequest(datapath, 0)
3010 datapath.send_msg(req)
3013 def __init__(self, datapath, flags=0, type_=None):
3014 super(OFPGroupFeaturesStatsRequest, self).__init__(datapath, flags)
3017 @OFPMultipartReply.register_stats_type(body_single_struct=True)
3018 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
3019 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3020 class OFPGroupFeaturesStatsReply(OFPMultipartReply):
3022 Group features reply message
3024 The switch responds with this message to a group features request.
3026 ================ ======================================================
3027 Attribute Description
3028 ================ ======================================================
3029 body Instance of ``OFPGroupFeaturesStats``
3030 ================ ======================================================
3034 @set_ev_cls(ofp_event.EventOFPGroupFeaturesStatsReply, MAIN_DISPATCHER)
3035 def group_features_stats_reply_handler(self, ev):
3038 self.logger.debug('GroupFeaturesStats: types=%d '
3039 'capabilities=0x%08x max_groups=%s '
3041 body.types, body.capabilities,
3042 body.max_groups, body.actions)
3045 def __init__(self, datapath, type_=None, **kwargs):
3046 super(OFPGroupFeaturesStatsReply, self).__init__(datapath, **kwargs)
3049 class OFPMeterBandStats(StringifyMixin):
3050 def __init__(self, packet_band_count, byte_band_count):
3051 super(OFPMeterBandStats, self).__init__()
3052 self.packet_band_count = packet_band_count
3053 self.byte_band_count = byte_band_count
3056 def parser(cls, buf, offset):
3057 band_stats = struct.unpack_from(
3058 ofproto.OFP_METER_BAND_STATS_PACK_STR, buf, offset)
3059 return cls(*band_stats)
3062 class OFPMeterStats(StringifyMixin):
3063 def __init__(self, meter_id=None, ref_count=None, packet_in_count=None,
3064 byte_in_count=None, duration_sec=None, duration_nsec=None,
3065 band_stats=None, len_=None):
3066 super(OFPMeterStats, self).__init__()
3067 self.meter_id = meter_id
3069 self.ref_count = ref_count
3070 self.packet_in_count = packet_in_count
3071 self.byte_in_count = byte_in_count
3072 self.duration_sec = duration_sec
3073 self.duration_nsec = duration_nsec
3074 self.band_stats = band_stats
3077 def parser(cls, buf, offset):
3080 (meter_stats.meter_id, meter_stats.len,
3081 meter_stats.ref_count, meter_stats.packet_in_count,
3082 meter_stats.byte_in_count, meter_stats.duration_sec,
3083 meter_stats.duration_nsec) = struct.unpack_from(
3084 ofproto.OFP_METER_STATS_PACK_STR, buf, offset)
3085 offset += ofproto.OFP_METER_STATS_SIZE
3087 meter_stats.band_stats = []
3088 length = ofproto.OFP_METER_STATS_SIZE
3089 while length < meter_stats.len:
3090 band_stats = OFPMeterBandStats.parser(buf, offset)
3091 meter_stats.band_stats.append(band_stats)
3092 offset += ofproto.OFP_METER_BAND_STATS_SIZE
3093 length += ofproto.OFP_METER_BAND_STATS_SIZE
3098 @_set_stats_type(ofproto.OFPMP_METER_STATS, OFPMeterStats)
3099 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3100 class OFPMeterStatsRequest(OFPMultipartRequest):
3102 Meter statistics request message
3104 The controller uses this message to query statistics for one or more
3107 ================ ======================================================
3108 Attribute Description
3109 ================ ======================================================
3110 flags Zero or ``OFPMPF_REQ_MORE``
3111 meter_id ID of meter to read (OFPM_ALL to all meters)
3112 ================ ======================================================
3116 def send_meter_stats_request(self, datapath):
3117 ofp = datapath.ofproto
3118 ofp_parser = datapath.ofproto_parser
3120 req = ofp_parser.OFPMeterStatsRequest(datapath, 0, ofp.OFPM_ALL)
3121 datapath.send_msg(req)
3124 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
3126 super(OFPMeterStatsRequest, self).__init__(datapath, flags)
3127 self.meter_id = meter_id
3129 def _serialize_stats_body(self):
3130 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
3132 ofproto.OFP_MULTIPART_REQUEST_SIZE,
3136 @OFPMultipartReply.register_stats_type()
3137 @_set_stats_type(ofproto.OFPMP_METER_STATS, OFPMeterStats)
3138 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3139 class OFPMeterStatsReply(OFPMultipartReply):
3141 Meter statistics reply message
3143 The switch responds with this message to a meter statistics request.
3145 ================ ======================================================
3146 Attribute Description
3147 ================ ======================================================
3148 body List of ``OFPMeterStats`` instance
3149 ================ ======================================================
3153 @set_ev_cls(ofp_event.EventOFPMeterStatsReply, MAIN_DISPATCHER)
3154 def meter_stats_reply_handler(self, ev):
3156 for stat in ev.msg.body:
3157 meters.append('meter_id=0x%08x len=%d ref_count=%d '
3158 'packet_in_count=%d byte_in_count=%d '
3159 'duration_sec=%d duration_nsec=%d '
3161 (stat.meter_id, stat.len, stat.ref_count,
3162 stat.packet_in_count, stat.byte_in_count,
3163 stat.duration_sec, stat.duration_nsec,
3165 self.logger.debug('MeterStats: %s', meters)
3168 def __init__(self, datapath, type_=None, **kwargs):
3169 super(OFPMeterStatsReply, self).__init__(datapath, **kwargs)
3172 class OFPMeterBand(StringifyMixin):
3173 def __init__(self, type_, len_):
3174 super(OFPMeterBand, self).__init__()
3179 class OFPMeterBandHeader(OFPMeterBand):
3183 def register_meter_band_type(type_, len_):
3184 def _register_meter_band_type(cls):
3185 OFPMeterBandHeader._METER_BAND[type_] = cls
3186 cls.cls_meter_band_type = type_
3187 cls.cls_meter_band_len = len_
3189 return _register_meter_band_type
3192 cls = self.__class__
3193 super(OFPMeterBandHeader, self).__init__(cls.cls_meter_band_type,
3194 cls.cls_meter_band_len)
3197 def parser(cls, buf, offset):
3198 type_, len_, _rate, _burst_size = struct.unpack_from(
3199 ofproto.OFP_METER_BAND_HEADER_PACK_STR, buf, offset)
3200 cls_ = cls._METER_BAND[type_]
3201 assert cls_.cls_meter_band_len == len_
3202 return cls_.parser(buf, offset)
3205 @OFPMeterBandHeader.register_meter_band_type(
3206 ofproto.OFPMBT_DROP, ofproto.OFP_METER_BAND_DROP_SIZE)
3207 class OFPMeterBandDrop(OFPMeterBandHeader):
3208 def __init__(self, rate=0, burst_size=0, type_=None, len_=None):
3209 super(OFPMeterBandDrop, self).__init__()
3211 self.burst_size = burst_size
3213 def serialize(self, buf, offset):
3214 msg_pack_into(ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset,
3215 self.type, self.len, self.rate, self.burst_size)
3218 def parser(cls, buf, offset):
3219 type_, len_, rate, burst_size = struct.unpack_from(
3220 ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset)
3221 assert cls.cls_meter_band_type == type_
3222 assert cls.cls_meter_band_len == len_
3223 return cls(rate, burst_size)
3226 @OFPMeterBandHeader.register_meter_band_type(
3227 ofproto.OFPMBT_DSCP_REMARK,
3228 ofproto.OFP_METER_BAND_DSCP_REMARK_SIZE)
3229 class OFPMeterBandDscpRemark(OFPMeterBandHeader):
3230 def __init__(self, rate=0, burst_size=0, prec_level=0,
3231 type_=None, len_=None):
3232 super(OFPMeterBandDscpRemark, self).__init__()
3234 self.burst_size = burst_size
3235 self.prec_level = prec_level
3237 def serialize(self, buf, offset):
3238 msg_pack_into(ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf,
3239 offset, self.type, self.len, self.rate,
3240 self.burst_size, self.prec_level)
3243 def parser(cls, buf, offset):
3244 type_, len_, rate, burst_size, prec_level = struct.unpack_from(
3245 ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf, offset)
3246 assert cls.cls_meter_band_type == type_
3247 assert cls.cls_meter_band_len == len_
3248 return cls(rate, burst_size, prec_level)
3251 @OFPMeterBandHeader.register_meter_band_type(
3252 ofproto.OFPMBT_EXPERIMENTER,
3253 ofproto.OFP_METER_BAND_EXPERIMENTER_SIZE)
3254 class OFPMeterBandExperimenter(OFPMeterBandHeader):
3255 def __init__(self, rate=0, burst_size=0, experimenter=None,
3256 type_=None, len_=None):
3257 super(OFPMeterBandExperimenter, self).__init__()
3259 self.burst_size = burst_size
3260 self.experimenter = experimenter
3262 def serialize(self, buf, offset):
3263 msg_pack_into(ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf,
3264 offset, self.type, self.len, self.rate,
3265 self.burst_size, self.experimenter)
3268 def parser(cls, buf, offset):
3269 type_, len_, rate, burst_size, experimenter = struct.unpack_from(
3270 ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf, offset)
3271 assert cls.cls_meter_band_type == type_
3272 assert cls.cls_meter_band_len == len_
3273 return cls(rate, burst_size, experimenter)
3276 class OFPMeterDescStats(StringifyMixin):
3277 def __init__(self, flags=None, meter_id=None, bands=None, length=None):
3278 super(OFPMeterDescStats, self).__init__()
3281 self.meter_id = meter_id
3285 def parser(cls, buf, offset):
3286 meter_config = cls()
3288 (meter_config.length, meter_config.flags,
3289 meter_config.meter_id) = struct.unpack_from(
3290 ofproto.OFP_METER_DESC_PACK_STR, buf, offset)
3291 offset += ofproto.OFP_METER_DESC_SIZE
3293 meter_config.bands = []
3294 length = ofproto.OFP_METER_DESC_SIZE
3295 while length < meter_config.length:
3296 band = OFPMeterBandHeader.parser(buf, offset)
3297 meter_config.bands.append(band)
3304 @_set_stats_type(ofproto.OFPMP_METER_DESC, OFPMeterDescStats)
3305 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3306 class OFPMeterDescStatsRequest(OFPMultipartRequest):
3308 Meter description statistics request message
3310 The controller uses this message to query configuration for one or more
3313 ================ ======================================================
3314 Attribute Description
3315 ================ ======================================================
3316 flags Zero or ``OFPMPF_REQ_MORE``
3317 meter_id ID of meter to read (OFPM_ALL to all meters)
3318 ================ ======================================================
3322 def send_meter_desc_stats_request(self, datapath):
3323 ofp = datapath.ofproto
3324 ofp_parser = datapath.ofproto_parser
3326 req = ofp_parser.OFPMeterDescStatsRequest(datapath, 0,
3328 datapath.send_msg(req)
3331 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
3333 super(OFPMeterDescStatsRequest, self).__init__(datapath, flags)
3334 self.meter_id = meter_id
3336 def _serialize_stats_body(self):
3337 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
3339 ofproto.OFP_MULTIPART_REQUEST_SIZE,
3343 @OFPMultipartReply.register_stats_type()
3344 @_set_stats_type(ofproto.OFPMP_METER_DESC, OFPMeterDescStats)
3345 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3346 class OFPMeterDescStatsReply(OFPMultipartReply):
3348 Meter description statistics reply message
3350 The switch responds with this message to a meter description
3353 ================ ======================================================
3354 Attribute Description
3355 ================ ======================================================
3356 body List of ``OFPMeterDescStats`` instance
3357 ================ ======================================================
3361 @set_ev_cls(ofp_event.EventOFPMeterDescStatsReply, MAIN_DISPATCHER)
3362 def meter_desc_stats_reply_handler(self, ev):
3364 for stat in ev.msg.body:
3365 configs.append('length=%d flags=0x%04x meter_id=0x%08x '
3367 (stat.length, stat.flags, stat.meter_id,
3369 self.logger.debug('MeterDescStats: %s', configs)
3372 def __init__(self, datapath, type_=None, **kwargs):
3373 super(OFPMeterDescStatsReply, self).__init__(datapath, **kwargs)
3376 class OFPMeterFeaturesStats(ofproto_parser.namedtuple('OFPMeterFeaturesStats',
3377 ('max_meter', 'band_types', 'capabilities',
3378 'max_bands', 'max_color', 'features'))):
3380 def parser(cls, buf, offset):
3381 meter_features = struct.unpack_from(
3382 ofproto.OFP_METER_FEATURES_PACK_STR, buf, offset)
3383 stats = cls(*meter_features)
3384 stats.length = ofproto.OFP_METER_FEATURES_SIZE
3388 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
3389 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3390 class OFPMeterFeaturesStatsRequest(OFPMultipartRequest):
3392 Meter features statistics request message
3394 The controller uses this message to query the set of features of the
3397 ================ ======================================================
3398 Attribute Description
3399 ================ ======================================================
3400 flags Zero or ``OFPMPF_REQ_MORE``
3401 ================ ======================================================
3405 def send_meter_features_stats_request(self, datapath):
3406 ofp_parser = datapath.ofproto_parser
3408 req = ofp_parser.OFPMeterFeaturesStatsRequest(datapath, 0)
3409 datapath.send_msg(req)
3412 def __init__(self, datapath, flags=0, type_=None):
3413 super(OFPMeterFeaturesStatsRequest, self).__init__(datapath, flags)
3416 @OFPMultipartReply.register_stats_type()
3417 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
3418 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3419 class OFPMeterFeaturesStatsReply(OFPMultipartReply):
3421 Meter features statistics reply message
3423 The switch responds with this message to a meter features statistics
3426 ================ ======================================================
3427 Attribute Description
3428 ================ ======================================================
3429 body List of ``OFPMeterFeaturesStats`` instance
3430 ================ ======================================================
3434 @set_ev_cls(ofp_event.EventOFPMeterFeaturesStatsReply, MAIN_DISPATCHER)
3435 def meter_features_stats_reply_handler(self, ev):
3437 for stat in ev.msg.body:
3438 features.append('max_meter=%d band_types=0x%08x '
3439 'capabilities=0x%08x max_bands=%d '
3441 (stat.max_meter, stat.band_types,
3442 stat.capabilities, stat.max_bands,
3444 self.logger.debug('MeterFeaturesStats: %s', features)
3447 def __init__(self, datapath, type_=None, **kwargs):
3448 super(OFPMeterFeaturesStatsReply, self).__init__(datapath, **kwargs)
3451 class OFPFlowUpdate(StringifyMixin):
3452 def __init__(self, length, event):
3453 super(OFPFlowUpdate, self).__init__()
3454 self.length = length
3458 class OFPFlowUpdateHeader(OFPFlowUpdate):
3462 def register_flow_update_event(event, length):
3463 def _register_flow_update_event(cls):
3464 OFPFlowUpdateHeader._EVENT[event] = cls
3465 cls.cls_flow_update_event = event
3466 cls.cls_flow_update_length = length
3468 return _register_flow_update_event
3470 def __init__(self, length=None, event=None):
3471 cls = self.__class__
3472 super(OFPFlowUpdateHeader, self).__init__(length,
3473 cls.cls_flow_update_event)
3474 self.length = length
3477 def parser(cls, buf, offset):
3478 length, event = struct.unpack_from(
3479 ofproto.OFP_FLOW_UPDATE_HEADER_PACK_STR, buf, offset)
3480 cls_ = cls._EVENT[event]
3481 return cls_.parser(buf, offset)
3484 @OFPFlowUpdateHeader.register_flow_update_event(
3485 ofproto.OFPFME_INITIAL, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3486 @OFPFlowUpdateHeader.register_flow_update_event(
3487 ofproto.OFPFME_ADDED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3488 @OFPFlowUpdateHeader.register_flow_update_event(
3489 ofproto.OFPFME_REMOVED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3490 @OFPFlowUpdateHeader.register_flow_update_event(
3491 ofproto.OFPFME_MODIFIED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3492 class OFPFlowUpdateFull(OFPFlowUpdateHeader):
3493 def __init__(self, length=None, event=None, table_id=None, reason=None,
3494 idle_timeout=None, hard_timeout=None, priority=None,
3495 cookie=None, match=None, instructions=None):
3496 instructions = instructions if instructions else []
3497 super(OFPFlowUpdateFull, self).__init__(length, event)
3498 self.table_id = table_id
3499 self.reason = reason
3500 self.idle_timeout = idle_timeout
3501 self.hard_timeout = hard_timeout
3502 self.priority = priority
3503 self.cookie = cookie
3505 assert (event != ofproto.OFPFME_REMOVED or len(instructions) == 0)
3506 for i in instructions:
3507 assert isinstance(i, OFPInstruction)
3508 self.instructions = instructions
3511 def parser(cls, buf, offset):
3512 (length, event, table_id, reason, idle_timeout, hard_timeout, priority,
3513 cookie) = struct.unpack_from(ofproto.OFP_FLOW_UPDATE_FULL_0_PACK_STR,
3515 offset += ofproto.OFP_FLOW_UPDATE_FULL_0_SIZE
3516 assert cls.cls_flow_update_length <= length
3517 assert cls.cls_flow_update_event == event
3519 match = OFPMatch.parser(buf, offset)
3520 match_length = utils.round_up(match.length, 8)
3521 offset += match_length
3523 inst_length = (length - ofproto.OFP_FLOW_UPDATE_FULL_0_SIZE -
3526 while inst_length > 0:
3527 inst = OFPInstruction.parser(buf, offset)
3528 instructions.append(inst)
3530 inst_length -= inst.len
3532 return cls(length, event, table_id, reason, idle_timeout,
3533 hard_timeout, priority, cookie, match, instructions)
3536 @OFPFlowUpdateHeader.register_flow_update_event(
3537 ofproto.OFPFME_ABBREV, ofproto.OFP_FLOW_UPDATE_ABBREV_SIZE)
3538 class OFPFlowUpdateAbbrev(OFPFlowUpdateHeader):
3539 def __init__(self, length=None, event=None, xid=None):
3540 super(OFPFlowUpdateAbbrev, self).__init__(length, event)
3544 def parser(cls, buf, offset):
3545 length, event, xid = struct.unpack_from(
3546 ofproto.OFP_FLOW_UPDATE_ABBREV_PACK_STR, buf, offset)
3547 assert cls.cls_flow_update_length == length
3548 assert cls.cls_flow_update_event == event
3550 return cls(length, event, xid)
3553 @OFPFlowUpdateHeader.register_flow_update_event(
3554 ofproto.OFPFME_PAUSED, ofproto.OFP_FLOW_UPDATE_PAUSED_SIZE)
3555 @OFPFlowUpdateHeader.register_flow_update_event(
3556 ofproto.OFPFME_RESUMED, ofproto.OFP_FLOW_UPDATE_PAUSED_SIZE)
3557 class OFPFlowUpdatePaused(OFPFlowUpdateHeader):
3559 def parser(cls, buf, offset):
3560 length, event = struct.unpack_from(
3561 ofproto.OFP_FLOW_UPDATE_PAUSED_PACK_STR, buf, offset)
3562 assert cls.cls_flow_update_length == length
3563 assert cls.cls_flow_update_event == event
3565 return cls(length, event)
3568 class OFPFlowMonitorRequestBase(OFPMultipartRequest):
3569 def __init__(self, datapath, flags, monitor_id, out_port, out_group,
3570 monitor_flags, table_id, command, match):
3571 super(OFPFlowMonitorRequestBase, self).__init__(datapath, flags)
3572 self.monitor_id = monitor_id
3573 self.out_port = out_port
3574 self.out_group = out_group
3575 self.monitor_flags = monitor_flags
3576 self.table_id = table_id
3577 self.command = command
3580 def _serialize_stats_body(self):
3581 offset = ofproto.OFP_MULTIPART_REQUEST_SIZE
3582 msg_pack_into(ofproto.OFP_FLOW_MONITOR_REQUEST_0_PACK_STR, self.buf,
3583 offset, self.monitor_id, self.out_port, self.out_group,
3584 self.monitor_flags, self.table_id, self.command)
3586 offset += ofproto.OFP_FLOW_MONITOR_REQUEST_0_SIZE
3587 self.match.serialize(self.buf, offset)
3590 @_set_stats_type(ofproto.OFPMP_FLOW_MONITOR, OFPFlowUpdateHeader)
3591 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3592 class OFPFlowMonitorRequest(OFPFlowMonitorRequestBase):
3594 Flow monitor request message
3596 The controller uses this message to query flow monitors.
3598 ================ ======================================================
3599 Attribute Description
3600 ================ ======================================================
3601 flags Zero or ``OFPMPF_REQ_MORE``
3602 monitor_id Controller-assigned ID for this monitor
3603 out_port Require matching entries to include this as an output
3605 out_group Require matching entries to include this as an output
3607 monitor_flags Bitmap of the following flags.
3613 | OFPFMF_INSTRUCTIONS
3616 table_id ID of table to monitor
3617 command One of the following values.
3622 match Instance of ``OFPMatch``
3623 ================ ======================================================
3627 def send_flow_monitor_request(self, datapath):
3628 ofp = datapath.ofproto
3629 ofp_parser = datapath.ofproto_parser
3631 monitor_flags = [ofp.OFPFMF_INITIAL, ofp.OFPFMF_ONLY_OWN]
3632 match = ofp_parser.OFPMatch(in_port=1)
3633 req = ofp_parser.OFPFlowMonitorRequest(datapath, 0, 10000,
3634 ofp.OFPP_ANY, ofp.OFPG_ANY,
3637 ofp.OFPFMC_ADD, match)
3638 datapath.send_msg(req)
3641 def __init__(self, datapath, flags=0, monitor_id=0,
3642 out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY,
3643 monitor_flags=0, table_id=ofproto.OFPTT_ALL,
3644 command=ofproto.OFPFMC_ADD, match=None, type_=None):
3647 super(OFPFlowMonitorRequest, self).__init__(datapath, flags,
3648 monitor_id, out_port,
3649 out_group, monitor_flags,
3650 table_id, command, match)
3653 @OFPMultipartReply.register_stats_type()
3654 @_set_stats_type(ofproto.OFPMP_FLOW_MONITOR, OFPFlowUpdateHeader)
3655 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3656 class OFPFlowMonitorReply(OFPMultipartReply):
3658 Flow monitor reply message
3660 The switch responds with this message to a flow monitor request.
3662 ================ ======================================================
3663 Attribute Description
3664 ================ ======================================================
3665 body List of list of the following class instance.
3667 | OFPFlowMonitorFull
3668 | OFPFlowMonitorAbbrev
3669 | OFPFlowMonitorPaused
3670 ================ ======================================================
3674 @set_ev_cls(ofp_event.EventOFPFlowMonitorReply, MAIN_DISPATCHER)
3675 def flow_monitor_reply_handler(self, ev):
3681 for update in msg.body:
3682 update_str = 'length=%d event=%d' %
3683 (update.length, update.event)
3684 if (update.event == ofp.OFPFME_INITIAL or
3685 update.event == ofp.OFPFME_ADDED or
3686 update.event == ofp.OFPFME_REMOVED or
3687 update.event == ofp.OFPFME_MODIFIED):
3688 update_str += 'table_id=%d reason=%d idle_timeout=%d '
3689 'hard_timeout=%d priority=%d cookie=%d '
3690 'match=%d instructions=%s' %
3691 (update.table_id, update.reason,
3692 update.idle_timeout, update.hard_timeout,
3693 update.priority, update.cookie,
3694 update.match, update.instructions)
3695 elif update.event == ofp.OFPFME_ABBREV:
3696 update_str += 'xid=%d' % (update.xid)
3697 flow_updates.append(update_str)
3698 self.logger.debug('FlowUpdates: %s', flow_updates)
3701 def __init__(self, datapath, type_=None, **kwargs):
3702 super(OFPFlowMonitorReply, self).__init__(datapath, **kwargs)
3705 class OFPBundleFeaturesProp(OFPPropBase):
3709 @OFPBundleFeaturesProp.register_type(ofproto.OFPTMPBF_TIME_CAPABILITY)
3710 class OFPBundleFeaturesPropTime(OFPBundleFeaturesProp):
3711 def __init__(self, type_=None, length=None, sched_accuracy=None,
3712 sched_max_future=None, sched_max_past=None, timestamp=None):
3713 super(OFPBundleFeaturesPropTime, self).__init__(type_, length)
3714 self.sched_accuracy = sched_accuracy
3715 self.sched_max_future = sched_max_future
3716 self.sched_max_past = sched_max_past
3717 self.timestamp = timestamp
3720 def parser(cls, buf):
3722 (prop.type, prop.length) = struct.unpack_from(
3723 ofproto.OFP_BUNDLE_FEATURES_PROP_TIME_0_PACK_STR, buf)
3724 offset = ofproto.OFP_BUNDLE_FEATURES_PROP_TIME_0_SIZE
3726 for f in ['sched_accuracy', 'sched_max_future', 'sched_max_past',
3728 t = OFPTime.parser(buf, offset)
3730 offset += ofproto.OFP_TIME_SIZE
3734 def serialize(self):
3736 self.length = ofproto.OFP_BUNDLE_FEATURES_PROP_TIME_SIZE
3739 msg_pack_into(ofproto.OFP_BUNDLE_FEATURES_PROP_TIME_0_PACK_STR, buf, 0,
3740 self.type, self.length)
3741 offset = ofproto.OFP_BUNDLE_FEATURES_PROP_TIME_0_SIZE
3743 for f in [self.sched_accuracy, self.sched_max_future,
3744 self.sched_max_past, self.timestamp]:
3745 f.serialize(buf, offset)
3746 offset += ofproto.OFP_TIME_SIZE
3751 @OFPBundleFeaturesProp.register_type(ofproto.OFPTMPBF_EXPERIMENTER)
3752 class OFPBundleFeaturesPropExperimenter(OFPPropCommonExperimenter4ByteData):
3756 class OFPBundleFeaturesStats(ofproto_parser.namedtuple(
3757 'OFPBundleFeaturesStats', ('capabilities', 'properties'))):
3759 def parser(cls, buf, offset):
3760 (capabilities, ) = struct.unpack_from(
3761 ofproto.OFP_BUNDLE_FEATURES_PACK_STR, buf, offset)
3764 length = ofproto.OFP_BUNDLE_FEATURES_SIZE
3765 rest = buf[offset + length:]
3767 p, rest = OFPBundleFeaturesProp.parse(rest)
3768 properties.append(p)
3771 bndl = cls(capabilities, properties)
3772 # Note: length field is not defined in the specification and
3773 # is specific to this implementation.
3774 bndl.length = length
3778 @_set_stats_type(ofproto.OFPMP_BUNDLE_FEATURES, OFPBundleFeaturesStats)
3779 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3780 class OFPBundleFeaturesStatsRequest(OFPMultipartRequest):
3782 Bundle features request message
3784 The controller uses this message to query a switch about its bundle
3785 capabilities, including whether it supports atomic bundles, ordered
3786 bundles, and scheduled bundles.
3788 ====================== ====================================================
3789 Attribute Description
3790 ====================== ====================================================
3791 flags Zero or ``OFPMPF_REQ_MORE``
3792 feature_request_flags Bitmap of the following flags.
3795 | OFPBF_TIME_SET_SCHED
3796 properties List of ``OFPBundleFeaturesProp`` subclass instance
3797 ====================== ====================================================
3801 def send_bundle_features_stats_request(self, datapath):
3802 ofp = datapath.ofproto
3803 ofp_parser = datapath.ofproto_parser
3805 req = ofp_parser.OFPBundleFeaturesStatsRequest(datapath, 0)
3806 datapath.send_msg(req)
3809 def __init__(self, datapath, flags=0, feature_request_flags=0,
3810 properties=None, type_=None):
3811 properties = properties if properties else []
3812 super(OFPBundleFeaturesStatsRequest, self).__init__(datapath, flags)
3813 self.feature_request_flags = feature_request_flags
3814 self.properties = properties
3816 def _serialize_stats_body(self):
3817 bin_props = bytearray()
3818 for p in self.properties:
3819 bin_props += p.serialize()
3821 msg_pack_into(ofproto.OFP_BUNDLE_FEATURES_REQUEST_PACK_STR,
3822 self.buf, ofproto.OFP_MULTIPART_REQUEST_SIZE,
3823 self.feature_request_flags)
3824 self.buf += bin_props
3827 @OFPMultipartReply.register_stats_type(body_single_struct=True)
3828 @_set_stats_type(ofproto.OFPMP_BUNDLE_FEATURES, OFPBundleFeaturesStats)
3829 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3830 class OFPBundleFeaturesStatsReply(OFPMultipartReply):
3832 Bundle features reply message
3834 The switch responds with this message to a bundle features request.
3836 ================ ======================================================
3837 Attribute Description
3838 ================ ======================================================
3839 body Instance of ``OFPBundleFeaturesStats``
3840 ================ ======================================================
3844 @set_ev_cls(ofp_event.EventOFPBundleFeaturesStatsReply, MAIN_DISPATCHER)
3845 def bundle_features_stats_reply_handler(self, ev):
3848 self.logger.debug('OFPBundleFeaturesStats: capabilities=%0x%08x '
3850 body.capabilities, repr(body.properties))
3853 def __init__(self, datapath, type_=None, **kwargs):
3854 super(OFPBundleFeaturesStatsReply, self).__init__(datapath, **kwargs)
3857 class OFPExperimenterMultipart(ofproto_parser.namedtuple(
3858 'OFPExperimenterMultipart',
3859 ('experimenter', 'exp_type', 'data'))):
3861 The body of OFPExperimenterStatsReply multipart messages.
3863 ================ ======================================================
3864 Attribute Description
3865 ================ ======================================================
3866 experimenter Experimenter ID
3867 exp_type Experimenter defined
3868 data Experimenter defined additional data
3869 ================ ======================================================
3873 def parser(cls, buf, offset):
3874 args = struct.unpack_from(
3875 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR, buf,
3878 args.append(buf[offset +
3879 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_SIZE:])
3881 stats.length = ofproto.OFP_METER_FEATURES_SIZE
3884 def serialize(self):
3886 msg_pack_into(ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR,
3888 self.experimenter, self.exp_type)
3889 return buf + self.data
3892 class OFPExperimenterStatsRequestBase(OFPMultipartRequest):
3893 def __init__(self, datapath, flags,
3894 experimenter, exp_type,
3896 super(OFPExperimenterStatsRequestBase, self).__init__(datapath, flags)
3897 self.experimenter = experimenter
3898 self.exp_type = exp_type
3901 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
3902 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3903 class OFPExperimenterStatsRequest(OFPExperimenterStatsRequestBase):
3905 Experimenter multipart request message
3907 ================ ======================================================
3908 Attribute Description
3909 ================ ======================================================
3910 flags Zero or ``OFPMPF_REQ_MORE``
3911 experimenter Experimenter ID
3912 exp_type Experimenter defined
3913 data Experimenter defined additional data
3914 ================ ======================================================
3917 def __init__(self, datapath, flags,
3918 experimenter, exp_type, data,
3920 super(OFPExperimenterStatsRequest, self).__init__(datapath, flags,
3925 def _serialize_stats_body(self):
3926 body = OFPExperimenterMultipart(experimenter=self.experimenter,
3927 exp_type=self.exp_type,
3929 self.buf += body.serialize()
3932 @OFPMultipartReply.register_stats_type(body_single_struct=True)
3933 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
3934 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3935 class OFPExperimenterStatsReply(OFPMultipartReply):
3937 Experimenter multipart reply message
3939 ================ ======================================================
3940 Attribute Description
3941 ================ ======================================================
3942 body An ``OFPExperimenterMultipart`` instance
3943 ================ ======================================================
3946 def __init__(self, datapath, type_=None, **kwargs):
3947 super(OFPExperimenterStatsReply, self).__init__(datapath, **kwargs)
3950 class OFPFlowDesc(StringifyMixin):
3951 def __init__(self, table_id=None, priority=None,
3952 idle_timeout=None, hard_timeout=None, flags=None,
3953 importance=None, cookie=None, match=None, stats=None,
3954 instructions=None, length=None):
3955 super(OFPFlowDesc, self).__init__()
3956 self.length = length
3957 self.table_id = table_id
3958 self.priority = priority
3959 self.idle_timeout = idle_timeout
3960 self.hard_timeout = hard_timeout
3962 self.importance = importance
3963 self.cookie = cookie
3966 self.instructions = instructions
3969 def parser(cls, buf, offset):
3972 (flow_desc.length, flow_desc.table_id,
3973 flow_desc.priority, flow_desc.idle_timeout,
3974 flow_desc.hard_timeout, flow_desc.flags,
3975 flow_desc.importance,
3976 flow_desc.cookie) = struct.unpack_from(
3977 ofproto.OFP_FLOW_DESC_0_PACK_STR, buf, offset)
3978 offset += ofproto.OFP_FLOW_DESC_0_SIZE
3980 flow_desc.match = OFPMatch.parser(buf, offset)
3981 match_length = utils.round_up(flow_desc.match.length, 8)
3982 offset += match_length
3984 flow_desc.stats = OFPStats.parser(buf, offset)
3985 stats_length = utils.round_up(flow_desc.stats.length, 8)
3986 offset += stats_length
3989 inst_length = (flow_desc.length - (ofproto.OFP_FLOW_DESC_0_SIZE +
3990 match_length + stats_length))
3991 while inst_length > 0:
3992 inst = OFPInstruction.parser(buf, offset)
3993 instructions.append(inst)
3995 inst_length -= inst.len
3997 flow_desc.instructions = instructions
4001 class OFPFlowStats(StringifyMixin):
4002 def __init__(self, table_id=None, reason=None, priority=None,
4003 match=None, stats=None, length=None):
4004 super(OFPFlowStats, self).__init__()
4005 self.table_id = table_id
4006 self.reason = reason
4007 self.priority = priority
4010 self.length = length
4013 def parser(cls, buf, offset):
4016 (flow_stats.length, flow_stats.table_id, flow_stats.reason,
4017 flow_stats.priority) = struct.unpack_from(
4018 ofproto.OFP_FLOW_STATS_0_PACK_STR, buf, offset)
4019 offset += ofproto.OFP_FLOW_STATS_0_SIZE
4021 flow_stats.match = OFPMatch.parser(buf, offset)
4022 match_length = utils.round_up(flow_stats.match.length, 8)
4023 offset += match_length
4025 stats_length = (flow_stats.length - (ofproto.OFP_FLOW_STATS_0_SIZE +
4027 if stats_length > 0:
4028 flow_stats.stats = OFPStats.parser(buf, offset)
4033 class OFPFlowStatsRequestBase(OFPMultipartRequest):
4034 def __init__(self, datapath, flags, table_id, out_port, out_group,
4035 cookie, cookie_mask, match):
4036 super(OFPFlowStatsRequestBase, self).__init__(datapath, flags)
4037 self.table_id = table_id
4038 self.out_port = out_port
4039 self.out_group = out_group
4040 self.cookie = cookie
4041 self.cookie_mask = cookie_mask
4044 def _serialize_stats_body(self):
4045 offset = ofproto.OFP_MULTIPART_REQUEST_SIZE
4046 msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_0_PACK_STR,
4047 self.buf, offset, self.table_id, self.out_port,
4048 self.out_group, self.cookie, self.cookie_mask)
4050 offset += ofproto.OFP_FLOW_STATS_REQUEST_0_SIZE
4051 self.match.serialize(self.buf, offset)
4054 @_set_stats_type(ofproto.OFPMP_FLOW_DESC, OFPFlowDesc)
4055 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4056 class OFPFlowDescStatsRequest(OFPFlowStatsRequestBase):
4058 Individual flow descriptions request message
4060 The controller uses this message to query individual flow descriptions.
4062 ================ ======================================================
4063 Attribute Description
4064 ================ ======================================================
4065 flags Zero or ``OFPMPF_REQ_MORE``
4066 table_id ID of table to read
4067 out_port Require matching entries to include this as an output
4069 out_group Require matching entries to include this as an output
4071 cookie Require matching entries to contain this cookie value
4072 cookie_mask Mask used to restrict the cookie bits that must match
4073 match Instance of ``OFPMatch``
4074 ================ ======================================================
4078 def send_flow_desc_request(self, datapath):
4079 ofp = datapath.ofproto
4080 ofp_parser = datapath.ofproto_parser
4082 cookie = cookie_mask = 0
4083 match = ofp_parser.OFPMatch(in_port=1)
4084 req = ofp_parser.OFPFlowDescStatsRequest(datapath, 0,
4088 cookie, cookie_mask,
4090 datapath.send_msg(req)
4093 def __init__(self, datapath, flags=0, table_id=ofproto.OFPTT_ALL,
4094 out_port=ofproto.OFPP_ANY,
4095 out_group=ofproto.OFPG_ANY,
4096 cookie=0, cookie_mask=0, match=None, type_=None):
4099 super(OFPFlowDescStatsRequest, self).__init__(
4100 datapath, flags, table_id, out_port, out_group, cookie,
4104 @OFPMultipartReply.register_stats_type()
4105 @_set_stats_type(ofproto.OFPMP_FLOW_DESC, OFPFlowDesc)
4106 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4107 class OFPFlowDescStatsReply(OFPMultipartReply):
4109 Individual flow descriptions reply message
4111 The switch responds with this message to an individual flow descriptions
4114 ================ ======================================================
4115 Attribute Description
4116 ================ ======================================================
4117 body List of ``OFPFlowDesc`` instance
4118 ================ ======================================================
4122 @set_ev_cls(ofp_event.EventOFPFlowDescStatsReply, MAIN_DISPATCHER)
4123 def flow_desc_reply_handler(self, ev):
4125 for stat in ev.msg.body:
4126 flows.append('table_id=%s priority=%d '
4127 'idle_timeout=%d hard_timeout=%d flags=0x%04x '
4128 'importance=%d cookie=%d match=%s '
4129 'stats=%s instructions=%s' %
4130 (stat.table_id, stat.priority,
4131 stat.idle_timeout, stat.hard_timeout,
4132 stat.flags, stat.importance,
4133 stat.cookie, stat.match,
4134 stat.stats, stat.instructions))
4135 self.logger.debug('FlowDesc: %s', flows)
4138 def __init__(self, datapath, type_=None, **kwargs):
4139 super(OFPFlowDescStatsReply, self).__init__(datapath, **kwargs)
4142 @_set_stats_type(ofproto.OFPMP_FLOW_STATS, OFPFlowStats)
4143 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4144 class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
4146 Individual flow statistics request message
4148 The controller uses this message to query individual flow statistics.
4150 ================ ======================================================
4151 Attribute Description
4152 ================ ======================================================
4153 flags Zero or ``OFPMPF_REQ_MORE``
4154 table_id ID of table to read
4155 out_port Require matching entries to include this as an output
4157 out_group Require matching entries to include this as an output
4159 cookie Require matching entries to contain this cookie value
4160 cookie_mask Mask used to restrict the cookie bits that must match
4161 match Instance of ``OFPMatch``
4162 ================ ======================================================
4166 def send_flow_stats_request(self, datapath):
4167 ofp = datapath.ofproto
4168 ofp_parser = datapath.ofproto_parser
4170 cookie = cookie_mask = 0
4171 match = ofp_parser.OFPMatch(in_port=1)
4172 req = ofp_parser.OFPFlowStatsRequest(datapath, 0,
4174 ofp.OFPP_ANY, ofp.OFPG_ANY,
4175 cookie, cookie_mask,
4177 datapath.send_msg(req)
4180 def __init__(self, datapath, flags=0, table_id=ofproto.OFPTT_ALL,
4181 out_port=ofproto.OFPP_ANY,
4182 out_group=ofproto.OFPG_ANY,
4183 cookie=0, cookie_mask=0, match=None, type_=None):
4186 super(OFPFlowStatsRequest, self).__init__(datapath, flags, table_id,
4187 out_port, out_group,
4188 cookie, cookie_mask, match)
4191 @OFPMultipartReply.register_stats_type()
4192 @_set_stats_type(ofproto.OFPMP_FLOW_STATS, OFPFlowStats)
4193 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4194 class OFPFlowStatsReply(OFPMultipartReply):
4196 Individual flow statistics reply message
4198 The switch responds with this message to an individual flow statistics
4201 ================ ======================================================
4202 Attribute Description
4203 ================ ======================================================
4204 body List of ``OFPFlowStats`` instance
4205 ================ ======================================================
4209 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
4210 def flow_stats_reply_handler(self, ev):
4212 for stat in ev.msg.body:
4213 flows.append('table_id=%s reason=%d priority=%d '
4214 'match=%s stats=%s' %
4215 (stat.table_id, stat.reason, stat.priority,
4216 stat.match, stat.stats))
4217 self.logger.debug('FlowStats: %s', flows)
4220 def __init__(self, datapath, type_=None, **kwargs):
4221 super(OFPFlowStatsReply, self).__init__(datapath, **kwargs)
4224 class OFPAggregateStats(StringifyMixin):
4225 def __init__(self, stats=None, length=None):
4226 super(OFPAggregateStats, self).__init__()
4228 # Note: length field is specific to this implementation.
4229 # It does not have a corresponding field in the specification.
4230 self.length = length
4233 def parser(cls, buf, offset):
4234 stats = OFPStats.parser(buf, offset)
4236 agg.length = utils.round_up(stats.length, 8)
4240 @_set_stats_type(ofproto.OFPMP_AGGREGATE_STATS, OFPAggregateStats)
4241 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4242 class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
4244 Aggregate flow statistics request message
4246 The controller uses this message to query aggregate flow statictics.
4248 ================ ======================================================
4249 Attribute Description
4250 ================ ======================================================
4251 flags Zero or ``OFPMPF_REQ_MORE``
4252 table_id ID of table to read
4253 out_port Require matching entries to include this as an output
4255 out_group Require matching entries to include this as an output
4257 cookie Require matching entries to contain this cookie value
4258 cookie_mask Mask used to restrict the cookie bits that must match
4259 match Instance of ``OFPMatch``
4260 ================ ======================================================
4264 def send_aggregate_stats_request(self, datapath):
4265 ofp = datapath.ofproto
4266 ofp_parser = datapath.ofproto_parser
4268 cookie = cookie_mask = 0
4269 match = ofp_parser.OFPMatch(in_port=1)
4270 req = ofp_parser.OFPAggregateStatsRequest(datapath, 0,
4274 cookie, cookie_mask,
4276 datapath.send_msg(req)
4279 def __init__(self, datapath, flags, table_id, out_port, out_group,
4280 cookie, cookie_mask, match, type_=None):
4281 super(OFPAggregateStatsRequest, self).__init__(datapath,
4291 @OFPMultipartReply.register_stats_type(body_single_struct=True)
4292 @_set_stats_type(ofproto.OFPMP_AGGREGATE_STATS, OFPAggregateStats)
4293 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4294 class OFPAggregateStatsReply(OFPMultipartReply):
4296 Aggregate flow statistics reply message
4298 The switch responds with this message to an aggregate flow statistics
4301 ================ ======================================================
4302 Attribute Description
4303 ================ ======================================================
4304 body Instance of ``OFPAggregateStats``
4305 ================ ======================================================
4309 @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
4310 def aggregate_stats_reply_handler(self, ev):
4313 self.logger.debug('AggregateStats: stats=%s', body.stats)
4316 def __init__(self, datapath, type_=None, **kwargs):
4317 super(OFPAggregateStatsReply, self).__init__(datapath, **kwargs)
4320 class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', (
4321 'table_id', 'active_count', 'lookup_count',
4324 def parser(cls, buf, offset):
4325 tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR,
4328 stats.length = ofproto.OFP_TABLE_STATS_SIZE
4332 @_set_stats_type(ofproto.OFPMP_TABLE_STATS, OFPTableStats)
4333 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4334 class OFPTableStatsRequest(OFPMultipartRequest):
4336 Table statistics request message
4338 The controller uses this message to query flow table statictics.
4340 ================ ======================================================
4341 Attribute Description
4342 ================ ======================================================
4343 flags Zero or ``OFPMPF_REQ_MORE``
4344 ================ ======================================================
4348 def send_table_stats_request(self, datapath):
4349 ofp_parser = datapath.ofproto_parser
4351 req = ofp_parser.OFPTableStatsRequest(datapath, 0)
4352 datapath.send_msg(req)
4355 def __init__(self, datapath, flags, type_=None):
4356 super(OFPTableStatsRequest, self).__init__(datapath, flags)
4359 @OFPMultipartReply.register_stats_type()
4360 @_set_stats_type(ofproto.OFPMP_TABLE_STATS, OFPTableStats)
4361 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4362 class OFPTableStatsReply(OFPMultipartReply):
4364 Table statistics reply message
4366 The switch responds with this message to a table statistics request.
4368 ================ ======================================================
4369 Attribute Description
4370 ================ ======================================================
4371 body List of ``OFPTableStats`` instance
4372 ================ ======================================================
4376 @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
4377 def table_stats_reply_handler(self, ev):
4379 for stat in ev.msg.body:
4380 tables.append('table_id=%d active_count=%d lookup_count=%d '
4381 ' matched_count=%d' %
4382 (stat.table_id, stat.active_count,
4383 stat.lookup_count, stat.matched_count))
4384 self.logger.debug('TableStats: %s', tables)
4387 def __init__(self, datapath, type_=None, **kwargs):
4388 super(OFPTableStatsReply, self).__init__(datapath, **kwargs)
4391 class OFPPortStatsProp(OFPPropBase):
4395 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_ETHERNET)
4396 class OFPPortStatsPropEthernet(OFPPortStatsProp):
4397 def __init__(self, type_=None, length=None, rx_frame_err=None,
4398 rx_over_err=None, rx_crc_err=None, collisions=None):
4400 self.length = length
4401 self.rx_frame_err = rx_frame_err
4402 self.rx_over_err = rx_over_err
4403 self.rx_crc_err = rx_crc_err
4404 self.collisions = collisions
4407 def parser(cls, buf):
4409 (ether.type, ether.length, ether.rx_frame_err, ether.rx_over_err,
4410 ether.rx_crc_err, ether.collisions) = struct.unpack_from(
4411 ofproto.OFP_PORT_STATS_PROP_ETHERNET_PACK_STR, buf, 0)
4415 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_OPTICAL)
4416 class OFPPortStatsPropOptical(OFPPortStatsProp):
4417 def __init__(self, type_=None, length=None, flags=None,
4418 tx_freq_lmda=None, tx_offset=None, tx_grid_span=None,
4419 rx_freq_lmda=None, rx_offset=None, rx_grid_span=None,
4420 tx_pwr=None, rx_pwr=None, bias_current=None,
4423 self.length = length
4425 self.tx_freq_lmda = tx_freq_lmda
4426 self.tx_offset = tx_offset
4427 self.tx_grid_span = tx_grid_span
4428 self.rx_freq_lmda = rx_freq_lmda
4429 self.rx_offset = rx_offset
4430 self.rx_grid_span = rx_grid_span
4431 self.tx_pwr = tx_pwr
4432 self.rx_pwr = rx_pwr
4433 self.bias_current = bias_current
4434 self.temperature = temperature
4437 def parser(cls, buf):
4439 (optical.type, optical.length, optical.flags,
4440 optical.tx_freq_lmda, optical.tx_offset, optical.tx_grid_span,
4441 optical.rx_freq_lmda, optical.rx_offset, optical.rx_grid_span,
4442 optical.tx_pwr, optical.rx_pwr, optical.bias_current,
4443 optical.temperature) = struct.unpack_from(
4444 ofproto.OFP_PORT_STATS_PROP_OPTICAL_PACK_STR, buf, 0)
4448 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_EXPERIMENTER)
4449 class OFPPortStatsPropExperimenter(OFPPropCommonExperimenter4ByteData):
4453 class OFPPortStats(StringifyMixin):
4454 def __init__(self, length=None, port_no=None, duration_sec=None,
4455 duration_nsec=None, rx_packets=None, tx_packets=None,
4456 rx_bytes=None, tx_bytes=None, rx_dropped=None,
4457 tx_dropped=None, rx_errors=None, tx_errors=None,
4459 super(OFPPortStats, self).__init__()
4460 self.length = length
4461 self.port_no = port_no
4462 self.duration_sec = duration_sec
4463 self.duration_nsec = duration_nsec
4464 self.rx_packets = rx_packets
4465 self.tx_packets = tx_packets
4466 self.rx_bytes = rx_bytes
4467 self.tx_bytes = tx_bytes
4468 self.rx_dropped = rx_dropped
4469 self.tx_dropped = tx_dropped
4470 self.rx_errors = rx_errors
4471 self.tx_errors = tx_errors
4472 self.properties = properties
4475 def parser(cls, buf, offset):
4476 (length, port_no, duration_sec, duration_nsec, rx_packets,
4477 tx_packets, rx_bytes, tx_bytes, rx_dropped, tx_dropped,
4478 rx_errors, tx_errors) = struct.unpack_from(
4479 ofproto.OFP_PORT_STATS_PACK_STR, buf, offset)
4481 rest = buf[offset + ofproto.OFP_PORT_STATS_SIZE:offset + length]
4483 p, rest = OFPPortStatsProp.parse(rest)
4485 stats = cls(length, port_no, duration_sec, duration_nsec, rx_packets,
4486 tx_packets, rx_bytes, tx_bytes, rx_dropped, tx_dropped,
4487 rx_errors, tx_errors, props)
4491 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
4492 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4493 class OFPPortStatsRequest(OFPMultipartRequest):
4495 Port statistics request message
4497 The controller uses this message to query information about ports
4500 ================ ======================================================
4501 Attribute Description
4502 ================ ======================================================
4503 flags Zero or ``OFPMPF_REQ_MORE``
4504 port_no Port number to read (OFPP_ANY to all ports)
4505 ================ ======================================================
4509 def send_port_stats_request(self, datapath):
4510 ofp = datapath.ofproto
4511 ofp_parser = datapath.ofproto_parser
4513 req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY)
4514 datapath.send_msg(req)
4517 def __init__(self, datapath, flags, port_no, type_=None):
4518 super(OFPPortStatsRequest, self).__init__(datapath, flags)
4519 self.port_no = port_no
4521 def _serialize_stats_body(self):
4522 msg_pack_into(ofproto.OFP_PORT_MULTIPART_REQUEST_PACK_STR,
4524 ofproto.OFP_MULTIPART_REQUEST_SIZE,
4528 @OFPMultipartReply.register_stats_type()
4529 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
4530 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4531 class OFPPortStatsReply(OFPMultipartReply):
4533 Port statistics reply message
4535 The switch responds with this message to a port statistics request.
4537 ================ ======================================================
4538 Attribute Description
4539 ================ ======================================================
4540 body List of ``OFPPortStats`` instance
4541 ================ ======================================================
4545 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
4546 def port_stats_reply_handler(self, ev):
4548 for stat in ev.msg.body:
4549 ports.append(stat.length, stat.port_no,
4550 stat.duration_sec, stat.duration_nsec,
4551 stat.rx_packets, stat.tx_packets,
4552 stat.rx_bytes, stat.tx_bytes,
4553 stat.rx_dropped, stat.tx_dropped,
4554 stat.rx_errors, stat.tx_errors,
4555 repr(stat.properties))
4556 self.logger.debug('PortStats: %s', ports)
4559 def __init__(self, datapath, type_=None, **kwargs):
4560 super(OFPPortStatsReply, self).__init__(datapath, **kwargs)
4563 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
4564 class OFPBarrierRequest(MsgBase):
4566 Barrier request message
4568 The controller sends this message to ensure message dependencies have
4569 been met or receive notifications for completed operations.
4573 def send_barrier_request(self, datapath):
4574 ofp_parser = datapath.ofproto_parser
4576 req = ofp_parser.OFPBarrierRequest(datapath)
4577 datapath.send_msg(req)
4580 def __init__(self, datapath):
4581 super(OFPBarrierRequest, self).__init__(datapath)
4585 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
4586 class OFPBarrierReply(MsgBase):
4588 Barrier reply message
4590 The switch responds with this message to a barrier request.
4594 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
4595 def barrier_reply_handler(self, ev):
4596 self.logger.debug('OFPBarrierReply received')
4599 def __init__(self, datapath):
4600 super(OFPBarrierReply, self).__init__(datapath)
4604 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
4605 class OFPPortStatus(MsgBase):
4609 The switch notifies controller of change of ports.
4611 ================ ======================================================
4612 Attribute Description
4613 ================ ======================================================
4614 reason One of the following values.
4619 desc instance of ``OFPPort``
4620 ================ ======================================================
4624 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
4625 def port_status_handler(self, ev):
4630 if msg.reason == ofp.OFPPR_ADD:
4632 elif msg.reason == ofp.OFPPR_DELETE:
4634 elif msg.reason == ofp.OFPPR_MODIFY:
4639 self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
4643 def __init__(self, datapath, reason=None, desc=None):
4644 super(OFPPortStatus, self).__init__(datapath)
4645 self.reason = reason
4649 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4650 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
4652 msg.reason = struct.unpack_from(
4653 ofproto.OFP_PORT_STATUS_PACK_STR, msg.buf,
4654 ofproto.OFP_HEADER_SIZE)[0]
4655 msg.desc = OFPPort.parser(msg.buf, ofproto.OFP_PORT_STATUS_DESC_OFFSET)
4660 @_set_msg_type(ofproto.OFPT_ROLE_STATUS)
4661 class OFPRoleStatus(MsgBase):
4665 The switch notifies controller of change of role.
4667 ================ ======================================================
4668 Attribute Description
4669 ================ ======================================================
4670 role One of the following values.
4672 | OFPCR_ROLE_NOCHANGE
4675 reason One of the following values.
4677 | OFPCRR_MASTER_REQUEST
4679 | OFPCRR_EXPERIMENTER
4680 generation_id Master Election Generation ID
4681 properties List of ``OFPRoleProp`` subclass instance
4682 ================ ======================================================
4686 @set_ev_cls(ofp_event.EventOFPRoleStatus, MAIN_DISPATCHER)
4687 def role_status_handler(self, ev):
4692 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
4693 role = 'ROLE NOCHANGE'
4694 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
4696 elif msg.role == ofp.OFPCR_ROLE_MASTER:
4697 role = 'ROLE MASTER'
4701 if msg.reason == ofp.OFPCRR_MASTER_REQUEST:
4702 reason = 'MASTER REQUEST'
4703 elif msg.reason == ofp.OFPCRR_CONFIG:
4705 elif msg.reason == ofp.OFPCRR_EXPERIMENTER:
4706 reason = 'EXPERIMENTER'
4710 self.logger.debug('OFPRoleStatus received: role=%s reason=%s '
4711 'generation_id=%d properties=%s', role, reason,
4712 msg.generation_id, repr(msg.properties))
4715 def __init__(self, datapath, role=None, reason=None,
4716 generation_id=None, properties=None):
4717 super(OFPRoleStatus, self).__init__(datapath)
4719 self.reason = reason
4720 self.generation_id = generation_id
4721 self.properties = properties
4724 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4725 msg = super(OFPRoleStatus, cls).parser(datapath, version, msg_type,
4727 (msg.role, msg.reason, msg.generation_id) = struct.unpack_from(
4728 ofproto.OFP_ROLE_STATUS_PACK_STR, msg.buf,
4729 ofproto.OFP_HEADER_SIZE)
4732 rest = msg.buf[ofproto.OFP_ROLE_STATUS_SIZE:]
4734 p, rest = OFPRoleProp.parse(rest)
4735 msg.properties.append(p)
4741 @_set_msg_type(ofproto.OFPT_TABLE_STATUS)
4742 class OFPTableStatus(MsgBase):
4744 Table status message
4746 The switch notifies controller of change of table status.
4748 ================ ======================================================
4749 Attribute Description
4750 ================ ======================================================
4751 reason One of the following values.
4753 | OFPTR_VACANCY_DOWN
4755 table ``OFPTableDesc`` instance
4756 ================ ======================================================
4760 @set_ev_cls(ofp_event.EventOFPTableStatus, MAIN_DISPATCHER)
4761 def table(self, ev):
4766 if msg.reason == ofp.OFPTR_VACANCY_DOWN:
4767 reason = 'VACANCY_DOWN'
4768 elif msg.reason == ofp.OFPTR_VACANCY_UP:
4769 reason = 'VACANCY_UP'
4773 self.logger.debug('OFPTableStatus received: reason=%s '
4774 'table_id=%d config=0x%08x properties=%s',
4775 reason, msg.table.table_id, msg.table.config,
4776 repr(msg.table.properties))
4779 def __init__(self, datapath, reason=None, table=None):
4780 super(OFPTableStatus, self).__init__(datapath)
4781 self.reason = reason
4785 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4786 msg = super(OFPTableStatus, cls).parser(datapath, version, msg_type,
4788 (msg.reason,) = struct.unpack_from(ofproto.OFP_TABLE_STATUS_0_PACK_STR,
4789 msg.buf, ofproto.OFP_HEADER_SIZE)
4791 msg.table = OFPTableDesc.parser(msg.buf,
4792 ofproto.OFP_TABLE_STATUS_0_SIZE)
4798 @_set_msg_type(ofproto.OFPT_REQUESTFORWARD)
4799 class OFPRequestForward(MsgInMsgBase):
4801 Forwarded request message
4803 The swtich forwards request messages from one controller to other
4806 ================ ======================================================
4807 Attribute Description
4808 ================ ======================================================
4809 request ``OFPGroupMod`` or ``OFPMeterMod`` instance
4810 ================ ======================================================
4814 @set_ev_cls(ofp_event.EventOFPRequestForward, MAIN_DISPATCHER)
4815 def request_forward_handler(self, ev):
4820 if msg.request.msg_type == ofp.OFPT_GROUP_MOD:
4822 'OFPRequestForward received: request=OFPGroupMod('
4823 'command=%d, type=%d, group_id=%d, command_bucket_id=%d, '
4824 'buckets=%s, properties=%s)',
4825 msg.request.command, msg.request.type,
4826 msg.request.group_id, msg.request.command_bucket_id,
4827 msg.request.buckets, repr(msg.request.properties))
4828 elif msg.request.msg_type == ofp.OFPT_METER_MOD:
4830 'OFPRequestForward received: request=OFPMeterMod('
4831 'command=%d, flags=%d, meter_id=%d, bands=%s)',
4832 msg.request.command, msg.request.flags,
4833 msg.request.meter_id, msg.request.bands)
4836 'OFPRequestForward received: request=Unknown')
4839 def __init__(self, datapath, request=None):
4840 super(OFPRequestForward, self).__init__(datapath)
4841 self.request = request
4844 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4845 msg = super(OFPRequestForward, cls).parser(
4846 datapath, version, msg_type, msg_len, xid, buf)
4847 req_buf = buf[ofproto.OFP_HEADER_SIZE:]
4848 (_ver, _type, _len, _xid) = ofproto_parser.header(req_buf)
4849 msg.request = ofproto_parser.msg(
4850 datapath, _ver, _type, _len, _xid, req_buf)
4853 def _serialize_body(self):
4854 assert isinstance(self.request, (OFPGroupMod, OFPMeterMod))
4855 self.request.serialize()
4856 self.buf += self.request.buf
4859 class OFPControllerStatusProp(OFPPropBase):
4863 @OFPControllerStatusProp.register_type(ofproto.OFPCSPT_URI)
4864 class OFPControllerStatusPropUri(OFPControllerStatusProp):
4871 def __init__(self, type_=None, length=None, uri=None):
4872 super(OFPControllerStatusPropUri, self).__init__(type_, length)
4876 def parser(cls, buf):
4877 rest = cls.get_rest(buf)
4878 pack_str = '!%ds' % len(rest)
4879 (uri, ) = struct.unpack_from(pack_str, rest, 0)
4883 @OFPControllerStatusProp.register_type(ofproto.OFPCSPT_EXPERIMENTER)
4884 class OFPControllerStatusPropExperimenter(OFPPropCommonExperimenter4ByteData):
4888 class OFPControllerStatusStats(StringifyMixin):
4891 Controller status structure
4893 ============== =========================================================
4894 Attribute Description
4895 ============== =========================================================
4896 length Length of this entry.
4897 short_id ID number which identifies the controller.
4898 role Bitmap of controller's role flags.
4900 | OFPCR_ROLE_NOCHANGE
4904 reason Bitmap of controller status reason flags.
4907 | OFPCSR_CHANNEL_STATUS
4909 | OFPCSR_CONTROLLER_ADDED
4910 | OFPCSR_CONTROLLER_REMOVED
4912 | OFPCSR_EXPERIMENTER
4913 channel_status Bitmap of control channel status flags.
4917 properties List of ``OFPControllerStatusProp`` subclass instance
4918 ============== =========================================================
4921 def __init__(self, short_id=None, role=None, reason=None,
4922 channel_status=None, properties=None, length=None):
4923 super(OFPControllerStatusStats, self).__init__()
4924 self.length = length
4925 self.short_id = short_id
4927 self.reason = reason
4928 self.channel_status = channel_status
4929 self.properties = properties
4932 def parser(cls, buf, offset):
4935 (status.length, status.short_id,
4936 status.role, status.reason,
4937 status.channel_status) = struct.unpack_from(
4938 ofproto.OFP_CONTROLLER_STATUS_PACK_STR, buf, offset)
4939 offset += ofproto.OFP_CONTROLLER_STATUS_SIZE
4941 status.properties = []
4942 rest = buf[offset:offset + status.length]
4944 p, rest = OFPControllerStatusProp.parse(rest)
4945 status.properties.append(p)
4950 @_set_stats_type(ofproto.OFPMP_CONTROLLER_STATUS, OFPControllerStatusStats)
4951 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
4952 class OFPControllerStatusStatsRequest(OFPMultipartRequest):
4954 Controller status multipart request message
4956 The controller uses this message to request the status, the roles
4957 and the control channels of other controllers configured on the switch.
4959 ================ ======================================================
4960 Attribute Description
4961 ================ ======================================================
4962 flags Zero or ``OFPMPF_REQ_MORE``
4963 ================ ======================================================
4967 def send_controller_status_multipart_request(self, datapath):
4968 ofp_parser = datapath.ofproto_parser
4970 req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
4971 datapath.send_msg(req)
4974 def __init__(self, datapath, flags=0, type_=None):
4975 super(OFPControllerStatusStatsRequest,
4976 self).__init__(datapath, flags)
4979 @OFPMultipartReply.register_stats_type()
4980 @_set_stats_type(ofproto.OFPMP_CONTROLLER_STATUS, OFPControllerStatusStats)
4981 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
4982 class OFPControllerStatusStatsReply(OFPMultipartReply):
4984 Controller status multipart reply message
4986 The switch responds with this message to a controller status
4989 ================ ======================================================
4990 Attribute Description
4991 ================ ======================================================
4992 body List of ``OFPControllerStatus`` instance
4993 ================ ======================================================
4997 @set_ev_cls(ofp_event.EventOFPControllerStatusStatsReply,
4999 def controller_status_multipart_reply_handler(self, ev):
5001 for s in ev.msg.body:
5002 status.append('short_id=%d role=%d reason=%d '
5003 'channel_status=%d properties=%s' %
5004 (s.short_id, s.role, s.reason,
5005 s.channel_status, repr(s.properties)))
5006 self.logger.debug('OFPControllerStatusStatsReply received: %s',
5010 def __init__(self, datapath, type_=None, **kwargs):
5011 super(OFPControllerStatusStatsReply, self).__init__(datapath,
5016 @_set_msg_type(ofproto.OFPT_CONTROLLER_STATUS)
5017 class OFPControllerStatus(MsgBase):
5019 Controller status message
5021 The switch informs the controller about the status of the control
5022 channel it maintains with each controller.
5024 ================ ======================================================
5025 Attribute Description
5026 ================ ======================================================
5027 status ``OFPControllerStatusStats`` instance
5028 ================ ======================================================
5032 @set_ev_cls(ofp_event.EventOFPControllerStatus, MAIN_DISPATCHER)
5033 def table(self, ev):
5039 if status.role == ofp.OFPCR_ROLE_NOCHANGE:
5041 elif status.role == ofp.OFPCR_ROLE_EQUAL:
5043 elif status.role == ofp.OFPCR_ROLE_MASTER:
5045 elif status.role == ofp.OFPCR_ROLE_SLAVE:
5050 if status.reason == ofp.OFPCSR_REQUEST:
5052 elif status.reason == ofp.OFPCSR_CHANNEL_STATUS:
5053 reason = 'CHANNEL_STATUS'
5054 elif status.reason == ofp.OFPCSR_ROLE:
5056 elif status.reason == ofp.OFPCSR_CONTROLLER_ADDED:
5057 reason = 'CONTROLLER_ADDED'
5058 elif status.reason == ofp.OFPCSR_CONTROLLER_REMOVED:
5059 reason = 'CONTROLLER_REMOVED'
5060 elif status.reason == ofp.OFPCSR_SHORT_ID:
5062 elif status.reason == ofp.OFPCSR_EXPERIMENTER:
5063 reason = 'EXPERIMENTER'
5067 if status.channel_status == OFPCT_STATUS_UP:
5068 channel_status = 'UP'
5069 if status.channel_status == OFPCT_STATUS_DOWN:
5070 channel_status = 'DOWN'
5072 channel_status = 'unknown'
5074 self.logger.debug('OFPControllerStatus received: short_id=%d'
5075 'role=%s reason=%s channel_status=%s '
5077 status.short_id, role, reason, channel_status,
5078 repr(status.properties))
5081 def __init__(self, datapath, status=None):
5082 super(OFPControllerStatus, self).__init__(datapath)
5083 self.status = status
5086 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5087 msg = super(OFPControllerStatus, cls).parser(datapath, version,
5091 msg.status = OFPControllerStatusStats.parser(msg.buf,
5092 ofproto.OFP_HEADER_SIZE)
5097 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
5098 class OFPPacketOut(MsgBase):
5102 The controller uses this message to send a packet out throught the
5105 ================ ======================================================
5106 Attribute Description
5107 ================ ======================================================
5108 buffer_id ID assigned by datapath (OFP_NO_BUFFER if none)
5109 match Instance of ``OFPMatch``
5110 (``in_port`` is mandatory in the match field)
5111 actions list of OpenFlow action class
5112 data Packet data of a binary type value or
5113 an instances of packet.Packet.
5114 ================ ======================================================
5118 def send_packet_out(self, datapath, buffer_id, in_port):
5119 ofp = datapath.ofproto
5120 ofp_parser = datapath.ofproto_parser
5122 match = OFPMatch(in_port=in_port)
5123 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
5124 req = ofp_parser.OFPPacketOut(datapath, buffer_id,
5126 datapath.send_msg(req)
5129 def __init__(self, datapath, buffer_id=None, match=None, actions=None,
5130 data=None, actions_len=None):
5131 super(OFPPacketOut, self).__init__(datapath)
5132 if buffer_id is None:
5133 self.buffer_id = ofproto.OFP_NO_BUFFER
5135 self.buffer_id = buffer_id
5136 self.actions_len = 0
5137 assert 'in_port' in match
5139 self.actions = actions
5142 def _serialize_body(self):
5144 offset = ofproto.OFP_PACKET_OUT_0_SIZE
5145 match_len = self.match.serialize(self.buf, offset)
5148 self.actions_len = 0
5149 for a in self.actions:
5150 a.serialize(self.buf, offset)
5152 self.actions_len += a.len
5154 if self.buffer_id == ofproto.OFP_NO_BUFFER:
5155 assert self.data is not None
5156 if isinstance(self.data, packet.Packet):
5157 self.data.serialize()
5158 self.buf += self.data.data
5160 self.buf += self.data
5162 assert self.data is None
5164 msg_pack_into(ofproto.OFP_PACKET_OUT_0_PACK_STR,
5165 self.buf, ofproto.OFP_HEADER_SIZE,
5166 self.buffer_id, self.actions_len)
5169 def from_jsondict(cls, dict_, decode_string=base64.b64decode,
5171 if isinstance(dict_['data'], dict):
5172 data = dict_.pop('data')
5173 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
5176 ins.data = packet.Packet.from_jsondict(data['Packet'])
5177 dict_['data'] = data
5179 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
5187 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
5188 class OFPFlowMod(MsgBase):
5190 Modify Flow entry message
5192 The controller sends this message to modify the flow table.
5194 ================ ======================================================
5195 Attribute Description
5196 ================ ======================================================
5197 cookie Opaque controller-issued identifier
5198 cookie_mask Mask used to restrict the cookie bits that must match
5199 when the command is ``OPFFC_MODIFY*`` or
5201 table_id ID of the table to put the flow in
5202 command One of the following values.
5206 | OFPFC_MODIFY_STRICT
5208 | OFPFC_DELETE_STRICT
5209 idle_timeout Idle time before discarding (seconds)
5210 hard_timeout Max time before discarding (seconds)
5211 priority Priority level of flow entry
5212 buffer_id Buffered packet to apply to (or OFP_NO_BUFFER)
5213 out_port For ``OFPFC_DELETE*`` commands, require matching
5214 entries to include this as an output port
5215 out_group For ``OFPFC_DELETE*`` commands, require matching
5216 entries to include this as an output group
5217 flags Bitmap of the following flags.
5219 | OFPFF_SEND_FLOW_REM
5220 | OFPFF_CHECK_OVERLAP
5221 | OFPFF_RESET_COUNTS
5222 | OFPFF_NO_PKT_COUNTS
5223 | OFPFF_NO_BYT_COUNTS
5224 importance Eviction precedence
5225 match Instance of ``OFPMatch``
5226 instructions list of ``OFPInstruction*`` instance
5227 ================ ======================================================
5231 def send_flow_mod(self, datapath):
5232 ofp = datapath.ofproto
5233 ofp_parser = datapath.ofproto_parser
5235 cookie = cookie_mask = 0
5237 idle_timeout = hard_timeout = 0
5239 buffer_id = ofp.OFP_NO_BUFFER
5241 match = ofp_parser.OFPMatch(in_port=1, eth_dst='ff:ff:ff:ff:ff:ff')
5242 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
5243 inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
5245 req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask,
5246 table_id, ofp.OFPFC_ADD,
5247 idle_timeout, hard_timeout,
5248 priority, buffer_id,
5249 ofp.OFPP_ANY, ofp.OFPG_ANY,
5250 ofp.OFPFF_SEND_FLOW_REM,
5253 datapath.send_msg(req)
5256 def __init__(self, datapath, cookie=0, cookie_mask=0, table_id=0,
5257 command=ofproto.OFPFC_ADD,
5258 idle_timeout=0, hard_timeout=0,
5259 priority=ofproto.OFP_DEFAULT_PRIORITY,
5260 buffer_id=ofproto.OFP_NO_BUFFER,
5261 out_port=0, out_group=0, flags=0, importance=0,
5264 instructions = instructions if instructions else []
5265 super(OFPFlowMod, self).__init__(datapath)
5266 self.cookie = cookie
5267 self.cookie_mask = cookie_mask
5268 self.table_id = table_id
5269 self.command = command
5270 self.idle_timeout = idle_timeout
5271 self.hard_timeout = hard_timeout
5272 self.priority = priority
5273 self.buffer_id = buffer_id
5274 self.out_port = out_port
5275 self.out_group = out_group
5277 self.importance = importance
5280 assert isinstance(match, OFPMatch)
5282 for i in instructions:
5283 assert isinstance(i, OFPInstruction)
5284 self.instructions = instructions
5286 def _serialize_body(self):
5287 msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf,
5288 ofproto.OFP_HEADER_SIZE,
5289 self.cookie, self.cookie_mask, self.table_id,
5290 self.command, self.idle_timeout, self.hard_timeout,
5291 self.priority, self.buffer_id, self.out_port,
5292 self.out_group, self.flags, self.importance)
5294 offset = (ofproto.OFP_FLOW_MOD_SIZE -
5295 ofproto.OFP_MATCH_SIZE)
5297 match_len = self.match.serialize(self.buf, offset)
5300 for inst in self.instructions:
5301 inst.serialize(self.buf, offset)
5305 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5306 msg = super(OFPFlowMod, cls).parser(
5307 datapath, version, msg_type, msg_len, xid, buf)
5309 (msg.cookie, msg.cookie_mask, msg.table_id,
5310 msg.command, msg.idle_timeout, msg.hard_timeout,
5311 msg.priority, msg.buffer_id, msg.out_port,
5312 msg.out_group, msg.flags, msg.importance) = struct.unpack_from(
5313 ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf,
5314 ofproto.OFP_HEADER_SIZE)
5315 offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE
5317 msg.match = OFPMatch.parser(buf, offset)
5318 offset += utils.round_up(msg.match.length, 8)
5321 while offset < msg_len:
5322 i = OFPInstruction.parser(buf, offset)
5323 instructions.append(i)
5325 msg.instructions = instructions
5330 class OFPInstruction(StringifyMixin):
5331 _INSTRUCTION_TYPES = {}
5334 def register_instruction_type(types):
5335 def _register_instruction_type(cls):
5337 OFPInstruction._INSTRUCTION_TYPES[type_] = cls
5339 return _register_instruction_type
5342 def parser(cls, buf, offset):
5343 (type_, len_) = struct.unpack_from('!HH', buf, offset)
5344 cls_ = cls._INSTRUCTION_TYPES.get(type_)
5345 return cls_.parser(buf, offset)
5348 @OFPInstruction.register_instruction_type([ofproto.OFPIT_GOTO_TABLE])
5349 class OFPInstructionGotoTable(OFPInstruction):
5351 Goto table instruction
5353 This instruction indicates the next table in the processing pipeline.
5355 ================ ======================================================
5356 Attribute Description
5357 ================ ======================================================
5359 ================ ======================================================
5362 def __init__(self, table_id, type_=None, len_=None):
5363 super(OFPInstructionGotoTable, self).__init__()
5364 self.type = ofproto.OFPIT_GOTO_TABLE
5365 self.len = ofproto.OFP_INSTRUCTION_GOTO_TABLE_SIZE
5366 self.table_id = table_id
5369 def parser(cls, buf, offset):
5370 (type_, len_, table_id) = struct.unpack_from(
5371 ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
5373 return cls(table_id)
5375 def serialize(self, buf, offset):
5376 msg_pack_into(ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
5377 buf, offset, self.type, self.len, self.table_id)
5380 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_METADATA])
5381 class OFPInstructionWriteMetadata(OFPInstruction):
5383 Write metadata instruction
5385 This instruction writes the masked metadata value into the metadata field.
5387 ================ ======================================================
5388 Attribute Description
5389 ================ ======================================================
5390 metadata Metadata value to write
5391 metadata_mask Metadata write bitmask
5392 ================ ======================================================
5395 def __init__(self, metadata, metadata_mask, type_=None, len_=None):
5396 super(OFPInstructionWriteMetadata, self).__init__()
5397 self.type = ofproto.OFPIT_WRITE_METADATA
5398 self.len = ofproto.OFP_INSTRUCTION_WRITE_METADATA_SIZE
5399 self.metadata = metadata
5400 self.metadata_mask = metadata_mask
5403 def parser(cls, buf, offset):
5404 (type_, len_, metadata, metadata_mask) = struct.unpack_from(
5405 ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
5407 return cls(metadata, metadata_mask)
5409 def serialize(self, buf, offset):
5410 msg_pack_into(ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
5411 buf, offset, self.type, self.len, self.metadata,
5415 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS,
5416 ofproto.OFPIT_APPLY_ACTIONS,
5417 ofproto.OFPIT_CLEAR_ACTIONS])
5418 class OFPInstructionActions(OFPInstruction):
5422 This instruction writes/applies/clears the actions.
5424 ================ ======================================================
5425 Attribute Description
5426 ================ ======================================================
5427 type One of following values.
5429 | OFPIT_WRITE_ACTIONS
5430 | OFPIT_APPLY_ACTIONS
5431 | OFPIT_CLEAR_ACTIONS
5432 actions list of OpenFlow action class
5433 ================ ======================================================
5435 ``type`` attribute corresponds to ``type_`` parameter of __init__.
5438 def __init__(self, type_, actions=None, len_=None):
5439 super(OFPInstructionActions, self).__init__()
5442 assert isinstance(a, OFPAction)
5443 self.actions = actions
5446 def parser(cls, buf, offset):
5447 (type_, len_) = struct.unpack_from(
5448 ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
5451 offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
5453 actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
5454 while actions_len > 0:
5455 a = OFPAction.parser(buf, offset)
5457 actions_len -= a.len
5460 inst = cls(type_, actions)
5464 def serialize(self, buf, offset):
5465 action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
5467 for a in self.actions:
5468 a.serialize(buf, action_offset)
5469 action_offset += a.len
5471 self.len = action_offset - offset
5472 pad_len = utils.round_up(self.len, 8) - self.len
5473 msg_pack_into("%dx" % pad_len, buf, action_offset)
5476 msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
5477 buf, offset, self.type, self.len)
5480 @OFPInstruction.register_instruction_type([ofproto.OFPIT_STAT_TRIGGER])
5481 class OFPInstructionStatTrigger(OFPInstruction):
5483 Statistics triggers instruction
5485 This instruction defines a set of statistics thresholds using OXS.
5487 ================ ======================================================
5488 Attribute Description
5489 ================ ======================================================
5490 flags Bitmap of the following flags.
5494 thresholds Instance of ``OFPStats``
5495 ================ ======================================================
5498 def __init__(self, flags, thresholds, type_=None, len_=None):
5499 super(OFPInstructionStatTrigger, self).__init__()
5500 self.type = ofproto.OFPIT_STAT_TRIGGER
5503 self.thresholds = thresholds
5506 def parser(cls, buf, offset):
5507 (type_, len_, flags) = struct.unpack_from(
5508 ofproto.OFP_INSTRUCTION_STAT_TRIGGER_PACK_STR0, buf, offset)
5512 thresholds = OFPStats.parser(buf, offset)
5514 inst = cls(flags, thresholds)
5518 def serialize(self, buf, offset):
5519 stats_len = self.thresholds.serialize(buf, offset + 8)
5521 self.len = 8 + stats_len
5522 msg_pack_into(ofproto.OFP_INSTRUCTION_STAT_TRIGGER_PACK_STR0,
5523 buf, offset, self.type, self.len, self.flags)
5526 class OFPActionHeader(StringifyMixin):
5527 def __init__(self, type_, len_):
5531 def serialize(self, buf, offset):
5532 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
5533 buf, offset, self.type, self.len)
5536 class OFPAction(OFPActionHeader):
5540 def register_action_type(type_, len_):
5541 def _register_action_type(cls):
5542 cls.cls_action_type = type_
5543 cls.cls_action_len = len_
5544 OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
5546 return _register_action_type
5549 cls = self.__class__
5550 super(OFPAction, self).__init__(cls.cls_action_type,
5554 def parser(cls, buf, offset):
5555 type_, len_ = struct.unpack_from(
5556 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5557 cls_ = cls._ACTION_TYPES.get(type_)
5558 assert cls_ is not None
5559 return cls_.parser(buf, offset)
5562 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
5563 ofproto.OFP_ACTION_OUTPUT_SIZE)
5564 class OFPActionOutput(OFPAction):
5568 This action indicates output a packet to the switch port.
5570 ================ ======================================================
5571 Attribute Description
5572 ================ ======================================================
5574 max_len Max length to send to controller
5575 ================ ======================================================
5578 def __init__(self, port, max_len=ofproto.OFPCML_MAX,
5579 type_=None, len_=None):
5580 super(OFPActionOutput, self).__init__()
5582 self.max_len = max_len
5585 def parser(cls, buf, offset):
5586 type_, len_, port, max_len = struct.unpack_from(
5587 ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
5588 return cls(port, max_len)
5590 def serialize(self, buf, offset):
5591 msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
5592 offset, self.type, self.len, self.port, self.max_len)
5595 @OFPAction.register_action_type(ofproto.OFPAT_GROUP,
5596 ofproto.OFP_ACTION_GROUP_SIZE)
5597 class OFPActionGroup(OFPAction):
5601 This action indicates the group used to process the packet.
5603 ================ ======================================================
5604 Attribute Description
5605 ================ ======================================================
5606 group_id Group identifier
5607 ================ ======================================================
5610 def __init__(self, group_id=0, type_=None, len_=None):
5611 super(OFPActionGroup, self).__init__()
5612 self.group_id = group_id
5615 def parser(cls, buf, offset):
5616 (type_, len_, group_id) = struct.unpack_from(
5617 ofproto.OFP_ACTION_GROUP_PACK_STR, buf, offset)
5618 return cls(group_id)
5620 def serialize(self, buf, offset):
5621 msg_pack_into(ofproto.OFP_ACTION_GROUP_PACK_STR, buf,
5622 offset, self.type, self.len, self.group_id)
5625 @OFPAction.register_action_type(ofproto.OFPAT_SET_QUEUE,
5626 ofproto.OFP_ACTION_SET_QUEUE_SIZE)
5627 class OFPActionSetQueue(OFPAction):
5631 This action sets the queue id that will be used to map a flow to an
5632 already-configured queue on a port.
5634 ================ ======================================================
5635 Attribute Description
5636 ================ ======================================================
5637 queue_id Queue ID for the packets
5638 ================ ======================================================
5641 def __init__(self, queue_id, type_=None, len_=None):
5642 super(OFPActionSetQueue, self).__init__()
5643 self.queue_id = queue_id
5646 def parser(cls, buf, offset):
5647 (type_, len_, queue_id) = struct.unpack_from(
5648 ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf, offset)
5649 return cls(queue_id)
5651 def serialize(self, buf, offset):
5652 msg_pack_into(ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
5653 offset, self.type, self.len, self.queue_id)
5656 @OFPAction.register_action_type(ofproto.OFPAT_SET_MPLS_TTL,
5657 ofproto.OFP_ACTION_MPLS_TTL_SIZE)
5658 class OFPActionSetMplsTtl(OFPAction):
5662 This action sets the MPLS TTL.
5664 ================ ======================================================
5665 Attribute Description
5666 ================ ======================================================
5668 ================ ======================================================
5671 def __init__(self, mpls_ttl, type_=None, len_=None):
5672 super(OFPActionSetMplsTtl, self).__init__()
5673 self.mpls_ttl = mpls_ttl
5676 def parser(cls, buf, offset):
5677 (type_, len_, mpls_ttl) = struct.unpack_from(
5678 ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf, offset)
5679 return cls(mpls_ttl)
5681 def serialize(self, buf, offset):
5682 msg_pack_into(ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf,
5683 offset, self.type, self.len, self.mpls_ttl)
5686 @OFPAction.register_action_type(ofproto.OFPAT_DEC_MPLS_TTL,
5687 ofproto.OFP_ACTION_HEADER_SIZE)
5688 class OFPActionDecMplsTtl(OFPAction):
5690 Decrement MPLS TTL action
5692 This action decrements the MPLS TTL.
5695 def __init__(self, type_=None, len_=None):
5696 super(OFPActionDecMplsTtl, self).__init__()
5699 def parser(cls, buf, offset):
5700 (type_, len_) = struct.unpack_from(
5701 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5705 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TTL,
5706 ofproto.OFP_ACTION_NW_TTL_SIZE)
5707 class OFPActionSetNwTtl(OFPAction):
5711 This action sets the IP TTL.
5713 ================ ======================================================
5714 Attribute Description
5715 ================ ======================================================
5717 ================ ======================================================
5720 def __init__(self, nw_ttl, type_=None, len_=None):
5721 super(OFPActionSetNwTtl, self).__init__()
5722 self.nw_ttl = nw_ttl
5725 def parser(cls, buf, offset):
5726 (type_, len_, nw_ttl) = struct.unpack_from(
5727 ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
5730 def serialize(self, buf, offset):
5731 msg_pack_into(ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset,
5732 self.type, self.len, self.nw_ttl)
5735 @OFPAction.register_action_type(ofproto.OFPAT_DEC_NW_TTL,
5736 ofproto.OFP_ACTION_HEADER_SIZE)
5737 class OFPActionDecNwTtl(OFPAction):
5739 Decrement IP TTL action
5741 This action decrements the IP TTL.
5744 def __init__(self, type_=None, len_=None):
5745 super(OFPActionDecNwTtl, self).__init__()
5748 def parser(cls, buf, offset):
5749 (type_, len_) = struct.unpack_from(
5750 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5754 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_OUT,
5755 ofproto.OFP_ACTION_HEADER_SIZE)
5756 class OFPActionCopyTtlOut(OFPAction):
5760 This action copies the TTL from the next-to-outermost header with TTL to
5761 the outermost header with TTL.
5764 def __init__(self, type_=None, len_=None):
5765 super(OFPActionCopyTtlOut, self).__init__()
5768 def parser(cls, buf, offset):
5769 (type_, len_) = struct.unpack_from(
5770 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5774 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_IN,
5775 ofproto.OFP_ACTION_HEADER_SIZE)
5776 class OFPActionCopyTtlIn(OFPAction):
5780 This action copies the TTL from the outermost header with TTL to the
5781 next-to-outermost header with TTL.
5784 def __init__(self, type_=None, len_=None):
5785 super(OFPActionCopyTtlIn, self).__init__()
5788 def parser(cls, buf, offset):
5789 (type_, len_) = struct.unpack_from(
5790 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5794 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_VLAN,
5795 ofproto.OFP_ACTION_PUSH_SIZE)
5796 class OFPActionPushVlan(OFPAction):
5800 This action pushes a new VLAN tag to the packet.
5802 ================ ======================================================
5803 Attribute Description
5804 ================ ======================================================
5805 ethertype Ether type. The default is 802.1Q. (0x8100)
5806 ================ ======================================================
5809 def __init__(self, ethertype=ether.ETH_TYPE_8021Q, type_=None, len_=None):
5810 super(OFPActionPushVlan, self).__init__()
5811 self.ethertype = ethertype
5814 def parser(cls, buf, offset):
5815 (type_, len_, ethertype) = struct.unpack_from(
5816 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
5817 return cls(ethertype)
5819 def serialize(self, buf, offset):
5820 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
5821 self.type, self.len, self.ethertype)
5824 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_MPLS,
5825 ofproto.OFP_ACTION_PUSH_SIZE)
5826 class OFPActionPushMpls(OFPAction):
5830 This action pushes a new MPLS header to the packet.
5832 ================ ======================================================
5833 Attribute Description
5834 ================ ======================================================
5835 ethertype Ether type
5836 ================ ======================================================
5839 def __init__(self, ethertype=ether.ETH_TYPE_MPLS, type_=None, len_=None):
5840 super(OFPActionPushMpls, self).__init__()
5841 self.ethertype = ethertype
5844 def parser(cls, buf, offset):
5845 (type_, len_, ethertype) = struct.unpack_from(
5846 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
5847 return cls(ethertype)
5849 def serialize(self, buf, offset):
5850 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
5851 self.type, self.len, self.ethertype)
5854 @OFPAction.register_action_type(ofproto.OFPAT_POP_VLAN,
5855 ofproto.OFP_ACTION_HEADER_SIZE)
5856 class OFPActionPopVlan(OFPAction):
5860 This action pops the outermost VLAN tag from the packet.
5863 def __init__(self, type_=None, len_=None):
5864 super(OFPActionPopVlan, self).__init__()
5867 def parser(cls, buf, offset):
5868 (type_, len_) = struct.unpack_from(
5869 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5873 @OFPAction.register_action_type(ofproto.OFPAT_POP_MPLS,
5874 ofproto.OFP_ACTION_POP_MPLS_SIZE)
5875 class OFPActionPopMpls(OFPAction):
5879 This action pops the MPLS header from the packet.
5882 def __init__(self, ethertype=ether.ETH_TYPE_IP, type_=None, len_=None):
5883 super(OFPActionPopMpls, self).__init__()
5884 self.ethertype = ethertype
5887 def parser(cls, buf, offset):
5888 (type_, len_, ethertype) = struct.unpack_from(
5889 ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset)
5890 return cls(ethertype)
5892 def serialize(self, buf, offset):
5893 msg_pack_into(ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset,
5894 self.type, self.len, self.ethertype)
5897 @OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
5898 ofproto.OFP_ACTION_SET_FIELD_SIZE)
5899 class OFPActionSetField(OFPAction):
5903 This action modifies a header field in the packet.
5905 The set of keywords available for this is same as OFPMatch
5906 which including with/without mask.
5910 set_field = OFPActionSetField(eth_src="00:00:00:00:00:00")
5911 set_field = OFPActionSetField(ipv4_src=("192.168.100.0",
5915 def __init__(self, field=None, **kwargs):
5916 super(OFPActionSetField, self).__init__()
5917 assert len(kwargs) == 1
5918 key = list(kwargs.keys())[0]
5920 assert isinstance(key, (str, six.text_type))
5925 def parser(cls, buf, offset):
5926 (type_, len_) = struct.unpack_from(
5927 ofproto.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
5928 (n, value, mask, _len) = ofproto.oxm_parse(buf, offset + 4)
5929 k, uv = ofproto.oxm_to_user(n, value, mask)
5930 action = cls(**{k: uv})
5934 def serialize(self, buf, offset):
5935 n, value, mask = ofproto.oxm_from_user(self.key, self.value)
5936 len_ = ofproto.oxm_serialize(n, value, mask, buf, offset + 4)
5937 self.len = utils.round_up(4 + len_, 8)
5938 msg_pack_into('!HH', buf, offset, self.type, self.len)
5939 pad_len = self.len - (4 + len_)
5940 msg_pack_into("%dx" % pad_len, buf, offset + 4 + len_)
5942 def to_jsondict(self):
5944 self.__class__.__name__: {
5945 'field': ofproto.oxm_to_jsondict(self.key, self.value),
5952 def from_jsondict(cls, dict_):
5953 k, v = ofproto.oxm_from_jsondict(dict_['field'])
5954 return OFPActionSetField(**{k: v})
5956 def stringify_attrs(self):
5957 yield (self.key, self.value)
5960 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_PBB,
5961 ofproto.OFP_ACTION_PUSH_SIZE)
5962 class OFPActionPushPbb(OFPAction):
5966 This action pushes a new PBB header to the packet.
5968 ================ ======================================================
5969 Attribute Description
5970 ================ ======================================================
5971 ethertype Ether type
5972 ================ ======================================================
5975 def __init__(self, ethertype, type_=None, len_=None):
5976 super(OFPActionPushPbb, self).__init__()
5977 self.ethertype = ethertype
5980 def parser(cls, buf, offset):
5981 (type_, len_, ethertype) = struct.unpack_from(
5982 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
5983 return cls(ethertype)
5985 def serialize(self, buf, offset):
5986 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
5987 self.type, self.len, self.ethertype)
5990 @OFPAction.register_action_type(ofproto.OFPAT_POP_PBB,
5991 ofproto.OFP_ACTION_HEADER_SIZE)
5992 class OFPActionPopPbb(OFPAction):
5996 This action pops the outermost PBB service instance header from
6000 def __init__(self, type_=None, len_=None):
6001 super(OFPActionPopPbb, self).__init__()
6004 def parser(cls, buf, offset):
6005 (type_, len_) = struct.unpack_from(
6006 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
6010 @OFPAction.register_action_type(ofproto.OFPAT_COPY_FIELD,
6011 ofproto.OFP_ACTION_COPY_FIELD_SIZE)
6012 class OFPActionCopyField(OFPAction):
6016 This action copy value between header and register.
6018 ================ ======================================================
6019 Attribute Description
6020 ================ ======================================================
6021 n_bits Number of bits to copy.
6022 src_offset Starting bit offset in source.
6023 dst_offset Starting bit offset in destination.
6024 oxm_ids List of ``OFPOxmId`` instances.
6025 The first element of this list, src_oxm_id,
6026 identifies the field where the value is copied from.
6027 The second element of this list, dst_oxm_id,
6028 identifies the field where the value is copied to.
6030 ================ ======================================================
6033 def __init__(self, n_bits=0, src_offset=0, dst_offset=0, oxm_ids=None,
6034 type_=None, len_=None):
6035 oxm_ids = oxm_ids if oxm_ids else []
6036 super(OFPActionCopyField, self).__init__()
6037 self.n_bits = n_bits
6038 self.src_offset = src_offset
6039 self.dst_offset = dst_offset
6040 assert len(oxm_ids) == 2
6043 if isinstance(i, OFPOxmId):
6044 i.hasmask = False # fixup
6045 self.oxm_ids.append(i)
6046 elif isinstance(i, six.text_type):
6047 self.oxm_ids.append(OFPOxmId(i, hasmask=False))
6049 raise ValueError('invalid value for oxm_ids: %s' % oxm_ids)
6052 def parser(cls, buf, offset):
6053 (type_, len_, n_bits, src_offset, dst_offset) = struct.unpack_from(
6054 ofproto.OFP_ACTION_COPY_FIELD_PACK_STR, buf, offset)
6055 offset += ofproto.OFP_ACTION_COPY_FIELD_SIZE
6057 rest = buf[offset:offset + len_]
6060 i, rest = OFPOxmId.parse(rest)
6062 return cls(n_bits, src_offset, dst_offset, oxm_ids, type_, len_)
6064 def serialize(self, buf, offset):
6066 for i in self.oxm_ids:
6067 oxm_ids_buf += i.serialize()
6068 action_len = ofproto.OFP_ACTION_COPY_FIELD_SIZE + len(oxm_ids_buf)
6069 self.len = utils.round_up(action_len, 8)
6070 pad_len = self.len - action_len
6071 msg_pack_into(ofproto.OFP_ACTION_COPY_FIELD_PACK_STR, buf,
6072 offset, self.type, self.len,
6073 self.n_bits, self.src_offset, self.dst_offset)
6074 buf += oxm_ids_buf + b'\x00' * pad_len
6077 @OFPAction.register_action_type(ofproto.OFPAT_METER,
6078 ofproto.OFP_ACTION_METER_SIZE)
6079 class OFPActionMeter(OFPAction):
6083 This action applies meter (rate limiter)
6085 ================ ======================================================
6086 Attribute Description
6087 ================ ======================================================
6088 meter_id Meter instance
6089 ================ ======================================================
6092 def __init__(self, meter_id,
6093 type_=None, len_=None):
6094 super(OFPActionMeter, self).__init__()
6095 self.meter_id = meter_id
6098 def parser(cls, buf, offset):
6099 type_, len_, meter_id = struct.unpack_from(
6100 ofproto.OFP_ACTION_METER_PACK_STR, buf, offset)
6101 return cls(meter_id)
6103 def serialize(self, buf, offset):
6104 msg_pack_into(ofproto.OFP_ACTION_METER_PACK_STR, buf,
6105 offset, self.type, self.len, self.meter_id)
6108 @OFPAction.register_action_type(
6109 ofproto.OFPAT_EXPERIMENTER,
6110 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
6111 class OFPActionExperimenter(OFPAction):
6115 This action is an extensible action for the experimenter.
6117 ================ ======================================================
6118 Attribute Description
6119 ================ ======================================================
6120 experimenter Experimenter ID
6121 ================ ======================================================
6125 For the list of the supported Nicira experimenter actions,
6126 please refer to :ref:`ryu.ofproto.nx_actions <nx_actions_structures>`.
6129 def __init__(self, experimenter):
6130 super(OFPActionExperimenter, self).__init__()
6131 self.type = ofproto.OFPAT_EXPERIMENTER
6132 self.experimenter = experimenter
6136 def parser(cls, buf, offset):
6137 (type_, len_, experimenter) = struct.unpack_from(
6138 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset)
6139 data = buf[(offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE
6141 if experimenter == ofproto_common.NX_EXPERIMENTER_ID:
6142 obj = NXAction.parse(data)
6144 obj = OFPActionExperimenterUnknown(experimenter, data)
6148 def serialize(self, buf, offset):
6149 msg_pack_into(ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR,
6150 buf, offset, self.type, self.len, self.experimenter)
6153 class OFPActionExperimenterUnknown(OFPActionExperimenter):
6154 def __init__(self, experimenter, data=None, type_=None, len_=None):
6155 super(OFPActionExperimenterUnknown,
6156 self).__init__(experimenter=experimenter)
6159 def serialize(self, buf, offset):
6164 self.len = (utils.round_up(len(data), 8) +
6165 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
6166 super(OFPActionExperimenterUnknown, self).serialize(buf, offset)
6167 msg_pack_into('!%ds' % len(self.data),
6169 offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE,
6173 class OFPGroupProp(OFPPropBase):
6177 @OFPGroupProp.register_type(ofproto.OFPGPT_EXPERIMENTER)
6178 class OFPGroupPropExperimenter(OFPPropCommonExperimenter4ByteData):
6183 @_set_msg_type(ofproto.OFPT_GROUP_MOD)
6184 class OFPGroupMod(MsgBase):
6186 Modify group entry message
6188 The controller sends this message to modify the group table.
6190 ================== ======================================================
6191 Attribute Description
6192 ================== ======================================================
6193 command One of the following values.
6198 | OFPGC_INSERT_BUCKET
6199 | OFPGC_REMOVE_BUCKET
6200 type One of the following values.
6206 group_id Group identifier.
6207 command_bucket_id Bucket Id used as part of OFPGC_INSERT_BUCKET and
6208 OFPGC_REMOVE_BUCKET commands execution.
6209 buckets List of ``OFPBucket`` instance
6210 properties List of ``OFPGroupProp`` instance
6211 ================== ======================================================
6213 ``type`` attribute corresponds to ``type_`` parameter of __init__.
6217 def send_group_mod(self, datapath):
6218 ofp = datapath.ofproto
6219 ofp_parser = datapath.ofproto_parser
6223 actions = [ofp_parser.OFPActionOutput(port, max_len)]
6228 buckets = [ofp_parser.OFPBucket(weight, watch_port, watch_group,
6233 req = ofp_parser.OFPGroupMod(datapath, ofp.OFPGC_ADD,
6234 ofp.OFPGT_SELECT, group_id,
6235 command_bucket_id, buckets)
6236 datapath.send_msg(req)
6239 def __init__(self, datapath, command=ofproto.OFPGC_ADD,
6240 type_=ofproto.OFPGT_ALL, group_id=0,
6241 command_bucket_id=ofproto.OFPG_BUCKET_ALL,
6242 buckets=None, properties=None, bucket_array_len=None):
6243 buckets = buckets if buckets else []
6244 properties = properties if properties else []
6245 super(OFPGroupMod, self).__init__(datapath)
6246 self.command = command
6248 self.group_id = group_id
6249 self.command_bucket_id = command_bucket_id
6250 self.buckets = buckets
6251 self.properties = properties
6254 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6255 msg = super(OFPGroupMod, cls).parser(
6256 datapath, version, msg_type, msg_len, xid, buf)
6257 (msg.command, msg.type, msg.group_id, msg.bucket_array_len,
6258 msg.command_bucket_id) = struct.unpack_from(
6259 ofproto.OFP_GROUP_MOD_PACK_STR, buf, ofproto.OFP_HEADER_SIZE)
6260 offset = ofproto.OFP_GROUP_MOD_SIZE
6262 bucket_buf = buf[offset:offset + msg.bucket_array_len]
6265 bucket = OFPBucket.parser(bucket_buf, 0)
6266 msg.buckets.append(bucket)
6267 bucket_buf = bucket_buf[bucket.len:]
6268 offset += msg.bucket_array_len
6270 rest = buf[offset:offset + msg.msg_len]
6272 p, rest = OFPGroupProp.parse(rest)
6273 msg.properties.append(p)
6277 def _serialize_body(self):
6278 offset = ofproto.OFP_GROUP_MOD_SIZE
6279 self.bucket_array_len = 0
6280 for b in self.buckets:
6281 b.serialize(self.buf, offset)
6283 self.bucket_array_len += b.len
6285 msg_pack_into(ofproto.OFP_GROUP_MOD_PACK_STR, self.buf,
6286 ofproto.OFP_HEADER_SIZE,
6287 self.command, self.type, self.group_id,
6288 self.bucket_array_len, self.command_bucket_id)
6290 bin_props = bytearray()
6291 for p in self.properties:
6292 bin_props += p.serialize()
6293 self.buf += bin_props
6296 class OFPPortModProp(OFPPropBase):
6300 class OFPPortModPropEthernet(OFPPortModProp):
6301 def __init__(self, type_=None, length=None, advertise=None):
6303 self.advertise = advertise
6305 def serialize(self):
6307 self.length = struct.calcsize(
6308 ofproto.OFP_PORT_MOD_PROP_ETHERNET_PACK_STR)
6311 msg_pack_into(ofproto.OFP_PORT_MOD_PROP_ETHERNET_PACK_STR,
6312 buf, 0, self.type, self.length, self.advertise)
6316 class OFPPortModPropOptical(OFPPortModProp):
6317 def __init__(self, type_=None, length=None, configure=None,
6318 freq_lmda=None, fl_offset=None, grid_span=None,
6321 self.length = length
6322 self.configure = configure
6323 self.freq_lmda = freq_lmda
6324 self.fl_offset = fl_offset
6325 self.grid_span = grid_span
6326 self.tx_pwr = tx_pwr
6328 def serialize(self):
6330 self.length = struct.calcsize(
6331 ofproto.OFP_PORT_MOD_PROP_OPTICAL_PACK_STR)
6334 msg_pack_into(ofproto.OFP_PORT_MOD_PROP_OPTICAL_PACK_STR, buf, 0,
6335 self.type, self.length, self.configure, self.freq_lmda,
6336 self.fl_offset, self.grid_span, self.tx_pwr)
6340 class OFPPortModPropExperimenter(OFPPropCommonExperimenter4ByteData):
6344 @_set_msg_type(ofproto.OFPT_PORT_MOD)
6345 class OFPPortMod(MsgBase):
6347 Port modification message
6349 The controller sneds this message to modify the behavior of the port.
6351 ================ ======================================================
6352 Attribute Description
6353 ================ ======================================================
6354 port_no Port number to modify
6355 hw_addr The hardware address that must be the same as hw_addr
6356 of ``OFPPort`` of ``OFPSwitchFeatures``
6357 config Bitmap of configuration flags.
6362 | OFPPC_NO_PACKET_IN
6363 mask Bitmap of configuration flags above to be changed
6364 properties List of ``OFPPortModProp`` subclass instance
6365 ================ ======================================================
6369 def send_port_mod(self, datapath):
6370 ofp = datapath.ofproto
6371 ofp_parser = datapath.ofproto_parser
6374 hw_addr = 'fa:c8:e8:76:1d:7e'
6376 mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
6377 ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
6378 advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
6379 ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
6380 ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
6381 ofp.OFPPF_PAUSE_ASYM)
6382 properties = [ofp_parser.OFPPortModPropEthernet(advertise)]
6383 req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
6385 datapath.send_msg(req)
6394 def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
6395 config=0, mask=0, properties=None):
6396 super(OFPPortMod, self).__init__(datapath)
6397 self.port_no = port_no
6398 self.hw_addr = hw_addr
6399 self.config = config
6401 self.properties = properties or []
6403 def _serialize_body(self):
6404 bin_props = bytearray()
6405 for p in self.properties:
6406 bin_props += p.serialize()
6408 msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR, self.buf,
6409 ofproto.OFP_HEADER_SIZE,
6410 self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
6413 self.buf += bin_props
6416 class OFPGroupBucketProp(OFPPropBase):
6420 @OFPGroupBucketProp.register_type(ofproto.OFPGBPT_WEIGHT)
6421 class OFPGroupBucketPropWeight(OFPGroupBucketProp):
6422 def __init__(self, type_=None, length=None, weight=None):
6423 super(OFPGroupBucketPropWeight, self).__init__(type_, length)
6424 self.weight = weight
6427 def parser(cls, buf):
6429 (prop.type, prop.length, prop.weight) = struct.unpack_from(
6430 ofproto.OFP_GROUP_BUCKET_PROP_WEIGHT_PACK_STR, buf, 0)
6433 def serialize(self):
6435 self.length = ofproto.OFP_GROUP_BUCKET_PROP_WEIGHT_SIZE
6438 msg_pack_into(ofproto.OFP_GROUP_BUCKET_PROP_WEIGHT_PACK_STR, buf, 0,
6439 self.type, self.length, self.weight)
6443 @OFPGroupBucketProp.register_type(ofproto.OFPGBPT_WATCH_PORT)
6444 @OFPGroupBucketProp.register_type(ofproto.OFPGBPT_WATCH_GROUP)
6445 class OFPGroupBucketPropWatch(OFPGroupBucketProp):
6446 def __init__(self, type_=None, length=None, watch=None):
6447 super(OFPGroupBucketPropWatch, self).__init__(type_, length)
6451 def parser(cls, buf):
6453 (prop.type, prop.length, prop.watch) = struct.unpack_from(
6454 ofproto.OFP_GROUP_BUCKET_PROP_WATCH_PACK_STR, buf, 0)
6457 def serialize(self):
6459 self.length = ofproto.OFP_GROUP_BUCKET_PROP_WATCH_SIZE
6462 msg_pack_into(ofproto.OFP_GROUP_BUCKET_PROP_WATCH_PACK_STR, buf, 0,
6463 self.type, self.length, self.watch)
6467 @OFPGroupBucketProp.register_type(ofproto.OFPGBPT_EXPERIMENTER)
6468 class OFPGroupBucketPropExperimenter(OFPPropCommonExperimenter4ByteData):
6472 class OFPBucket(StringifyMixin):
6473 def __init__(self, bucket_id=0, actions=None, properties=None,
6474 len_=None, action_array_len=None):
6475 actions = actions if actions else []
6476 properties = properties if properties else []
6477 super(OFPBucket, self).__init__()
6478 self.bucket_id = bucket_id
6479 self.actions = actions
6480 self.properties = properties
6483 def parser(cls, buf, offset):
6485 (msg.len, msg.action_array_len,
6486 msg.bucket_id) = struct.unpack_from(
6487 ofproto.OFP_BUCKET_PACK_STR, buf, offset)
6488 offset += ofproto.OFP_BUCKET_SIZE
6490 action_buf = buf[offset:offset + msg.action_array_len]
6493 action = OFPAction.parser(action_buf, 0)
6494 msg.actions.append(action)
6495 action_buf = action_buf[action.len:]
6496 offset += msg.action_array_len
6498 rest = buf[offset:offset + msg.len]
6501 p, rest = OFPGroupBucketProp.parse(rest)
6502 msg.properties.append(p)
6506 def serialize(self, buf, offset):
6507 action_offset = offset + ofproto.OFP_BUCKET_SIZE
6508 self.action_array_len = 0
6509 for a in self.actions:
6510 a.serialize(buf, action_offset)
6511 action_offset += a.len
6512 self.action_array_len += a.len
6514 bin_props = bytearray()
6515 for p in self.properties:
6516 bin_props += p.serialize()
6517 props_len = len(bin_props)
6519 self.len = utils.round_up(ofproto.OFP_BUCKET_SIZE +
6520 self.action_array_len + props_len, 8)
6521 msg_pack_into(ofproto.OFP_BUCKET_PACK_STR, buf, offset,
6522 self.len, self.action_array_len, self.bucket_id)
6527 @_set_msg_type(ofproto.OFPT_ROLE_REQUEST)
6528 class OFPRoleRequest(MsgBase):
6530 Role request message
6532 The controller uses this message to change its role.
6534 ================ ======================================================
6535 Attribute Description
6536 ================ ======================================================
6537 role One of the following values.
6539 | OFPCR_ROLE_NOCHANGE
6543 short_id ID number for the controller.
6544 The default is OFPCID_UNDEFINED.
6545 generation_id Master Election Generation ID
6546 ================ ======================================================
6550 def send_role_request(self, datapath):
6551 ofp = datapath.ofproto
6552 ofp_parser = datapath.ofproto_parser
6554 req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL,
6555 ofp.OFPCID_UNDEFINED, 0)
6556 datapath.send_msg(req)
6559 def __init__(self, datapath, role=None, short_id=None,
6560 generation_id=None):
6561 super(OFPRoleRequest, self).__init__(datapath)
6563 self.short_id = short_id
6564 self.generation_id = generation_id
6566 def _serialize_body(self):
6567 assert self.role is not None
6568 assert self.generation_id is not None
6569 if self.short_id is None:
6570 self.short_id = ofproto.OFPCID_UNDEFINED
6571 msg_pack_into(ofproto.OFP_ROLE_REQUEST_PACK_STR,
6572 self.buf, ofproto.OFP_HEADER_SIZE,
6573 self.role, self.short_id, self.generation_id)
6577 @_set_msg_type(ofproto.OFPT_ROLE_REPLY)
6578 class OFPRoleReply(MsgBase):
6582 The switch responds with this message to a role request.
6584 ================ ======================================================
6585 Attribute Description
6586 ================ ======================================================
6587 role One of the following values.
6589 | OFPCR_ROLE_NOCHANGE
6593 short_id ID number for the controller.
6594 The default is OFPCID_UNDEFINED.
6595 generation_id Master Election Generation ID
6596 ================ ======================================================
6600 @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
6601 def role_reply_handler(self, ev):
6606 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
6608 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
6610 elif msg.role == ofp.OFPCR_ROLE_MASTER:
6612 elif msg.role == ofp.OFPCR_ROLE_SLAVE:
6617 self.logger.debug('OFPRoleReply received: '
6618 'role=%s short_id=%d, generation_id=%d',
6619 role, msg.short_id, msg.generation_id)
6622 def __init__(self, datapath, role=None, short_id=None,
6623 generation_id=None):
6624 super(OFPRoleReply, self).__init__(datapath)
6626 self.short_id = short_id
6627 self.generation_id = generation_id
6630 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6631 msg = super(OFPRoleReply, cls).parser(datapath, version,
6632 msg_type, msg_len, xid,
6634 (msg.role, msg.short_id, msg.generation_id) = struct.unpack_from(
6635 ofproto.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
6636 ofproto.OFP_HEADER_SIZE)
6640 class OFPAsyncConfigProp(OFPPropBase):
6644 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PACKET_IN_SLAVE)
6645 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PACKET_IN_MASTER)
6646 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PORT_STATUS_SLAVE)
6647 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PORT_STATUS_MASTER)
6648 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_FLOW_REMOVED_SLAVE)
6649 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_FLOW_REMOVED_MASTER)
6650 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_ROLE_STATUS_SLAVE)
6651 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_ROLE_STATUS_MASTER)
6652 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_TABLE_STATUS_SLAVE)
6653 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_TABLE_STATUS_MASTER)
6654 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_REQUESTFORWARD_SLAVE)
6655 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_REQUESTFORWARD_MASTER)
6656 class OFPAsyncConfigPropReasons(OFPAsyncConfigProp):
6657 def __init__(self, type_=None, length=None, mask=None):
6659 self.length = length
6663 def parser(cls, buf):
6665 (reasons.type, reasons.length, reasons.mask) = struct.unpack_from(
6666 ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_PACK_STR, buf, 0)
6669 def serialize(self):
6671 self.length = ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_SIZE
6674 msg_pack_into(ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_PACK_STR, buf, 0,
6675 self.type, self.length, self.mask)
6679 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_EXPERIMENTER_SLAVE)
6680 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_EXPERIMENTER_MASTER)
6681 class OFPAsyncConfigPropExperimenter(OFPPropCommonExperimenter4ByteData):
6685 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REQUEST)
6686 class OFPGetAsyncRequest(MsgBase):
6688 Get asynchronous configuration request message
6690 The controller uses this message to query the asynchronous message.
6694 def send_get_async_request(self, datapath):
6695 ofp_parser = datapath.ofproto_parser
6697 req = ofp_parser.OFPGetAsyncRequest(datapath)
6698 datapath.send_msg(req)
6701 def __init__(self, datapath):
6702 super(OFPGetAsyncRequest, self).__init__(datapath)
6706 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REPLY)
6707 class OFPGetAsyncReply(MsgBase):
6709 Get asynchronous configuration reply message
6711 The switch responds with this message to a get asynchronous configuration
6714 ================== ====================================================
6715 Attribute Description
6716 ================== ====================================================
6717 properties List of ``OFPAsyncConfigProp`` subclass instances
6718 ================== ====================================================
6722 @set_ev_cls(ofp_event.EventOFPGetAsyncReply, MAIN_DISPATCHER)
6723 def get_async_reply_handler(self, ev):
6726 self.logger.debug('OFPGetAsyncReply received: '
6727 'properties=%s', repr(msg.properties))
6730 def __init__(self, datapath, properties=None):
6731 super(OFPGetAsyncReply, self).__init__(datapath)
6732 self.properties = properties
6735 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6736 msg = super(OFPGetAsyncReply, cls).parser(datapath, version,
6741 rest = msg.buf[ofproto.OFP_HEADER_SIZE:]
6743 p, rest = OFPAsyncConfigProp.parse(rest)
6744 msg.properties.append(p)
6749 @_set_msg_type(ofproto.OFPT_SET_ASYNC)
6750 class OFPSetAsync(MsgBase):
6752 Set asynchronous configuration message
6754 The controller sends this message to set the asynchronous messages that
6755 it wants to receive on a given OpneFlow channel.
6757 ================== ====================================================
6758 Attribute Description
6759 ================== ====================================================
6760 properties List of ``OFPAsyncConfigProp`` subclass instances
6761 ================== ====================================================
6765 def send_set_async(self, datapath):
6766 ofp = datapath.ofproto
6767 ofp_parser = datapath.ofproto_parser
6770 ofp_parser.OFPAsyncConfigPropReasons(
6771 ofp.OFPACPT_PACKET_IN_SLAVE, 8,
6772 (1 << ofp.OFPR_APPLY_ACTION
6773 | 1 << ofp.OFPR_INVALID_TTL))]
6774 req = ofp_parser.OFPSetAsync(datapath, properties)
6775 datapath.send_msg(req)
6778 def __init__(self, datapath, properties=None):
6779 super(OFPSetAsync, self).__init__(datapath)
6780 self.properties = properties
6782 def _serialize_body(self):
6783 bin_props = bytearray()
6784 for p in self.properties:
6785 bin_props += p.serialize()
6787 self.buf += bin_props
6791 @_set_msg_type(ofproto.OFPT_BUNDLE_CONTROL)
6792 class OFPBundleCtrlMsg(MsgBase):
6794 Bundle control message
6796 The controller uses this message to create, destroy and commit bundles
6798 ================ ======================================================
6799 Attribute Description
6800 ================ ======================================================
6801 bundle_id Id of the bundle
6802 type One of the following values.
6804 | OFPBCT_OPEN_REQUEST
6806 | OFPBCT_CLOSE_REQUEST
6807 | OFPBCT_CLOSE_REPLY
6808 | OFPBCT_COMMIT_REQUEST
6809 | OFPBCT_COMMIT_REPLY
6810 | OFPBCT_DISCARD_REQUEST
6811 | OFPBCT_DISCARD_REPLY
6812 flags Bitmap of the following flags.
6816 properties List of ``OFPBundleProp`` subclass instance
6817 ================ ======================================================
6821 def send_bundle_control(self, datapath):
6822 ofp = datapath.ofproto
6823 ofp_parser = datapath.ofproto_parser
6825 req = ofp_parser.OFPBundleCtrlMsg(datapath, 7,
6826 ofp.OFPBCT_OPEN_REQUEST,
6827 ofp.OFPBF_ATOMIC, [])
6828 datapath.send_msg(req)
6831 def __init__(self, datapath, bundle_id=None, type_=None, flags=None,
6833 super(OFPBundleCtrlMsg, self).__init__(datapath)
6834 self.bundle_id = bundle_id
6837 self.properties = properties
6839 def _serialize_body(self):
6840 bin_props = bytearray()
6841 for p in self.properties:
6842 bin_props += p.serialize()
6844 msg_pack_into(ofproto.OFP_BUNDLE_CTRL_MSG_PACK_STR,
6845 self.buf, ofproto.OFP_HEADER_SIZE, self.bundle_id,
6846 self.type, self.flags)
6847 self.buf += bin_props
6850 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
6851 msg = super(OFPBundleCtrlMsg, cls).parser(datapath, version,
6854 (bundle_id, type_, flags) = struct.unpack_from(
6855 ofproto.OFP_BUNDLE_CTRL_MSG_PACK_STR, buf,
6856 ofproto.OFP_HEADER_SIZE)
6857 msg.bundle_id = bundle_id
6861 rest = msg.buf[ofproto.OFP_BUNDLE_CTRL_MSG_SIZE:]
6863 p, rest = OFPBundleProp.parse(rest)
6864 msg.properties.append(p)
6869 @_set_msg_type(ofproto.OFPT_BUNDLE_ADD_MESSAGE)
6870 class OFPBundleAddMsg(MsgInMsgBase):
6874 The controller uses this message to add a message to a bundle
6876 ================ ======================================================
6877 Attribute Description
6878 ================ ======================================================
6879 bundle_id Id of the bundle
6880 flags Bitmap of the following flags.
6884 message ``MsgBase`` subclass instance
6885 properties List of ``OFPBundleProp`` subclass instance
6886 ================ ======================================================
6890 def send_bundle_add_message(self, datapath):
6891 ofp = datapath.ofproto
6892 ofp_parser = datapath.ofproto_parser
6894 msg = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
6896 req = ofp_parser.OFPBundleAddMsg(datapath, 7, ofp.OFPBF_ATOMIC,
6898 datapath.send_msg(req)
6901 def __init__(self, datapath, bundle_id, flags, message, properties):
6902 super(OFPBundleAddMsg, self).__init__(datapath)
6903 self.bundle_id = bundle_id
6905 self.message = message
6906 self.properties = properties
6908 def _serialize_body(self):
6909 # The xid of the inner message must be the same as
6910 # that of the outer message (OF1.4.0 7.3.9.2)
6911 if self.message.xid != self.xid:
6912 self.message.set_xid(self.xid)
6915 self.message.serialize()
6916 tail_buf = self.message.buf
6919 if len(self.properties) > 0:
6920 message_len = len(tail_buf)
6921 pad_len = utils.round_up(message_len, 8) - message_len
6922 msg_pack_into("%dx" % pad_len, tail_buf, message_len)
6925 for p in self.properties:
6926 tail_buf += p.serialize()
6929 msg_pack_into(ofproto.OFP_BUNDLE_ADD_MSG_0_PACK_STR,
6930 self.buf, ofproto.OFP_HEADER_SIZE, self.bundle_id,
6934 self.buf += tail_buf
6937 nx_actions.generate(
6938 'ryu.ofproto.ofproto_v1_5',
6939 'ryu.ofproto.ofproto_v1_5_parser'