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.4.
26 from ryu.lib import addrconv
27 from ryu.lib.pack_utils import msg_pack_into
28 from ryu.lib.packet import packet
30 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase, MsgInMsgBase
31 from ryu.ofproto import ether
32 from ryu.ofproto import nx_actions
33 from ryu.ofproto import ofproto_parser
34 from ryu.ofproto import ofproto_common
35 from ryu.ofproto import ofproto_v1_4 as ofproto
40 def _set_msg_type(msg_type):
41 def _set_cls_msg_type(cls):
42 cls.cls_msg_type = msg_type
44 return _set_cls_msg_type
47 def _register_parser(cls):
48 '''class decorator to register msg parser'''
49 assert cls.cls_msg_type is not None
50 assert cls.cls_msg_type not in _MSG_PARSERS
51 _MSG_PARSERS[cls.cls_msg_type] = cls.parser
55 @ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
56 def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
57 parser = _MSG_PARSERS.get(msg_type)
58 return parser(datapath, version, msg_type, msg_len, xid, buf)
62 @_set_msg_type(ofproto.OFPT_HELLO)
63 class OFPHello(MsgBase):
67 When connection is started, the hello message is exchanged between a
68 switch and a controller.
70 This message is handled by the Ryu framework, so the Ryu application
71 do not need to process this typically.
73 ========== =========================================================
75 ========== =========================================================
76 elements list of ``OFPHelloElemVersionBitmap`` instance
77 ========== =========================================================
80 def __init__(self, datapath, elements=None):
81 elements = elements if elements else []
82 super(OFPHello, self).__init__(datapath)
83 self.elements = elements
86 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
87 msg = super(OFPHello, cls).parser(datapath, version, msg_type,
90 offset = ofproto.OFP_HELLO_HEADER_SIZE
92 while offset < msg.msg_len:
93 type_, length = struct.unpack_from(
94 ofproto.OFP_HELLO_ELEM_HEADER_PACK_STR, msg.buf, offset)
96 # better to register Hello Element classes but currently
97 # Only VerisonBitmap is supported so let's be simple.
99 if type_ == ofproto.OFPHET_VERSIONBITMAP:
100 elem = OFPHelloElemVersionBitmap.parser(msg.buf, offset)
108 class OFPHelloElemVersionBitmap(StringifyMixin):
110 Version bitmap Hello Element
112 ========== =========================================================
113 Attribute Description
114 ========== =========================================================
115 versions list of versions of OpenFlow protocol a device supports
116 ========== =========================================================
119 def __init__(self, versions, type_=None, length=None):
120 super(OFPHelloElemVersionBitmap, self).__init__()
121 self.type = ofproto.OFPHET_VERSIONBITMAP
124 self.versions = versions
127 def parser(cls, buf, offset):
128 type_, length = struct.unpack_from(
129 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_PACK_STR,
131 assert type_ == ofproto.OFPHET_VERSIONBITMAP
133 bitmaps_len = (length -
134 ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE)
135 offset += ofproto.OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE
137 while bitmaps_len >= 4:
138 bitmap = struct.unpack_from('!I', buf, offset)
139 bitmaps.append(bitmap[0])
143 versions = [i * 32 + shift
144 for i, bitmap in enumerate(bitmaps)
145 for shift in range(31) if bitmap & (1 << shift)]
148 elem._bitmaps = bitmaps
153 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
154 class OFPEchoRequest(MsgBase):
158 This message is handled by the Ryu framework, so the Ryu application
159 do not need to process this typically.
161 ========== =========================================================
162 Attribute Description
163 ========== =========================================================
164 data An arbitrary length data
165 ========== =========================================================
169 def send_echo_request(self, datapath, data):
170 ofp = datapath.ofproto
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 (EXT-109 ONF Extension)
663 actset_output Integer 32bit Output port from action set metadata
664 (EXT-233 ONF Extension)
665 ================ =============== ==================================
670 >>> match = parser.OFPMatch(
673 ... ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
674 ... 'ffff:ffff:ffff:ffff::'),
675 ... ipv6_dst='2001:db8:bd05:1d2:288a:1fc0:1:10ee')
677 >>> if 'ipv6_src' in match:
678 ... print match['ipv6_src']
680 ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::')
684 For the list of the supported Nicira experimenter matches,
685 please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`.
689 For VLAN id match field, special values are defined in OpenFlow Spec.
691 1) Packets with and without a VLAN tag
695 match = parser.OFPMatch()
699 ====================== =====
700 non-VLAN-tagged MATCH
701 VLAN-tagged(vlan_id=3) MATCH
702 VLAN-tagged(vlan_id=5) MATCH
703 ====================== =====
705 2) Only packets without a VLAN tag
709 match = parser.OFPMatch(vlan_vid=0x0000)
713 ====================== =====
714 non-VLAN-tagged MATCH
715 VLAN-tagged(vlan_id=3) x
716 VLAN-tagged(vlan_id=5) x
717 ====================== =====
719 3) Only packets with a VLAN tag regardless of its value
723 match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000))
727 ====================== =====
729 VLAN-tagged(vlan_id=3) MATCH
730 VLAN-tagged(vlan_id=5) MATCH
731 ====================== =====
733 4) Only packets with VLAN tag and VID equal
737 match = parser.OFPMatch(vlan_vid=(0x1000 | 3))
741 ====================== =====
743 VLAN-tagged(vlan_id=3) MATCH
744 VLAN-tagged(vlan_id=5) x
745 ====================== =====
748 def __init__(self, type_=None, length=None, _ordered_fields=None,
750 super(OFPMatch, self).__init__()
751 self.type = ofproto.OFPMT_OXM
754 if _ordered_fields is not None:
756 self._fields2 = _ordered_fields
758 kwargs = dict(ofproto.oxm_normalize_user(k, v) for
759 (k, v) in kwargs.items())
760 fields = [ofproto.oxm_from_user(k, v) for (k, v)
762 # assumption: sorting by OXM type values makes fields
763 # meet ordering requirements (eg. eth_type before ipv4_src)
765 key=lambda x: x[0][0] if isinstance(x[0], tuple) else x[0])
766 self._fields2 = [ofproto.oxm_to_user(n, v, m) for (n, v, m)
770 def parser(cls, buf, offset):
772 Returns an object which is generated from a buffer including the
773 expression of the wire protocol of the flow match.
776 type_, length = struct.unpack_from('!HH', buf, offset)
779 match.length = length
781 # ofp_match adjustment
787 n, value, mask, field_len = ofproto.oxm_parse(buf, offset)
788 k, uv = ofproto.oxm_to_user(n, value, mask)
789 fields.append((k, uv))
792 match._fields2 = fields
795 def serialize(self, buf, offset):
797 Outputs the expression of the wire protocol of the flow match into
799 Returns the output length.
801 fields = [ofproto.oxm_from_user(k, uv) for (k, uv)
805 field_offset = offset + struct.calcsize(hdr_pack_str)
806 for (n, value, mask) in fields:
807 field_offset += ofproto.oxm_serialize(n, value, mask, buf,
810 length = field_offset - offset
811 msg_pack_into(hdr_pack_str, buf, offset, ofproto.OFPMT_OXM, length)
814 pad_len = utils.round_up(length, 8) - length
815 msg_pack_into("%dx" % pad_len, buf, field_offset)
817 return length + pad_len
819 def __getitem__(self, key):
820 return dict(self._fields2)[key]
822 def __contains__(self, key):
823 return key in dict(self._fields2)
826 return iter(dict(self._fields2).items())
831 def get(self, key, default=None):
832 return dict(self._fields2).get(key, default)
834 def stringify_attrs(self):
835 yield "oxm_fields", dict(self._fields2)
837 def to_jsondict(self):
839 Returns a dict expressing the flow match.
841 body = {"oxm_fields": [ofproto.oxm_to_jsondict(k, uv) for k, uv
843 "length": self.length,
845 return {self.__class__.__name__: body}
848 def from_jsondict(cls, dict_):
850 Returns an object which is generated from a dict.
853 KeyError -- Unknown match field is defined in dict
855 fields = [ofproto.oxm_from_jsondict(f) for f
856 in dict_['oxm_fields']]
857 return OFPMatch(_ordered_fields=fields)
860 class OFPPropUnknown(StringifyMixin):
861 def __init__(self, type_=None, length=None, buf=None):
865 def parser(cls, buf):
869 class OFPPropBase(StringifyMixin):
871 # _TYPES = {} must be an attribute of subclass
873 def __init__(self, type_, length=None):
878 def register_type(cls, type_):
879 def _register_type(subcls):
880 cls._TYPES[type_] = subcls
882 return _register_type
886 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
887 rest = buf[utils.round_up(length, 8):]
889 subcls = cls._TYPES[type_]
891 subcls = OFPPropUnknown
892 prop = subcls.parser(buf)
898 def get_rest(cls, buf):
899 (type_, length) = struct.unpack_from(cls._PACK_STR, buf, 0)
900 offset = struct.calcsize(cls._PACK_STR)
901 return buf[offset:length]
905 # serialize_body should be implemented by subclass
907 body += self.serialize_body()
910 self.length = len(body) + struct.calcsize(self._PACK_STR)
914 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.length)
918 pad_len = utils.round_up(self.length, 8) - self.length
919 msg_pack_into("%dx" % pad_len, buf, len(buf))
924 class OFPPropCommonExperimenter4ByteData(StringifyMixin):
926 _EXPERIMENTER_DATA_PACK_STR = '!I'
927 _EXPERIMENTER_DATA_SIZE = 4
929 def __init__(self, type_=None, length=None, experimenter=None,
930 exp_type=None, data=bytearray()):
933 self.experimenter = experimenter
934 self.exp_type = exp_type
938 def parser(cls, buf):
939 (type_, length, experimenter, exp_type) = struct.unpack_from(
940 ofproto.OFP_PROP_EXPERIMENTER_PACK_STR, buf, 0)
942 rest = buf[ofproto.OFP_PROP_EXPERIMENTER_SIZE:length]
945 (d,) = struct.unpack_from(
946 cls._EXPERIMENTER_DATA_PACK_STR, rest, 0)
948 rest = rest[cls._EXPERIMENTER_DATA_SIZE:]
950 return cls(type_, length, experimenter, exp_type, data)
954 bin_data = bytearray()
956 msg_pack_into(self._EXPERIMENTER_DATA_PACK_STR,
958 offset += self._EXPERIMENTER_DATA_SIZE
961 self.length = struct.calcsize(self._PACK_STR)
962 self.length += len(bin_data)
965 msg_pack_into(self._PACK_STR, buf,
966 0, self.type, self.length, self.experimenter,
971 pad_len = utils.round_up(self.length, 8) - self.length
972 msg_pack_into("%dx" % pad_len, buf, len(buf))
977 class OFPPortDescProp(OFPPropBase):
981 @OFPPortDescProp.register_type(ofproto.OFPPDPT_ETHERNET)
982 class OFPPortDescPropEthernet(OFPPortDescProp):
983 def __init__(self, type_=None, length=None, curr=None, advertised=None,
984 supported=None, peer=None, curr_speed=None, max_speed=None):
988 self.advertised = advertised
989 self.supported = supported
991 self.curr_speed = curr_speed
992 self.max_speed = max_speed
995 def parser(cls, buf):
997 (ether.type, ether.length, ether.curr,
998 ether.advertised, ether.supported,
999 ether.peer, ether.curr_speed, ether.max_speed) = struct.unpack_from(
1000 ofproto.OFP_PORT_DESC_PROP_ETHERNET_PACK_STR, buf, 0)
1004 @OFPPortDescProp.register_type(ofproto.OFPPDPT_OPTICAL)
1005 class OFPPortDescPropOptical(OFPPortDescProp):
1006 def __init__(self, type_=None, length=None, supported=None,
1007 tx_min_freq_lmda=None, tx_max_freq_lmda=None,
1008 tx_grid_freq_lmda=None, rx_min_freq_lmda=None,
1009 rx_max_freq_lmda=None, rx_grid_freq_lmda=None,
1010 tx_pwr_min=None, tx_pwr_max=None):
1012 self.length = length
1013 self.supported = supported
1014 self.tx_min_freq_lmda = tx_min_freq_lmda
1015 self.tx_max_freq_lmda = tx_max_freq_lmda
1016 self.tx_grid_freq_lmda = tx_grid_freq_lmda
1017 self.rx_min_freq_lmda = rx_min_freq_lmda
1018 self.rx_max_freq_lmda = rx_max_freq_lmda
1019 self.rx_grid_freq_lmda = rx_grid_freq_lmda
1020 self.tx_pwr_min = tx_pwr_min
1021 self.tx_pwr_max = tx_pwr_max
1024 def parser(cls, buf):
1026 (optical.type, optical.length, optical.supported,
1027 optical.tx_min_freq_lmda, optical.tx_max_freq_lmda,
1028 optical.tx_grid_freq_lmda, optical.rx_min_freq_lmda,
1029 optical.rx_max_freq_lmda, optical.rx_grid_freq_lmda,
1030 optical.tx_pwr_min, optical.tx_pwr_max) = struct.unpack_from(
1031 ofproto.OFP_PORT_DESC_PROP_OPTICAL_PACK_STR, buf, 0)
1035 @OFPPortDescProp.register_type(ofproto.OFPPDPT_EXPERIMENTER)
1036 class OFPPortDescPropExperimenter(OFPPropCommonExperimenter4ByteData):
1040 class OFPTableModProp(OFPPropBase):
1044 @OFPTableModProp.register_type(ofproto.OFPTMPT_EVICTION)
1045 class OFPTableModPropEviction(OFPTableModProp):
1046 def __init__(self, type_=None, length=None, flags=None):
1048 self.length = length
1052 def parser(cls, buf):
1054 (eviction.type, eviction.length, eviction.flags) = struct.unpack_from(
1055 ofproto.OFP_TABLE_MOD_PROP_EVICTION_PACK_STR, buf, 0)
1058 def serialize(self):
1060 self.length = ofproto.OFP_TABLE_MOD_PROP_EVICTION_SIZE
1063 msg_pack_into(ofproto.OFP_TABLE_MOD_PROP_EVICTION_PACK_STR, buf, 0,
1064 self.type, self.length, self.flags)
1068 @OFPTableModProp.register_type(ofproto.OFPTMPT_VACANCY)
1069 class OFPTableModPropVacancy(OFPTableModProp):
1070 def __init__(self, type_=None, length=None, vacancy_down=None,
1071 vacancy_up=None, vacancy=None):
1073 self.length = length
1074 self.vacancy_down = vacancy_down
1075 self.vacancy_up = vacancy_up
1076 self.vacancy = vacancy
1079 def parser(cls, buf):
1081 (vacancy.type, vacancy.length, vacancy.vacancy_down,
1082 vacancy.vacancy_up, vacancy.vacancy) = struct.unpack_from(
1083 ofproto.OFP_TABLE_MOD_PROP_VACANCY_PACK_STR, buf, 0)
1086 def serialize(self):
1088 self.length = ofproto.OFP_TABLE_MOD_PROP_VACANCY_SIZE
1091 msg_pack_into(ofproto.OFP_TABLE_MOD_PROP_VACANCY_PACK_STR, buf, 0,
1092 self.type, self.length, self.vacancy_down,
1093 self.vacancy_up, self.vacancy)
1097 @OFPTableModProp.register_type(ofproto.OFPTMPT_EXPERIMENTER)
1098 class OFPTableModPropExperimenter(OFPPropCommonExperimenter4ByteData):
1102 class OFPQueueDescProp(OFPPropBase):
1106 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_MIN_RATE)
1107 class OFPQueueDescPropMinRate(OFPQueueDescProp):
1108 def __init__(self, type_=None, length=None, rate=None):
1110 self.length = length
1114 def parser(cls, buf):
1116 (minrate.type, minrate.length, minrate.rate) = struct.unpack_from(
1117 ofproto.OFP_QUEUE_DESC_PROP_MIN_RATE_PACK_STR, buf, 0)
1121 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_MAX_RATE)
1122 class OFPQueueDescPropMaxRate(OFPQueueDescProp):
1123 def __init__(self, type_=None, length=None, rate=None):
1125 self.length = length
1129 def parser(cls, buf):
1131 (maxrate.type, maxrate.length, maxrate.rate) = struct.unpack_from(
1132 ofproto.OFP_QUEUE_DESC_PROP_MAX_RATE_PACK_STR, buf, 0)
1136 @OFPQueueDescProp.register_type(ofproto.OFPQDPT_EXPERIMENTER)
1137 class OFPQueueDescPropExperimenter(OFPPropCommonExperimenter4ByteData):
1141 class OFPRoleProp(OFPPropBase):
1145 @OFPRoleProp.register_type(ofproto.OFPRPT_EXPERIMENTER)
1146 class OFPRolePropExperimenter(OFPPropCommonExperimenter4ByteData):
1150 class OFPBundleProp(OFPPropBase):
1154 @OFPBundleProp.register_type(ofproto.OFPRPT_EXPERIMENTER)
1155 class OFPBundlePropExperimenter(OFPPropCommonExperimenter4ByteData):
1160 @_set_msg_type(ofproto.OFPT_PACKET_IN)
1161 class OFPPacketIn(MsgBase):
1165 The switch sends the packet that received to the controller by this
1168 ============= =========================================================
1169 Attribute Description
1170 ============= =========================================================
1171 buffer_id ID assigned by datapath
1172 total_len Full length of frame
1173 reason Reason packet is being sent.
1181 table_id ID of the table that was looked up
1182 cookie Cookie of the flow entry that was looked up
1183 match Instance of ``OFPMatch``
1185 ============= =========================================================
1189 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
1190 def packet_in_handler(self, ev):
1195 if msg.reason == ofp.TABLE_MISS:
1196 reason = 'TABLE MISS'
1197 elif msg.reason == ofp.OFPR_APPLY_ACTION:
1198 reason = 'APPLY ACTION'
1199 elif msg.reason == ofp.OFPR_INVALID_TTL:
1200 reason = 'INVALID TTL'
1201 elif msg.reason == ofp.OFPR_ACTION_SET:
1202 reason = 'ACTION SET'
1203 elif msg.reason == ofp.OFPR_GROUP:
1205 elif msg.reason == ofp.OFPR_PACKET_OUT:
1206 reason = 'PACKET OUT'
1210 self.logger.debug('OFPPacketIn received: '
1211 'buffer_id=%x total_len=%d reason=%s '
1212 'table_id=%d cookie=%d match=%s data=%s',
1213 msg.buffer_id, msg.total_len, reason,
1214 msg.table_id, msg.cookie, msg.match,
1215 utils.hex_array(msg.data))
1218 def __init__(self, datapath, buffer_id=None, total_len=None, reason=None,
1219 table_id=None, cookie=None, match=None, data=None):
1220 super(OFPPacketIn, self).__init__(datapath)
1221 self.buffer_id = buffer_id
1222 self.total_len = total_len
1223 self.reason = reason
1224 self.table_id = table_id
1225 self.cookie = cookie
1230 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1231 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
1233 (msg.buffer_id, msg.total_len, msg.reason,
1234 msg.table_id, msg.cookie) = struct.unpack_from(
1235 ofproto.OFP_PACKET_IN_PACK_STR,
1236 msg.buf, ofproto.OFP_HEADER_SIZE)
1238 msg.match = OFPMatch.parser(msg.buf, ofproto.OFP_PACKET_IN_SIZE -
1239 ofproto.OFP_MATCH_SIZE)
1241 match_len = utils.round_up(msg.match.length, 8)
1242 msg.data = msg.buf[(ofproto.OFP_PACKET_IN_SIZE -
1243 ofproto.OFP_MATCH_SIZE + match_len + 2):]
1245 if msg.total_len < len(msg.data):
1246 # discard padding for 8-byte alignment of OFP packet
1247 msg.data = msg.data[:msg.total_len]
1253 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
1254 class OFPFlowRemoved(MsgBase):
1256 Flow removed message
1258 When flow entries time out or are deleted, the switch notifies controller
1261 ================ ======================================================
1262 Attribute Description
1263 ================ ======================================================
1264 cookie Opaque controller-issued identifier
1265 priority Priority level of flow entry
1266 reason One of the following values.
1268 | OFPRR_IDLE_TIMEOUT
1269 | OFPRR_HARD_TIMEOUT
1271 | OFPRR_GROUP_DELETE
1272 | OFPRR_METER_DELETE
1274 table_id ID of the table
1275 duration_sec Time flow was alive in seconds
1276 duration_nsec Time flow was alive in nanoseconds beyond duration_sec
1277 idle_timeout Idle timeout from original flow mod
1278 hard_timeout Hard timeout from original flow mod
1279 packet_count Number of packets that was associated with the flow
1280 byte_count Number of bytes that was associated with the flow
1281 match Instance of ``OFPMatch``
1282 ================ ======================================================
1286 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
1287 def flow_removed_handler(self, ev):
1292 if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
1293 reason = 'IDLE TIMEOUT'
1294 elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
1295 reason = 'HARD TIMEOUT'
1296 elif msg.reason == ofp.OFPRR_DELETE:
1298 elif msg.reason == ofp.OFPRR_GROUP_DELETE:
1299 reason = 'GROUP DELETE'
1303 self.logger.debug('OFPFlowRemoved received: '
1304 'cookie=%d priority=%d reason=%s table_id=%d '
1305 'duration_sec=%d duration_nsec=%d '
1306 'idle_timeout=%d hard_timeout=%d '
1307 'packet_count=%d byte_count=%d match.fields=%s',
1308 msg.cookie, msg.priority, reason, msg.table_id,
1309 msg.duration_sec, msg.duration_nsec,
1310 msg.idle_timeout, msg.hard_timeout,
1311 msg.packet_count, msg.byte_count, msg.match)
1314 def __init__(self, datapath, cookie=None, priority=None, reason=None,
1315 table_id=None, duration_sec=None, duration_nsec=None,
1316 idle_timeout=None, hard_timeout=None, packet_count=None,
1317 byte_count=None, match=None):
1318 super(OFPFlowRemoved, self).__init__(datapath)
1319 self.cookie = cookie
1320 self.priority = priority
1321 self.reason = reason
1322 self.table_id = table_id
1323 self.duration_sec = duration_sec
1324 self.duration_nsec = duration_nsec
1325 self.idle_timeout = idle_timeout
1326 self.hard_timeout = hard_timeout
1327 self.packet_count = packet_count
1328 self.byte_count = byte_count
1332 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1333 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
1336 (msg.cookie, msg.priority, msg.reason,
1337 msg.table_id, msg.duration_sec, msg.duration_nsec,
1338 msg.idle_timeout, msg.hard_timeout, msg.packet_count,
1339 msg.byte_count) = struct.unpack_from(
1340 ofproto.OFP_FLOW_REMOVED_PACK_STR0,
1341 msg.buf, ofproto.OFP_HEADER_SIZE)
1343 offset = (ofproto.OFP_FLOW_REMOVED_SIZE - ofproto.OFP_MATCH_SIZE)
1345 msg.match = OFPMatch.parser(msg.buf, offset)
1350 class OFPPort(StringifyMixin):
1353 Description of a port
1355 ========== =========================================================
1356 Attribute Description
1357 ========== =========================================================
1358 port_no Port number and it uniquely identifies a port within
1360 length Length of ofp_port (excluding padding).
1361 hw_addr MAC address for the port.
1362 name Null-terminated string containing a human-readable name
1364 config Bitmap of port configration flags.
1369 | OFPPC_NO_PACKET_IN
1370 state Bitmap of port state flags.
1375 properties List of ``OFPPortDescProp`` subclass instance
1376 ========== =========================================================
1384 # OF spec is unclear about the encoding of name.
1385 # we assumes UTF-8, which is used by OVS.
1390 def __init__(self, port_no=None, length=None, hw_addr=None, name=None,
1391 config=None, state=None, properties=None):
1392 super(OFPPort, self).__init__()
1393 self.port_no = port_no
1394 self.length = length
1395 self.hw_addr = hw_addr
1397 self.config = config
1399 self.properties = properties
1402 def parser(cls, buf, offset):
1403 (port_no, length, hw_addr, name, config, state) = struct.unpack_from(
1404 ofproto.OFP_PORT_PACK_STR, buf, offset)
1405 hw_addr = addrconv.mac.bin_to_text(hw_addr)
1406 name = name.rstrip(b'\0')
1408 rest = buf[offset + ofproto.OFP_PORT_SIZE:offset + length]
1410 p, rest = OFPPortDescProp.parse(rest)
1412 ofpport = cls(port_no, length, hw_addr, name, config, state, props)
1416 class OFPTableDesc(StringifyMixin):
1417 def __init__(self, length=None, table_id=None, config=None,
1419 super(OFPTableDesc, self).__init__()
1420 self.table_id = table_id
1421 self.length = length
1422 self.config = config
1423 self.properties = properties
1426 def parser(cls, buf, offset):
1427 (length, table_id, config) = struct.unpack_from(
1428 ofproto.OFP_TABLE_DESC_PACK_STR, buf, offset)
1430 rest = buf[offset + ofproto.OFP_TABLE_DESC_SIZE:offset + length]
1432 p, rest = OFPTableModProp.parse(rest)
1434 ofptabledesc = cls(length, table_id, config, props)
1438 class OFPQueueDesc(StringifyMixin):
1439 def __init__(self, port_no=None, queue_id=None, len_=None,
1441 super(OFPQueueDesc, self).__init__()
1442 self.port_no = port_no
1443 self.queue_id = queue_id
1445 self.properties = properties
1448 def parser(cls, buf, offset):
1449 (port_no, queue_id, len_) = struct.unpack_from(
1450 ofproto.OFP_QUEUE_DESC_PACK_STR, buf, offset)
1452 rest = buf[offset + ofproto.OFP_QUEUE_DESC_SIZE:offset + len_]
1454 p, rest = OFPQueueDescProp.parse(rest)
1456 ofpqueuedesc = cls(port_no, queue_id, len_, props)
1460 def _set_stats_type(stats_type, stats_body_cls):
1461 def _set_cls_stats_type(cls):
1462 cls.cls_stats_type = stats_type
1463 cls.cls_stats_body_cls = stats_body_cls
1465 return _set_cls_stats_type
1468 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
1469 class OFPMultipartRequest(MsgBase):
1470 def __init__(self, datapath, flags):
1471 super(OFPMultipartRequest, self).__init__(datapath)
1472 self.type = self.__class__.cls_stats_type
1475 def _serialize_stats_body(self):
1478 def _serialize_body(self):
1479 msg_pack_into(ofproto.OFP_MULTIPART_REQUEST_PACK_STR,
1480 self.buf, ofproto.OFP_HEADER_SIZE,
1481 self.type, self.flags)
1482 self._serialize_stats_body()
1486 @_set_msg_type(ofproto.OFPT_METER_MOD)
1487 class OFPMeterMod(MsgBase):
1489 Meter modification message
1491 The controller sends this message to modify the meter.
1493 ================ ======================================================
1494 Attribute Description
1495 ================ ======================================================
1496 command One of the following values.
1501 flags Bitmap of the following flags.
1507 meter_id Meter instance
1508 bands list of the following class instance.
1511 | OFPMeterBandDscpRemark
1512 | OFPMeterBandExperimenter
1513 ================ ======================================================
1516 def __init__(self, datapath, command=ofproto.OFPMC_ADD,
1517 flags=ofproto.OFPMF_KBPS, meter_id=1, bands=None):
1518 bands = bands if bands else []
1519 super(OFPMeterMod, self).__init__(datapath)
1520 self.command = command
1522 self.meter_id = meter_id
1526 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1527 msg = super(OFPMeterMod, cls).parser(
1528 datapath, version, msg_type, msg_len, xid, buf)
1530 (msg.command, msg.flags, msg.meter_id) = struct.unpack_from(
1531 ofproto.OFP_METER_MOD_PACK_STR, buf, ofproto.OFP_HEADER_SIZE)
1532 offset = ofproto.OFP_METER_MOD_SIZE
1535 while offset < msg.msg_len:
1536 band = OFPMeterBandHeader.parser(buf, offset)
1537 msg.bands.append(band)
1542 def _serialize_body(self):
1543 msg_pack_into(ofproto.OFP_METER_MOD_PACK_STR, self.buf,
1544 ofproto.OFP_HEADER_SIZE,
1545 self.command, self.flags, self.meter_id)
1547 offset = ofproto.OFP_METER_MOD_SIZE
1548 for b in self.bands:
1549 b.serialize(self.buf, offset)
1553 @_set_msg_type(ofproto.OFPT_TABLE_MOD)
1554 class OFPTableMod(MsgBase):
1556 Flow table configuration message
1558 The controller sends this message to configure table state.
1560 ================ ======================================================
1561 Attribute Description
1562 ================ ======================================================
1563 table_id ID of the table (OFPTT_ALL indicates all tables)
1564 config Bitmap of configuration flags.
1567 | OFPTC_VACANCY_EVENTS
1568 properties List of ``OFPTableModProp`` subclass instance
1569 ================ ======================================================
1573 def send_table_mod(self, datapath):
1574 ofp = datapath.ofproto
1575 ofp_parser = datapath.ofproto_parser
1577 req = ofp_parser.OFPTableMod(datapath, 1, 3)
1578 flags = ofp.OFPTC_VACANCY_EVENTS
1579 properties = [ofp_parser.OFPTableModPropEviction(flags)]
1580 req = ofp_parser.OFPTableMod(datapath, 1, 3, properties)
1581 datapath.send_msg(req)
1584 def __init__(self, datapath, table_id, config, properties):
1585 super(OFPTableMod, self).__init__(datapath)
1586 self.table_id = table_id
1587 self.config = config
1588 self.properties = properties
1590 def _serialize_body(self):
1591 props_buf = bytearray()
1592 for p in self.properties:
1593 props_buf += p.serialize()
1595 msg_pack_into(ofproto.OFP_TABLE_MOD_PACK_STR, self.buf,
1596 ofproto.OFP_HEADER_SIZE,
1597 self.table_id, self.config)
1599 self.buf += props_buf
1603 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
1604 class OFPMultipartReply(MsgBase):
1605 _STATS_MSG_TYPES = {}
1608 def register_stats_type(body_single_struct=False):
1609 def _register_stats_type(cls):
1610 assert cls.cls_stats_type is not None
1611 assert cls.cls_stats_type not in OFPMultipartReply._STATS_MSG_TYPES
1612 assert cls.cls_stats_body_cls is not None
1613 cls.cls_body_single_struct = body_single_struct
1614 OFPMultipartReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls
1616 return _register_stats_type
1618 def __init__(self, datapath, body=None, flags=None):
1619 super(OFPMultipartReply, self).__init__(datapath)
1624 def parser_stats_body(cls, buf, msg_len, offset):
1625 body_cls = cls.cls_stats_body_cls
1627 while offset < msg_len:
1628 entry = body_cls.parser(buf, offset)
1630 offset += entry.length
1632 if cls.cls_body_single_struct:
1637 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf):
1638 msg = MsgBase.parser.__func__(
1639 cls, datapath, version, msg_type, msg_len, xid, buf)
1640 msg.body = msg.parser_stats_body(msg.buf, msg.msg_len,
1641 ofproto.OFP_MULTIPART_REPLY_SIZE)
1645 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1646 type_, flags = struct.unpack_from(
1647 ofproto.OFP_MULTIPART_REPLY_PACK_STR, six.binary_type(buf),
1648 ofproto.OFP_HEADER_SIZE)
1649 stats_type_cls = cls._STATS_MSG_TYPES.get(type_)
1650 msg = super(OFPMultipartReply, stats_type_cls).parser(
1651 datapath, version, msg_type, msg_len, xid, buf)
1655 offset = ofproto.OFP_MULTIPART_REPLY_SIZE
1657 while offset < msg_len:
1658 b = stats_type_cls.cls_stats_body_cls.parser(msg.buf, offset)
1660 offset += b.length if hasattr(b, 'length') else b.len
1662 if stats_type_cls.cls_body_single_struct:
1669 class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
1670 'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
1683 def parser(cls, buf, offset):
1684 desc = struct.unpack_from(ofproto.OFP_DESC_PACK_STR,
1687 desc = [x.rstrip(b'\0') for x in desc]
1689 stats.length = ofproto.OFP_DESC_SIZE
1693 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
1694 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
1695 class OFPDescStatsRequest(OFPMultipartRequest):
1697 Description statistics request message
1699 The controller uses this message to query description of the switch.
1701 ================ ======================================================
1702 Attribute Description
1703 ================ ======================================================
1704 flags Zero or ``OFPMPF_REQ_MORE``
1705 ================ ======================================================
1709 def send_desc_stats_request(self, datapath):
1710 ofp_parser = datapath.ofproto_parser
1712 req = ofp_parser.OFPDescStatsRequest(datapath, 0)
1713 datapath.send_msg(req)
1716 def __init__(self, datapath, flags=0, type_=None):
1717 super(OFPDescStatsRequest, self).__init__(datapath, flags)
1720 @OFPMultipartReply.register_stats_type(body_single_struct=True)
1721 @_set_stats_type(ofproto.OFPMP_DESC, OFPDescStats)
1722 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
1723 class OFPDescStatsReply(OFPMultipartReply):
1725 Description statistics reply message
1727 The switch responds with this message to a description statistics
1730 ================ ======================================================
1731 Attribute Description
1732 ================ ======================================================
1733 body Instance of ``OFPDescStats``
1734 ================ ======================================================
1738 @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
1739 def desc_stats_reply_handler(self, ev):
1742 self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
1743 'serial_num=%s dp_desc=%s',
1744 body.mfr_desc, body.hw_desc, body.sw_desc,
1745 body.serial_num, body.dp_desc)
1748 def __init__(self, datapath, type_=None, **kwargs):
1749 super(OFPDescStatsReply, self).__init__(datapath, **kwargs)
1752 class OFPTableFeaturesStats(StringifyMixin):
1756 # OF spec is unclear about the encoding of name.
1762 def __init__(self, table_id=None, name=None, metadata_match=None,
1763 metadata_write=None, config=None, max_entries=None,
1764 properties=None, length=None):
1765 super(OFPTableFeaturesStats, self).__init__()
1767 self.table_id = table_id
1769 self.metadata_match = metadata_match
1770 self.metadata_write = metadata_write
1771 self.config = config
1772 self.max_entries = max_entries
1773 self.properties = properties
1776 def parser(cls, buf, offset):
1777 table_features = cls()
1778 (table_features.length, table_features.table_id,
1779 name, table_features.metadata_match,
1780 table_features.metadata_write, table_features.config,
1781 table_features.max_entries
1782 ) = struct.unpack_from(ofproto.OFP_TABLE_FEATURES_PACK_STR,
1784 table_features.name = name.rstrip(b'\0')
1787 rest = buf[offset + ofproto.OFP_TABLE_FEATURES_SIZE:
1788 offset + table_features.length]
1790 p, rest = OFPTableFeatureProp.parse(rest)
1792 table_features.properties = props
1794 return table_features
1796 def serialize(self):
1798 bin_props = bytearray()
1799 for p in self.properties:
1800 bin_props += p.serialize()
1801 self.length = ofproto.OFP_TABLE_FEATURES_SIZE + len(bin_props)
1804 msg_pack_into(ofproto.OFP_TABLE_FEATURES_PACK_STR, buf, 0,
1805 self.length, self.table_id, self.name,
1806 self.metadata_match, self.metadata_write,
1807 self.config, self.max_entries)
1808 return buf + bin_props
1811 class OFPTableFeatureProp(OFPPropBase):
1815 class OFPInstructionId(StringifyMixin):
1816 _PACK_STR = '!HH' # type, len
1818 def __init__(self, type_, len_=None):
1824 def parse(cls, buf):
1825 (type_, len_,) = struct.unpack_from(cls._PACK_STR,
1826 six.binary_type(buf), 0)
1828 return cls(type_=type_, len_=len_), rest
1830 def serialize(self):
1832 self.len = struct.calcsize(self._PACK_STR)
1835 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
1839 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS)
1840 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_INSTRUCTIONS_MISS)
1841 class OFPTableFeaturePropInstructions(OFPTableFeatureProp):
1842 def __init__(self, type_=None, length=None, instruction_ids=None):
1843 instruction_ids = instruction_ids if instruction_ids else []
1844 super(OFPTableFeaturePropInstructions, self).__init__(type_, length)
1845 self.instruction_ids = instruction_ids
1848 def parser(cls, buf):
1849 rest = cls.get_rest(buf)
1852 i, rest = OFPInstructionId.parse(rest)
1854 return cls(instruction_ids=ids)
1856 def serialize_body(self):
1857 bin_ids = bytearray()
1858 for i in self.instruction_ids:
1859 bin_ids += i.serialize()
1864 # Implementation note: While OpenFlow 1.3.2 shares the same ofp_action_header
1865 # for flow_mod and table_features, we have separate classes. We named this
1866 # class to match with OpenFlow 1.4's name. (ofp_action_id)
1867 class OFPActionId(StringifyMixin):
1868 _PACK_STR = '!HH' # type, len
1870 def __init__(self, type_, len_=None):
1876 def parse(cls, buf):
1877 (type_, len_,) = struct.unpack_from(cls._PACK_STR,
1878 six.binary_type(buf), 0)
1880 return cls(type_=type_, len_=len_), rest
1882 def serialize(self):
1884 self.len = struct.calcsize(self._PACK_STR)
1887 msg_pack_into(self._PACK_STR, buf, 0, self.type, self.len)
1891 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS)
1892 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_ACTIONS_MISS)
1893 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS)
1894 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_ACTIONS_MISS)
1895 class OFPTableFeaturePropActions(OFPTableFeatureProp):
1896 def __init__(self, type_=None, length=None, action_ids=None):
1897 action_ids = action_ids if action_ids else []
1898 super(OFPTableFeaturePropActions, self).__init__(type_, length)
1899 self.action_ids = action_ids
1902 def parser(cls, buf):
1903 rest = cls.get_rest(buf)
1906 i, rest = OFPActionId.parse(rest)
1908 return cls(action_ids=ids)
1910 def serialize_body(self):
1911 bin_ids = bytearray()
1912 for i in self.action_ids:
1913 bin_ids += i.serialize()
1917 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES)
1918 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_NEXT_TABLES_MISS)
1919 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_TABLE_SYNC_FROM)
1920 class OFPTableFeaturePropNextTables(OFPTableFeatureProp):
1921 _TABLE_ID_PACK_STR = '!B'
1923 def __init__(self, type_=None, length=None, table_ids=None):
1924 table_ids = table_ids if table_ids else []
1925 super(OFPTableFeaturePropNextTables, self).__init__(type_, length)
1926 self.table_ids = table_ids
1929 def parser(cls, buf):
1930 rest = cls.get_rest(buf)
1933 (i,) = struct.unpack_from(cls._TABLE_ID_PACK_STR,
1934 six.binary_type(rest), 0)
1935 rest = rest[struct.calcsize(cls._TABLE_ID_PACK_STR):]
1937 return cls(table_ids=ids)
1939 def serialize_body(self):
1940 bin_ids = bytearray()
1941 for i in self.table_ids:
1942 bin_id = bytearray()
1943 msg_pack_into(self._TABLE_ID_PACK_STR, bin_id, 0, i)
1948 # Implementation note: OFPOxmId is specific to this implementation.
1949 # It does not have a corresponding structure in the specification.
1950 # (the specification uses plain uint32_t for non-experimenter OXMs
1951 # and uint64_t for experimenter OXMs.)
1953 # i have taken a look at some of software switch implementations
1954 # but they all look broken or incomplete. according to the spec,
1955 # oxm_hasmask should be 1 if a switch supports masking for the type.
1956 # the right value for oxm_length is not clear from the spec.
1957 # update: OpenFlow 1.3.3 "clarified" that oxm_length here is the payload
1958 # length. it's still unclear if it should be doubled for hasmask or not,
1961 # oxm_hasmask always 0
1962 # oxm_length same as ofp_match etc (as without mask)
1964 # oxm_hasmask always 0
1965 # oxm_length always 0
1967 # seems in flux as of writing this [20141003]
1968 class OFPOxmId(StringifyMixin):
1969 _PACK_STR = '!I' # oxm header
1970 _EXPERIMENTER_ID_PACK_STR = '!I'
1978 def __init__(self, type_, hasmask=False, length=None):
1980 self.hasmask = hasmask
1981 self.length = length
1984 def parse(cls, buf):
1985 (oxm,) = struct.unpack_from(cls._PACK_STR, six.binary_type(buf), 0)
1986 # oxm (32 bit) == class (16) | field (7) | hasmask (1) | length (8)
1987 # in case of experimenter OXMs, another 32 bit value
1988 # (experimenter id) follows.
1989 (type_, _v) = ofproto.oxm_to_user(oxm >> (1 + 8), None, None)
1990 rest = buf[struct.calcsize(cls._PACK_STR):]
1991 hasmask = ofproto.oxm_tlv_header_extract_hasmask(oxm)
1992 length = oxm & 0xff # XXX see the comment on OFPOxmId
1993 class_ = oxm >> (7 + 1 + 8)
1994 if class_ == ofproto.OFPXMC_EXPERIMENTER:
1995 (exp_id,) = struct.unpack_from(cls._EXPERIMENTER_ID_PACK_STR,
1996 six.binary_type(rest), 0)
1997 rest = rest[struct.calcsize(cls._EXPERIMENTER_ID_PACK_STR):]
1998 subcls = OFPExperimenterOxmId
1999 return subcls(type_=type_, exp_id=exp_id, hasmask=hasmask,
2000 length=length), rest
2002 return cls(type_=type_, hasmask=hasmask, length=length), rest
2004 def serialize(self):
2006 self.length = 0 # XXX see the comment on OFPOxmId
2008 (n, _v, _m) = ofproto.oxm_from_user(self.type, None)
2009 oxm = (n << (1 + 8)) | (self.hasmask << 8) | self.length
2011 msg_pack_into(self._PACK_STR, buf, 0, oxm)
2012 assert n >> 7 != ofproto.OFPXMC_EXPERIMENTER
2016 class OFPExperimenterOxmId(OFPOxmId):
2017 def __init__(self, type_, exp_id, hasmask=False, length=None):
2018 super(OFPExperimenterOxmId, self).__init__(type_=type_,
2021 self.exp_id = exp_id
2023 def serialize(self):
2024 buf = super(OFPExperimenterOxmId, self).serialize()
2025 msg_pack_into(self._EXPERIMENTER_ID_PACK_STR, buf,
2026 struct.calcsize(self._PACK_STR), self.exp_id)
2029 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_MATCH)
2030 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WILDCARDS)
2031 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD)
2032 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_WRITE_SETFIELD_MISS)
2033 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD)
2034 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_APPLY_SETFIELD_MISS)
2035 class OFPTableFeaturePropOxm(OFPTableFeatureProp):
2036 def __init__(self, type_=None, length=None, oxm_ids=None):
2037 oxm_ids = oxm_ids if oxm_ids else []
2038 super(OFPTableFeaturePropOxm, self).__init__(type_, length)
2039 self.oxm_ids = oxm_ids
2042 def parser(cls, buf):
2043 rest = cls.get_rest(buf)
2046 i, rest = OFPOxmId.parse(rest)
2048 return cls(oxm_ids=ids)
2050 def serialize_body(self):
2051 bin_ids = bytearray()
2052 for i in self.oxm_ids:
2053 bin_ids += i.serialize()
2057 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER)
2058 @OFPTableFeatureProp.register_type(ofproto.OFPTFPT_EXPERIMENTER_MISS)
2059 class OFPTableFeaturePropExperimenter(OFPPropCommonExperimenter4ByteData):
2063 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
2064 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2065 class OFPTableFeaturesStatsRequest(OFPMultipartRequest):
2067 Table features statistics request message
2069 The controller uses this message to query table features.
2071 ================ ======================================================
2072 Attribute Description
2073 ================ ======================================================
2074 body List of ``OFPTableFeaturesStats`` instances.
2076 ================ ======================================================
2079 def __init__(self, datapath, flags=0, body=None, type_=None):
2080 body = body if body else []
2081 super(OFPTableFeaturesStatsRequest, self).__init__(datapath, flags)
2084 def _serialize_stats_body(self):
2085 bin_body = bytearray()
2087 bin_body += p.serialize()
2088 self.buf += bin_body
2091 @OFPMultipartReply.register_stats_type()
2092 @_set_stats_type(ofproto.OFPMP_TABLE_FEATURES, OFPTableFeaturesStats)
2093 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2094 class OFPTableFeaturesStatsReply(OFPMultipartReply):
2096 Table features statistics reply message
2098 The switch responds with this message to a table features statistics
2101 ================ ======================================================
2102 Attribute Description
2103 ================ ======================================================
2104 body List of ``OFPTableFeaturesStats`` instance
2105 ================ ======================================================
2108 def __init__(self, datapath, type_=None, **kwargs):
2109 super(OFPTableFeaturesStatsReply, self).__init__(datapath, **kwargs)
2112 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
2113 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2114 class OFPPortDescStatsRequest(OFPMultipartRequest):
2116 Port description request message
2118 The controller uses this message to query description of all the ports.
2120 ================ ======================================================
2121 Attribute Description
2122 ================ ======================================================
2123 flags Zero or ``OFPMPF_REQ_MORE``
2124 ================ ======================================================
2128 def send_port_desc_stats_request(self, datapath):
2129 ofp_parser = datapath.ofproto_parser
2131 req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
2132 datapath.send_msg(req)
2135 def __init__(self, datapath, flags=0, type_=None):
2136 super(OFPPortDescStatsRequest, self).__init__(datapath, flags)
2139 @OFPMultipartReply.register_stats_type()
2140 @_set_stats_type(ofproto.OFPMP_PORT_DESC, OFPPort)
2141 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2142 class OFPPortDescStatsReply(OFPMultipartReply):
2144 Port description reply message
2146 The switch responds with this message to a port description request.
2148 ================ ======================================================
2149 Attribute Description
2150 ================ ======================================================
2151 body List of ``OFPPort`` instance
2152 ================ ======================================================
2156 @set_ev_cls(ofp_event.EventOFPPortDescStatsReply, MAIN_DISPATCHER)
2157 def port_desc_stats_reply_handler(self, ev):
2159 for p in ev.msg.body:
2160 ports.append('port_no=%d hw_addr=%s name=%s config=0x%08x '
2161 'state=0x%08x properties=%s' %
2162 (p.port_no, p.hw_addr,
2163 p.name, p.config, p.state, repr(p.properties)))
2164 self.logger.debug('OFPPortDescStatsReply received: %s', ports)
2167 def __init__(self, datapath, type_=None, **kwargs):
2168 super(OFPPortDescStatsReply, self).__init__(datapath, **kwargs)
2171 @_set_stats_type(ofproto.OFPMP_TABLE_DESC, OFPTableDesc)
2172 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2173 class OFPTableDescStatsRequest(OFPMultipartRequest):
2175 Table description request message
2177 The controller uses this message to query description of all the tables.
2179 ================ ======================================================
2180 Attribute Description
2181 ================ ======================================================
2182 flags Zero or ``OFPMPF_REQ_MORE``
2183 ================ ======================================================
2187 def send_table_desc_stats_request(self, datapath):
2188 ofp_parser = datapath.ofproto_parser
2190 req = ofp_parser.OFPTableDescStatsRequest(datapath, 0)
2191 datapath.send_msg(req)
2194 def __init__(self, datapath, flags=0, type_=None):
2195 super(OFPTableDescStatsRequest, self).__init__(datapath, flags)
2198 @OFPMultipartReply.register_stats_type()
2199 @_set_stats_type(ofproto.OFPMP_TABLE_DESC, OFPTableDesc)
2200 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2201 class OFPTableDescStatsReply(OFPMultipartReply):
2203 Table description reply message
2205 The switch responds with this message to a table description request.
2207 ================ ======================================================
2208 Attribute Description
2209 ================ ======================================================
2210 body List of ``OFPTableDesc`` instance
2211 ================ ======================================================
2215 @set_ev_cls(ofp_event.EventOFPTableDescStatsReply, MAIN_DISPATCHER)
2216 def table_desc_stats_reply_handler(self, ev):
2218 for p in ev.msg.body:
2219 tables.append('table_id=%d config=0x%08x properties=%s' %
2220 (p.table_id, p.config, repr(p.properties)))
2221 self.logger.debug('OFPTableDescStatsReply received: %s', tables)
2224 def __init__(self, datapath, type_=None, **kwargs):
2225 super(OFPTableDescStatsReply, self).__init__(datapath, **kwargs)
2228 @_set_stats_type(ofproto.OFPMP_QUEUE_DESC, OFPQueueDesc)
2229 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2230 class OFPQueueDescStatsRequest(OFPMultipartRequest):
2232 Queue description request message
2234 The controller uses this message to query description of all the queues.
2236 ================ ======================================================
2237 Attribute Description
2238 ================ ======================================================
2239 flags Zero or ``OFPMPF_REQ_MORE``
2240 port_no Port number to read (OFPP_ANY for all ports)
2241 queue_id ID of queue to read (OFPQ_ALL for all queues)
2242 ================ ======================================================
2246 def send_queue_desc_stats_request(self, datapath):
2247 ofp = datapath.ofproto
2248 ofp_parser = datapath.ofproto_parser
2249 req = ofp_parser.OFPQueueDescStatsRequest(datapath, 0,
2252 datapath.send_msg(req)
2255 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
2256 queue_id=ofproto.OFPQ_ALL, type_=None):
2257 super(OFPQueueDescStatsRequest, self).__init__(datapath, flags)
2258 self.port_no = port_no
2259 self.queue_id = queue_id
2261 def _serialize_stats_body(self):
2262 msg_pack_into(ofproto.OFP_QUEUE_DESC_REQUEST_PACK_STR,
2264 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2265 self.port_no, self.queue_id)
2268 @OFPMultipartReply.register_stats_type()
2269 @_set_stats_type(ofproto.OFPMP_QUEUE_DESC, OFPQueueDesc)
2270 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2271 class OFPQueueDescStatsReply(OFPMultipartReply):
2273 Queue description reply message
2275 The switch responds with this message to a queue description request.
2277 ================ ======================================================
2278 Attribute Description
2279 ================ ======================================================
2280 body List of ``OFPQueueDesc`` instance
2281 ================ ======================================================
2285 @set_ev_cls(ofp_event.EventOFPQueueDescStatsReply, MAIN_DISPATCHER)
2286 def queue_desc_stats_reply_handler(self, ev):
2288 for q in ev.msg.body:
2289 queues.append('port_no=%d queue_id=0x%08x properties=%s' %
2290 (q.port_no, q.queue_id, repr(q.properties)))
2291 self.logger.debug('OFPQueueDescStatsReply received: %s', queues)
2294 def __init__(self, datapath, type_=None, **kwargs):
2295 super(OFPQueueDescStatsReply, self).__init__(datapath, **kwargs)
2298 class OFPQueueStatsProp(OFPPropBase):
2302 @OFPQueueStatsProp.register_type(ofproto.OFPQSPT_EXPERIMENTER)
2303 class OFPQueueStatsPropExperimenter(OFPPropCommonExperimenter4ByteData):
2307 class OFPQueueStats(StringifyMixin):
2308 def __init__(self, length=None, port_no=None, queue_id=None,
2309 tx_bytes=None, tx_packets=None, tx_errors=None,
2310 duration_sec=None, duration_nsec=None, properties=None):
2311 super(OFPQueueStats, self).__init__()
2312 self.length = length
2313 self.port_no = port_no
2314 self.queue_id = queue_id
2315 self.tx_bytes = tx_bytes
2316 self.tx_packets = tx_packets
2317 self.tx_errors = tx_errors
2318 self.duration_sec = duration_sec
2319 self.duration_nsec = duration_nsec
2320 self.properties = properties
2323 def parser(cls, buf, offset):
2324 (length, port_no, queue_id, tx_bytes, tx_packets, tx_errors,
2325 duration_sec, duration_nsec) = struct.unpack_from(
2326 ofproto.OFP_QUEUE_STATS_PACK_STR, buf, offset)
2328 rest = buf[offset + ofproto.OFP_QUEUE_STATS_SIZE:offset + length]
2330 p, rest = OFPQueueStatsProp.parse(rest)
2332 stats = cls(length, port_no, queue_id, tx_bytes, tx_packets, tx_errors,
2333 duration_sec, duration_nsec, props)
2337 @_set_stats_type(ofproto.OFPMP_QUEUE_STATS, OFPQueueStats)
2338 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2339 class OFPQueueStatsRequest(OFPMultipartRequest):
2341 Queue statistics request message
2343 The controller uses this message to query queue statictics.
2345 ================ ======================================================
2346 Attribute Description
2347 ================ ======================================================
2348 flags Zero or ``OFPMPF_REQ_MORE``
2349 port_no Port number to read
2350 queue_id ID of queue to read
2351 ================ ======================================================
2355 def send_queue_stats_request(self, datapath):
2356 ofp = datapath.ofproto
2357 ofp_parser = datapath.ofproto_parser
2359 req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPP_ANY,
2361 datapath.send_msg(req)
2364 def __init__(self, datapath, flags=0, port_no=ofproto.OFPP_ANY,
2365 queue_id=ofproto.OFPQ_ALL, type_=None):
2366 super(OFPQueueStatsRequest, self).__init__(datapath, flags)
2367 self.port_no = port_no
2368 self.queue_id = queue_id
2370 def _serialize_stats_body(self):
2371 msg_pack_into(ofproto.OFP_QUEUE_STATS_REQUEST_PACK_STR,
2373 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2374 self.port_no, self.queue_id)
2377 @OFPMultipartReply.register_stats_type()
2378 @_set_stats_type(ofproto.OFPMP_QUEUE_STATS, OFPQueueStats)
2379 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2380 class OFPQueueStatsReply(OFPMultipartReply):
2382 Queue statistics reply message
2384 The switch responds with this message to an aggregate flow statistics
2387 ================ ======================================================
2388 Attribute Description
2389 ================ ======================================================
2390 body List of ``OFPQueueStats`` instance
2391 ================ ======================================================
2395 @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
2396 def queue_stats_reply_handler(self, ev):
2398 for stat in ev.msg.body:
2399 queues.append('port_no=%d queue_id=%d '
2400 'tx_bytes=%d tx_packets=%d tx_errors=%d '
2401 'duration_sec=%d duration_nsec=%d'
2403 (stat.port_no, stat.queue_id,
2404 stat.tx_bytes, stat.tx_packets, stat.tx_errors,
2405 stat.duration_sec, stat.duration_nsec,
2406 repr(stat.properties)))
2407 self.logger.debug('QueueStats: %s', queues)
2410 def __init__(self, datapath, type_=None, **kwargs):
2411 super(OFPQueueStatsReply, self).__init__(datapath, **kwargs)
2414 class OFPBucketCounter(StringifyMixin):
2415 def __init__(self, packet_count, byte_count):
2416 super(OFPBucketCounter, self).__init__()
2417 self.packet_count = packet_count
2418 self.byte_count = byte_count
2421 def parser(cls, buf, offset):
2422 packet_count, byte_count = struct.unpack_from(
2423 ofproto.OFP_BUCKET_COUNTER_PACK_STR, buf, offset)
2424 return cls(packet_count, byte_count)
2427 class OFPGroupStats(StringifyMixin):
2428 def __init__(self, length=None, group_id=None, ref_count=None,
2429 packet_count=None, byte_count=None, duration_sec=None,
2430 duration_nsec=None, bucket_stats=None):
2431 super(OFPGroupStats, self).__init__()
2432 self.length = length
2433 self.group_id = group_id
2434 self.ref_count = ref_count
2435 self.packet_count = packet_count
2436 self.byte_count = byte_count
2437 self.duration_sec = duration_sec
2438 self.duration_nsec = duration_nsec
2439 self.bucket_stats = bucket_stats
2442 def parser(cls, buf, offset):
2443 group = struct.unpack_from(ofproto.OFP_GROUP_STATS_PACK_STR,
2445 group_stats = cls(*group)
2447 group_stats.bucket_stats = []
2448 total_len = group_stats.length + offset
2449 offset += ofproto.OFP_GROUP_STATS_SIZE
2450 while total_len > offset:
2451 b = OFPBucketCounter.parser(buf, offset)
2452 group_stats.bucket_stats.append(b)
2453 offset += ofproto.OFP_BUCKET_COUNTER_SIZE
2458 @_set_stats_type(ofproto.OFPMP_GROUP, OFPGroupStats)
2459 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2460 class OFPGroupStatsRequest(OFPMultipartRequest):
2462 Group statistics request message
2464 The controller uses this message to query statistics of one or more
2467 ================ ======================================================
2468 Attribute Description
2469 ================ ======================================================
2470 flags Zero or ``OFPMPF_REQ_MORE``
2471 group_id ID of group to read (OFPG_ALL to all groups)
2472 ================ ======================================================
2476 def send_group_stats_request(self, datapath):
2477 ofp = datapath.ofproto
2478 ofp_parser = datapath.ofproto_parser
2480 req = ofp_parser.OFPGroupStatsRequest(datapath, 0, ofp.OFPG_ALL)
2481 datapath.send_msg(req)
2484 def __init__(self, datapath, flags=0, group_id=ofproto.OFPG_ALL,
2486 super(OFPGroupStatsRequest, self).__init__(datapath, flags)
2487 self.group_id = group_id
2489 def _serialize_stats_body(self):
2490 msg_pack_into(ofproto.OFP_GROUP_STATS_REQUEST_PACK_STR,
2492 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2496 @OFPMultipartReply.register_stats_type()
2497 @_set_stats_type(ofproto.OFPMP_GROUP, OFPGroupStats)
2498 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2499 class OFPGroupStatsReply(OFPMultipartReply):
2501 Group statistics reply message
2503 The switch responds with this message to a group statistics request.
2505 ================ ======================================================
2506 Attribute Description
2507 ================ ======================================================
2508 body List of ``OFPGroupStats`` instance
2509 ================ ======================================================
2513 @set_ev_cls(ofp_event.EventOFPGroupStatsReply, MAIN_DISPATCHER)
2514 def group_stats_reply_handler(self, ev):
2516 for stat in ev.msg.body:
2517 groups.append('length=%d group_id=%d '
2518 'ref_count=%d packet_count=%d byte_count=%d '
2519 'duration_sec=%d duration_nsec=%d' %
2520 (stat.length, stat.group_id,
2521 stat.ref_count, stat.packet_count,
2522 stat.byte_count, stat.duration_sec,
2523 stat.duration_nsec))
2524 self.logger.debug('GroupStats: %s', groups)
2527 def __init__(self, datapath, type_=None, **kwargs):
2528 super(OFPGroupStatsReply, self).__init__(datapath, **kwargs)
2531 class OFPGroupDescStats(StringifyMixin):
2532 def __init__(self, type_=None, group_id=None, buckets=None, length=None):
2533 super(OFPGroupDescStats, self).__init__()
2535 self.group_id = group_id
2536 self.buckets = buckets
2539 def parser(cls, buf, offset):
2542 (stats.length, stats.type, stats.group_id) = struct.unpack_from(
2543 ofproto.OFP_GROUP_DESC_STATS_PACK_STR, buf, offset)
2544 offset += ofproto.OFP_GROUP_DESC_STATS_SIZE
2547 length = ofproto.OFP_GROUP_DESC_STATS_SIZE
2548 while length < stats.length:
2549 bucket = OFPBucket.parser(buf, offset)
2550 stats.buckets.append(bucket)
2552 offset += bucket.len
2553 length += bucket.len
2558 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
2559 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2560 class OFPGroupDescStatsRequest(OFPMultipartRequest):
2562 Group description request message
2564 The controller uses this message to list the set of groups on a switch.
2566 ================ ======================================================
2567 Attribute Description
2568 ================ ======================================================
2569 flags Zero or ``OFPMPF_REQ_MORE``
2570 ================ ======================================================
2574 def send_group_desc_stats_request(self, datapath):
2575 ofp = datapath.ofproto
2576 ofp_parser = datapath.ofproto_parser
2578 req = ofp_parser.OFPGroupDescStatsRequest(datapath, 0)
2579 datapath.send_msg(req)
2582 def __init__(self, datapath, flags=0, type_=None):
2583 super(OFPGroupDescStatsRequest, self).__init__(datapath, flags)
2586 @OFPMultipartReply.register_stats_type()
2587 @_set_stats_type(ofproto.OFPMP_GROUP_DESC, OFPGroupDescStats)
2588 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2589 class OFPGroupDescStatsReply(OFPMultipartReply):
2591 Group description reply message
2593 The switch responds with this message to a group description request.
2595 ================ ======================================================
2596 Attribute Description
2597 ================ ======================================================
2598 body List of ``OFPGroupDescStats`` instance
2599 ================ ======================================================
2603 @set_ev_cls(ofp_event.EventOFPGroupDescStatsReply, MAIN_DISPATCHER)
2604 def group_desc_stats_reply_handler(self, ev):
2606 for stat in ev.msg.body:
2607 descs.append('length=%d type=%d group_id=%d '
2609 (stat.length, stat.type, stat.group_id,
2611 self.logger.debug('GroupDescStats: %s', descs)
2614 def __init__(self, datapath, type_=None, **kwargs):
2615 super(OFPGroupDescStatsReply, self).__init__(datapath, **kwargs)
2618 class OFPGroupFeaturesStats(ofproto_parser.namedtuple('OFPGroupFeaturesStats',
2619 ('types', 'capabilities', 'max_groups',
2622 def parser(cls, buf, offset):
2623 group_features = struct.unpack_from(
2624 ofproto.OFP_GROUP_FEATURES_PACK_STR, buf, offset)
2625 types = group_features[0]
2626 capabilities = group_features[1]
2627 max_groups = list(group_features[2:6])
2628 actions = list(group_features[6:10])
2629 stats = cls(types, capabilities, max_groups, actions)
2630 stats.length = ofproto.OFP_GROUP_FEATURES_SIZE
2634 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
2635 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2636 class OFPGroupFeaturesStatsRequest(OFPMultipartRequest):
2638 Group features request message
2640 The controller uses this message to list the capabilities of groups on
2643 ================ ======================================================
2644 Attribute Description
2645 ================ ======================================================
2646 flags Zero or ``OFPMPF_REQ_MORE``
2647 ================ ======================================================
2651 def send_group_features_stats_request(self, datapath):
2652 ofp_parser = datapath.ofproto_parser
2654 req = ofp_parser.OFPGroupFeaturesStatsRequest(datapath, 0)
2655 datapath.send_msg(req)
2658 def __init__(self, datapath, flags=0, type_=None):
2659 super(OFPGroupFeaturesStatsRequest, self).__init__(datapath, flags)
2662 @OFPMultipartReply.register_stats_type(body_single_struct=True)
2663 @_set_stats_type(ofproto.OFPMP_GROUP_FEATURES, OFPGroupFeaturesStats)
2664 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2665 class OFPGroupFeaturesStatsReply(OFPMultipartReply):
2667 Group features reply message
2669 The switch responds with this message to a group features request.
2671 ================ ======================================================
2672 Attribute Description
2673 ================ ======================================================
2674 body Instance of ``OFPGroupFeaturesStats``
2675 ================ ======================================================
2679 @set_ev_cls(ofp_event.EventOFPGroupFeaturesStatsReply, MAIN_DISPATCHER)
2680 def group_features_stats_reply_handler(self, ev):
2683 self.logger.debug('GroupFeaturesStats: types=%d '
2684 'capabilities=0x%08x max_groups=%s '
2686 body.types, body.capabilities,
2687 body.max_groups, body.actions)
2690 def __init__(self, datapath, type_=None, **kwargs):
2691 super(OFPGroupFeaturesStatsReply, self).__init__(datapath, **kwargs)
2694 class OFPMeterBandStats(StringifyMixin):
2695 def __init__(self, packet_band_count, byte_band_count):
2696 super(OFPMeterBandStats, self).__init__()
2697 self.packet_band_count = packet_band_count
2698 self.byte_band_count = byte_band_count
2701 def parser(cls, buf, offset):
2702 band_stats = struct.unpack_from(
2703 ofproto.OFP_METER_BAND_STATS_PACK_STR, buf, offset)
2704 return cls(*band_stats)
2707 class OFPMeterStats(StringifyMixin):
2708 def __init__(self, meter_id=None, flow_count=None, packet_in_count=None,
2709 byte_in_count=None, duration_sec=None, duration_nsec=None,
2710 band_stats=None, len_=None):
2711 super(OFPMeterStats, self).__init__()
2712 self.meter_id = meter_id
2714 self.flow_count = flow_count
2715 self.packet_in_count = packet_in_count
2716 self.byte_in_count = byte_in_count
2717 self.duration_sec = duration_sec
2718 self.duration_nsec = duration_nsec
2719 self.band_stats = band_stats
2722 def parser(cls, buf, offset):
2725 (meter_stats.meter_id, meter_stats.len,
2726 meter_stats.flow_count, meter_stats.packet_in_count,
2727 meter_stats.byte_in_count, meter_stats.duration_sec,
2728 meter_stats.duration_nsec) = struct.unpack_from(
2729 ofproto.OFP_METER_STATS_PACK_STR, buf, offset)
2730 offset += ofproto.OFP_METER_STATS_SIZE
2732 meter_stats.band_stats = []
2733 length = ofproto.OFP_METER_STATS_SIZE
2734 while length < meter_stats.len:
2735 band_stats = OFPMeterBandStats.parser(buf, offset)
2736 meter_stats.band_stats.append(band_stats)
2737 offset += ofproto.OFP_METER_BAND_STATS_SIZE
2738 length += ofproto.OFP_METER_BAND_STATS_SIZE
2743 @_set_stats_type(ofproto.OFPMP_METER, OFPMeterStats)
2744 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2745 class OFPMeterStatsRequest(OFPMultipartRequest):
2747 Meter statistics request message
2749 The controller uses this message to query statistics for one or more
2752 ================ ======================================================
2753 Attribute Description
2754 ================ ======================================================
2755 flags Zero or ``OFPMPF_REQ_MORE``
2756 meter_id ID of meter to read (OFPM_ALL to all meters)
2757 ================ ======================================================
2761 def send_meter_stats_request(self, datapath):
2762 ofp = datapath.ofproto
2763 ofp_parser = datapath.ofproto_parser
2765 req = ofp_parser.OFPMeterStatsRequest(datapath, 0, ofp.OFPM_ALL)
2766 datapath.send_msg(req)
2769 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
2771 super(OFPMeterStatsRequest, self).__init__(datapath, flags)
2772 self.meter_id = meter_id
2774 def _serialize_stats_body(self):
2775 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
2777 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2781 @OFPMultipartReply.register_stats_type()
2782 @_set_stats_type(ofproto.OFPMP_METER, OFPMeterStats)
2783 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2784 class OFPMeterStatsReply(OFPMultipartReply):
2786 Meter statistics reply message
2788 The switch responds with this message to a meter statistics request.
2790 ================ ======================================================
2791 Attribute Description
2792 ================ ======================================================
2793 body List of ``OFPMeterStats`` instance
2794 ================ ======================================================
2798 @set_ev_cls(ofp_event.EventOFPMeterStatsReply, MAIN_DISPATCHER)
2799 def meter_stats_reply_handler(self, ev):
2801 for stat in ev.msg.body:
2802 meters.append('meter_id=0x%08x len=%d flow_count=%d '
2803 'packet_in_count=%d byte_in_count=%d '
2804 'duration_sec=%d duration_nsec=%d '
2806 (stat.meter_id, stat.len, stat.flow_count,
2807 stat.packet_in_count, stat.byte_in_count,
2808 stat.duration_sec, stat.duration_nsec,
2810 self.logger.debug('MeterStats: %s', meters)
2813 def __init__(self, datapath, type_=None, **kwargs):
2814 super(OFPMeterStatsReply, self).__init__(datapath, **kwargs)
2817 class OFPMeterBand(StringifyMixin):
2818 def __init__(self, type_, len_):
2819 super(OFPMeterBand, self).__init__()
2824 class OFPMeterBandHeader(OFPMeterBand):
2828 def register_meter_band_type(type_, len_):
2829 def _register_meter_band_type(cls):
2830 OFPMeterBandHeader._METER_BAND[type_] = cls
2831 cls.cls_meter_band_type = type_
2832 cls.cls_meter_band_len = len_
2834 return _register_meter_band_type
2837 cls = self.__class__
2838 super(OFPMeterBandHeader, self).__init__(cls.cls_meter_band_type,
2839 cls.cls_meter_band_len)
2842 def parser(cls, buf, offset):
2843 type_, len_, _rate, _burst_size = struct.unpack_from(
2844 ofproto.OFP_METER_BAND_HEADER_PACK_STR, buf, offset)
2845 cls_ = cls._METER_BAND[type_]
2846 assert cls_.cls_meter_band_len == len_
2847 return cls_.parser(buf, offset)
2850 @OFPMeterBandHeader.register_meter_band_type(
2851 ofproto.OFPMBT_DROP, ofproto.OFP_METER_BAND_DROP_SIZE)
2852 class OFPMeterBandDrop(OFPMeterBandHeader):
2853 def __init__(self, rate=0, burst_size=0, type_=None, len_=None):
2854 super(OFPMeterBandDrop, self).__init__()
2856 self.burst_size = burst_size
2858 def serialize(self, buf, offset):
2859 msg_pack_into(ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset,
2860 self.type, self.len, self.rate, self.burst_size)
2863 def parser(cls, buf, offset):
2864 type_, len_, rate, burst_size = struct.unpack_from(
2865 ofproto.OFP_METER_BAND_DROP_PACK_STR, buf, offset)
2866 assert cls.cls_meter_band_type == type_
2867 assert cls.cls_meter_band_len == len_
2868 return cls(rate, burst_size)
2871 @OFPMeterBandHeader.register_meter_band_type(
2872 ofproto.OFPMBT_DSCP_REMARK,
2873 ofproto.OFP_METER_BAND_DSCP_REMARK_SIZE)
2874 class OFPMeterBandDscpRemark(OFPMeterBandHeader):
2875 def __init__(self, rate=0, burst_size=0, prec_level=0,
2876 type_=None, len_=None):
2877 super(OFPMeterBandDscpRemark, self).__init__()
2879 self.burst_size = burst_size
2880 self.prec_level = prec_level
2882 def serialize(self, buf, offset):
2883 msg_pack_into(ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf,
2884 offset, self.type, self.len, self.rate,
2885 self.burst_size, self.prec_level)
2888 def parser(cls, buf, offset):
2889 type_, len_, rate, burst_size, prec_level = struct.unpack_from(
2890 ofproto.OFP_METER_BAND_DSCP_REMARK_PACK_STR, buf, offset)
2891 assert cls.cls_meter_band_type == type_
2892 assert cls.cls_meter_band_len == len_
2893 return cls(rate, burst_size, prec_level)
2896 @OFPMeterBandHeader.register_meter_band_type(
2897 ofproto.OFPMBT_EXPERIMENTER,
2898 ofproto.OFP_METER_BAND_EXPERIMENTER_SIZE)
2899 class OFPMeterBandExperimenter(OFPMeterBandHeader):
2900 def __init__(self, rate=0, burst_size=0, experimenter=None,
2901 type_=None, len_=None):
2902 super(OFPMeterBandExperimenter, self).__init__()
2904 self.burst_size = burst_size
2905 self.experimenter = experimenter
2907 def serialize(self, buf, offset):
2908 msg_pack_into(ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf,
2909 offset, self.type, self.len, self.rate,
2910 self.burst_size, self.experimenter)
2913 def parser(cls, buf, offset):
2914 type_, len_, rate, burst_size, experimenter = struct.unpack_from(
2915 ofproto.OFP_METER_BAND_EXPERIMENTER_PACK_STR, buf, offset)
2916 assert cls.cls_meter_band_type == type_
2917 assert cls.cls_meter_band_len == len_
2918 return cls(rate, burst_size, experimenter)
2921 class OFPMeterConfigStats(StringifyMixin):
2922 def __init__(self, flags=None, meter_id=None, bands=None, length=None):
2923 super(OFPMeterConfigStats, self).__init__()
2926 self.meter_id = meter_id
2930 def parser(cls, buf, offset):
2931 meter_config = cls()
2933 (meter_config.length, meter_config.flags,
2934 meter_config.meter_id) = struct.unpack_from(
2935 ofproto.OFP_METER_CONFIG_PACK_STR, buf, offset)
2936 offset += ofproto.OFP_METER_CONFIG_SIZE
2938 meter_config.bands = []
2939 length = ofproto.OFP_METER_CONFIG_SIZE
2940 while length < meter_config.length:
2941 band = OFPMeterBandHeader.parser(buf, offset)
2942 meter_config.bands.append(band)
2949 @_set_stats_type(ofproto.OFPMP_METER_CONFIG, OFPMeterConfigStats)
2950 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
2951 class OFPMeterConfigStatsRequest(OFPMultipartRequest):
2953 Meter configuration statistics request message
2955 The controller uses this message to query configuration for one or more
2958 ================ ======================================================
2959 Attribute Description
2960 ================ ======================================================
2961 flags Zero or ``OFPMPF_REQ_MORE``
2962 meter_id ID of meter to read (OFPM_ALL to all meters)
2963 ================ ======================================================
2967 def send_meter_config_stats_request(self, datapath):
2968 ofp = datapath.ofproto
2969 ofp_parser = datapath.ofproto_parser
2971 req = ofp_parser.OFPMeterConfigStatsRequest(datapath, 0,
2973 datapath.send_msg(req)
2976 def __init__(self, datapath, flags=0, meter_id=ofproto.OFPM_ALL,
2978 super(OFPMeterConfigStatsRequest, self).__init__(datapath, flags)
2979 self.meter_id = meter_id
2981 def _serialize_stats_body(self):
2982 msg_pack_into(ofproto.OFP_METER_MULTIPART_REQUEST_PACK_STR,
2984 ofproto.OFP_MULTIPART_REQUEST_SIZE,
2988 @OFPMultipartReply.register_stats_type()
2989 @_set_stats_type(ofproto.OFPMP_METER_CONFIG, OFPMeterConfigStats)
2990 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
2991 class OFPMeterConfigStatsReply(OFPMultipartReply):
2993 Meter configuration statistics reply message
2995 The switch responds with this message to a meter configuration
2998 ================ ======================================================
2999 Attribute Description
3000 ================ ======================================================
3001 body List of ``OFPMeterConfigStats`` instance
3002 ================ ======================================================
3006 @set_ev_cls(ofp_event.EventOFPMeterConfigStatsReply, MAIN_DISPATCHER)
3007 def meter_config_stats_reply_handler(self, ev):
3009 for stat in ev.msg.body:
3010 configs.append('length=%d flags=0x%04x meter_id=0x%08x '
3012 (stat.length, stat.flags, stat.meter_id,
3014 self.logger.debug('MeterConfigStats: %s', configs)
3017 def __init__(self, datapath, type_=None, **kwargs):
3018 super(OFPMeterConfigStatsReply, self).__init__(datapath, **kwargs)
3021 class OFPMeterFeaturesStats(ofproto_parser.namedtuple('OFPMeterFeaturesStats',
3022 ('max_meter', 'band_types', 'capabilities',
3023 'max_bands', 'max_color'))):
3025 def parser(cls, buf, offset):
3026 meter_features = struct.unpack_from(
3027 ofproto.OFP_METER_FEATURES_PACK_STR, buf, offset)
3028 stats = cls(*meter_features)
3029 stats.length = ofproto.OFP_METER_FEATURES_SIZE
3033 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
3034 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3035 class OFPMeterFeaturesStatsRequest(OFPMultipartRequest):
3037 Meter features statistics request message
3039 The controller uses this message to query the set of features of the
3042 ================ ======================================================
3043 Attribute Description
3044 ================ ======================================================
3045 flags Zero or ``OFPMPF_REQ_MORE``
3046 ================ ======================================================
3050 def send_meter_features_stats_request(self, datapath):
3051 ofp_parser = datapath.ofproto_parser
3053 req = ofp_parser.OFPMeterFeaturesStatsRequest(datapath, 0)
3054 datapath.send_msg(req)
3057 def __init__(self, datapath, flags=0, type_=None):
3058 super(OFPMeterFeaturesStatsRequest, self).__init__(datapath, flags)
3061 @OFPMultipartReply.register_stats_type()
3062 @_set_stats_type(ofproto.OFPMP_METER_FEATURES, OFPMeterFeaturesStats)
3063 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3064 class OFPMeterFeaturesStatsReply(OFPMultipartReply):
3066 Meter features statistics reply message
3068 The switch responds with this message to a meter features statistics
3071 ================ ======================================================
3072 Attribute Description
3073 ================ ======================================================
3074 body List of ``OFPMeterFeaturesStats`` instance
3075 ================ ======================================================
3079 @set_ev_cls(ofp_event.EventOFPMeterFeaturesStatsReply, MAIN_DISPATCHER)
3080 def meter_features_stats_reply_handler(self, ev):
3082 for stat in ev.msg.body:
3083 features.append('max_meter=%d band_types=0x%08x '
3084 'capabilities=0x%08x max_bands=%d '
3086 (stat.max_meter, stat.band_types,
3087 stat.capabilities, stat.max_bands,
3089 self.logger.debug('MeterFeaturesStats: %s', features)
3092 def __init__(self, datapath, type_=None, **kwargs):
3093 super(OFPMeterFeaturesStatsReply, self).__init__(datapath, **kwargs)
3096 class OFPFlowUpdate(StringifyMixin):
3097 def __init__(self, length, event):
3098 super(OFPFlowUpdate, self).__init__()
3099 self.length = length
3103 class OFPFlowUpdateHeader(OFPFlowUpdate):
3107 def register_flow_update_event(event, length):
3108 def _register_flow_update_event(cls):
3109 OFPFlowUpdateHeader._EVENT[event] = cls
3110 cls.cls_flow_update_event = event
3111 cls.cls_flow_update_length = length
3113 return _register_flow_update_event
3115 def __init__(self, length=None, event=None):
3116 cls = self.__class__
3117 super(OFPFlowUpdateHeader, self).__init__(length,
3118 cls.cls_flow_update_event)
3119 self.length = length
3122 def parser(cls, buf, offset):
3123 length, event = struct.unpack_from(
3124 ofproto.OFP_FLOW_UPDATE_HEADER_PACK_STR, buf, offset)
3125 cls_ = cls._EVENT[event]
3126 return cls_.parser(buf, offset)
3129 @OFPFlowUpdateHeader.register_flow_update_event(
3130 ofproto.OFPFME_INITIAL, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3131 @OFPFlowUpdateHeader.register_flow_update_event(
3132 ofproto.OFPFME_ADDED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3133 @OFPFlowUpdateHeader.register_flow_update_event(
3134 ofproto.OFPFME_REMOVED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3135 @OFPFlowUpdateHeader.register_flow_update_event(
3136 ofproto.OFPFME_MODIFIED, ofproto.OFP_FLOW_UPDATE_FULL_SIZE)
3137 class OFPFlowUpdateFull(OFPFlowUpdateHeader):
3138 def __init__(self, length=None, event=None, table_id=None, reason=None,
3139 idle_timeout=None, hard_timeout=None, priority=None,
3140 cookie=None, match=None, instructions=None):
3141 instructions = instructions if instructions else []
3142 super(OFPFlowUpdateFull, self).__init__(length, event)
3143 self.table_id = table_id
3144 self.reason = reason
3145 self.idle_timeout = idle_timeout
3146 self.hard_timeout = hard_timeout
3147 self.priority = priority
3148 self.cookie = cookie
3150 assert (event != ofproto.OFPFME_REMOVED or len(instructions) == 0)
3151 for i in instructions:
3152 assert isinstance(i, OFPInstruction)
3153 self.instructions = instructions
3156 def parser(cls, buf, offset):
3157 (length, event, table_id, reason, idle_timeout, hard_timeout, priority,
3158 cookie) = struct.unpack_from(ofproto.OFP_FLOW_UPDATE_FULL_0_PACK_STR,
3160 offset += ofproto.OFP_FLOW_UPDATE_FULL_0_SIZE
3161 assert cls.cls_flow_update_length <= length
3162 assert cls.cls_flow_update_event == event
3164 match = OFPMatch.parser(buf, offset)
3165 match_length = utils.round_up(match.length, 8)
3166 offset += match_length
3168 inst_length = (length - ofproto.OFP_FLOW_UPDATE_FULL_0_SIZE -
3171 while inst_length > 0:
3172 inst = OFPInstruction.parser(buf, offset)
3173 instructions.append(inst)
3175 inst_length -= inst.len
3177 return cls(length, event, table_id, reason, idle_timeout,
3178 hard_timeout, priority, cookie, match, instructions)
3181 @OFPFlowUpdateHeader.register_flow_update_event(
3182 ofproto.OFPFME_ABBREV, ofproto.OFP_FLOW_UPDATE_ABBREV_SIZE)
3183 class OFPFlowUpdateAbbrev(OFPFlowUpdateHeader):
3184 def __init__(self, length=None, event=None, xid=None):
3185 super(OFPFlowUpdateAbbrev, self).__init__(length, event)
3189 def parser(cls, buf, offset):
3190 length, event, xid = struct.unpack_from(
3191 ofproto.OFP_FLOW_UPDATE_ABBREV_PACK_STR, buf, offset)
3192 assert cls.cls_flow_update_length == length
3193 assert cls.cls_flow_update_event == event
3195 return cls(length, event, xid)
3198 @OFPFlowUpdateHeader.register_flow_update_event(
3199 ofproto.OFPFME_PAUSED, ofproto.OFP_FLOW_UPDATE_PAUSED_SIZE)
3200 @OFPFlowUpdateHeader.register_flow_update_event(
3201 ofproto.OFPFME_RESUMED, ofproto.OFP_FLOW_UPDATE_PAUSED_SIZE)
3202 class OFPFlowUpdatePaused(OFPFlowUpdateHeader):
3204 def parser(cls, buf, offset):
3205 length, event = struct.unpack_from(
3206 ofproto.OFP_FLOW_UPDATE_PAUSED_PACK_STR, buf, offset)
3207 assert cls.cls_flow_update_length == length
3208 assert cls.cls_flow_update_event == event
3210 return cls(length, event)
3213 class OFPFlowMonitorRequestBase(OFPMultipartRequest):
3214 def __init__(self, datapath, flags, monitor_id, out_port, out_group,
3215 monitor_flags, table_id, command, match):
3216 super(OFPFlowMonitorRequestBase, self).__init__(datapath, flags)
3217 self.monitor_id = monitor_id
3218 self.out_port = out_port
3219 self.out_group = out_group
3220 self.monitor_flags = monitor_flags
3221 self.table_id = table_id
3222 self.command = command
3225 def _serialize_stats_body(self):
3226 offset = ofproto.OFP_MULTIPART_REQUEST_SIZE
3227 msg_pack_into(ofproto.OFP_FLOW_MONITOR_REQUEST_0_PACK_STR, self.buf,
3228 offset, self.monitor_id, self.out_port, self.out_group,
3229 self.monitor_flags, self.table_id, self.command)
3231 offset += ofproto.OFP_FLOW_MONITOR_REQUEST_0_SIZE
3232 self.match.serialize(self.buf, offset)
3235 @_set_stats_type(ofproto.OFPMP_FLOW_MONITOR, OFPFlowUpdateHeader)
3236 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3237 class OFPFlowMonitorRequest(OFPFlowMonitorRequestBase):
3239 Flow monitor request message
3241 The controller uses this message to query flow monitors.
3243 ================ ======================================================
3244 Attribute Description
3245 ================ ======================================================
3246 flags Zero or ``OFPMPF_REQ_MORE``
3247 monitor_id Controller-assigned ID for this monitor
3248 out_port Require matching entries to include this as an output
3250 out_group Require matching entries to include this as an output
3252 monitor_flags Bitmap of the following flags.
3258 | OFPFMF_INSTRUCTIONS
3261 table_id ID of table to monitor
3262 command One of the following values.
3267 match Instance of ``OFPMatch``
3268 ================ ======================================================
3272 def send_flow_monitor_request(self, datapath):
3273 ofp = datapath.ofproto
3274 ofp_parser = datapath.ofproto_parser
3276 monitor_flags = [ofp.OFPFMF_INITIAL, ofp.OFPFMF_ONLY_OWN]
3277 match = ofp_parser.OFPMatch(in_port=1)
3278 req = ofp_parser.OFPFlowMonitorRequest(datapath, 0, 10000,
3279 ofp.OFPP_ANY, ofp.OFPG_ANY,
3282 ofp.OFPFMC_ADD, match)
3283 datapath.send_msg(req)
3286 def __init__(self, datapath, flags=0, monitor_id=0,
3287 out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY,
3288 monitor_flags=0, table_id=ofproto.OFPTT_ALL,
3289 command=ofproto.OFPFMC_ADD, match=None, type_=None):
3292 super(OFPFlowMonitorRequest, self).__init__(datapath, flags,
3293 monitor_id, out_port,
3294 out_group, monitor_flags,
3295 table_id, command, match)
3298 @OFPMultipartReply.register_stats_type()
3299 @_set_stats_type(ofproto.OFPMP_FLOW_MONITOR, OFPFlowUpdateHeader)
3300 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3301 class OFPFlowMonitorReply(OFPMultipartReply):
3303 Flow monitor reply message
3305 The switch responds with this message to a flow monitor request.
3307 ================ ======================================================
3308 Attribute Description
3309 ================ ======================================================
3310 body List of list of the following class instance.
3312 | OFPFlowMonitorFull
3313 | OFPFlowMonitorAbbrev
3314 | OFPFlowMonitorPaused
3315 ================ ======================================================
3319 @set_ev_cls(ofp_event.EventOFPFlowMonitorReply, MAIN_DISPATCHER)
3320 def flow_monitor_reply_handler(self, ev):
3326 for update in msg.body:
3327 update_str = 'length=%d event=%d' %
3328 (update.length, update.event)
3329 if (update.event == ofp.OFPFME_INITIAL or
3330 update.event == ofp.OFPFME_ADDED or
3331 update.event == ofp.OFPFME_REMOVED or
3332 update.event == ofp.OFPFME_MODIFIED):
3333 update_str += 'table_id=%d reason=%d idle_timeout=%d '
3334 'hard_timeout=%d priority=%d cookie=%d '
3335 'match=%d instructions=%s' %
3336 (update.table_id, update.reason,
3337 update.idle_timeout, update.hard_timeout,
3338 update.priority, update.cookie,
3339 update.match, update.instructions)
3340 elif update.event == ofp.OFPFME_ABBREV:
3341 update_str += 'xid=%d' % (update.xid)
3342 flow_updates.append(update_str)
3343 self.logger.debug('FlowUpdates: %s', flow_updates)
3346 def __init__(self, datapath, type_=None, **kwargs):
3347 super(OFPFlowMonitorReply, self).__init__(datapath, **kwargs)
3350 class OFPExperimenterMultipart(ofproto_parser.namedtuple(
3351 'OFPExperimenterMultipart',
3352 ('experimenter', 'exp_type', 'data'))):
3354 The body of OFPExperimenterStatsReply multipart messages.
3356 ================ ======================================================
3357 Attribute Description
3358 ================ ======================================================
3359 experimenter Experimenter ID
3360 exp_type Experimenter defined
3361 data Experimenter defined additional data
3362 ================ ======================================================
3366 def parser(cls, buf, offset):
3367 args = struct.unpack_from(
3368 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR, buf,
3371 args.append(buf[offset +
3372 ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_SIZE:])
3374 stats.length = ofproto.OFP_METER_FEATURES_SIZE
3377 def serialize(self):
3379 msg_pack_into(ofproto.OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR,
3381 self.experimenter, self.exp_type)
3382 return buf + self.data
3385 class OFPExperimenterStatsRequestBase(OFPMultipartRequest):
3386 def __init__(self, datapath, flags,
3387 experimenter, exp_type,
3389 super(OFPExperimenterStatsRequestBase, self).__init__(datapath, flags)
3390 self.experimenter = experimenter
3391 self.exp_type = exp_type
3394 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
3395 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3396 class OFPExperimenterStatsRequest(OFPExperimenterStatsRequestBase):
3398 Experimenter multipart request message
3400 ================ ======================================================
3401 Attribute Description
3402 ================ ======================================================
3403 flags Zero or ``OFPMPF_REQ_MORE``
3404 experimenter Experimenter ID
3405 exp_type Experimenter defined
3406 data Experimenter defined additional data
3407 ================ ======================================================
3410 def __init__(self, datapath, flags,
3411 experimenter, exp_type, data,
3413 super(OFPExperimenterStatsRequest, self).__init__(datapath, flags,
3418 def _serialize_stats_body(self):
3419 body = OFPExperimenterMultipart(experimenter=self.experimenter,
3420 exp_type=self.exp_type,
3422 self.buf += body.serialize()
3425 @OFPMultipartReply.register_stats_type(body_single_struct=True)
3426 @_set_stats_type(ofproto.OFPMP_EXPERIMENTER, OFPExperimenterMultipart)
3427 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3428 class OFPExperimenterStatsReply(OFPMultipartReply):
3430 Experimenter multipart reply message
3432 ================ ======================================================
3433 Attribute Description
3434 ================ ======================================================
3435 body An ``OFPExperimenterMultipart`` instance
3436 ================ ======================================================
3439 def __init__(self, datapath, type_=None, **kwargs):
3440 super(OFPExperimenterStatsReply, self).__init__(datapath, **kwargs)
3443 class OFPFlowStats(StringifyMixin):
3444 def __init__(self, table_id=None, duration_sec=None, duration_nsec=None,
3445 priority=None, idle_timeout=None, hard_timeout=None,
3446 flags=None, importance=None, cookie=None, packet_count=None,
3447 byte_count=None, match=None, instructions=None,
3449 super(OFPFlowStats, self).__init__()
3450 self.table_id = table_id
3451 self.duration_sec = duration_sec
3452 self.duration_nsec = duration_nsec
3453 self.priority = priority
3454 self.idle_timeout = idle_timeout
3455 self.hard_timeout = hard_timeout
3457 self.importance = importance
3458 self.cookie = cookie
3459 self.packet_count = packet_count
3460 self.byte_count = byte_count
3462 self.instructions = instructions
3463 self.length = length
3466 def parser(cls, buf, offset):
3469 (flow_stats.length, flow_stats.table_id,
3470 flow_stats.duration_sec, flow_stats.duration_nsec,
3471 flow_stats.priority, flow_stats.idle_timeout,
3472 flow_stats.hard_timeout, flow_stats.flags,
3473 flow_stats.importance, flow_stats.cookie,
3474 flow_stats.packet_count,
3475 flow_stats.byte_count) = struct.unpack_from(
3476 ofproto.OFP_FLOW_STATS_0_PACK_STR, buf, offset)
3477 offset += ofproto.OFP_FLOW_STATS_0_SIZE
3479 flow_stats.match = OFPMatch.parser(buf, offset)
3480 match_length = utils.round_up(flow_stats.match.length, 8)
3481 inst_length = (flow_stats.length - (ofproto.OFP_FLOW_STATS_SIZE -
3482 ofproto.OFP_MATCH_SIZE +
3484 offset += match_length
3486 while inst_length > 0:
3487 inst = OFPInstruction.parser(buf, offset)
3488 instructions.append(inst)
3490 inst_length -= inst.len
3492 flow_stats.instructions = instructions
3496 class OFPFlowStatsRequestBase(OFPMultipartRequest):
3497 def __init__(self, datapath, flags, table_id, out_port, out_group,
3498 cookie, cookie_mask, match):
3499 super(OFPFlowStatsRequestBase, self).__init__(datapath, flags)
3500 self.table_id = table_id
3501 self.out_port = out_port
3502 self.out_group = out_group
3503 self.cookie = cookie
3504 self.cookie_mask = cookie_mask
3507 def _serialize_stats_body(self):
3508 offset = ofproto.OFP_MULTIPART_REQUEST_SIZE
3509 msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_0_PACK_STR,
3510 self.buf, offset, self.table_id, self.out_port,
3511 self.out_group, self.cookie, self.cookie_mask)
3513 offset += ofproto.OFP_FLOW_STATS_REQUEST_0_SIZE
3514 self.match.serialize(self.buf, offset)
3517 @_set_stats_type(ofproto.OFPMP_FLOW, OFPFlowStats)
3518 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3519 class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
3521 Individual flow statistics request message
3523 The controller uses this message to query individual flow statistics.
3525 ================ ======================================================
3526 Attribute Description
3527 ================ ======================================================
3528 flags Zero or ``OFPMPF_REQ_MORE``
3529 table_id ID of table to read
3530 out_port Require matching entries to include this as an output
3532 out_group Require matching entries to include this as an output
3534 cookie Require matching entries to contain this cookie value
3535 cookie_mask Mask used to restrict the cookie bits that must match
3536 match Instance of ``OFPMatch``
3537 ================ ======================================================
3541 def send_flow_stats_request(self, datapath):
3542 ofp = datapath.ofproto
3543 ofp_parser = datapath.ofproto_parser
3545 cookie = cookie_mask = 0
3546 match = ofp_parser.OFPMatch(in_port=1)
3547 req = ofp_parser.OFPFlowStatsRequest(datapath, 0,
3549 ofp.OFPP_ANY, ofp.OFPG_ANY,
3550 cookie, cookie_mask,
3552 datapath.send_msg(req)
3555 def __init__(self, datapath, flags=0, table_id=ofproto.OFPTT_ALL,
3556 out_port=ofproto.OFPP_ANY,
3557 out_group=ofproto.OFPG_ANY,
3558 cookie=0, cookie_mask=0, match=None, type_=None):
3561 super(OFPFlowStatsRequest, self).__init__(datapath, flags, table_id,
3562 out_port, out_group,
3563 cookie, cookie_mask, match)
3566 @OFPMultipartReply.register_stats_type()
3567 @_set_stats_type(ofproto.OFPMP_FLOW, OFPFlowStats)
3568 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3569 class OFPFlowStatsReply(OFPMultipartReply):
3571 Individual flow statistics reply message
3573 The switch responds with this message to an individual flow statistics
3576 ================ ======================================================
3577 Attribute Description
3578 ================ ======================================================
3579 body List of ``OFPFlowStats`` instance
3580 ================ ======================================================
3584 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
3585 def flow_stats_reply_handler(self, ev):
3587 for stat in ev.msg.body:
3588 flows.append('table_id=%s '
3589 'duration_sec=%d duration_nsec=%d '
3591 'idle_timeout=%d hard_timeout=%d flags=0x%04x '
3592 'importance=%d cookie=%d packet_count=%d '
3593 'byte_count=%d match=%s instructions=%s' %
3595 stat.duration_sec, stat.duration_nsec,
3597 stat.idle_timeout, stat.hard_timeout,
3598 stat.flags, stat.importance,
3599 stat.cookie, stat.packet_count, stat.byte_count,
3600 stat.match, stat.instructions))
3601 self.logger.debug('FlowStats: %s', flows)
3604 def __init__(self, datapath, type_=None, **kwargs):
3605 super(OFPFlowStatsReply, self).__init__(datapath, **kwargs)
3608 class OFPAggregateStats(ofproto_parser.namedtuple('OFPAggregateStats', (
3609 'packet_count', 'byte_count', 'flow_count'))):
3611 def parser(cls, buf, offset):
3612 agg = struct.unpack_from(
3613 ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
3615 stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
3619 @_set_stats_type(ofproto.OFPMP_AGGREGATE, OFPAggregateStats)
3620 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3621 class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
3623 Aggregate flow statistics request message
3625 The controller uses this message to query aggregate flow statictics.
3627 ================ ======================================================
3628 Attribute Description
3629 ================ ======================================================
3630 flags Zero or ``OFPMPF_REQ_MORE``
3631 table_id ID of table to read
3632 out_port Require matching entries to include this as an output
3634 out_group Require matching entries to include this as an output
3636 cookie Require matching entries to contain this cookie value
3637 cookie_mask Mask used to restrict the cookie bits that must match
3638 match Instance of ``OFPMatch``
3639 ================ ======================================================
3643 def send_aggregate_stats_request(self, datapath):
3644 ofp = datapath.ofproto
3645 ofp_parser = datapath.ofproto_parser
3647 cookie = cookie_mask = 0
3648 match = ofp_parser.OFPMatch(in_port=1)
3649 req = ofp_parser.OFPAggregateStatsRequest(datapath, 0,
3653 cookie, cookie_mask,
3655 datapath.send_msg(req)
3658 def __init__(self, datapath, flags, table_id, out_port, out_group,
3659 cookie, cookie_mask, match, type_=None):
3660 super(OFPAggregateStatsRequest, self).__init__(datapath,
3670 @OFPMultipartReply.register_stats_type(body_single_struct=True)
3671 @_set_stats_type(ofproto.OFPMP_AGGREGATE, OFPAggregateStats)
3672 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3673 class OFPAggregateStatsReply(OFPMultipartReply):
3675 Aggregate flow statistics reply message
3677 The switch responds with this message to an aggregate flow statistics
3680 ================ ======================================================
3681 Attribute Description
3682 ================ ======================================================
3683 body Instance of ``OFPAggregateStats``
3684 ================ ======================================================
3688 @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
3689 def aggregate_stats_reply_handler(self, ev):
3692 self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
3694 body.packet_count, body.byte_count,
3698 def __init__(self, datapath, type_=None, **kwargs):
3699 super(OFPAggregateStatsReply, self).__init__(datapath, **kwargs)
3702 class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', (
3703 'table_id', 'active_count', 'lookup_count',
3706 def parser(cls, buf, offset):
3707 tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR,
3710 stats.length = ofproto.OFP_TABLE_STATS_SIZE
3714 @_set_stats_type(ofproto.OFPMP_TABLE, OFPTableStats)
3715 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3716 class OFPTableStatsRequest(OFPMultipartRequest):
3718 Table statistics request message
3720 The controller uses this message to query flow table statictics.
3722 ================ ======================================================
3723 Attribute Description
3724 ================ ======================================================
3725 flags Zero or ``OFPMPF_REQ_MORE``
3726 ================ ======================================================
3730 def send_table_stats_request(self, datapath):
3731 ofp_parser = datapath.ofproto_parser
3733 req = ofp_parser.OFPTableStatsRequest(datapath, 0)
3734 datapath.send_msg(req)
3737 def __init__(self, datapath, flags, type_=None):
3738 super(OFPTableStatsRequest, self).__init__(datapath, flags)
3741 @OFPMultipartReply.register_stats_type()
3742 @_set_stats_type(ofproto.OFPMP_TABLE, OFPTableStats)
3743 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3744 class OFPTableStatsReply(OFPMultipartReply):
3746 Table statistics reply message
3748 The switch responds with this message to a table statistics request.
3750 ================ ======================================================
3751 Attribute Description
3752 ================ ======================================================
3753 body List of ``OFPTableStats`` instance
3754 ================ ======================================================
3758 @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
3759 def table_stats_reply_handler(self, ev):
3761 for stat in ev.msg.body:
3762 tables.append('table_id=%d active_count=%d lookup_count=%d '
3763 ' matched_count=%d' %
3764 (stat.table_id, stat.active_count,
3765 stat.lookup_count, stat.matched_count))
3766 self.logger.debug('TableStats: %s', tables)
3769 def __init__(self, datapath, type_=None, **kwargs):
3770 super(OFPTableStatsReply, self).__init__(datapath, **kwargs)
3773 class OFPPortStatsProp(OFPPropBase):
3777 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_ETHERNET)
3778 class OFPPortStatsPropEthernet(OFPPortStatsProp):
3779 def __init__(self, type_=None, length=None, rx_frame_err=None,
3780 rx_over_err=None, rx_crc_err=None, collisions=None):
3782 self.length = length
3783 self.rx_frame_err = rx_frame_err
3784 self.rx_over_err = rx_over_err
3785 self.rx_crc_err = rx_crc_err
3786 self.collisions = collisions
3789 def parser(cls, buf):
3791 (ether.type, ether.length, ether.rx_frame_err, ether.rx_over_err,
3792 ether.rx_crc_err, ether.collisions) = struct.unpack_from(
3793 ofproto.OFP_PORT_STATS_PROP_ETHERNET_PACK_STR, buf, 0)
3797 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_OPTICAL)
3798 class OFPPortStatsPropOptical(OFPPortStatsProp):
3799 def __init__(self, type_=None, length=None, flags=None,
3800 tx_freq_lmda=None, tx_offset=None, tx_grid_span=None,
3801 rx_freq_lmda=None, rx_offset=None, rx_grid_span=None,
3802 tx_pwr=None, rx_pwr=None, bias_current=None,
3805 self.length = length
3807 self.tx_freq_lmda = tx_freq_lmda
3808 self.tx_offset = tx_offset
3809 self.tx_grid_span = tx_grid_span
3810 self.rx_freq_lmda = rx_freq_lmda
3811 self.rx_offset = rx_offset
3812 self.rx_grid_span = rx_grid_span
3813 self.tx_pwr = tx_pwr
3814 self.rx_pwr = rx_pwr
3815 self.bias_current = bias_current
3816 self.temperature = temperature
3819 def parser(cls, buf):
3821 (optical.type, optical.length, optical.flags,
3822 optical.tx_freq_lmda, optical.tx_offset, optical.tx_grid_span,
3823 optical.rx_freq_lmda, optical.rx_offset, optical.rx_grid_span,
3824 optical.tx_pwr, optical.rx_pwr, optical.bias_current,
3825 optical.temperature) = struct.unpack_from(
3826 ofproto.OFP_PORT_STATS_PROP_OPTICAL_PACK_STR, buf, 0)
3830 @OFPPortStatsProp.register_type(ofproto.OFPPSPT_EXPERIMENTER)
3831 class OFPPortStatsPropExperimenter(OFPPropCommonExperimenter4ByteData):
3835 class OFPPortStats(StringifyMixin):
3836 def __init__(self, length=None, port_no=None, duration_sec=None,
3837 duration_nsec=None, rx_packets=None, tx_packets=None,
3838 rx_bytes=None, tx_bytes=None, rx_dropped=None,
3839 tx_dropped=None, rx_errors=None, tx_errors=None,
3841 super(OFPPortStats, self).__init__()
3842 self.length = length
3843 self.port_no = port_no
3844 self.duration_sec = duration_sec
3845 self.duration_nsec = duration_nsec
3846 self.rx_packets = rx_packets
3847 self.tx_packets = tx_packets
3848 self.rx_bytes = rx_bytes
3849 self.tx_bytes = tx_bytes
3850 self.rx_dropped = rx_dropped
3851 self.tx_dropped = tx_dropped
3852 self.rx_errors = rx_errors
3853 self.tx_errors = tx_errors
3854 self.properties = properties
3857 def parser(cls, buf, offset):
3858 (length, port_no, duration_sec, duration_nsec, rx_packets,
3859 tx_packets, rx_bytes, tx_bytes, rx_dropped, tx_dropped,
3860 rx_errors, tx_errors) = struct.unpack_from(
3861 ofproto.OFP_PORT_STATS_PACK_STR, buf, offset)
3863 rest = buf[offset + ofproto.OFP_PORT_STATS_SIZE:offset + length]
3865 p, rest = OFPPortStatsProp.parse(rest)
3867 stats = cls(length, port_no, duration_sec, duration_nsec, rx_packets,
3868 tx_packets, rx_bytes, tx_bytes, rx_dropped, tx_dropped,
3869 rx_errors, tx_errors, props)
3873 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
3874 @_set_msg_type(ofproto.OFPT_MULTIPART_REQUEST)
3875 class OFPPortStatsRequest(OFPMultipartRequest):
3877 Port statistics request message
3879 The controller uses this message to query information about ports
3882 ================ ======================================================
3883 Attribute Description
3884 ================ ======================================================
3885 flags Zero or ``OFPMPF_REQ_MORE``
3886 port_no Port number to read (OFPP_ANY to all ports)
3887 ================ ======================================================
3891 def send_port_stats_request(self, datapath):
3892 ofp = datapath.ofproto
3893 ofp_parser = datapath.ofproto_parser
3895 req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY)
3896 datapath.send_msg(req)
3899 def __init__(self, datapath, flags, port_no, type_=None):
3900 super(OFPPortStatsRequest, self).__init__(datapath, flags)
3901 self.port_no = port_no
3903 def _serialize_stats_body(self):
3904 msg_pack_into(ofproto.OFP_PORT_STATS_REQUEST_PACK_STR,
3906 ofproto.OFP_MULTIPART_REQUEST_SIZE,
3910 @OFPMultipartReply.register_stats_type()
3911 @_set_stats_type(ofproto.OFPMP_PORT_STATS, OFPPortStats)
3912 @_set_msg_type(ofproto.OFPT_MULTIPART_REPLY)
3913 class OFPPortStatsReply(OFPMultipartReply):
3915 Port statistics reply message
3917 The switch responds with this message to a port statistics request.
3919 ================ ======================================================
3920 Attribute Description
3921 ================ ======================================================
3922 body List of ``OFPPortStats`` instance
3923 ================ ======================================================
3927 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
3928 def port_stats_reply_handler(self, ev):
3930 for stat in ev.msg.body:
3931 ports.append(stat.length, stat.port_no,
3932 stat.duration_sec, stat.duration_nsec,
3933 stat.rx_packets, stat.tx_packets,
3934 stat.rx_bytes, stat.tx_bytes,
3935 stat.rx_dropped, stat.tx_dropped,
3936 stat.rx_errors, stat.tx_errors,
3937 repr(stat.properties))
3938 self.logger.debug('PortStats: %s', ports)
3941 def __init__(self, datapath, type_=None, **kwargs):
3942 super(OFPPortStatsReply, self).__init__(datapath, **kwargs)
3945 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
3946 class OFPBarrierRequest(MsgBase):
3948 Barrier request message
3950 The controller sends this message to ensure message dependencies have
3951 been met or receive notifications for completed operations.
3955 def send_barrier_request(self, datapath):
3956 ofp_parser = datapath.ofproto_parser
3958 req = ofp_parser.OFPBarrierRequest(datapath)
3959 datapath.send_msg(req)
3962 def __init__(self, datapath):
3963 super(OFPBarrierRequest, self).__init__(datapath)
3967 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
3968 class OFPBarrierReply(MsgBase):
3970 Barrier reply message
3972 The switch responds with this message to a barrier request.
3976 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
3977 def barrier_reply_handler(self, ev):
3978 self.logger.debug('OFPBarrierReply received')
3981 def __init__(self, datapath):
3982 super(OFPBarrierReply, self).__init__(datapath)
3986 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
3987 class OFPPortStatus(MsgBase):
3991 The switch notifies controller of change of ports.
3993 ================ ======================================================
3994 Attribute Description
3995 ================ ======================================================
3996 reason One of the following values.
4001 desc instance of ``OFPPort``
4002 ================ ======================================================
4006 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
4007 def port_status_handler(self, ev):
4012 if msg.reason == ofp.OFPPR_ADD:
4014 elif msg.reason == ofp.OFPPR_DELETE:
4016 elif msg.reason == ofp.OFPPR_MODIFY:
4021 self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
4025 def __init__(self, datapath, reason=None, desc=None):
4026 super(OFPPortStatus, self).__init__(datapath)
4027 self.reason = reason
4031 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4032 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
4034 msg.reason = struct.unpack_from(
4035 ofproto.OFP_PORT_STATUS_PACK_STR, msg.buf,
4036 ofproto.OFP_HEADER_SIZE)[0]
4037 msg.desc = OFPPort.parser(msg.buf, ofproto.OFP_PORT_STATUS_DESC_OFFSET)
4042 @_set_msg_type(ofproto.OFPT_ROLE_STATUS)
4043 class OFPRoleStatus(MsgBase):
4047 The switch notifies controller of change of role.
4049 ================ ======================================================
4050 Attribute Description
4051 ================ ======================================================
4052 role One of the following values.
4054 | OFPCR_ROLE_NOCHANGE
4057 reason One of the following values.
4059 | OFPCRR_MASTER_REQUEST
4061 | OFPCRR_EXPERIMENTER
4062 generation_id Master Election Generation ID
4063 properties List of ``OFPRoleProp`` subclass instance
4064 ================ ======================================================
4068 @set_ev_cls(ofp_event.EventOFPRoleStatus, MAIN_DISPATCHER)
4069 def role_status_handler(self, ev):
4074 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
4075 role = 'ROLE NOCHANGE'
4076 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
4078 elif msg.role == ofp.OFPCR_ROLE_MASTER:
4079 role = 'ROLE MASTER'
4083 if msg.reason == ofp.OFPCRR_MASTER_REQUEST:
4084 reason = 'MASTER REQUEST'
4085 elif msg.reason == ofp.OFPCRR_CONFIG:
4087 elif msg.reason == ofp.OFPCRR_EXPERIMENTER:
4088 reason = 'EXPERIMENTER'
4092 self.logger.debug('OFPRoleStatus received: role=%s reason=%s '
4093 'generation_id=%d properties=%s', role, reason,
4094 msg.generation_id, repr(msg.properties))
4097 def __init__(self, datapath, role=None, reason=None,
4098 generation_id=None, properties=None):
4099 super(OFPRoleStatus, self).__init__(datapath)
4101 self.reason = reason
4102 self.generation_id = generation_id
4103 self.properties = properties
4106 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4107 msg = super(OFPRoleStatus, cls).parser(datapath, version, msg_type,
4109 (msg.role, msg.reason, msg.generation_id) = struct.unpack_from(
4110 ofproto.OFP_ROLE_STATUS_PACK_STR, msg.buf,
4111 ofproto.OFP_HEADER_SIZE)
4114 rest = msg.buf[ofproto.OFP_ROLE_STATUS_SIZE:]
4116 p, rest = OFPRoleProp.parse(rest)
4117 msg.properties.append(p)
4123 @_set_msg_type(ofproto.OFPT_TABLE_STATUS)
4124 class OFPTableStatus(MsgBase):
4126 Table status message
4128 The switch notifies controller of change of table status.
4130 ================ ======================================================
4131 Attribute Description
4132 ================ ======================================================
4133 reason One of the following values.
4135 | OFPTR_VACANCY_DOWN
4137 table ``OFPTableDesc`` instance
4138 ================ ======================================================
4142 @set_ev_cls(ofp_event.EventOFPTableStatus, MAIN_DISPATCHER)
4143 def table(self, ev):
4148 if msg.reason == ofp.OFPTR_VACANCY_DOWN:
4149 reason = 'VACANCY_DOWN'
4150 elif msg.reason == ofp.OFPTR_VACANCY_UP:
4151 reason = 'VACANCY_UP'
4155 self.logger.debug('OFPTableStatus received: reason=%s '
4156 'table_id=%d config=0x%08x properties=%s',
4157 reason, msg.table.table_id, msg.table.config,
4158 repr(msg.table.properties))
4161 def __init__(self, datapath, reason=None, table=None):
4162 super(OFPTableStatus, self).__init__(datapath)
4163 self.reason = reason
4167 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4168 msg = super(OFPTableStatus, cls).parser(datapath, version, msg_type,
4170 (msg.reason,) = struct.unpack_from(ofproto.OFP_TABLE_STATUS_0_PACK_STR,
4171 msg.buf, ofproto.OFP_HEADER_SIZE)
4173 msg.table = OFPTableDesc.parser(msg.buf,
4174 ofproto.OFP_TABLE_STATUS_0_SIZE)
4180 @_set_msg_type(ofproto.OFPT_REQUESTFORWARD)
4181 class OFPRequestForward(MsgInMsgBase):
4183 Forwarded request message
4185 The swtich forwards request messages from one controller to other
4188 ================ ======================================================
4189 Attribute Description
4190 ================ ======================================================
4191 request ``OFPGroupMod`` or ``OFPMeterMod`` instance
4192 ================ ======================================================
4196 @set_ev_cls(ofp_event.EventOFPRequestForward, MAIN_DISPATCHER)
4197 def request_forward_handler(self, ev):
4202 if msg.request.msg_type == ofp.OFPT_GROUP_MOD:
4204 'OFPRequestForward received: request=OFPGroupMod('
4205 'command=%d, type=%d, group_id=%d, buckets=%s)',
4206 msg.request.command, msg.request.type,
4207 msg.request.group_id, msg.request.buckets)
4208 elif msg.request.msg_type == ofp.OFPT_METER_MOD:
4210 'OFPRequestForward received: request=OFPMeterMod('
4211 'command=%d, flags=%d, meter_id=%d, bands=%s)',
4212 msg.request.command, msg.request.flags,
4213 msg.request.meter_id, msg.request.bands)
4216 'OFPRequestForward received: request=Unknown')
4219 def __init__(self, datapath, request=None):
4220 super(OFPRequestForward, self).__init__(datapath)
4221 self.request = request
4224 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4225 msg = super(OFPRequestForward, cls).parser(
4226 datapath, version, msg_type, msg_len, xid, buf)
4227 req_buf = buf[ofproto.OFP_HEADER_SIZE:]
4228 (_ver, _type, _len, _xid) = ofproto_parser.header(req_buf)
4229 msg.request = ofproto_parser.msg(
4230 datapath, _ver, _type, _len, _xid, req_buf)
4233 def _serialize_body(self):
4234 assert isinstance(self.request, (OFPGroupMod, OFPMeterMod))
4235 self.request.serialize()
4236 self.buf += self.request.buf
4239 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
4240 class OFPPacketOut(MsgBase):
4244 The controller uses this message to send a packet out throught the
4247 ================ ======================================================
4248 Attribute Description
4249 ================ ======================================================
4250 buffer_id ID assigned by datapath (OFP_NO_BUFFER if none)
4251 in_port Packet's input port or ``OFPP_CONTROLLER``
4252 actions list of OpenFlow action class
4253 data Packet data of a binary type value or
4254 an instances of packet.Packet.
4255 ================ ======================================================
4259 def send_packet_out(self, datapath, buffer_id, in_port):
4260 ofp = datapath.ofproto
4261 ofp_parser = datapath.ofproto_parser
4263 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
4264 req = ofp_parser.OFPPacketOut(datapath, buffer_id,
4266 datapath.send_msg(req)
4269 def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
4270 data=None, actions_len=None):
4271 assert in_port is not None
4273 super(OFPPacketOut, self).__init__(datapath)
4274 self.buffer_id = buffer_id
4275 self.in_port = in_port
4276 self.actions_len = 0
4277 self.actions = actions
4280 def _serialize_body(self):
4281 self.actions_len = 0
4282 offset = ofproto.OFP_PACKET_OUT_SIZE
4283 for a in self.actions:
4284 a.serialize(self.buf, offset)
4286 self.actions_len += a.len
4288 if self.data is not None:
4289 assert self.buffer_id == 0xffffffff
4290 if isinstance(self.data, packet.Packet):
4291 self.data.serialize()
4292 self.buf += self.data.data
4294 self.buf += self.data
4296 msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR,
4297 self.buf, ofproto.OFP_HEADER_SIZE,
4298 self.buffer_id, self.in_port, self.actions_len)
4301 def from_jsondict(cls, dict_, decode_string=base64.b64decode,
4303 if isinstance(dict_['data'], dict):
4304 data = dict_.pop('data')
4305 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
4308 ins.data = packet.Packet.from_jsondict(data['Packet'])
4309 dict_['data'] = data
4311 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
4319 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
4320 class OFPFlowMod(MsgBase):
4322 Modify Flow entry message
4324 The controller sends this message to modify the flow table.
4326 ================ ======================================================
4327 Attribute Description
4328 ================ ======================================================
4329 cookie Opaque controller-issued identifier
4330 cookie_mask Mask used to restrict the cookie bits that must match
4331 when the command is ``OPFFC_MODIFY*`` or
4333 table_id ID of the table to put the flow in
4334 command One of the following values.
4338 | OFPFC_MODIFY_STRICT
4340 | OFPFC_DELETE_STRICT
4341 idle_timeout Idle time before discarding (seconds)
4342 hard_timeout Max time before discarding (seconds)
4343 priority Priority level of flow entry
4344 buffer_id Buffered packet to apply to (or OFP_NO_BUFFER)
4345 out_port For ``OFPFC_DELETE*`` commands, require matching
4346 entries to include this as an output port
4347 out_group For ``OFPFC_DELETE*`` commands, require matching
4348 entries to include this as an output group
4349 flags Bitmap of the following flags.
4351 | OFPFF_SEND_FLOW_REM
4352 | OFPFF_CHECK_OVERLAP
4353 | OFPFF_RESET_COUNTS
4354 | OFPFF_NO_PKT_COUNTS
4355 | OFPFF_NO_BYT_COUNTS
4356 importance Eviction precedence
4357 match Instance of ``OFPMatch``
4358 instructions list of ``OFPInstruction*`` instance
4359 ================ ======================================================
4363 def send_flow_mod(self, datapath):
4364 ofp = datapath.ofproto
4365 ofp_parser = datapath.ofproto_parser
4367 cookie = cookie_mask = 0
4369 idle_timeout = hard_timeout = 0
4371 buffer_id = ofp.OFP_NO_BUFFER
4373 match = ofp_parser.OFPMatch(in_port=1, eth_dst='ff:ff:ff:ff:ff:ff')
4374 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
4375 inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
4377 req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask,
4378 table_id, ofp.OFPFC_ADD,
4379 idle_timeout, hard_timeout,
4380 priority, buffer_id,
4381 ofp.OFPP_ANY, ofp.OFPG_ANY,
4382 ofp.OFPFF_SEND_FLOW_REM,
4385 datapath.send_msg(req)
4388 def __init__(self, datapath, cookie=0, cookie_mask=0, table_id=0,
4389 command=ofproto.OFPFC_ADD,
4390 idle_timeout=0, hard_timeout=0,
4391 priority=ofproto.OFP_DEFAULT_PRIORITY,
4392 buffer_id=ofproto.OFP_NO_BUFFER,
4393 out_port=0, out_group=0, flags=0, importance=0,
4396 instructions = instructions if instructions else []
4397 super(OFPFlowMod, self).__init__(datapath)
4398 self.cookie = cookie
4399 self.cookie_mask = cookie_mask
4400 self.table_id = table_id
4401 self.command = command
4402 self.idle_timeout = idle_timeout
4403 self.hard_timeout = hard_timeout
4404 self.priority = priority
4405 self.buffer_id = buffer_id
4406 self.out_port = out_port
4407 self.out_group = out_group
4409 self.importance = importance
4412 assert isinstance(match, OFPMatch)
4414 for i in instructions:
4415 assert isinstance(i, OFPInstruction)
4416 self.instructions = instructions
4418 def _serialize_body(self):
4419 msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf,
4420 ofproto.OFP_HEADER_SIZE,
4421 self.cookie, self.cookie_mask, self.table_id,
4422 self.command, self.idle_timeout, self.hard_timeout,
4423 self.priority, self.buffer_id, self.out_port,
4424 self.out_group, self.flags, self.importance)
4426 offset = (ofproto.OFP_FLOW_MOD_SIZE -
4427 ofproto.OFP_MATCH_SIZE)
4429 match_len = self.match.serialize(self.buf, offset)
4432 for inst in self.instructions:
4433 inst.serialize(self.buf, offset)
4437 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
4438 msg = super(OFPFlowMod, cls).parser(
4439 datapath, version, msg_type, msg_len, xid, buf)
4441 (msg.cookie, msg.cookie_mask, msg.table_id,
4442 msg.command, msg.idle_timeout, msg.hard_timeout,
4443 msg.priority, msg.buffer_id, msg.out_port,
4444 msg.out_group, msg.flags, msg.importance) = struct.unpack_from(
4445 ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf,
4446 ofproto.OFP_HEADER_SIZE)
4447 offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE
4449 msg.match = OFPMatch.parser(buf, offset)
4450 offset += utils.round_up(msg.match.length, 8)
4453 while offset < msg_len:
4454 i = OFPInstruction.parser(buf, offset)
4455 instructions.append(i)
4457 msg.instructions = instructions
4462 class OFPInstruction(StringifyMixin):
4463 _INSTRUCTION_TYPES = {}
4466 def register_instruction_type(types):
4467 def _register_instruction_type(cls):
4469 OFPInstruction._INSTRUCTION_TYPES[type_] = cls
4471 return _register_instruction_type
4474 def parser(cls, buf, offset):
4475 (type_, len_) = struct.unpack_from('!HH', buf, offset)
4476 cls_ = cls._INSTRUCTION_TYPES.get(type_)
4477 return cls_.parser(buf, offset)
4480 @OFPInstruction.register_instruction_type([ofproto.OFPIT_GOTO_TABLE])
4481 class OFPInstructionGotoTable(OFPInstruction):
4483 Goto table instruction
4485 This instruction indicates the next table in the processing pipeline.
4487 ================ ======================================================
4488 Attribute Description
4489 ================ ======================================================
4491 ================ ======================================================
4494 def __init__(self, table_id, type_=None, len_=None):
4495 super(OFPInstructionGotoTable, self).__init__()
4496 self.type = ofproto.OFPIT_GOTO_TABLE
4497 self.len = ofproto.OFP_INSTRUCTION_GOTO_TABLE_SIZE
4498 self.table_id = table_id
4501 def parser(cls, buf, offset):
4502 (type_, len_, table_id) = struct.unpack_from(
4503 ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
4505 return cls(table_id)
4507 def serialize(self, buf, offset):
4508 msg_pack_into(ofproto.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
4509 buf, offset, self.type, self.len, self.table_id)
4512 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_METADATA])
4513 class OFPInstructionWriteMetadata(OFPInstruction):
4515 Write metadata instruction
4517 This instruction writes the masked metadata value into the metadata field.
4519 ================ ======================================================
4520 Attribute Description
4521 ================ ======================================================
4522 metadata Metadata value to write
4523 metadata_mask Metadata write bitmask
4524 ================ ======================================================
4527 def __init__(self, metadata, metadata_mask, type_=None, len_=None):
4528 super(OFPInstructionWriteMetadata, self).__init__()
4529 self.type = ofproto.OFPIT_WRITE_METADATA
4530 self.len = ofproto.OFP_INSTRUCTION_WRITE_METADATA_SIZE
4531 self.metadata = metadata
4532 self.metadata_mask = metadata_mask
4535 def parser(cls, buf, offset):
4536 (type_, len_, metadata, metadata_mask) = struct.unpack_from(
4537 ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
4539 return cls(metadata, metadata_mask)
4541 def serialize(self, buf, offset):
4542 msg_pack_into(ofproto.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
4543 buf, offset, self.type, self.len, self.metadata,
4547 @OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS,
4548 ofproto.OFPIT_APPLY_ACTIONS,
4549 ofproto.OFPIT_CLEAR_ACTIONS])
4550 class OFPInstructionActions(OFPInstruction):
4554 This instruction writes/applies/clears the actions.
4556 ================ ======================================================
4557 Attribute Description
4558 ================ ======================================================
4559 type One of following values.
4561 | OFPIT_WRITE_ACTIONS
4562 | OFPIT_APPLY_ACTIONS
4563 | OFPIT_CLEAR_ACTIONS
4564 actions list of OpenFlow action class
4565 ================ ======================================================
4567 ``type`` attribute corresponds to ``type_`` parameter of __init__.
4570 def __init__(self, type_, actions=None, len_=None):
4571 super(OFPInstructionActions, self).__init__()
4574 assert isinstance(a, OFPAction)
4575 self.actions = actions
4578 def parser(cls, buf, offset):
4579 (type_, len_) = struct.unpack_from(
4580 ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
4583 offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
4585 actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
4586 while actions_len > 0:
4587 a = OFPAction.parser(buf, offset)
4589 actions_len -= a.len
4592 inst = cls(type_, actions)
4596 def serialize(self, buf, offset):
4597 action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE
4599 for a in self.actions:
4600 a.serialize(buf, action_offset)
4601 action_offset += a.len
4603 self.len = action_offset - offset
4604 pad_len = utils.round_up(self.len, 8) - self.len
4605 msg_pack_into("%dx" % pad_len, buf, action_offset)
4608 msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR,
4609 buf, offset, self.type, self.len)
4612 @OFPInstruction.register_instruction_type([ofproto.OFPIT_METER])
4613 class OFPInstructionMeter(OFPInstruction):
4617 This instruction applies the meter.
4619 ================ ======================================================
4620 Attribute Description
4621 ================ ======================================================
4622 meter_id Meter instance
4623 ================ ======================================================
4626 def __init__(self, meter_id=1, type_=None, len_=None):
4627 super(OFPInstructionMeter, self).__init__()
4628 self.type = ofproto.OFPIT_METER
4629 self.len = ofproto.OFP_INSTRUCTION_METER_SIZE
4630 self.meter_id = meter_id
4633 def parser(cls, buf, offset):
4634 (type_, len_, meter_id) = struct.unpack_from(
4635 ofproto.OFP_INSTRUCTION_METER_PACK_STR,
4637 return cls(meter_id)
4639 def serialize(self, buf, offset):
4640 msg_pack_into(ofproto.OFP_INSTRUCTION_METER_PACK_STR,
4641 buf, offset, self.type, self.len, self.meter_id)
4644 class OFPActionHeader(StringifyMixin):
4645 def __init__(self, type_, len_):
4649 def serialize(self, buf, offset):
4650 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
4651 buf, offset, self.type, self.len)
4654 class OFPAction(OFPActionHeader):
4658 def register_action_type(type_, len_):
4659 def _register_action_type(cls):
4660 cls.cls_action_type = type_
4661 cls.cls_action_len = len_
4662 OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
4664 return _register_action_type
4667 cls = self.__class__
4668 super(OFPAction, self).__init__(cls.cls_action_type,
4672 def parser(cls, buf, offset):
4673 type_, len_ = struct.unpack_from(
4674 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4675 cls_ = cls._ACTION_TYPES.get(type_)
4676 assert cls_ is not None
4677 return cls_.parser(buf, offset)
4680 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
4681 ofproto.OFP_ACTION_OUTPUT_SIZE)
4682 class OFPActionOutput(OFPAction):
4686 This action indicates output a packet to the switch port.
4688 ================ ======================================================
4689 Attribute Description
4690 ================ ======================================================
4692 max_len Max length to send to controller
4693 ================ ======================================================
4696 def __init__(self, port, max_len=ofproto.OFPCML_MAX,
4697 type_=None, len_=None):
4698 super(OFPActionOutput, self).__init__()
4700 self.max_len = max_len
4703 def parser(cls, buf, offset):
4704 type_, len_, port, max_len = struct.unpack_from(
4705 ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
4706 return cls(port, max_len)
4708 def serialize(self, buf, offset):
4709 msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
4710 offset, self.type, self.len, self.port, self.max_len)
4713 @OFPAction.register_action_type(ofproto.OFPAT_GROUP,
4714 ofproto.OFP_ACTION_GROUP_SIZE)
4715 class OFPActionGroup(OFPAction):
4719 This action indicates the group used to process the packet.
4721 ================ ======================================================
4722 Attribute Description
4723 ================ ======================================================
4724 group_id Group identifier
4725 ================ ======================================================
4728 def __init__(self, group_id=0, type_=None, len_=None):
4729 super(OFPActionGroup, self).__init__()
4730 self.group_id = group_id
4733 def parser(cls, buf, offset):
4734 (type_, len_, group_id) = struct.unpack_from(
4735 ofproto.OFP_ACTION_GROUP_PACK_STR, buf, offset)
4736 return cls(group_id)
4738 def serialize(self, buf, offset):
4739 msg_pack_into(ofproto.OFP_ACTION_GROUP_PACK_STR, buf,
4740 offset, self.type, self.len, self.group_id)
4743 @OFPAction.register_action_type(ofproto.OFPAT_SET_QUEUE,
4744 ofproto.OFP_ACTION_SET_QUEUE_SIZE)
4745 class OFPActionSetQueue(OFPAction):
4749 This action sets the queue id that will be used to map a flow to an
4750 already-configured queue on a port.
4752 ================ ======================================================
4753 Attribute Description
4754 ================ ======================================================
4755 queue_id Queue ID for the packets
4756 ================ ======================================================
4759 def __init__(self, queue_id, type_=None, len_=None):
4760 super(OFPActionSetQueue, self).__init__()
4761 self.queue_id = queue_id
4764 def parser(cls, buf, offset):
4765 (type_, len_, queue_id) = struct.unpack_from(
4766 ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf, offset)
4767 return cls(queue_id)
4769 def serialize(self, buf, offset):
4770 msg_pack_into(ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
4771 offset, self.type, self.len, self.queue_id)
4774 @OFPAction.register_action_type(ofproto.OFPAT_SET_MPLS_TTL,
4775 ofproto.OFP_ACTION_MPLS_TTL_SIZE)
4776 class OFPActionSetMplsTtl(OFPAction):
4780 This action sets the MPLS TTL.
4782 ================ ======================================================
4783 Attribute Description
4784 ================ ======================================================
4786 ================ ======================================================
4789 def __init__(self, mpls_ttl, type_=None, len_=None):
4790 super(OFPActionSetMplsTtl, self).__init__()
4791 self.mpls_ttl = mpls_ttl
4794 def parser(cls, buf, offset):
4795 (type_, len_, mpls_ttl) = struct.unpack_from(
4796 ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf, offset)
4797 return cls(mpls_ttl)
4799 def serialize(self, buf, offset):
4800 msg_pack_into(ofproto.OFP_ACTION_MPLS_TTL_PACK_STR, buf,
4801 offset, self.type, self.len, self.mpls_ttl)
4804 @OFPAction.register_action_type(ofproto.OFPAT_DEC_MPLS_TTL,
4805 ofproto.OFP_ACTION_HEADER_SIZE)
4806 class OFPActionDecMplsTtl(OFPAction):
4808 Decrement MPLS TTL action
4810 This action decrements the MPLS TTL.
4813 def __init__(self, type_=None, len_=None):
4814 super(OFPActionDecMplsTtl, self).__init__()
4817 def parser(cls, buf, offset):
4818 (type_, len_) = struct.unpack_from(
4819 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4823 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TTL,
4824 ofproto.OFP_ACTION_NW_TTL_SIZE)
4825 class OFPActionSetNwTtl(OFPAction):
4829 This action sets the IP TTL.
4831 ================ ======================================================
4832 Attribute Description
4833 ================ ======================================================
4835 ================ ======================================================
4838 def __init__(self, nw_ttl, type_=None, len_=None):
4839 super(OFPActionSetNwTtl, self).__init__()
4840 self.nw_ttl = nw_ttl
4843 def parser(cls, buf, offset):
4844 (type_, len_, nw_ttl) = struct.unpack_from(
4845 ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
4848 def serialize(self, buf, offset):
4849 msg_pack_into(ofproto.OFP_ACTION_NW_TTL_PACK_STR, buf, offset,
4850 self.type, self.len, self.nw_ttl)
4853 @OFPAction.register_action_type(ofproto.OFPAT_DEC_NW_TTL,
4854 ofproto.OFP_ACTION_HEADER_SIZE)
4855 class OFPActionDecNwTtl(OFPAction):
4857 Decrement IP TTL action
4859 This action decrements the IP TTL.
4862 def __init__(self, type_=None, len_=None):
4863 super(OFPActionDecNwTtl, self).__init__()
4866 def parser(cls, buf, offset):
4867 (type_, len_) = struct.unpack_from(
4868 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4872 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_OUT,
4873 ofproto.OFP_ACTION_HEADER_SIZE)
4874 class OFPActionCopyTtlOut(OFPAction):
4878 This action copies the TTL from the next-to-outermost header with TTL to
4879 the outermost header with TTL.
4882 def __init__(self, type_=None, len_=None):
4883 super(OFPActionCopyTtlOut, self).__init__()
4886 def parser(cls, buf, offset):
4887 (type_, len_) = struct.unpack_from(
4888 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4892 @OFPAction.register_action_type(ofproto.OFPAT_COPY_TTL_IN,
4893 ofproto.OFP_ACTION_HEADER_SIZE)
4894 class OFPActionCopyTtlIn(OFPAction):
4898 This action copies the TTL from the outermost header with TTL to the
4899 next-to-outermost header with TTL.
4902 def __init__(self, type_=None, len_=None):
4903 super(OFPActionCopyTtlIn, self).__init__()
4906 def parser(cls, buf, offset):
4907 (type_, len_) = struct.unpack_from(
4908 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4912 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_VLAN,
4913 ofproto.OFP_ACTION_PUSH_SIZE)
4914 class OFPActionPushVlan(OFPAction):
4918 This action pushes a new VLAN tag to the packet.
4920 ================ ======================================================
4921 Attribute Description
4922 ================ ======================================================
4923 ethertype Ether type. The default is 802.1Q. (0x8100)
4924 ================ ======================================================
4927 def __init__(self, ethertype=ether.ETH_TYPE_8021Q, type_=None, len_=None):
4928 super(OFPActionPushVlan, self).__init__()
4929 self.ethertype = ethertype
4932 def parser(cls, buf, offset):
4933 (type_, len_, ethertype) = struct.unpack_from(
4934 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
4935 return cls(ethertype)
4937 def serialize(self, buf, offset):
4938 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
4939 self.type, self.len, self.ethertype)
4942 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_MPLS,
4943 ofproto.OFP_ACTION_PUSH_SIZE)
4944 class OFPActionPushMpls(OFPAction):
4948 This action pushes a new MPLS header to the packet.
4950 ================ ======================================================
4951 Attribute Description
4952 ================ ======================================================
4953 ethertype Ether type
4954 ================ ======================================================
4957 def __init__(self, ethertype=ether.ETH_TYPE_MPLS, type_=None, len_=None):
4958 super(OFPActionPushMpls, self).__init__()
4959 self.ethertype = ethertype
4962 def parser(cls, buf, offset):
4963 (type_, len_, ethertype) = struct.unpack_from(
4964 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
4965 return cls(ethertype)
4967 def serialize(self, buf, offset):
4968 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
4969 self.type, self.len, self.ethertype)
4972 @OFPAction.register_action_type(ofproto.OFPAT_POP_VLAN,
4973 ofproto.OFP_ACTION_HEADER_SIZE)
4974 class OFPActionPopVlan(OFPAction):
4978 This action pops the outermost VLAN tag from the packet.
4981 def __init__(self, type_=None, len_=None):
4982 super(OFPActionPopVlan, self).__init__()
4985 def parser(cls, buf, offset):
4986 (type_, len_) = struct.unpack_from(
4987 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
4991 @OFPAction.register_action_type(ofproto.OFPAT_POP_MPLS,
4992 ofproto.OFP_ACTION_POP_MPLS_SIZE)
4993 class OFPActionPopMpls(OFPAction):
4997 This action pops the MPLS header from the packet.
5000 def __init__(self, ethertype=ether.ETH_TYPE_IP, type_=None, len_=None):
5001 super(OFPActionPopMpls, self).__init__()
5002 self.ethertype = ethertype
5005 def parser(cls, buf, offset):
5006 (type_, len_, ethertype) = struct.unpack_from(
5007 ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset)
5008 return cls(ethertype)
5010 def serialize(self, buf, offset):
5011 msg_pack_into(ofproto.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset,
5012 self.type, self.len, self.ethertype)
5015 @OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
5016 ofproto.OFP_ACTION_SET_FIELD_SIZE)
5017 class OFPActionSetField(OFPAction):
5021 This action modifies a header field in the packet.
5023 The set of keywords available for this is same as OFPMatch.
5027 set_field = OFPActionSetField(eth_src="00:00:00:00:00:00")
5030 def __init__(self, field=None, **kwargs):
5031 super(OFPActionSetField, self).__init__()
5032 assert len(kwargs) == 1
5033 key = list(kwargs.keys())[0]
5035 assert isinstance(key, (str, six.text_type))
5036 assert not isinstance(value, tuple) # no mask
5041 def parser(cls, buf, offset):
5042 (type_, len_) = struct.unpack_from(
5043 ofproto.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
5044 (n, value, mask, _len) = ofproto.oxm_parse(buf, offset + 4)
5045 k, uv = ofproto.oxm_to_user(n, value, mask)
5046 action = cls(**{k: uv})
5050 def serialize(self, buf, offset):
5051 n, value, mask = ofproto.oxm_from_user(self.key, self.value)
5052 len_ = ofproto.oxm_serialize(n, value, mask, buf, offset + 4)
5053 self.len = utils.round_up(4 + len_, 8)
5054 msg_pack_into('!HH', buf, offset, self.type, self.len)
5055 pad_len = self.len - (4 + len_)
5056 msg_pack_into("%dx" % pad_len, buf, offset + 4 + len_)
5058 def to_jsondict(self):
5060 self.__class__.__name__: {
5061 'field': ofproto.oxm_to_jsondict(self.key, self.value),
5068 def from_jsondict(cls, dict_):
5069 k, v = ofproto.oxm_from_jsondict(dict_['field'])
5070 return OFPActionSetField(**{k: v})
5072 def stringify_attrs(self):
5073 yield (self.key, self.value)
5076 @OFPAction.register_action_type(ofproto.OFPAT_PUSH_PBB,
5077 ofproto.OFP_ACTION_PUSH_SIZE)
5078 class OFPActionPushPbb(OFPAction):
5082 This action pushes a new PBB header to the packet.
5084 ================ ======================================================
5085 Attribute Description
5086 ================ ======================================================
5087 ethertype Ether type
5088 ================ ======================================================
5091 def __init__(self, ethertype, type_=None, len_=None):
5092 super(OFPActionPushPbb, self).__init__()
5093 self.ethertype = ethertype
5096 def parser(cls, buf, offset):
5097 (type_, len_, ethertype) = struct.unpack_from(
5098 ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset)
5099 return cls(ethertype)
5101 def serialize(self, buf, offset):
5102 msg_pack_into(ofproto.OFP_ACTION_PUSH_PACK_STR, buf, offset,
5103 self.type, self.len, self.ethertype)
5106 @OFPAction.register_action_type(ofproto.OFPAT_POP_PBB,
5107 ofproto.OFP_ACTION_HEADER_SIZE)
5108 class OFPActionPopPbb(OFPAction):
5112 This action pops the outermost PBB service instance header from
5116 def __init__(self, type_=None, len_=None):
5117 super(OFPActionPopPbb, self).__init__()
5120 def parser(cls, buf, offset):
5121 (type_, len_) = struct.unpack_from(
5122 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
5126 @OFPAction.register_action_type(
5127 ofproto.OFPAT_EXPERIMENTER,
5128 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
5129 class OFPActionExperimenter(OFPAction):
5133 This action is an extensible action for the experimenter.
5135 ================ ======================================================
5136 Attribute Description
5137 ================ ======================================================
5138 experimenter Experimenter ID
5139 ================ ======================================================
5143 For the list of the supported Nicira experimenter actions,
5144 please refer to :ref:`ryu.ofproto.nx_actions <nx_actions_structures>`.
5147 def __init__(self, experimenter):
5148 super(OFPActionExperimenter, self).__init__()
5149 self.type = ofproto.OFPAT_EXPERIMENTER
5150 self.experimenter = experimenter
5154 def parser(cls, buf, offset):
5155 (type_, len_, experimenter) = struct.unpack_from(
5156 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset)
5157 data = buf[(offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE
5159 if experimenter == ofproto_common.NX_EXPERIMENTER_ID:
5160 obj = NXAction.parse(data) # noqa
5162 obj = OFPActionExperimenterUnknown(experimenter, data)
5166 def serialize(self, buf, offset):
5167 msg_pack_into(ofproto.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR,
5168 buf, offset, self.type, self.len, self.experimenter)
5171 class OFPActionExperimenterUnknown(OFPActionExperimenter):
5172 def __init__(self, experimenter, data=None, type_=None, len_=None):
5173 super(OFPActionExperimenterUnknown,
5174 self).__init__(experimenter=experimenter)
5177 def serialize(self, buf, offset):
5182 self.len = (utils.round_up(len(data), 8) +
5183 ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
5184 super(OFPActionExperimenterUnknown, self).serialize(buf, offset)
5185 msg_pack_into('!%ds' % len(self.data),
5187 offset + ofproto.OFP_ACTION_EXPERIMENTER_HEADER_SIZE,
5192 @_set_msg_type(ofproto.OFPT_GROUP_MOD)
5193 class OFPGroupMod(MsgBase):
5195 Modify group entry message
5197 The controller sends this message to modify the group table.
5199 ================ ======================================================
5200 Attribute Description
5201 ================ ======================================================
5202 command One of the following values.
5207 type One of the following values.
5213 group_id Group identifier
5214 buckets list of ``OFPBucket``
5215 ================ ======================================================
5217 ``type`` attribute corresponds to ``type_`` parameter of __init__.
5221 def send_group_mod(self, datapath):
5222 ofp = datapath.ofproto
5223 ofp_parser = datapath.ofproto_parser
5227 actions = [ofp_parser.OFPActionOutput(port, max_len)]
5232 buckets = [ofp_parser.OFPBucket(weight, watch_port, watch_group,
5236 req = ofp_parser.OFPGroupMod(datapath, ofp.OFPGC_ADD,
5237 ofp.OFPGT_SELECT, group_id, buckets)
5238 datapath.send_msg(req)
5241 def __init__(self, datapath, command=ofproto.OFPGC_ADD,
5242 type_=ofproto.OFPGT_ALL, group_id=0, buckets=None):
5243 buckets = buckets if buckets else []
5244 super(OFPGroupMod, self).__init__(datapath)
5245 self.command = command
5247 self.group_id = group_id
5248 self.buckets = buckets
5251 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5252 msg = super(OFPGroupMod, cls).parser(
5253 datapath, version, msg_type, msg_len, xid, buf)
5254 (msg.command, msg.type, msg.group_id) = struct.unpack_from(
5255 ofproto.OFP_GROUP_MOD_PACK_STR, buf, ofproto.OFP_HEADER_SIZE)
5256 offset = ofproto.OFP_GROUP_MOD_SIZE
5259 while offset < msg.msg_len:
5260 bucket = OFPBucket.parser(buf, offset)
5261 msg.buckets.append(bucket)
5262 offset += bucket.len
5266 def _serialize_body(self):
5267 msg_pack_into(ofproto.OFP_GROUP_MOD_PACK_STR, self.buf,
5268 ofproto.OFP_HEADER_SIZE,
5269 self.command, self.type, self.group_id)
5271 offset = ofproto.OFP_GROUP_MOD_SIZE
5272 for b in self.buckets:
5273 b.serialize(self.buf, offset)
5277 class OFPPortModProp(OFPPropBase):
5281 class OFPPortModPropEthernet(OFPPortModProp):
5282 def __init__(self, type_=None, length=None, advertise=None):
5284 self.advertise = advertise
5286 def serialize(self):
5288 self.length = struct.calcsize(
5289 ofproto.OFP_PORT_MOD_PROP_ETHERNET_PACK_STR)
5292 msg_pack_into(ofproto.OFP_PORT_MOD_PROP_ETHERNET_PACK_STR,
5293 buf, 0, self.type, self.length, self.advertise)
5297 class OFPPortModPropOptical(OFPPortModProp):
5298 def __init__(self, type_=None, length=None, configure=None,
5299 freq_lmda=None, fl_offset=None, grid_span=None,
5302 self.length = length
5303 self.configure = configure
5304 self.freq_lmda = freq_lmda
5305 self.fl_offset = fl_offset
5306 self.grid_span = grid_span
5307 self.tx_pwr = tx_pwr
5309 def serialize(self):
5311 self.length = struct.calcsize(
5312 ofproto.OFP_PORT_MOD_PROP_OPTICAL_PACK_STR)
5315 msg_pack_into(ofproto.OFP_PORT_MOD_PROP_OPTICAL_PACK_STR, buf, 0,
5316 self.type, self.length, self.configure, self.freq_lmda,
5317 self.fl_offset, self.grid_span, self.tx_pwr)
5321 class OFPPortModPropExperimenter(OFPPropCommonExperimenter4ByteData):
5325 @_set_msg_type(ofproto.OFPT_PORT_MOD)
5326 class OFPPortMod(MsgBase):
5328 Port modification message
5330 The controller sneds this message to modify the behavior of the port.
5332 ================ ======================================================
5333 Attribute Description
5334 ================ ======================================================
5335 port_no Port number to modify
5336 hw_addr The hardware address that must be the same as hw_addr
5337 of ``OFPPort`` of ``OFPSwitchFeatures``
5338 config Bitmap of configuration flags.
5343 | OFPPC_NO_PACKET_IN
5344 mask Bitmap of configuration flags above to be changed
5345 properties List of ``OFPPortModProp`` subclass instance
5346 ================ ======================================================
5350 def send_port_mod(self, datapath):
5351 ofp = datapath.ofproto
5352 ofp_parser = datapath.ofproto_parser
5355 hw_addr = 'fa:c8:e8:76:1d:7e'
5357 mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
5358 ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
5359 advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
5360 ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
5361 ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
5362 ofp.OFPPF_PAUSE_ASYM)
5363 properties = [ofp_parser.OFPPortModPropEthernet(advertise)]
5364 req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
5366 datapath.send_msg(req)
5375 def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
5376 config=0, mask=0, properties=None):
5377 super(OFPPortMod, self).__init__(datapath)
5378 self.port_no = port_no
5379 self.hw_addr = hw_addr
5380 self.config = config
5382 self.properties = properties or []
5384 def _serialize_body(self):
5385 bin_props = bytearray()
5386 for p in self.properties:
5387 bin_props += p.serialize()
5389 msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR, self.buf,
5390 ofproto.OFP_HEADER_SIZE,
5391 self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
5394 self.buf += bin_props
5397 class OFPBucket(StringifyMixin):
5398 def __init__(self, weight=0, watch_port=ofproto.OFPP_ANY,
5399 watch_group=ofproto.OFPG_ANY, actions=None, len_=None):
5400 super(OFPBucket, self).__init__()
5401 self.weight = weight
5402 self.watch_port = watch_port
5403 self.watch_group = watch_group
5404 self.actions = actions
5407 def parser(cls, buf, offset):
5408 (len_, weight, watch_port, watch_group) = struct.unpack_from(
5409 ofproto.OFP_BUCKET_PACK_STR, buf, offset)
5410 msg = cls(weight, watch_port, watch_group, [])
5413 length = ofproto.OFP_BUCKET_SIZE
5414 offset += ofproto.OFP_BUCKET_SIZE
5415 while length < msg.len:
5416 action = OFPAction.parser(buf, offset)
5417 msg.actions.append(action)
5418 offset += action.len
5419 length += action.len
5423 def serialize(self, buf, offset):
5424 action_offset = offset + ofproto.OFP_BUCKET_SIZE
5426 for a in self.actions:
5427 a.serialize(buf, action_offset)
5428 action_offset += a.len
5431 self.len = utils.round_up(ofproto.OFP_BUCKET_SIZE + action_len, 8)
5432 msg_pack_into(ofproto.OFP_BUCKET_PACK_STR, buf, offset,
5433 self.len, self.weight, self.watch_port,
5437 @_set_msg_type(ofproto.OFPT_ROLE_REQUEST)
5438 class OFPRoleRequest(MsgBase):
5440 Role request message
5442 The controller uses this message to change its role.
5444 ================ ======================================================
5445 Attribute Description
5446 ================ ======================================================
5447 role One of the following values.
5449 | OFPCR_ROLE_NOCHANGE
5453 generation_id Master Election Generation ID
5454 ================ ======================================================
5458 def send_role_request(self, datapath):
5459 ofp = datapath.ofproto
5460 ofp_parser = datapath.ofproto_parser
5462 req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
5463 datapath.send_msg(req)
5466 def __init__(self, datapath, role=None, generation_id=None):
5467 super(OFPRoleRequest, self).__init__(datapath)
5469 self.generation_id = generation_id
5471 def _serialize_body(self):
5472 assert self.role is not None
5473 assert self.generation_id is not None
5474 msg_pack_into(ofproto.OFP_ROLE_REQUEST_PACK_STR,
5475 self.buf, ofproto.OFP_HEADER_SIZE,
5476 self.role, self.generation_id)
5480 @_set_msg_type(ofproto.OFPT_ROLE_REPLY)
5481 class OFPRoleReply(MsgBase):
5485 The switch responds with this message to a role request.
5487 ================ ======================================================
5488 Attribute Description
5489 ================ ======================================================
5490 role One of the following values.
5492 | OFPCR_ROLE_NOCHANGE
5496 generation_id Master Election Generation ID
5497 ================ ======================================================
5501 @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
5502 def role_reply_handler(self, ev):
5507 if msg.role == ofp.OFPCR_ROLE_NOCHANGE:
5509 elif msg.role == ofp.OFPCR_ROLE_EQUAL:
5511 elif msg.role == ofp.OFPCR_ROLE_MASTER:
5513 elif msg.role == ofp.OFPCR_ROLE_SLAVE:
5518 self.logger.debug('OFPRoleReply received: '
5519 'role=%s generation_id=%d',
5520 role, msg.generation_id)
5523 def __init__(self, datapath, role=None, generation_id=None):
5524 super(OFPRoleReply, self).__init__(datapath)
5526 self.generation_id = generation_id
5529 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5530 msg = super(OFPRoleReply, cls).parser(datapath, version,
5531 msg_type, msg_len, xid,
5533 (msg.role, msg.generation_id) = struct.unpack_from(
5534 ofproto.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
5535 ofproto.OFP_HEADER_SIZE)
5539 class OFPAsyncConfigProp(OFPPropBase):
5543 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PACKET_IN_SLAVE)
5544 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PACKET_IN_MASTER)
5545 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PORT_STATUS_SLAVE)
5546 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_PORT_STATUS_MASTER)
5547 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_FLOW_REMOVED_SLAVE)
5548 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_FLOW_REMOVED_MASTER)
5549 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_ROLE_STATUS_SLAVE)
5550 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_ROLE_STATUS_MASTER)
5551 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_TABLE_STATUS_SLAVE)
5552 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_TABLE_STATUS_MASTER)
5553 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_REQUESTFORWARD_SLAVE)
5554 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_REQUESTFORWARD_MASTER)
5555 class OFPAsyncConfigPropReasons(OFPAsyncConfigProp):
5556 def __init__(self, type_=None, length=None, mask=None):
5558 self.length = length
5562 def parser(cls, buf):
5564 (reasons.type, reasons.length, reasons.mask) = struct.unpack_from(
5565 ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_PACK_STR, buf, 0)
5568 def serialize(self):
5570 self.length = ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_SIZE
5573 msg_pack_into(ofproto.OFP_ASYNC_CONFIG_PROP_REASONS_PACK_STR, buf, 0,
5574 self.type, self.length, self.mask)
5578 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_EXPERIMENTER_SLAVE)
5579 @OFPAsyncConfigProp.register_type(ofproto.OFPACPT_EXPERIMENTER_MASTER)
5580 class OFPAsyncConfigPropExperimenter(OFPPropCommonExperimenter4ByteData):
5584 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REQUEST)
5585 class OFPGetAsyncRequest(MsgBase):
5587 Get asynchronous configuration request message
5589 The controller uses this message to query the asynchronous message.
5593 def send_get_async_request(self, datapath):
5594 ofp_parser = datapath.ofproto_parser
5596 req = ofp_parser.OFPGetAsyncRequest(datapath)
5597 datapath.send_msg(req)
5600 def __init__(self, datapath):
5601 super(OFPGetAsyncRequest, self).__init__(datapath)
5605 @_set_msg_type(ofproto.OFPT_GET_ASYNC_REPLY)
5606 class OFPGetAsyncReply(MsgBase):
5608 Get asynchronous configuration reply message
5610 The switch responds with this message to a get asynchronous configuration
5613 ================== ====================================================
5614 Attribute Description
5615 ================== ====================================================
5616 properties List of ``OFPAsyncConfigProp`` subclass instances
5617 ================== ====================================================
5621 @set_ev_cls(ofp_event.EventOFPGetAsyncReply, MAIN_DISPATCHER)
5622 def get_async_reply_handler(self, ev):
5625 self.logger.debug('OFPGetAsyncReply received: '
5626 'properties=%s', repr(msg.properties))
5629 def __init__(self, datapath, properties=None):
5630 super(OFPGetAsyncReply, self).__init__(datapath)
5631 self.properties = properties
5634 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5635 msg = super(OFPGetAsyncReply, cls).parser(datapath, version,
5640 rest = msg.buf[ofproto.OFP_HEADER_SIZE:]
5642 p, rest = OFPAsyncConfigProp.parse(rest)
5643 msg.properties.append(p)
5648 @_set_msg_type(ofproto.OFPT_SET_ASYNC)
5649 class OFPSetAsync(MsgBase):
5651 Set asynchronous configuration message
5653 The controller sends this message to set the asynchronous messages that
5654 it wants to receive on a given OpneFlow channel.
5656 ================== ====================================================
5657 Attribute Description
5658 ================== ====================================================
5659 properties List of ``OFPAsyncConfigProp`` subclass instances
5660 ================== ====================================================
5664 def send_set_async(self, datapath):
5665 ofp = datapath.ofproto
5666 ofp_parser = datapath.ofproto_parser
5669 ofp_parser.OFPAsyncConfigPropReasons(
5670 ofp.OFPACPT_PACKET_IN_SLAVE, 8,
5671 (1 << ofp.OFPR_APPLY_ACTION
5672 | 1 << ofp.OFPR_INVALID_TTL))]
5673 req = ofp_parser.OFPSetAsync(datapath, properties)
5674 datapath.send_msg(req)
5677 def __init__(self, datapath, properties=None):
5678 super(OFPSetAsync, self).__init__(datapath)
5679 self.properties = properties
5681 def _serialize_body(self):
5682 bin_props = bytearray()
5683 for p in self.properties:
5684 bin_props += p.serialize()
5686 self.buf += bin_props
5690 @_set_msg_type(ofproto.OFPT_BUNDLE_CONTROL)
5691 class OFPBundleCtrlMsg(MsgBase):
5693 Bundle control message
5695 The controller uses this message to create, destroy and commit bundles
5697 ================ ======================================================
5698 Attribute Description
5699 ================ ======================================================
5700 bundle_id Id of the bundle
5701 type One of the following values.
5703 | OFPBCT_OPEN_REQUEST
5705 | OFPBCT_CLOSE_REQUEST
5706 | OFPBCT_CLOSE_REPLY
5707 | OFPBCT_COMMIT_REQUEST
5708 | OFPBCT_COMMIT_REPLY
5709 | OFPBCT_DISCARD_REQUEST
5710 | OFPBCT_DISCARD_REPLY
5711 flags Bitmap of the following flags.
5715 properties List of ``OFPBundleProp`` subclass instance
5716 ================ ======================================================
5720 def send_bundle_control(self, datapath):
5721 ofp = datapath.ofproto
5722 ofp_parser = datapath.ofproto_parser
5724 req = ofp_parser.OFPBundleCtrlMsg(datapath, 7,
5725 ofp.OFPBCT_OPEN_REQUEST,
5726 ofp.OFPBF_ATOMIC, [])
5727 datapath.send_msg(req)
5730 def __init__(self, datapath, bundle_id=None, type_=None, flags=None,
5732 super(OFPBundleCtrlMsg, self).__init__(datapath)
5733 self.bundle_id = bundle_id
5736 self.properties = properties
5738 def _serialize_body(self):
5739 bin_props = bytearray()
5740 for p in self.properties:
5741 bin_props += p.serialize()
5743 msg_pack_into(ofproto.OFP_BUNDLE_CTRL_MSG_PACK_STR,
5744 self.buf, ofproto.OFP_HEADER_SIZE, self.bundle_id,
5745 self.type, self.flags)
5746 self.buf += bin_props
5749 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
5750 msg = super(OFPBundleCtrlMsg, cls).parser(datapath, version,
5753 (bundle_id, type_, flags) = struct.unpack_from(
5754 ofproto.OFP_BUNDLE_CTRL_MSG_PACK_STR, buf,
5755 ofproto.OFP_HEADER_SIZE)
5756 msg.bundle_id = bundle_id
5760 rest = msg.buf[ofproto.OFP_BUNDLE_CTRL_MSG_SIZE:]
5762 p, rest = OFPBundleProp.parse(rest)
5763 msg.properties.append(p)
5768 @_set_msg_type(ofproto.OFPT_BUNDLE_ADD_MESSAGE)
5769 class OFPBundleAddMsg(MsgInMsgBase):
5773 The controller uses this message to add a message to a bundle
5775 ================ ======================================================
5776 Attribute Description
5777 ================ ======================================================
5778 bundle_id Id of the bundle
5779 flags Bitmap of the following flags.
5783 message ``MsgBase`` subclass instance
5784 properties List of ``OFPBundleProp`` subclass instance
5785 ================ ======================================================
5789 def send_bundle_add_message(self, datapath):
5790 ofp = datapath.ofproto
5791 ofp_parser = datapath.ofproto_parser
5793 msg = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
5795 req = ofp_parser.OFPBundleAddMsg(datapath, 7, ofp.OFPBF_ATOMIC,
5797 datapath.send_msg(req)
5800 def __init__(self, datapath, bundle_id, flags, message, properties):
5801 super(OFPBundleAddMsg, self).__init__(datapath)
5802 self.bundle_id = bundle_id
5804 self.message = message
5805 self.properties = properties
5807 def _serialize_body(self):
5808 # The xid of the inner message must be the same as
5809 # that of the outer message (OF1.4.0 7.3.9.2)
5810 if self.message.xid != self.xid:
5811 self.message.set_xid(self.xid)
5814 self.message.serialize()
5815 tail_buf = self.message.buf
5818 if len(self.properties) > 0:
5819 message_len = len(tail_buf)
5820 pad_len = utils.round_up(message_len, 8) - message_len
5821 msg_pack_into("%dx" % pad_len, tail_buf, message_len)
5824 for p in self.properties:
5825 tail_buf += p.serialize()
5828 msg_pack_into(ofproto.OFP_BUNDLE_ADD_MSG_0_PACK_STR,
5829 self.buf, ofproto.OFP_HEADER_SIZE, self.bundle_id,
5833 self.buf += tail_buf
5836 nx_actions.generate(
5837 'ryu.ofproto.ofproto_v1_4',
5838 'ryu.ofproto.ofproto_v1_4_parser'