1 # Copyright (C) 2011, 2012 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 Decoder/Encoder implementations of OpenFlow 1.0.
27 from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase
28 from ryu.lib import addrconv
29 from ryu.lib import ip
30 from ryu.lib import mac
31 from ryu.lib.packet import packet
32 from ryu.lib.pack_utils import msg_pack_into
33 from ryu.ofproto import nx_match
34 from ryu.ofproto import ofproto_common
35 from ryu.ofproto import ofproto_parser
36 from ryu.ofproto import ofproto_v1_0 as ofproto
37 from ryu.ofproto import nx_actions
41 LOG = logging.getLogger('ryu.ofproto.ofproto_v1_0_parser')
46 def _set_msg_type(msg_type):
47 '''Annotate corresponding OFP message type'''
48 def _set_cls_msg_type(cls):
49 cls.cls_msg_type = msg_type
51 return _set_cls_msg_type
54 def _register_parser(cls):
55 '''class decorator to register msg parser'''
56 assert cls.cls_msg_type is not None
57 assert cls.cls_msg_type not in _MSG_PARSERS
58 _MSG_PARSERS[cls.cls_msg_type] = cls.parser
62 @ofproto_parser.register_msg_parser(ofproto.OFP_VERSION)
63 def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
64 parser = _MSG_PARSERS.get(msg_type)
65 return parser(datapath, version, msg_type, msg_len, xid, buf)
69 # OFPFeaturesRequest: OFPSwitchFeatures,
70 # OFPBarrierRequest: OFPBarrierReply,
71 # OFPQueueGetConfigRequest: OFPQueueGetConfigReply,
73 # # ofp_stats_request -> ofp_stats_reply
74 # OFPDescStatsRequest: OFPDescStatsReply,
75 # OFPFlowStatsRequest: OFPFlowStatsReply,
76 # OFPAggregateStatsRequest: OFPAggregateStatsReply,
77 # OFPTableStatsRequest: OFPTableStatsReply,
78 # OFPPortStatsRequest: OFPPortStatsReply,
79 # OFPQueueStatsRequest: OFPQueueStatsReply,
80 # OFPVendorStatsRequest: OFPVendorStatsReply,
82 def _set_msg_reply(msg_reply):
83 '''Annotate OFP reply message class'''
84 def _set_cls_msg_reply(cls):
85 cls.cls_msg_reply = msg_reply
87 return _set_cls_msg_reply
94 class OFPPhyPort(ofproto_parser.namedtuple('OFPPhyPort', (
95 'port_no', 'hw_addr', 'name', 'config', 'state', 'curr', 'advertised',
96 'supported', 'peer'))):
100 ========== =========================================================
101 Attribute Description
102 ========== =========================================================
103 port_no Port number and it uniquely identifies a port within
105 hw_addr MAC address for the port.
106 name Null-terminated string containing a human-readable name
108 config Bitmap of port configration flags.
117 state Bitmap of port state flags.
125 curr Current features.
126 advertised Features being advertised by the port.
127 supported Features supported by the port.
128 peer Features advertised by peer.
129 ========== =========================================================
136 # OF spec is unclear about the encoding of name.
137 # we assumes UTF-8, which is used by OVS.
143 def parser(cls, buf, offset):
144 port = struct.unpack_from(ofproto.OFP_PHY_PORT_PACK_STR,
147 i = cls._fields.index('hw_addr')
148 port[i] = addrconv.mac.bin_to_text(port[i])
149 i = cls._fields.index('name')
150 port[i] = port[i].rstrip(b'\0')
154 class OFPMatch(StringifyMixin):
158 This class is implementation of the flow match structure having
161 ================ ==================================================
162 Attribute Description
163 ================ ==================================================
164 wildcards Wildcard fields.
165 (match fields) For the available match fields,
166 please refer to the following.
167 ================ ==================================================
169 ================ =============== ==================================
170 Argument Value Description
171 ================ =============== ==================================
172 in_port Integer 16bit Switch input port.
173 dl_src MAC address Ethernet source address.
174 dl_dst MAC address Ethernet destination address.
175 dl_vlan Integer 16bit Input VLAN id.
176 dl_vlan_pcp Integer 8bit Input VLAN priority.
177 dl_type Integer 16bit Ethernet frame type.
178 nw_tos Integer 8bit IP ToS (actually DSCP field, 6 bits).
179 nw_proto Integer 8bit IP protocol or lower 8 bits of
181 nw_src IPv4 address IP source address.
182 nw_dst IPv4 address IP destination address.
183 tp_src Integer 16bit TCP/UDP source port.
184 tp_dst Integer 16bit TCP/UDP destination port.
185 nw_src_mask Integer 8bit IP source address mask
186 specified as IPv4 address prefix.
187 nw_dst_mask Integer 8bit IP destination address mask
188 specified as IPv4 address prefix.
189 ================ =============== ==================================
194 >>> match = parser.OFPMatch(
197 ... dl_src='aa:bb:cc:dd:ee:ff',
198 ... nw_src='192.168.0.1')
200 >>> if 'nw_src' in match:
201 ... print match['nw_src']
206 def __init__(self, wildcards=None, in_port=None, dl_src=None, dl_dst=None,
207 dl_vlan=None, dl_vlan_pcp=None, dl_type=None, nw_tos=None,
208 nw_proto=None, nw_src=None, nw_dst=None,
209 tp_src=None, tp_dst=None, nw_src_mask=32, nw_dst_mask=32):
210 super(OFPMatch, self).__init__()
211 wc = ofproto.OFPFW_ALL
215 wc &= ~ofproto.OFPFW_IN_PORT
216 self.in_port = in_port
219 self.dl_src = mac.DONTCARE
221 wc &= ~ofproto.OFPFW_DL_SRC
222 if (isinstance(dl_src, (six.text_type, str)) and
223 netaddr.valid_mac(dl_src)):
224 dl_src = addrconv.mac.text_to_bin(dl_src)
226 self.dl_src = mac.DONTCARE
231 self.dl_dst = mac.DONTCARE
233 wc &= ~ofproto.OFPFW_DL_DST
234 if (isinstance(dl_dst, (six.text_type, str)) and
235 netaddr.valid_mac(dl_dst)):
236 dl_dst = addrconv.mac.text_to_bin(dl_dst)
238 self.dl_dst = mac.DONTCARE
245 wc &= ~ofproto.OFPFW_DL_VLAN
246 self.dl_vlan = dl_vlan
248 if dl_vlan_pcp is None:
251 wc &= ~ofproto.OFPFW_DL_VLAN_PCP
252 self.dl_vlan_pcp = dl_vlan_pcp
257 wc &= ~ofproto.OFPFW_DL_TYPE
258 self.dl_type = dl_type
263 wc &= ~ofproto.OFPFW_NW_TOS
269 wc &= ~ofproto.OFPFW_NW_PROTO
270 self.nw_proto = nw_proto
275 wc &= (32 - nw_src_mask) << ofproto.OFPFW_NW_SRC_SHIFT \
276 | ~ofproto.OFPFW_NW_SRC_MASK
277 if not isinstance(nw_src, int):
278 nw_src = ip.ipv4_to_int(nw_src)
284 wc &= (32 - nw_dst_mask) << ofproto.OFPFW_NW_DST_SHIFT \
285 | ~ofproto.OFPFW_NW_DST_MASK
286 if not isinstance(nw_dst, int):
287 nw_dst = ip.ipv4_to_int(nw_dst)
293 wc &= ~ofproto.OFPFW_TP_SRC
299 wc &= ~ofproto.OFPFW_TP_DST
302 if wildcards is None:
305 self.wildcards = wildcards
307 def __getitem__(self, name):
308 if not isinstance(name, str):
310 elif name == 'nw_src_mask':
311 _m = 32 - ((self.wildcards & ofproto.OFPFW_NW_SRC_MASK) >>
312 ofproto.OFPFW_NW_SRC_SHIFT)
313 return 0 if _m < 0 else _m
314 elif name == 'nw_dst_mask':
315 _m = 32 - ((self.wildcards & ofproto.OFPFW_NW_DST_MASK) >>
316 ofproto.OFPFW_NW_DST_SHIFT)
317 return 0 if _m < 0 else _m
318 elif name == 'wildcards':
319 return self.wildcards
321 wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0)
322 if ~self.wildcards & wc:
323 value = getattr(self, name)
324 if name in ['dl_src', 'dl_dst']:
325 value = addrconv.mac.bin_to_text(value)
326 elif name in ['nw_src', 'nw_dst']:
327 value = ip.ipv4_to_str(value)
332 def __contains__(self, name):
333 wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0)
334 return ~self.wildcards & wc
336 def serialize(self, buf, offset):
337 msg_pack_into(ofproto.OFP_MATCH_PACK_STR, buf, offset,
338 self.wildcards, self.in_port, self.dl_src,
339 self.dl_dst, self.dl_vlan, self.dl_vlan_pcp,
340 self.dl_type, self.nw_tos, self.nw_proto,
341 self.nw_src, self.nw_dst, self.tp_src, self.tp_dst)
344 def parse(cls, buf, offset):
345 match = struct.unpack_from(ofproto.OFP_MATCH_PACK_STR,
349 def to_jsondict(self):
351 # copy values to avoid original values conversion
352 for k, v in self.__dict__.items():
353 if k in ['dl_src', 'dl_dst']:
354 fields[k] = addrconv.mac.bin_to_text(v)
355 elif k in ['nw_src', 'nw_dst']:
356 fields[k] = ip.ipv4_to_str(v)
359 return {self.__class__.__name__: fields}
362 def from_jsondict(cls, dict_):
366 class OFPActionHeader(StringifyMixin):
367 _base_attributes = ['type', 'len']
369 def __init__(self, type_, len_):
373 def serialize(self, buf, offset):
374 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
375 buf, offset, self.type, self.len)
378 class OFPAction(OFPActionHeader):
382 def register_action_type(type_, len_):
383 def _register_action_type(cls):
384 cls.cls_action_type = type_
385 cls.cls_action_len = len_
386 OFPAction._ACTION_TYPES[cls.cls_action_type] = cls
388 return _register_action_type
392 super(OFPAction, self).__init__(cls.cls_action_type,
396 def parser(cls, buf, offset):
397 type_, len_ = struct.unpack_from(
398 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
399 cls_ = cls._ACTION_TYPES.get(type_)
400 assert cls_ is not None
401 return cls_.parser(buf, offset)
404 @OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
405 ofproto.OFP_ACTION_OUTPUT_SIZE)
406 class OFPActionOutput(OFPAction):
410 This action indicates output a packet to the switch port.
412 ================ ======================================================
413 Attribute Description
414 ================ ======================================================
416 max_len Max length to send to controller.
417 ================ ======================================================
420 The reason of this magic number (0xffe5)
421 is because there is no good constant in of1.0.
422 The same value as OFPCML_MAX of of1.2 and of1.3 is used.
425 def __init__(self, port, max_len=0xffe5):
426 super(OFPActionOutput, self).__init__()
428 self.max_len = max_len
431 def parser(cls, buf, offset):
432 type_, len_, port, max_len = struct.unpack_from(
433 ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
434 assert type_ == ofproto.OFPAT_OUTPUT
435 assert len_ == ofproto.OFP_ACTION_OUTPUT_SIZE
436 return cls(port, max_len)
438 def serialize(self, buf, offset):
439 msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf,
440 offset, self.type, self.len, self.port, self.max_len)
443 @OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_VID,
444 ofproto.OFP_ACTION_VLAN_VID_SIZE)
445 class OFPActionVlanVid(OFPAction):
447 Set the 802.1q VLAN id action
449 This action indicates the 802.1q VLAN id to be set.
451 ================ ======================================================
452 Attribute Description
453 ================ ======================================================
455 ================ ======================================================
458 def __init__(self, vlan_vid):
459 super(OFPActionVlanVid, self).__init__()
460 self.vlan_vid = vlan_vid
463 def parser(cls, buf, offset):
464 type_, len_, vlan_vid = struct.unpack_from(
465 ofproto.OFP_ACTION_VLAN_VID_PACK_STR, buf, offset)
466 assert type_ == ofproto.OFPAT_SET_VLAN_VID
467 assert len_ == ofproto.OFP_ACTION_VLAN_VID_SIZE
470 def serialize(self, buf, offset):
471 msg_pack_into(ofproto.OFP_ACTION_VLAN_VID_PACK_STR,
472 buf, offset, self.type, self.len, self.vlan_vid)
475 @OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_PCP,
476 ofproto.OFP_ACTION_VLAN_PCP_SIZE)
477 class OFPActionVlanPcp(OFPAction):
479 Set the 802.1q priority action
481 This action indicates the 802.1q priority to be set.
483 ================ ======================================================
484 Attribute Description
485 ================ ======================================================
486 vlan_pcp VLAN priority.
487 ================ ======================================================
490 def __init__(self, vlan_pcp):
491 super(OFPActionVlanPcp, self).__init__()
492 self.vlan_pcp = vlan_pcp
495 def parser(cls, buf, offset):
496 type_, len_, vlan_pcp = struct.unpack_from(
497 ofproto.OFP_ACTION_VLAN_PCP_PACK_STR, buf, offset)
498 assert type_ == ofproto.OFPAT_SET_VLAN_PCP
499 assert len_ == ofproto.OFP_ACTION_VLAN_PCP_SIZE
502 def serialize(self, buf, offset):
503 msg_pack_into(ofproto.OFP_ACTION_VLAN_PCP_PACK_STR,
504 buf, offset, self.type, self.len, self.vlan_pcp)
507 @OFPAction.register_action_type(ofproto.OFPAT_STRIP_VLAN,
508 ofproto.OFP_ACTION_HEADER_SIZE)
509 class OFPActionStripVlan(OFPAction):
511 Strip the 802.1q header action
513 This action indicates the 802.1q priority to be striped.
517 super(OFPActionStripVlan, self).__init__()
520 def parser(cls, buf, offset):
521 type_, len_ = struct.unpack_from(
522 ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
523 assert type_ == ofproto.OFPAT_STRIP_VLAN
524 assert len_ == ofproto.OFP_ACTION_HEADER_SIZE
528 class OFPActionDlAddr(OFPAction):
529 def __init__(self, dl_addr):
530 super(OFPActionDlAddr, self).__init__()
531 if (isinstance(dl_addr, (six.text_type, str)) and
532 netaddr.valid_mac(dl_addr)):
533 dl_addr = addrconv.mac.text_to_bin(dl_addr)
534 self.dl_addr = dl_addr
537 def parser(cls, buf, offset):
538 type_, len_, dl_addr = struct.unpack_from(
539 ofproto.OFP_ACTION_DL_ADDR_PACK_STR, buf, offset)
540 assert type_ in (ofproto.OFPAT_SET_DL_SRC,
541 ofproto.OFPAT_SET_DL_DST)
542 assert len_ == ofproto.OFP_ACTION_DL_ADDR_SIZE
545 def serialize(self, buf, offset):
546 msg_pack_into(ofproto.OFP_ACTION_DL_ADDR_PACK_STR,
547 buf, offset, self.type, self.len, self.dl_addr)
549 def to_jsondict(self):
550 body = {"dl_addr": addrconv.mac.bin_to_text(self.dl_addr)}
551 return {self.__class__.__name__: body}
554 def from_jsondict(cls, dict_):
558 @OFPAction.register_action_type(ofproto.OFPAT_SET_DL_SRC,
559 ofproto.OFP_ACTION_DL_ADDR_SIZE)
560 class OFPActionSetDlSrc(OFPActionDlAddr):
562 Set the ethernet source address action
564 This action indicates the ethernet source address to be set.
566 ================ ======================================================
567 Attribute Description
568 ================ ======================================================
569 dl_addr Ethernet address.
570 ================ ======================================================
573 def __init__(self, dl_addr):
574 super(OFPActionSetDlSrc, self).__init__(dl_addr)
577 @OFPAction.register_action_type(ofproto.OFPAT_SET_DL_DST,
578 ofproto.OFP_ACTION_DL_ADDR_SIZE)
579 class OFPActionSetDlDst(OFPActionDlAddr):
581 Set the ethernet destination address action
583 This action indicates the ethernet destination address to be set.
585 ================ ======================================================
586 Attribute Description
587 ================ ======================================================
588 dl_addr Ethernet address.
589 ================ ======================================================
592 def __init__(self, dl_addr):
593 super(OFPActionSetDlDst, self).__init__(dl_addr)
596 class OFPActionNwAddr(OFPAction):
597 def __init__(self, nw_addr):
598 super(OFPActionNwAddr, self).__init__()
599 if not isinstance(nw_addr, int):
600 nw_addr = ip.ipv4_to_int(nw_addr)
601 self.nw_addr = nw_addr
604 def parser(cls, buf, offset):
605 type_, len_, nw_addr = struct.unpack_from(
606 ofproto.OFP_ACTION_NW_ADDR_PACK_STR, buf, offset)
607 assert type_ in (ofproto.OFPAT_SET_NW_SRC,
608 ofproto.OFPAT_SET_NW_DST)
609 assert len_ == ofproto.OFP_ACTION_NW_ADDR_SIZE
612 def serialize(self, buf, offset):
613 msg_pack_into(ofproto.OFP_ACTION_NW_ADDR_PACK_STR,
614 buf, offset, self.type, self.len, self.nw_addr)
616 def to_jsondict(self):
617 body = {"nw_addr": ip.ipv4_to_str(self.nw_addr)}
618 return {self.__class__.__name__: body}
621 def from_jsondict(cls, dict_):
625 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_SRC,
626 ofproto.OFP_ACTION_NW_ADDR_SIZE)
627 class OFPActionSetNwSrc(OFPActionNwAddr):
629 Set the IP source address action
631 This action indicates the IP source address to be set.
633 ================ ======================================================
634 Attribute Description
635 ================ ======================================================
637 ================ ======================================================
640 def __init__(self, nw_addr):
641 super(OFPActionSetNwSrc, self).__init__(nw_addr)
644 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_DST,
645 ofproto.OFP_ACTION_NW_ADDR_SIZE)
646 class OFPActionSetNwDst(OFPActionNwAddr):
648 Set the IP destination address action
650 This action indicates the IP destination address to be set.
652 ================ ======================================================
653 Attribute Description
654 ================ ======================================================
656 ================ ======================================================
659 def __init__(self, nw_addr):
660 super(OFPActionSetNwDst, self).__init__(nw_addr)
663 @OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TOS,
664 ofproto.OFP_ACTION_NW_TOS_SIZE)
665 class OFPActionSetNwTos(OFPAction):
667 Set the IP ToS action
669 This action indicates the IP ToS (DSCP field, 6 bits) to be set.
671 ================ ======================================================
672 Attribute Description
673 ================ ======================================================
674 tos IP ToS (DSCP field, 6 bits).
675 ================ ======================================================
678 def __init__(self, tos):
679 super(OFPActionSetNwTos, self).__init__()
683 def parser(cls, buf, offset):
684 type_, len_, tos = struct.unpack_from(
685 ofproto.OFP_ACTION_NW_TOS_PACK_STR, buf, offset)
686 assert type_ == ofproto.OFPAT_SET_NW_TOS
687 assert len_ == ofproto.OFP_ACTION_NW_TOS_SIZE
690 def serialize(self, buf, offset):
691 msg_pack_into(ofproto.OFP_ACTION_NW_TOS_PACK_STR,
692 buf, offset, self.type, self.len, self.tos)
695 class OFPActionTpPort(OFPAction):
696 def __init__(self, tp):
697 super(OFPActionTpPort, self).__init__()
701 def parser(cls, buf, offset):
702 type_, len_, tp = struct.unpack_from(
703 ofproto.OFP_ACTION_TP_PORT_PACK_STR, buf, offset)
704 assert type_ in (ofproto.OFPAT_SET_TP_SRC,
705 ofproto.OFPAT_SET_TP_DST)
706 assert len_ == ofproto.OFP_ACTION_TP_PORT_SIZE
709 def serialize(self, buf, offset):
710 msg_pack_into(ofproto.OFP_ACTION_TP_PORT_PACK_STR,
711 buf, offset, self.type, self.len, self.tp)
714 @OFPAction.register_action_type(ofproto.OFPAT_SET_TP_SRC,
715 ofproto.OFP_ACTION_TP_PORT_SIZE)
716 class OFPActionSetTpSrc(OFPActionTpPort):
718 Set the TCP/UDP source port action
720 This action indicates the TCP/UDP source port to be set.
722 ================ ======================================================
723 Attribute Description
724 ================ ======================================================
726 ================ ======================================================
729 def __init__(self, tp):
730 super(OFPActionSetTpSrc, self).__init__(tp)
733 @OFPAction.register_action_type(ofproto.OFPAT_SET_TP_DST,
734 ofproto.OFP_ACTION_TP_PORT_SIZE)
735 class OFPActionSetTpDst(OFPActionTpPort):
737 Set the TCP/UDP destination port action
739 This action indicates the TCP/UDP destination port to be set.
741 ================ ======================================================
742 Attribute Description
743 ================ ======================================================
745 ================ ======================================================
748 def __init__(self, tp):
749 super(OFPActionSetTpDst, self).__init__(tp)
752 @OFPAction.register_action_type(ofproto.OFPAT_ENQUEUE,
753 ofproto.OFP_ACTION_ENQUEUE_SIZE)
754 class OFPActionEnqueue(OFPAction):
756 Output to queue action
758 This action indicates send packets to given queue on port.
760 ================ ======================================================
761 Attribute Description
762 ================ ======================================================
763 port Port that queue belongs.
764 queue_id Where to enqueue the packets.
765 ================ ======================================================
768 def __init__(self, port, queue_id):
769 super(OFPActionEnqueue, self).__init__()
771 self.queue_id = queue_id
774 def parser(cls, buf, offset):
775 type_, len_, port, queue_id = struct.unpack_from(
776 ofproto.OFP_ACTION_ENQUEUE_PACK_STR, buf, offset)
777 assert type_ == ofproto.OFPAT_ENQUEUE
778 assert len_ == ofproto.OFP_ACTION_ENQUEUE_SIZE
779 return cls(port, queue_id)
781 def serialize(self, buf, offset):
782 msg_pack_into(ofproto.OFP_ACTION_ENQUEUE_PACK_STR, buf, offset,
783 self.type, self.len, self.port, self.queue_id)
786 @OFPAction.register_action_type(ofproto.OFPAT_VENDOR, 0)
787 class OFPActionVendor(OFPAction):
791 This action is an extensible action for the vendor.
796 def register_action_vendor(vendor):
797 def _register_action_vendor(cls):
798 cls.cls_vendor = vendor
799 OFPActionVendor._ACTION_VENDORS[cls.cls_vendor] = cls
801 return _register_action_vendor
803 def __init__(self, vendor=None):
804 super(OFPActionVendor, self).__init__()
805 self.type = ofproto.OFPAT_VENDOR
809 self.vendor = self.cls_vendor
814 def parser(cls, buf, offset):
815 type_, len_, vendor = struct.unpack_from(
816 ofproto.OFP_ACTION_VENDOR_HEADER_PACK_STR, buf, offset)
818 data = buf[(offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE
821 if vendor == ofproto_common.NX_EXPERIMENTER_ID:
822 obj = NXAction.parse(data) # noqa
824 cls_ = cls._ACTION_VENDORS.get(vendor, None)
827 obj = OFPActionVendorUnknown(vendor, data)
829 obj = cls_.parser(buf, offset)
834 def serialize(self, buf, offset):
835 msg_pack_into(ofproto.OFP_ACTION_VENDOR_HEADER_PACK_STR,
836 buf, offset, self.type, self.len, self.vendor)
839 # OpenFlow1.2 or later compatible
840 OFPActionExperimenter = OFPActionVendor
843 class OFPActionVendorUnknown(OFPActionVendor):
844 def __init__(self, vendor, data=None, type_=None, len_=None):
845 super(OFPActionVendorUnknown,
846 self).__init__(vendor=vendor)
849 def serialize(self, buf, offset):
854 self.len = (utils.round_up(len(data), 8) +
855 ofproto.OFP_ACTION_VENDOR_HEADER_SIZE)
856 super(OFPActionVendorUnknown, self).serialize(buf, offset)
857 msg_pack_into('!%ds' % len(self.data),
859 offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE,
863 @OFPActionVendor.register_action_vendor(ofproto_common.NX_EXPERIMENTER_ID)
864 class NXActionHeader(OFPActionVendor):
865 _NX_ACTION_SUBTYPES = {}
868 def register_nx_action_subtype(subtype, len_):
869 def _register_nx_action_subtype(cls):
870 cls.cls_action_len = len_
871 cls.cls_subtype = subtype
872 NXActionHeader._NX_ACTION_SUBTYPES[cls.cls_subtype] = cls
874 return _register_nx_action_subtype
877 super(NXActionHeader, self).__init__()
878 self.subtype = self.cls_subtype
880 def serialize(self, buf, offset):
881 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR,
882 buf, offset, self.type, self.len)
885 def parser(cls, buf, offset):
886 type_, len_, vendor, subtype = struct.unpack_from(
887 ofproto.NX_ACTION_HEADER_PACK_STR, buf, offset)
888 cls_ = cls._NX_ACTION_SUBTYPES.get(subtype)
889 return cls_.parser(buf, offset)
892 class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', (
893 'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))):
906 def parser(cls, buf, offset):
907 desc = struct.unpack_from(ofproto.OFP_DESC_STATS_PACK_STR,
910 desc = [x.rstrip(b'\0') for x in desc]
912 stats.length = ofproto.OFP_DESC_STATS_SIZE
916 class OFPFlowStats(StringifyMixin):
918 super(OFPFlowStats, self).__init__()
922 self.duration_sec = None
923 self.duration_nsec = None
925 self.idle_timeout = None
926 self.hard_timeout = None
928 self.packet_count = None
929 self.byte_count = None
933 def parser(cls, buf, offset):
936 flow_stats.length, flow_stats.table_id = struct.unpack_from(
937 ofproto.OFP_FLOW_STATS_0_PACK_STR, buf, offset)
938 offset += ofproto.OFP_FLOW_STATS_0_SIZE
940 flow_stats.match = OFPMatch.parse(buf, offset)
941 offset += ofproto.OFP_MATCH_SIZE
943 (flow_stats.duration_sec,
944 flow_stats.duration_nsec,
946 flow_stats.idle_timeout,
947 flow_stats.hard_timeout,
949 flow_stats.packet_count,
950 flow_stats.byte_count) = struct.unpack_from(
951 ofproto.OFP_FLOW_STATS_1_PACK_STR, buf, offset)
952 offset += ofproto.OFP_FLOW_STATS_1_SIZE
954 flow_stats.actions = []
955 length = ofproto.OFP_FLOW_STATS_SIZE
956 while length < flow_stats.length:
957 action = OFPAction.parser(buf, offset)
958 flow_stats.actions.append(action)
966 class OFPAggregateStats(ofproto_parser.namedtuple('OFPAggregateStats', (
967 'packet_count', 'byte_count', 'flow_count'))):
969 def parser(cls, buf, offset):
970 agg = struct.unpack_from(
971 ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
973 stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE
977 class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', (
978 'table_id', 'name', 'wildcards', 'max_entries', 'active_count',
979 'lookup_count', 'matched_count'))):
983 # OF spec is unclear about the encoding of name.
990 def parser(cls, buf, offset):
991 tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR,
994 i = cls._fields.index('name')
995 tbl[i] = tbl[i].rstrip(b'\0')
997 stats.length = ofproto.OFP_TABLE_STATS_SIZE
1001 class OFPPortStats(ofproto_parser.namedtuple('OFPPortStats', (
1002 'port_no', 'rx_packets', 'tx_packets', 'rx_bytes', 'tx_bytes',
1003 'rx_dropped', 'tx_dropped', 'rx_errors', 'tx_errors',
1004 'rx_frame_err', 'rx_over_err', 'rx_crc_err', 'collisions'))):
1006 def parser(cls, buf, offset):
1007 port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR,
1010 stats.length = ofproto.OFP_PORT_STATS_SIZE
1014 class OFPQueueStats(ofproto_parser.namedtuple('OFPQueueStats', (
1015 'port_no', 'queue_id', 'tx_bytes', 'tx_packets', 'tx_errors'))):
1017 def parser(cls, buf, offset):
1018 queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR,
1021 stats.length = ofproto.OFP_QUEUE_STATS_SIZE
1025 class OFPVendorStats(ofproto_parser.namedtuple('OFPVendorStats',
1026 ('specific_data'))):
1028 def parser(cls, buf, offset):
1029 stats = cls(buf[offset:])
1030 stats.length = len(stats.specific_data)
1034 class NXFlowStats(StringifyMixin):
1036 super(NXFlowStats, self).__init__()
1038 self.table_id = None
1039 self.duration_sec = None
1040 self.duration_nsec = None
1041 self.priority = None
1042 self.idle_timeout = None
1043 self.hard_timeout = None
1044 self.match_len = None
1045 self.idle_age = None
1046 self.hard_age = None
1048 self.packet_count = None
1049 self.byte_count = None
1052 def parser(cls, buf, offset):
1053 original_offset = offset
1054 nxflow_stats = cls()
1055 (nxflow_stats.length, nxflow_stats.table_id,
1056 nxflow_stats.duration_sec, nxflow_stats.duration_nsec,
1057 nxflow_stats.priority, nxflow_stats.idle_timeout,
1058 nxflow_stats.hard_timeout, nxflow_stats.match_len,
1059 nxflow_stats.idle_age, nxflow_stats.hard_age,
1060 nxflow_stats.cookie, nxflow_stats.packet_count,
1061 nxflow_stats.byte_count) = struct.unpack_from(
1062 ofproto.NX_FLOW_STATS_PACK_STR, buf, offset)
1063 offset += ofproto.NX_FLOW_STATS_SIZE
1066 match_len = nxflow_stats.match_len
1068 while match_len > 0:
1069 field = nx_match.MFField.parser(buf, offset)
1070 offset += field.length
1071 match_len -= field.length
1072 fields.append(field)
1073 nxflow_stats.fields = fields
1076 total_len = original_offset + nxflow_stats.length
1077 match_len = nxflow_stats.match_len
1078 offset += utils.round_up(match_len, 8) - match_len
1079 while offset < total_len:
1080 action = OFPAction.parser(buf, offset)
1081 actions.append(action)
1082 offset += action.len
1083 nxflow_stats.actions = actions
1088 class NXAggregateStats(ofproto_parser.namedtuple('NXAggregateStats', (
1089 'packet_count', 'byte_count', 'flow_count'))):
1091 def parser(cls, buf, offset):
1092 agg = struct.unpack_from(
1093 ofproto.NX_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset)
1095 stats.length = ofproto.NX_AGGREGATE_STATS_REPLY_SIZE
1100 class OFPQueuePropHeader(StringifyMixin):
1101 _QUEUE_PROPERTIES = {}
1104 def register_queue_property(prop_type, prop_len):
1105 def _register_queue_propery(cls):
1106 cls.cls_prop_type = prop_type
1107 cls.cls_prop_len = prop_len
1108 OFPQueuePropHeader._QUEUE_PROPERTIES[prop_type] = cls
1110 return _register_queue_propery
1113 self.property = self.cls_prop_type
1114 self.len = self.cls_prop_len
1117 def parser(cls, buf, offset):
1118 property_, len_ = struct.unpack_from(
1119 ofproto.OFP_QUEUE_PROP_HEADER_PACK_STR, buf, offset)
1120 prop_cls = cls._QUEUE_PROPERTIES[property_]
1121 assert property_ == prop_cls.cls_prop_type
1122 assert len_ == prop_cls.cls_prop_len
1124 offset += ofproto.OFP_QUEUE_PROP_HEADER_SIZE
1125 return prop_cls.parser(buf, offset)
1128 @OFPQueuePropHeader.register_queue_property(
1129 ofproto.OFPQT_NONE, ofproto.OFP_QUEUE_PROP_HEADER_SIZE)
1130 class OFPQueuePropNone(OFPQueuePropHeader):
1132 super(OFPQueuePropNone, self).__init__()
1135 def parser(cls, buf, offset):
1139 @OFPQueuePropHeader.register_queue_property(
1140 ofproto.OFPQT_MIN_RATE, ofproto.OFP_QUEUE_PROP_MIN_RATE_SIZE)
1141 class OFPQueuePropMinRate(OFPQueuePropHeader):
1142 def __init__(self, rate):
1143 super(OFPQueuePropMinRate, self).__init__()
1147 def parser(cls, buf, offset):
1148 (rate,) = struct.unpack_from(
1149 ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR,
1154 class OFPPacketQueue(StringifyMixin):
1156 Description of a queue
1158 ========== =========================================================
1159 Attribute Description
1160 ========== =========================================================
1161 queue_id ID for the specific queue.
1162 len Length in bytes of this queue desc.
1163 properties List of ``OFPQueueProp*`` instance.
1164 ========== =========================================================
1167 def __init__(self, queue_id, len_):
1168 self.queue_id = queue_id
1170 self.properties = None
1173 def parser(cls, buf, offset):
1174 queue_id, len_ = struct.unpack_from(
1175 ofproto.OFP_PACKET_QUEUE_PQCK_STR, buf, offset)
1176 packet_queue = cls(queue_id, len_)
1178 packet_queue.properties = []
1179 cur_len = ofproto.OFP_PACKET_QUEUE_SIZE
1180 offset += ofproto.OFP_PACKET_QUEUE_SIZE
1181 while (cur_len + ofproto.OFP_QUEUE_PROP_HEADER_SIZE <=
1183 prop = OFPQueuePropHeader.parser(buf, offset)
1184 packet_queue.properties.append(prop)
1192 # Symmetric messages
1193 # parser + serializer
1198 @_set_msg_type(ofproto.OFPT_HELLO)
1199 class OFPHello(MsgBase):
1203 When connection is started, the hello message is exchanged between a
1204 switch and a controller.
1206 This message is handled by the Ryu framework, so the Ryu application
1207 do not need to process this typically.
1210 def __init__(self, datapath):
1211 super(OFPHello, self).__init__(datapath)
1215 @_set_msg_type(ofproto.OFPT_ERROR)
1216 class OFPErrorMsg(MsgBase):
1220 The switch notifies controller of problems by this message.
1222 ========== =========================================================
1223 Attribute Description
1224 ========== =========================================================
1225 type High level type of error
1226 code Details depending on the type
1227 data Variable length data depending on the type and code
1228 ========== =========================================================
1230 ``type`` attribute corresponds to ``type_`` parameter of __init__.
1232 Types and codes are defined in ``ryu.ofproto.ofproto``.
1234 =========================== ===========
1236 =========================== ===========
1237 OFPET_HELLO_FAILED OFPHFC_*
1238 OFPET_BAD_REQUEST OFPBRC_*
1239 OFPET_BAD_ACTION OFPBAC_*
1240 OFPET_FLOW_MOD_FAILED OFPFMFC_*
1241 OFPET_PORT_MOD_FAILED OFPPMFC_*
1242 OFPET_QUEUE_OP_FAILED OFPQOFC_*
1243 =========================== ===========
1247 @set_ev_cls(ofp_event.EventOFPErrorMsg,
1248 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
1249 def error_msg_handler(self, ev):
1252 self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
1254 msg.type, msg.code, utils.hex_array(msg.data))
1257 def __init__(self, datapath, type_=None, code=None, data=None):
1258 super(OFPErrorMsg, self).__init__(datapath)
1261 if isinstance(data, six.string_types):
1262 data = data.encode('ascii')
1266 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1267 msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
1269 msg.type, msg.code = struct.unpack_from(
1270 ofproto.OFP_ERROR_MSG_PACK_STR, msg.buf,
1271 ofproto.OFP_HEADER_SIZE)
1272 msg.data = msg.buf[ofproto.OFP_ERROR_MSG_SIZE:]
1275 def _serialize_body(self):
1276 assert self.data is not None
1277 msg_pack_into(ofproto.OFP_ERROR_MSG_PACK_STR, self.buf,
1278 ofproto.OFP_HEADER_SIZE, self.type, self.code)
1279 self.buf += self.data
1283 @_set_msg_type(ofproto.OFPT_ECHO_REQUEST)
1284 class OFPEchoRequest(MsgBase):
1286 Echo request message
1288 This message is handled by the Ryu framework, so the Ryu application
1289 do not need to process this typically.
1291 ========== =========================================================
1292 Attribute Description
1293 ========== =========================================================
1294 data An arbitrary length data.
1295 ========== =========================================================
1299 def send_echo_request(self, datapath, data):
1300 ofp_parser = datapath.ofproto_parser
1302 req = ofp_parser.OFPEchoRequest(datapath, data)
1303 datapath.send_msg(req)
1306 def __init__(self, datapath, data=None):
1307 super(OFPEchoRequest, self).__init__(datapath)
1311 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1312 msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
1314 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
1317 def _serialize_body(self):
1318 if self.data is not None:
1319 self.buf += self.data
1323 @_set_msg_type(ofproto.OFPT_ECHO_REPLY)
1324 class OFPEchoReply(MsgBase):
1328 This message is handled by the Ryu framework, so the Ryu application
1329 do not need to process this typically.
1331 ========== =========================================================
1332 Attribute Description
1333 ========== =========================================================
1334 data An arbitrary length data.
1335 ========== =========================================================
1339 @set_ev_cls(ofp_event.EventOFPEchoReply,
1340 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
1341 def echo_reply_handler(self, ev):
1342 self.logger.debug('OFPEchoReply received: data=%s',
1343 utils.hex_array(ev.msg.data))
1346 def __init__(self, datapath, data=None):
1347 super(OFPEchoReply, self).__init__(datapath)
1351 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1352 msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
1354 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:]
1357 def _serialize_body(self):
1358 assert self.data is not None
1359 self.buf += self.data
1363 @_set_msg_type(ofproto.OFPT_VENDOR)
1364 class OFPVendor(MsgBase):
1368 The controller send this message to send the vendor-specific
1369 information to a switch.
1374 def register_vendor(id_):
1375 def _register_vendor(cls):
1376 OFPVendor._VENDORS[id_] = cls
1378 return _register_vendor
1380 def __init__(self, datapath):
1381 super(OFPVendor, self).__init__(datapath)
1386 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1387 msg = super(OFPVendor, cls).parser(datapath, version, msg_type,
1389 (msg.vendor,) = struct.unpack_from(
1390 ofproto.OFP_VENDOR_HEADER_PACK_STR, msg.buf,
1391 ofproto.OFP_HEADER_SIZE)
1393 cls_ = cls._VENDORS.get(msg.vendor)
1395 msg.data = cls_.parser(datapath, msg.buf, 0)
1397 msg.data = msg.buf[ofproto.OFP_VENDOR_HEADER_SIZE:]
1401 def serialize_header(self):
1402 msg_pack_into(ofproto.OFP_VENDOR_HEADER_PACK_STR,
1403 self.buf, ofproto.OFP_HEADER_SIZE, self.vendor)
1405 def _serialize_body(self):
1406 assert self.data is not None
1407 self.serialize_header()
1408 self.buf += self.data
1411 @OFPVendor.register_vendor(ofproto_common.NX_EXPERIMENTER_ID)
1412 class NiciraHeader(OFPVendor):
1416 def register_nx_subtype(subtype):
1417 def _register_nx_subtype(cls):
1418 cls.cls_subtype = subtype
1419 NiciraHeader._NX_SUBTYPES[cls.cls_subtype] = cls
1421 return _register_nx_subtype
1423 def __init__(self, datapath, subtype):
1424 super(NiciraHeader, self).__init__(datapath)
1425 self.vendor = ofproto_common.NX_EXPERIMENTER_ID
1426 self.subtype = subtype
1428 def serialize_header(self):
1429 super(NiciraHeader, self).serialize_header()
1430 msg_pack_into(ofproto.NICIRA_HEADER_PACK_STR,
1431 self.buf, ofproto.OFP_HEADER_SIZE,
1432 self.vendor, self.subtype)
1435 def parser(cls, datapath, buf, offset):
1436 vendor, subtype = struct.unpack_from(
1437 ofproto.NICIRA_HEADER_PACK_STR, buf,
1438 offset + ofproto.OFP_HEADER_SIZE)
1439 cls_ = cls._NX_SUBTYPES.get(subtype)
1440 return cls_.parser(datapath, buf,
1441 offset + ofproto.NICIRA_HEADER_SIZE)
1444 class NXTSetFlowFormat(NiciraHeader):
1445 def __init__(self, datapath, flow_format):
1446 super(NXTSetFlowFormat, self).__init__(
1447 datapath, ofproto.NXT_SET_FLOW_FORMAT)
1448 self.format = flow_format
1450 def _serialize_body(self):
1451 self.serialize_header()
1452 msg_pack_into(ofproto.NX_SET_FLOW_FORMAT_PACK_STR,
1453 self.buf, ofproto.NICIRA_HEADER_SIZE, self.format)
1456 class NXTFlowMod(NiciraHeader):
1457 def __init__(self, datapath, cookie, command,
1458 idle_timeout=0, hard_timeout=0,
1459 priority=ofproto.OFP_DEFAULT_PRIORITY,
1460 buffer_id=0xffffffff, out_port=ofproto.OFPP_NONE,
1461 flags=0, rule=None, actions=None):
1463 # the argument, rule, is positioned at the one before the last due
1464 # to the layout struct nxt_flow_mod.
1465 # Although rule must be given, default argument to rule, None,
1466 # is given to allow other default value of argument before rule.
1467 assert rule is not None
1471 super(NXTFlowMod, self).__init__(datapath, ofproto.NXT_FLOW_MOD)
1472 self.cookie = cookie
1473 self.command = command
1474 self.idle_timeout = idle_timeout
1475 self.hard_timeout = hard_timeout
1476 self.priority = priority
1477 self.buffer_id = buffer_id
1478 self.out_port = out_port
1481 self.actions = actions
1483 def _serialize_body(self):
1484 self.serialize_header()
1486 offset = ofproto.NX_FLOW_MOD_SIZE
1487 match_len = nx_match.serialize_nxm_match(self.rule, self.buf, offset)
1488 offset += nx_match.round_up(match_len)
1490 msg_pack_into(ofproto.NX_FLOW_MOD_PACK_STR,
1491 self.buf, ofproto.NICIRA_HEADER_SIZE,
1492 self.cookie, self.command, self.idle_timeout,
1493 self.hard_timeout, self.priority, self.buffer_id,
1494 self.out_port, self.flags, match_len)
1496 if self.actions is not None:
1497 for a in self.actions:
1498 a.serialize(self.buf, offset)
1502 class NXTRoleRequest(NiciraHeader):
1503 def __init__(self, datapath, role):
1504 super(NXTRoleRequest, self).__init__(
1505 datapath, ofproto.NXT_ROLE_REQUEST)
1508 def _serialize_body(self):
1509 self.serialize_header()
1510 msg_pack_into(ofproto.NX_ROLE_PACK_STR,
1511 self.buf, ofproto.NICIRA_HEADER_SIZE, self.role)
1514 @NiciraHeader.register_nx_subtype(ofproto.NXT_ROLE_REPLY)
1515 class NXTRoleReply(NiciraHeader):
1516 def __init__(self, datapath, role):
1517 super(NXTRoleReply, self).__init__(
1518 datapath, ofproto.NXT_ROLE_REPLY)
1522 def parser(cls, datapath, buf, offset):
1523 (role,) = struct.unpack_from(
1524 ofproto.NX_ROLE_PACK_STR, buf, offset)
1525 return cls(datapath, role)
1528 class NXTFlowModTableId(NiciraHeader):
1529 def __init__(self, datapath, set_):
1530 super(NXTFlowModTableId, self).__init__(
1531 datapath, ofproto.NXT_FLOW_MOD_TABLE_ID)
1534 def _serialize_body(self):
1535 self.serialize_header()
1536 msg_pack_into(ofproto.NX_FLOW_MOD_TABLE_ID_PACK_STR,
1537 self.buf, ofproto.NICIRA_HEADER_SIZE,
1541 @NiciraHeader.register_nx_subtype(ofproto.NXT_FLOW_REMOVED)
1542 class NXTFlowRemoved(NiciraHeader):
1543 def __init__(self, datapath, cookie, priority, reason,
1544 duration_sec, duration_nsec, idle_timeout, match_len,
1545 packet_count, byte_count, match):
1546 super(NXTFlowRemoved, self).__init__(
1547 datapath, ofproto.NXT_FLOW_REMOVED)
1548 self.cookie = cookie
1549 self.priority = priority
1550 self.reason = reason
1551 self.duration_sec = duration_sec
1552 self.duration_nsec = duration_nsec
1553 self.idle_timeout = idle_timeout
1554 self.match_len = match_len
1555 self.packet_count = packet_count
1556 self.byte_count = byte_count
1560 def parser(cls, datapath, buf, offset):
1561 (cookie, priority, reason, duration_sec, duration_nsec,
1562 idle_timeout, match_len,
1563 packet_count, byte_count) = struct.unpack_from(
1564 ofproto.NX_FLOW_REMOVED_PACK_STR, buf, offset)
1565 offset += (ofproto.NX_FLOW_REMOVED_SIZE -
1566 ofproto.NICIRA_HEADER_SIZE)
1567 match = nx_match.NXMatch.parser(buf, offset, match_len)
1568 return cls(datapath, cookie, priority, reason, duration_sec,
1569 duration_nsec, idle_timeout, match_len, packet_count,
1573 class NXTSetPacketInFormat(NiciraHeader):
1574 def __init__(self, datapath, packet_in_format):
1575 super(NXTSetPacketInFormat, self).__init__(
1576 datapath, ofproto.NXT_SET_PACKET_IN_FORMAT)
1577 self.format = packet_in_format
1579 def _serialize_body(self):
1580 self.serialize_header()
1581 msg_pack_into(ofproto.NX_SET_PACKET_IN_FORMAT_PACK_STR,
1582 self.buf, ofproto.NICIRA_HEADER_SIZE,
1586 @NiciraHeader.register_nx_subtype(ofproto.NXT_PACKET_IN)
1587 class NXTPacketIn(NiciraHeader):
1588 def __init__(self, datapath, buffer_id, total_len, reason, table_id,
1589 cookie, match_len, match, frame):
1590 super(NXTPacketIn, self).__init__(
1591 datapath, ofproto.NXT_PACKET_IN)
1592 self.buffer_id = buffer_id
1593 self.total_len = total_len
1594 self.reason = reason
1595 self.table_id = table_id
1596 self.cookie = cookie
1597 self.match_len = match_len
1602 def parser(cls, datapath, buf, offset):
1603 (buffer_id, total_len, reason, table_id,
1604 cookie, match_len) = struct.unpack_from(
1605 ofproto.NX_PACKET_IN_PACK_STR, buf, offset)
1607 offset += (ofproto.NX_PACKET_IN_SIZE -
1608 ofproto.NICIRA_HEADER_SIZE)
1610 match = nx_match.NXMatch.parser(buf, offset, match_len)
1611 offset += (match_len + 7) // 8 * 8
1612 frame = buf[offset:]
1613 if total_len < len(frame):
1614 frame = frame[:total_len]
1615 return cls(datapath, buffer_id, total_len, reason, table_id,
1616 cookie, match_len, match, frame)
1619 class NXTFlowAge(NiciraHeader):
1620 def __init__(self, datapath):
1621 super(NXTFlowAge, self).__init__(
1622 datapath, ofproto.NXT_FLOW_AGE)
1624 def _serialize_body(self):
1625 self.serialize_header()
1628 class NXTSetAsyncConfig(NiciraHeader):
1629 def __init__(self, datapath, packet_in_mask, port_status_mask,
1631 super(NXTSetAsyncConfig, self).__init__(
1632 datapath, ofproto.NXT_SET_ASYNC_CONFIG)
1633 self.packet_in_mask = packet_in_mask
1634 self.port_status_mask = port_status_mask
1635 self.flow_removed_mask = flow_removed_mask
1637 def _serialize_body(self):
1638 self.serialize_header()
1639 msg_pack_into(ofproto.NX_ASYNC_CONFIG_PACK_STR,
1640 self.buf, ofproto.NICIRA_HEADER_SIZE,
1641 self.packet_in_mask[0], self.packet_in_mask[1],
1642 self.port_status_mask[0], self.port_status_mask[1],
1643 self.flow_removed_mask[0], self.flow_removed_mask[1])
1646 class NXTSetControllerId(NiciraHeader):
1647 def __init__(self, datapath, controller_id):
1648 super(NXTSetControllerId, self).__init__(
1649 datapath, ofproto.NXT_SET_CONTROLLER_ID)
1650 self.controller_id = controller_id
1652 def _serialize_body(self):
1653 self.serialize_header()
1654 msg_pack_into(ofproto.NX_CONTROLLER_ID_PACK_STR,
1655 self.buf, ofproto.NICIRA_HEADER_SIZE,
1660 # asymmetric message (datapath -> controller)
1666 @_set_msg_type(ofproto.OFPT_FEATURES_REPLY)
1667 class OFPSwitchFeatures(MsgBase):
1669 Features reply message
1671 The switch responds with a features reply message to a features
1674 This message is handled by the Ryu framework, so the Ryu application
1675 do not need to process this typically.
1677 ================ ======================================================
1678 Attribute Description
1679 ================ ======================================================
1680 datapath_id Datapath unique ID.
1681 n_buffers Max packets buffered at once.
1682 n_tables Number of tables supported by datapath.
1683 capabilities Bitmap of capabilities flag.
1693 actions Bitmap of supported OFPAT_*.
1694 ports List of ``OFPPhyPort`` instances.
1695 ================ ======================================================
1699 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
1700 def switch_features_handler(self, ev):
1703 self.logger.debug('OFPSwitchFeatures received: '
1704 'datapath_id=0x%016x n_buffers=%d '
1705 'n_tables=%d capabilities=0x%08x ports=%s',
1706 msg.datapath_id, msg.n_buffers, msg.n_tables,
1707 msg.capabilities, msg.ports)
1710 def __init__(self, datapath, datapath_id=None, n_buffers=None,
1711 n_tables=None, capabilities=None, actions=None, ports=None):
1712 super(OFPSwitchFeatures, self).__init__(datapath)
1713 self.datapath_id = datapath_id
1714 self.n_buffers = n_buffers
1715 self.n_tables = n_tables
1716 self.capabilities = capabilities
1717 self.actions = actions
1721 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1722 msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
1728 msg.actions) = struct.unpack_from(
1729 ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
1730 ofproto.OFP_HEADER_SIZE)
1733 n_ports = ((msg_len - ofproto.OFP_SWITCH_FEATURES_SIZE) //
1734 ofproto.OFP_PHY_PORT_SIZE)
1735 offset = ofproto.OFP_SWITCH_FEATURES_SIZE
1736 for _i in range(n_ports):
1737 port = OFPPhyPort.parser(msg.buf, offset)
1738 # print 'port = %s' % str(port)
1739 msg.ports[port.port_no] = port
1740 offset += ofproto.OFP_PHY_PORT_SIZE
1746 @_set_msg_type(ofproto.OFPT_PORT_STATUS)
1747 class OFPPortStatus(MsgBase):
1751 The switch notifies controller of change of ports.
1753 ================ ======================================================
1754 Attribute Description
1755 ================ ======================================================
1756 reason One of the following values.
1761 desc instance of ``OFPPhyPort``
1762 ================ ======================================================
1766 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
1767 def port_status_handler(self, ev):
1772 if msg.reason == ofp.OFPPR_ADD:
1774 elif msg.reason == ofp.OFPPR_DELETE:
1776 elif msg.reason == ofp.OFPPR_MODIFY:
1781 self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
1785 def __init__(self, datapath, reason=None, desc=None):
1786 super(OFPPortStatus, self).__init__(datapath)
1787 self.reason = reason
1791 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1792 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
1794 msg.reason = struct.unpack_from(
1795 ofproto.OFP_PORT_STATUS_PACK_STR,
1796 msg.buf, ofproto.OFP_HEADER_SIZE)[0]
1797 msg.desc = OFPPhyPort.parser(msg.buf,
1798 ofproto.OFP_PORT_STATUS_DESC_OFFSET)
1803 @_set_msg_type(ofproto.OFPT_PACKET_IN)
1804 class OFPPacketIn(MsgBase):
1808 The switch sends the packet that received to the controller by this
1811 ============= =========================================================
1812 Attribute Description
1813 ============= =========================================================
1814 buffer_id ID assigned by datapath.
1815 total_len Full length of frame.
1816 in_port Port on which frame was received.
1817 reason Reason packet is being sent.
1822 data Ethernet frame.
1823 ============= =========================================================
1827 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
1828 def packet_in_handler(self, ev):
1833 if msg.reason == ofp.OFPR_NO_MATCH:
1835 elif msg.reason == ofp.OFPR_ACTION:
1837 elif msg.reason == ofp.OFPR_INVALID_TTL:
1838 reason = 'INVALID TTL'
1842 self.logger.debug('OFPPacketIn received: '
1843 'buffer_id=%x total_len=%d in_port=%d, '
1844 'reason=%s data=%s',
1845 msg.buffer_id, msg.total_len, msg.in_port,
1846 reason, utils.hex_array(msg.data))
1849 def __init__(self, datapath, buffer_id=None, total_len=None, in_port=None,
1850 reason=None, data=None):
1851 super(OFPPacketIn, self).__init__(datapath)
1852 self.buffer_id = buffer_id
1853 self.total_len = total_len
1854 self.in_port = in_port
1855 self.reason = reason
1859 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1860 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
1865 msg.reason) = struct.unpack_from(
1866 ofproto.OFP_PACKET_IN_PACK_STR,
1867 msg.buf, ofproto.OFP_HEADER_SIZE)
1868 msg.data = msg.buf[ofproto.OFP_PACKET_IN_SIZE:]
1869 if msg.total_len < len(msg.data):
1870 # discard padding for 8-byte alignment of OFP packet
1871 msg.data = msg.data[:msg.total_len]
1876 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY)
1877 class OFPGetConfigReply(MsgBase):
1879 Get config reply message
1881 The switch responds to a configuration request with a get config reply
1884 ============= =========================================================
1885 Attribute Description
1886 ============= =========================================================
1887 flags One of the following configuration flags.
1893 miss_send_len Max bytes of new flow that datapath should send to the
1895 ============= =========================================================
1899 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
1900 def get_config_reply_handler(self, ev):
1905 if msg.flags == ofp.OFPC_FRAG_NORMAL:
1907 elif msg.flags == ofp.OFPC_FRAG_DROP:
1909 elif msg.flags == ofp.OFPC_FRAG_REASM:
1911 elif msg.flags == ofp.OFPC_FRAG_MASK:
1915 self.logger.debug('OFPGetConfigReply received: '
1916 'flags=%s miss_send_len=%d',
1917 flags, msg.miss_send_len)
1920 def __init__(self, datapath):
1921 super(OFPGetConfigReply, self).__init__(datapath)
1924 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
1925 msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
1927 (msg.flags, msg.miss_send_len) = struct.unpack_from(
1928 ofproto.OFP_SWITCH_CONFIG_PACK_STR,
1929 msg.buf, ofproto.OFP_HEADER_SIZE)
1934 @_set_msg_type(ofproto.OFPT_BARRIER_REPLY)
1935 class OFPBarrierReply(MsgBase):
1937 Barrier reply message
1939 The switch responds with this message to a barrier request.
1943 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
1944 def barrier_reply_handler(self, ev):
1945 self.logger.debug('OFPBarrierReply received')
1948 def __init__(self, datapath):
1949 super(OFPBarrierReply, self).__init__(datapath)
1953 @_set_msg_type(ofproto.OFPT_FLOW_REMOVED)
1954 class OFPFlowRemoved(MsgBase):
1956 Flow removed message
1958 When flow entries time out or are deleted, the switch notifies controller
1961 ================ ======================================================
1962 Attribute Description
1963 ================ ======================================================
1964 match Instance of ``OFPMatch``.
1965 cookie Opaque controller-issued identifier.
1966 priority Priority level of flow entry.
1967 reason One of the following values.
1969 | OFPRR_IDLE_TIMEOUT
1970 | OFPRR_HARD_TIMEOUT
1972 duration_sec Time flow was alive in seconds.
1973 duration_nsec Time flow was alive in nanoseconds
1974 beyond duration_sec.
1975 idle_timeout Idle timeout from original flow mod.
1976 packet_count Number of packets that was associated with the flow.
1977 byte_count Number of bytes that was associated with the flow.
1978 ================ ======================================================
1982 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
1983 def flow_removed_handler(self, ev):
1988 if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
1989 reason = 'IDLE TIMEOUT'
1990 elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
1991 reason = 'HARD TIMEOUT'
1992 elif msg.reason == ofp.OFPRR_DELETE:
1994 elif msg.reason == ofp.OFPRR_GROUP_DELETE:
1995 reason = 'GROUP DELETE'
1999 self.logger.debug('OFPFlowRemoved received: '
2000 'match=%s cookie=%d priority=%d reason=%s '
2001 'duration_sec=%d duration_nsec=%d '
2002 'idle_timeout=%d packet_count=%d byte_count=%d',
2003 msg.match, msg.cookie, msg.priority, reason,
2004 msg.duration_sec, msg.duration_nsec,
2005 msg.idle_timeout, msg.packet_count,
2009 def __init__(self, datapath):
2010 super(OFPFlowRemoved, self).__init__(datapath)
2013 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2014 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
2017 msg.match = OFPMatch.parse(msg.buf, ofproto.OFP_HEADER_SIZE)
2026 msg.byte_count) = struct.unpack_from(
2027 ofproto.OFP_FLOW_REMOVED_PACK_STR0, msg.buf,
2028 ofproto.OFP_HEADER_SIZE + ofproto.OFP_MATCH_SIZE)
2034 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY)
2035 class OFPQueueGetConfigReply(MsgBase):
2037 Queue configuration reply message
2039 The switch responds with this message to a queue configuration request.
2041 ================ ======================================================
2042 Attribute Description
2043 ================ ======================================================
2044 port Port to be queried.
2045 queues List of ``OFPPacketQueue`` instance.
2046 ================ ======================================================
2050 @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
2051 def queue_get_config_reply_handler(self, ev):
2054 self.logger.debug('OFPQueueGetConfigReply received: '
2055 'port=%s queues=%s',
2056 msg.port, msg.queues)
2059 def __init__(self, datapath):
2060 super(OFPQueueGetConfigReply, self).__init__(datapath)
2063 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2064 msg = super(OFPQueueGetConfigReply, cls).parser(
2065 datapath, version, msg_type, msg_len, xid, buf)
2067 offset = ofproto.OFP_HEADER_SIZE
2068 (msg.port,) = struct.unpack_from(
2069 ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf, offset)
2072 offset = ofproto.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
2073 while offset + ofproto.OFP_PACKET_QUEUE_SIZE <= msg_len:
2074 queue = OFPPacketQueue.parser(msg.buf, offset)
2075 msg.queues.append(queue)
2082 def _set_stats_type(stats_type, stats_body_cls):
2083 def _set_cls_stats_type(cls):
2084 cls.cls_stats_type = stats_type
2085 cls.cls_stats_body_cls = stats_body_cls
2087 return _set_cls_stats_type
2091 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2092 class OFPStatsReply(MsgBase):
2093 _STATS_MSG_TYPES = {}
2096 def register_stats_type(body_single_struct=False):
2097 def _register_stats_type(cls):
2098 assert cls.cls_stats_type is not None
2099 assert cls.cls_stats_type not in OFPStatsReply._STATS_MSG_TYPES
2100 assert cls.cls_stats_body_cls is not None
2101 cls.cls_body_single_struct = body_single_struct
2102 OFPStatsReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls
2104 return _register_stats_type
2106 def __init__(self, datapath):
2107 super(OFPStatsReply, self).__init__(datapath)
2113 def parser_stats_body(cls, buf, msg_len, offset):
2114 body_cls = cls.cls_stats_body_cls
2116 while offset < msg_len:
2117 entry = body_cls.parser(buf, offset)
2119 offset += entry.length
2121 if cls.cls_body_single_struct:
2126 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf):
2127 # call MsgBase::parser, not OFPStatsReply::parser
2128 msg = MsgBase.parser.__func__(
2129 cls, datapath, version, msg_type, msg_len, xid, buf)
2130 msg.body = msg.parser_stats_body(msg.buf, msg.msg_len,
2131 ofproto.OFP_STATS_MSG_SIZE)
2135 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2136 type_, flags = struct.unpack_from(ofproto.OFP_STATS_MSG_PACK_STR,
2137 six.binary_type(buf),
2138 ofproto.OFP_HEADER_SIZE)
2139 stats_type_cls = cls._STATS_MSG_TYPES.get(type_)
2140 msg = stats_type_cls.parser_stats(
2141 datapath, version, msg_type, msg_len, xid, buf)
2147 @OFPStatsReply.register_stats_type(body_single_struct=True)
2148 @_set_stats_type(ofproto.OFPST_DESC, OFPDescStats)
2149 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2150 class OFPDescStatsReply(OFPStatsReply):
2152 Description statistics reply message
2154 The switch responds with a stats reply that include this message to
2155 a description statistics request.
2157 ================ ======================================================
2158 Attribute Description
2159 ================ ======================================================
2160 mfr_desc Manufacturer description.
2161 hw_desc Hardware description.
2162 sw_desc Software description.
2163 serial_num Serial number.
2164 dp_desc Human readable description of datapath.
2165 ================ ======================================================
2169 @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
2170 def desc_stats_reply_handler(self, ev):
2172 ofp = msg.datapath.ofproto
2175 self.logger.debug('DescStats: mfr_desc=%s hw_desc=%s sw_desc=%s '
2176 'serial_num=%s dp_desc=%s',
2177 body.mfr_desc, body.hw_desc, body.sw_desc,
2178 body.serial_num, body.dp_desc)
2181 def __init__(self, datapath):
2182 super(OFPDescStatsReply, self).__init__(datapath)
2185 @OFPStatsReply.register_stats_type()
2186 @_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats)
2187 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2188 class OFPFlowStatsReply(OFPStatsReply):
2190 Individual flow statistics reply message
2192 The switch responds with a stats reply that include this message to
2193 an individual flow statistics request.
2195 ================ ======================================================
2196 Attribute Description
2197 ================ ======================================================
2198 table_id ID of table flow came from.
2199 match Instance of ``OFPMatch``.
2200 duration_sec Time flow has been alive in seconds.
2201 duration_nsec Time flow has been alive in nanoseconds beyond
2203 priority Priority of the entry. Only meaningful
2204 when this is not an exact-match entry.
2205 idle_timeout Number of seconds idle before expiration.
2206 hard_timeout Number of seconds before expiration.
2207 cookie Opaque controller-issued identifier.
2208 packet_count Number of packets in flow.
2209 byte_count Number of bytes in flow.
2210 actions List of ``OFPAction*`` instance
2211 ================ ======================================================
2215 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
2216 def flow_stats_reply_handler(self, ev):
2218 ofp = msg.datapath.ofproto
2223 flows.append('table_id=%s match=%s '
2224 'duration_sec=%d duration_nsec=%d '
2226 'idle_timeout=%d hard_timeout=%d '
2227 'cookie=%d packet_count=%d byte_count=%d '
2229 (stat.table_id, stat.match,
2230 stat.duration_sec, stat.duration_nsec,
2232 stat.idle_timeout, stat.hard_timeout,
2233 stat.cookie, stat.packet_count, stat.byte_count,
2235 self.logger.debug('FlowStats: %s', flows)
2238 def __init__(self, datapath):
2239 super(OFPFlowStatsReply, self).__init__(datapath)
2242 @OFPStatsReply.register_stats_type()
2243 @_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats)
2244 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2245 class OFPAggregateStatsReply(OFPStatsReply):
2247 Aggregate flow statistics reply message
2249 The switch responds with a stats reply that include this message to
2250 an aggregate flow statistics request.
2252 ================ ======================================================
2253 Attribute Description
2254 ================ ======================================================
2255 packet_count Number of packets in flows.
2256 byte_count Number of bytes in flows.
2257 flow_count Number of flows.
2258 ================ ======================================================
2262 @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
2263 def aggregate_stats_reply_handler(self, ev):
2265 ofp = msg.datapath.ofproto
2268 self.logger.debug('AggregateStats: packet_count=%d byte_count=%d '
2270 body.packet_count, body.byte_count,
2274 def __init__(self, datapath):
2275 super(OFPAggregateStatsReply, self).__init__(datapath)
2278 @OFPStatsReply.register_stats_type()
2279 @_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats)
2280 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2281 class OFPTableStatsReply(OFPStatsReply):
2283 Table statistics reply message
2285 The switch responds with a stats reply that include this message to
2286 a table statistics request.
2288 ================ ======================================================
2289 Attribute Description
2290 ================ ======================================================
2291 table_id ID of table.
2293 wildcards Bitmap of OFPFW_* wildcards that are
2294 supported by the table.
2295 max_entries Max number of entries supported
2296 active_count Number of active entries
2297 lookup_count Number of packets looked up in table
2298 matched_count Number of packets that hit table
2299 ================ ======================================================
2303 @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
2304 def stats_reply_handler(self, ev):
2306 ofp = msg.datapath.ofproto
2311 tables.append('table_id=%d name=%s wildcards=0x%02x '
2312 'max_entries=%d active_count=%d '
2313 'lookup_count=%d matched_count=%d' %
2314 (stat.table_id, stat.name, stat.wildcards,
2315 stat.max_entries, stat.active_count,
2316 stat.lookup_count, stat.matched_count))
2317 self.logger.debug('TableStats: %s', tables)
2320 def __init__(self, datapath):
2321 super(OFPTableStatsReply, self).__init__(datapath)
2324 @OFPStatsReply.register_stats_type()
2325 @_set_stats_type(ofproto.OFPST_PORT, OFPPortStats)
2326 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2327 class OFPPortStatsReply(OFPStatsReply):
2329 Port statistics reply message
2331 The switch responds with a stats reply that include this message to
2332 a port statistics request.
2334 ================ ======================================================
2335 Attribute Description
2336 ================ ======================================================
2337 port_no Port number.
2338 rx_packets Number of received packets.
2339 tx_packets Number of transmitted packets.
2340 rx_bytes Number of received bytes.
2341 tx_bytes Number of transmitted bytes.
2342 rx_dropped Number of packets dropped by RX.
2343 tx_dropped Number of packets dropped by TX.
2344 rx_errors Number of receive errors.
2345 tx_errors Number of transmit errors.
2346 rx_frame_err Number of frame alignment errors.
2347 rx_over_err Number of packet with RX overrun.
2348 rx_crc_err Number of CRC errors.
2349 collisions Number of collisions.
2350 ================ ======================================================
2354 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
2355 def port_stats_reply_handler(self, ev):
2357 ofp = msg.datapath.ofproto
2362 ports.append('port_no=%d '
2363 'rx_packets=%d tx_packets=%d '
2364 'rx_bytes=%d tx_bytes=%d '
2365 'rx_dropped=%d tx_dropped=%d '
2366 'rx_errors=%d tx_errors=%d '
2367 'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
2370 stat.rx_packets, stat.tx_packets,
2371 stat.rx_bytes, stat.tx_bytes,
2372 stat.rx_dropped, stat.tx_dropped,
2373 stat.rx_errors, stat.tx_errors,
2374 stat.rx_frame_err, stat.rx_over_err,
2375 stat.rx_crc_err, stat.collisions))
2376 self.logger.debug('PortStats: %s', ports)
2379 def __init__(self, datapath):
2380 super(OFPPortStatsReply, self).__init__(datapath)
2383 @OFPStatsReply.register_stats_type()
2384 @_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats)
2385 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2386 class OFPQueueStatsReply(OFPStatsReply):
2388 Queue statistics reply message
2390 The switch responds with a stats reply that include this message to
2391 an aggregate flow statistics request.
2393 ================ ======================================================
2394 Attribute Description
2395 ================ ======================================================
2396 port_no Port number.
2397 queue_id ID of queue.
2398 tx_bytes Number of transmitted bytes.
2399 tx_packets Number of transmitted packets.
2400 tx_errors Number of packets dropped due to overrun.
2401 ================ ======================================================
2405 @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
2406 def stats_reply_handler(self, ev):
2408 ofp = msg.datapath.ofproto
2413 queues.append('port_no=%d queue_id=%d '
2414 'tx_bytes=%d tx_packets=%d tx_errors=%d ' %
2415 (stat.port_no, stat.queue_id,
2416 stat.tx_bytes, stat.tx_packets, stat.tx_errors))
2417 self.logger.debug('QueueStats: %s', queues)
2420 def __init__(self, datapath):
2421 super(OFPQueueStatsReply, self).__init__(datapath)
2424 @OFPStatsReply.register_stats_type()
2425 @_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats)
2426 @_set_msg_type(ofproto.OFPT_STATS_REPLY)
2427 class OFPVendorStatsReply(OFPStatsReply):
2429 Vendor statistics reply message
2431 The switch responds with a stats reply that include this message to
2432 an vendor statistics request.
2437 def register_stats_vendor(vendor):
2438 def _register_stats_vendor(cls):
2439 cls.cls_vendor = vendor
2440 OFPVendorStatsReply._STATS_VENDORS[cls.cls_vendor] = cls
2442 return _register_stats_vendor
2444 def __init__(self, datapath):
2445 super(OFPVendorStatsReply, self).__init__(datapath)
2448 def parser_stats(cls, datapath, version, msg_type, msg_len, xid,
2450 (type_,) = struct.unpack_from(
2451 ofproto.OFP_VENDOR_STATS_MSG_PACK_STR, six.binary_type(buf),
2452 ofproto.OFP_STATS_MSG_SIZE)
2454 cls_ = cls._STATS_VENDORS.get(type_)
2457 msg = MsgBase.parser.__func__(
2458 cls, datapath, version, msg_type, msg_len, xid, buf)
2459 body_cls = cls.cls_stats_body_cls
2460 body = body_cls.parser(buf,
2461 ofproto.OFP_STATS_MSG_SIZE)
2466 datapath, version, msg_type, msg_len, xid, buf,
2467 ofproto.OFP_VENDOR_STATS_MSG_SIZE)
2470 @OFPVendorStatsReply.register_stats_vendor(ofproto_common.NX_EXPERIMENTER_ID)
2471 class NXStatsReply(OFPStatsReply):
2472 _NX_STATS_TYPES = {}
2475 def register_nx_stats_type(body_single_struct=False):
2476 def _register_nx_stats_type(cls):
2477 assert cls.cls_stats_type is not None
2478 assert cls.cls_stats_type not in \
2479 NXStatsReply._NX_STATS_TYPES
2480 assert cls.cls_stats_body_cls is not None
2481 cls.cls_body_single_struct = body_single_struct
2482 NXStatsReply._NX_STATS_TYPES[cls.cls_stats_type] = cls
2484 return _register_nx_stats_type
2487 def parser_stats_body(cls, buf, msg_len, offset):
2488 body_cls = cls.cls_stats_body_cls
2490 while offset < msg_len:
2491 entry = body_cls.parser(buf, offset)
2493 offset += entry.length
2495 if cls.cls_body_single_struct:
2500 def parser_stats(cls, datapath, version, msg_type, msg_len, xid,
2502 msg = MsgBase.parser.__func__(
2503 cls, datapath, version, msg_type, msg_len, xid, buf)
2504 msg.body = msg.parser_stats_body(msg.buf, msg.msg_len, offset)
2509 def parser(cls, datapath, version, msg_type, msg_len, xid, buf,
2511 (type_,) = struct.unpack_from(
2512 ofproto.NX_STATS_MSG_PACK_STR, six.binary_type(buf), offset)
2513 offset += ofproto.NX_STATS_MSG0_SIZE
2515 cls_ = cls._NX_STATS_TYPES.get(type_)
2517 msg = cls_.parser_stats(
2518 datapath, version, msg_type, msg_len, xid, buf, offset)
2523 @NXStatsReply.register_nx_stats_type()
2524 @_set_stats_type(ofproto.NXST_FLOW, NXFlowStats)
2525 class NXFlowStatsReply(NXStatsReply):
2526 def __init__(self, datapath):
2527 super(NXFlowStatsReply, self).__init__(datapath)
2530 @NXStatsReply.register_nx_stats_type()
2531 @_set_stats_type(ofproto.NXST_AGGREGATE, NXAggregateStats)
2532 class NXAggregateStatsReply(NXStatsReply):
2533 def __init__(self, datapath):
2534 super(NXAggregateStatsReply, self).__init__(datapath)
2538 # controller-to-switch message
2543 @_set_msg_reply(OFPSwitchFeatures)
2544 @_set_msg_type(ofproto.OFPT_FEATURES_REQUEST)
2545 class OFPFeaturesRequest(MsgBase):
2547 Features request message
2549 The controller sends a feature request to the switch upon session
2552 This message is handled by the Ryu framework, so the Ryu application
2553 do not need to process this typically.
2557 def send_features_request(self, datapath):
2558 ofp_parser = datapath.ofproto_parser
2560 req = ofp_parser.OFPFeaturesRequest(datapath)
2561 datapath.send_msg(req)
2564 def __init__(self, datapath):
2565 super(OFPFeaturesRequest, self).__init__(datapath)
2568 @_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST)
2569 class OFPGetConfigRequest(MsgBase):
2571 Get config request message
2573 The controller sends a get config request to query configuration
2574 parameters in the switch.
2578 def send_get_config_request(self, datapath):
2579 ofp_parser = datapath.ofproto_parser
2581 req = ofp_parser.OFPGetConfigRequest(datapath)
2582 datapath.send_msg(req)
2585 def __init__(self, datapath):
2586 super(OFPGetConfigRequest, self).__init__(datapath)
2589 @_set_msg_type(ofproto.OFPT_SET_CONFIG)
2590 class OFPSetConfig(MsgBase):
2592 Set config request message
2594 The controller sends a set config request message to set configuraion
2597 ============= =========================================================
2598 Attribute Description
2599 ============= =========================================================
2600 flags One of the following configuration flags.
2606 miss_send_len Max bytes of new flow that datapath should send to the
2608 ============= =========================================================
2612 def send_set_config(self, datapath):
2613 ofp = datapath.ofproto
2614 ofp_parser = datapath.ofproto_parser
2616 req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
2617 datapath.send_msg(req)
2620 def __init__(self, datapath, flags=None, miss_send_len=None):
2621 super(OFPSetConfig, self).__init__(datapath)
2623 self.miss_send_len = miss_send_len
2625 def _serialize_body(self):
2626 assert self.flags is not None
2627 assert self.miss_send_len is not None
2628 msg_pack_into(ofproto.OFP_SWITCH_CONFIG_PACK_STR,
2629 self.buf, ofproto.OFP_HEADER_SIZE,
2630 self.flags, self.miss_send_len)
2633 @_set_msg_type(ofproto.OFPT_PACKET_OUT)
2634 class OFPPacketOut(MsgBase):
2638 The controller uses this message to send a packet out throught the
2641 ================ ======================================================
2642 Attribute Description
2643 ================ ======================================================
2644 buffer_id ID assigned by datapath (0xffffffff if none).
2645 in_port Packet's input port (OFPP_NONE if none).
2646 actions ist of ``OFPAction*`` instance.
2647 data Packet data of a binary type value or
2648 an instances of packet.Packet.
2649 ================ ======================================================
2653 def send_packet_out(self, datapath):
2654 ofp = datapath.ofproto
2655 ofp_parser = datapath.ofproto_parser
2657 buffer_id = 0xffffffff
2658 in_port = ofp.OFPP_NONE
2659 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
2660 req = ofp_parser.OFPPacketOut(datapath, buffer_id,
2662 datapath.send_msg(req)
2665 def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
2667 super(OFPPacketOut, self).__init__(datapath)
2668 self.buffer_id = buffer_id
2669 self.in_port = in_port
2670 self._actions_len = None
2671 self.actions = actions
2674 def _serialize_body(self):
2675 assert self.buffer_id is not None
2676 assert self.in_port is not None
2677 assert self.actions is not None
2679 self._actions_len = 0
2680 offset = ofproto.OFP_PACKET_OUT_SIZE
2681 for a in self.actions:
2682 a.serialize(self.buf, offset)
2684 self._actions_len += a.len
2686 if self.data is not None:
2687 assert self.buffer_id == 0xffffffff
2688 if isinstance(self.data, packet.Packet):
2689 self.data.serialize()
2690 self.buf += self.data.data
2692 self.buf += self.data
2694 msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR,
2695 self.buf, ofproto.OFP_HEADER_SIZE,
2696 self.buffer_id, self.in_port, self._actions_len)
2699 def from_jsondict(cls, dict_, decode_string=base64.b64decode,
2701 if isinstance(dict_['data'], dict):
2702 data = dict_.pop('data')
2703 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2706 ins.data = packet.Packet.from_jsondict(data['Packet'])
2707 dict_['data'] = data
2709 ins = super(OFPPacketOut, cls).from_jsondict(dict_,
2717 @_set_msg_type(ofproto.OFPT_FLOW_MOD)
2718 class OFPFlowMod(MsgBase):
2720 Modify Flow entry message
2722 The controller sends this message to modify the flow table.
2724 ================ ======================================================
2725 Attribute Description
2726 ================ ======================================================
2727 match Instance of ``OFPMatch``.
2728 cookie Opaque controller-issued identifier.
2729 command One of the following values.
2733 | OFPFC_MODIFY_STRICT
2735 | OFPFC_DELETE_STRICT
2736 idle_timeout Idle time before discarding (seconds).
2737 hard_timeout Max time before discarding (seconds).
2738 priority Priority level of flow entry.
2739 buffer_id Buffered packet to apply to (or 0xffffffff).
2740 Not meaningful for OFPFC_DELETE*.
2741 out_port For OFPFC_DELETE* commands, require
2742 matching entries to include this as an
2743 output port. A value of OFPP_NONE
2744 indicates no restriction.
2745 flags One of the following values.
2747 | OFPFF_SEND_FLOW_REM
2748 | OFPFF_CHECK_OVERLAP
2750 actions List of ``OFPAction*`` instance.
2751 ================ ======================================================
2755 def send_flow_mod(self, datapath):
2756 ofp = datapath.ofproto
2757 ofp_parser = datapath.ofproto_parser
2759 match = ofp_parser.OFPMatch(in_port=1)
2761 command = ofp.OFPFC_ADD
2762 idle_timeout = hard_timeout = 0
2764 buffer_id = 0xffffffff
2765 out_port = ofproto.OFPP_NONE
2767 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
2768 req = ofp_parser.OFPFlowMod(
2769 datapath, match, cookie, command, idle_timeout, hard_timeout,
2770 priority, buffer_id, out_port, flags, actions)
2771 datapath.send_msg(req)
2774 def __init__(self, datapath, match=None, cookie=0,
2775 command=ofproto.OFPFC_ADD,
2776 idle_timeout=0, hard_timeout=0,
2777 priority=ofproto.OFP_DEFAULT_PRIORITY,
2778 buffer_id=0xffffffff, out_port=ofproto.OFPP_NONE,
2779 flags=0, actions=None):
2780 super(OFPFlowMod, self).__init__(datapath)
2781 self.match = OFPMatch() if match is None else match
2782 self.cookie = cookie
2783 self.command = command
2784 self.idle_timeout = idle_timeout
2785 self.hard_timeout = hard_timeout
2786 self.priority = priority
2787 self.buffer_id = buffer_id
2788 self.out_port = out_port
2790 self.actions = [] if actions is None else actions
2792 def _serialize_body(self):
2793 offset = ofproto.OFP_HEADER_SIZE
2794 self.match.serialize(self.buf, offset)
2796 offset += ofproto.OFP_MATCH_SIZE
2797 msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf, offset,
2798 self.cookie, self.command,
2799 self.idle_timeout, self.hard_timeout,
2800 self.priority, self.buffer_id, self.out_port,
2803 offset = ofproto.OFP_FLOW_MOD_SIZE
2804 if self.actions is not None:
2805 for a in self.actions:
2806 a.serialize(self.buf, offset)
2810 def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
2811 msg = super(OFPFlowMod, cls).parser(
2812 datapath, version, msg_type, msg_len, xid, buf)
2813 offset = ofproto.OFP_HEADER_SIZE
2815 msg.match = OFPMatch.parse(msg.buf, offset)
2816 offset += ofproto.OFP_MATCH_SIZE
2818 (msg.cookie, msg.command, msg.idle_timeout, msg.hard_timeout,
2819 msg.priority, msg.buffer_id, msg.out_port,
2820 msg.flags) = struct.unpack_from(
2821 ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf, offset)
2822 offset = ofproto.OFP_FLOW_MOD_SIZE
2825 while offset < msg_len:
2826 a = OFPAction.parser(buf, offset)
2829 msg.actions = actions
2834 @_set_msg_type(ofproto.OFPT_PORT_MOD)
2835 class OFPPortMod(MsgBase):
2837 Port modification message
2839 The controller send this message to modify the behavior of the port.
2841 ================ ======================================================
2842 Attribute Description
2843 ================ ======================================================
2844 port_no Port number to modify.
2845 hw_addr The hardware address that must be the same as hw_addr
2846 of ``OFPPhyPort`` of ``OFPSwitchFeatures``.
2847 config Bitmap of configuration flags.
2855 | OFPPC_NO_PACKET_IN
2856 mask Bitmap of configuration flags above to be changed
2857 advertise Bitmap of the following flags.
2871 ================ ======================================================
2875 def send_port_mod(self, datapath):
2876 ofp = datapath.ofproto
2877 ofp_parser = datapath.ofproto_parser
2880 hw_addr = 'fa:c8:e8:76:1d:7e'
2882 mask = (ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
2883 ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN)
2884 advertise = (ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
2885 ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
2886 ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
2887 ofp.OFPPF_PAUSE_ASYM)
2888 req = ofp_parser.OFPPortMod(datapath, port_no, hw_addr, config,
2890 datapath.send_msg(req)
2898 def __init__(self, datapath, port_no=0, hw_addr='00:00:00:00:00:00',
2899 config=0, mask=0, advertise=0):
2900 super(OFPPortMod, self).__init__(datapath)
2901 self.port_no = port_no
2902 self.hw_addr = hw_addr
2903 self.config = config
2905 self.advertise = advertise
2907 def _serialize_body(self):
2908 msg_pack_into(ofproto.OFP_PORT_MOD_PACK_STR,
2909 self.buf, ofproto.OFP_HEADER_SIZE,
2910 self.port_no, addrconv.mac.text_to_bin(self.hw_addr),
2911 self.config, self.mask, self.advertise)
2914 @_set_msg_reply(OFPBarrierReply)
2915 @_set_msg_type(ofproto.OFPT_BARRIER_REQUEST)
2916 class OFPBarrierRequest(MsgBase):
2918 Barrier request message
2920 The controller sends this message to ensure message dependencies have
2921 been met or receive notifications for completed operations.
2925 def send_barrier_request(self, datapath):
2926 ofp_parser = datapath.ofproto_parser
2928 req = ofp_parser.OFPBarrierRequest(datapath)
2929 datapath.send_msg(req)
2932 def __init__(self, datapath):
2933 super(OFPBarrierRequest, self).__init__(datapath)
2936 @_set_msg_reply(OFPQueueGetConfigReply)
2937 @_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST)
2938 class OFPQueueGetConfigRequest(MsgBase):
2940 Queue configuration request message
2942 ================ ======================================================
2943 Attribute Description
2944 ================ ======================================================
2945 port Port to be queried. Should refer
2946 to a valid physical port (i.e. < OFPP_MAX).
2947 ================ ======================================================
2951 def send_queue_get_config_request(self, datapath):
2952 ofp = datapath.ofproto
2953 ofp_parser = datapath.ofproto_parser
2955 req = ofp_parser.OFPQueueGetConfigRequest(datapath,
2957 datapath.send_msg(req)
2960 def __init__(self, datapath, port):
2961 super(OFPQueueGetConfigRequest, self).__init__(datapath)
2964 def _serialize_body(self):
2965 msg_pack_into(ofproto.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR,
2966 self.buf, ofproto.OFP_HEADER_SIZE, self.port)
2969 class OFPStatsRequest(MsgBase):
2970 def __init__(self, datapath, flags):
2971 assert flags == 0 # none yet defined
2973 super(OFPStatsRequest, self).__init__(datapath)
2974 self.type = self.__class__.cls_stats_type
2977 def _serialize_stats_body(self):
2980 def _serialize_body(self):
2981 msg_pack_into(ofproto.OFP_STATS_MSG_PACK_STR,
2982 self.buf, ofproto.OFP_HEADER_SIZE,
2983 self.type, self.flags)
2984 self._serialize_stats_body()
2987 @_set_msg_reply(OFPDescStatsReply)
2988 @_set_stats_type(ofproto.OFPST_DESC, OFPDescStats)
2989 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
2990 class OFPDescStatsRequest(OFPStatsRequest):
2992 Description statistics request message
2994 The controller uses this message to query description of the switch.
2996 ================ ======================================================
2997 Attribute Description
2998 ================ ======================================================
2999 flags Zero (none yet defined in the spec).
3000 ================ ======================================================
3004 def send_desc_stats_request(self, datapath):
3005 ofp_parser = datapath.ofproto_parser
3007 req = ofp_parser.OFPDescStatsRequest(datapath)
3008 datapath.send_msg(req)
3011 def __init__(self, datapath, flags):
3012 super(OFPDescStatsRequest, self).__init__(datapath, flags)
3015 class OFPFlowStatsRequestBase(OFPStatsRequest):
3016 def __init__(self, datapath, flags, match, table_id, out_port):
3017 super(OFPFlowStatsRequestBase, self).__init__(datapath, flags)
3019 self.table_id = table_id
3020 self.out_port = out_port
3022 def _serialize_stats_body(self):
3023 offset = ofproto.OFP_STATS_MSG_SIZE
3024 self.match.serialize(self.buf, offset)
3026 offset += ofproto.OFP_MATCH_SIZE
3027 msg_pack_into(ofproto.OFP_FLOW_STATS_REQUEST_ID_PORT_STR,
3028 self.buf, offset, self.table_id, self.out_port)
3031 @_set_msg_reply(OFPFlowStatsReply)
3032 @_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats)
3033 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3034 class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
3036 Individual flow statistics request message
3038 The controller uses this message to query individual flow statistics.
3040 ================ ======================================================
3041 Attribute Description
3042 ================ ======================================================
3043 flags Zero (none yet defined in the spec).
3044 match Instance of ``OFPMatch``.
3045 table_id ID of table to read (from ofp_table_stats),
3046 0xff for all tables or 0xfe for emergency.
3047 out_port Require matching entries to include this
3048 as an output port. A value of OFPP_NONE
3049 indicates no restriction.
3050 ================ ======================================================
3054 def send_flow_stats_request(self, datapath):
3055 ofp = datapath.ofproto
3056 ofp_parser = datapath.ofproto_parser
3058 match = ofp_parser.OFPMatch(in_port=1)
3060 out_port = ofp.OFPP_NONE
3061 req = ofp_parser.OFPFlowStatsRequest(
3062 datapath, 0, match, table_id, out_port)
3064 datapath.send_msg(req)
3067 def __init__(self, datapath, flags, match, table_id, out_port):
3068 super(OFPFlowStatsRequest, self).__init__(
3069 datapath, flags, match, table_id, out_port)
3072 @_set_msg_reply(OFPAggregateStatsReply)
3073 @_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats)
3074 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3075 class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
3077 Aggregate flow statistics request message
3079 The controller uses this message to query aggregate flow statictics.
3081 ================ ======================================================
3082 Attribute Description
3083 ================ ======================================================
3084 flags Zero (none yet defined in the spec).
3085 match Fields to match.
3086 table_id ID of table to read (from ofp_table_stats)
3087 0xff for all tables or 0xfe for emergency.
3088 out_port Require matching entries to include this
3089 as an output port. A value of OFPP_NONE
3090 indicates no restriction.
3091 ================ ======================================================
3095 def send_aggregate_stats_request(self, datapath):
3096 ofp = datapath.ofproto
3097 ofp_parser = datapath.ofproto_parser
3099 cookie = cookie_mask = 0
3100 match = ofp_parser.OFPMatch(in_port=1)
3101 req = ofp_parser.OFPAggregateStatsRequest(
3102 datapath, 0, match, 0xff, ofp.OFPP_NONE)
3104 datapath.send_msg(req)
3107 def __init__(self, datapath, flags, match, table_id, out_port):
3108 super(OFPAggregateStatsRequest, self).__init__(
3109 datapath, flags, match, table_id, out_port)
3112 @_set_msg_reply(OFPTableStatsReply)
3113 @_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats)
3114 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3115 class OFPTableStatsRequest(OFPStatsRequest):
3117 Table statistics request message
3119 The controller uses this message to query flow table statictics.
3121 ================ ======================================================
3122 Attribute Description
3123 ================ ======================================================
3124 flags Zero (none yet defined in the spec).
3125 ================ ======================================================
3129 def send_table_stats_request(self, datapath):
3130 ofp_parser = datapath.ofproto_parser
3132 req = ofp_parser.OFPTableStatsRequest(datapath)
3133 datapath.send_msg(req)
3136 def __init__(self, datapath, flags):
3137 super(OFPTableStatsRequest, self).__init__(datapath, flags)
3140 @_set_msg_reply(OFPPortStatsReply)
3141 @_set_stats_type(ofproto.OFPST_PORT, OFPPortStats)
3142 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3143 class OFPPortStatsRequest(OFPStatsRequest):
3145 Port statistics request message
3147 The controller uses this message to query information about ports
3150 ================ ======================================================
3151 Attribute Description
3152 ================ ======================================================
3153 flags Zero (none yet defined in the spec).
3154 port_no Port number to read (OFPP_NONE to all ports).
3155 ================ ======================================================
3159 def send_port_stats_request(self, datapath):
3160 ofp = datapath.ofproto
3161 ofp_parser = datapath.ofproto_parser
3163 req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY)
3164 datapath.send_msg(req)
3167 def __init__(self, datapath, flags, port_no):
3168 super(OFPPortStatsRequest, self).__init__(datapath, flags)
3169 self.port_no = port_no
3171 def _serialize_stats_body(self):
3172 msg_pack_into(ofproto.OFP_PORT_STATS_REQUEST_PACK_STR,
3173 self.buf, ofproto.OFP_STATS_MSG_SIZE, self.port_no)
3176 @_set_msg_reply(OFPQueueStatsReply)
3177 @_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats)
3178 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3179 class OFPQueueStatsRequest(OFPStatsRequest):
3181 Queue statistics request message
3183 The controller uses this message to query queue statictics.
3185 ================ ======================================================
3186 Attribute Description
3187 ================ ======================================================
3188 flags Zero (none yet defined in the spec)
3189 port_no Port number to read (All ports if OFPT_ALL).
3190 queue_id ID of queue to read (All queues if OFPQ_ALL).
3191 ================ ======================================================
3195 def send_queue_stats_request(self, datapath):
3196 ofp = datapath.ofproto
3197 ofp_parser = datapath.ofproto_parser
3199 req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPT_ALL,
3201 datapath.send_msg(req)
3204 def __init__(self, datapath, flags, port_no, queue_id):
3205 super(OFPQueueStatsRequest, self).__init__(datapath, flags)
3206 self.port_no = port_no
3207 self.queue_id = queue_id
3209 def _serialize_stats_body(self):
3210 msg_pack_into(ofproto.OFP_QUEUE_STATS_REQUEST_PACK_STR,
3211 self.buf, ofproto.OFP_STATS_MSG_SIZE,
3212 self.port_no, self.queue_id)
3215 @_set_msg_reply(OFPVendorStatsReply)
3216 @_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats)
3217 @_set_msg_type(ofproto.OFPT_STATS_REQUEST)
3218 class OFPVendorStatsRequest(OFPStatsRequest):
3220 Vendor statistics request message
3222 The controller uses this message to query vendor-specific information
3226 def __init__(self, datapath, flags, vendor, specific_data=None):
3227 super(OFPVendorStatsRequest, self).__init__(datapath, flags)
3228 self.vendor = vendor
3229 self.specific_data = specific_data
3231 def _serialize_vendor_stats(self):
3232 self.buf += self.specific_data
3234 def _serialize_stats_body(self):
3235 msg_pack_into(ofproto.OFP_VENDOR_STATS_MSG_PACK_STR,
3236 self.buf, ofproto.OFP_STATS_MSG_SIZE,
3238 self._serialize_vendor_stats()
3241 class NXStatsRequest(OFPVendorStatsRequest):
3242 def __init__(self, datapath, flags, subtype):
3243 super(NXStatsRequest, self).__init__(datapath, flags,
3244 ofproto_common.NX_EXPERIMENTER_ID)
3245 self.subtype = subtype
3247 def _serialize_vendor_stats_body(self):
3250 def _serialize_vendor_stats(self):
3251 msg_pack_into(ofproto.NX_STATS_MSG_PACK_STR, self.buf,
3252 ofproto.OFP_VENDOR_STATS_MSG_SIZE,
3254 self._serialize_vendor_stats_body()
3257 class NXFlowStatsRequest(NXStatsRequest):
3258 def __init__(self, datapath, flags, out_port, table_id, rule=None):
3259 super(NXFlowStatsRequest, self).__init__(datapath, flags,
3261 self.out_port = out_port
3262 self.table_id = table_id
3266 def _serialize_vendor_stats_body(self):
3267 if self.rule is not None:
3268 offset = ofproto.NX_STATS_MSG_SIZE + \
3269 ofproto.NX_FLOW_STATS_REQUEST_SIZE
3270 self.match_len = nx_match.serialize_nxm_match(
3271 self.rule, self.buf, offset)
3274 ofproto.NX_FLOW_STATS_REQUEST_PACK_STR,
3275 self.buf, ofproto.NX_STATS_MSG_SIZE, self.out_port,
3276 self.match_len, self.table_id)
3279 class NXAggregateStatsRequest(NXStatsRequest):
3280 def __init__(self, datapath, flags, out_port, table_id, rule=None):
3281 super(NXAggregateStatsRequest, self).__init__(
3282 datapath, flags, ofproto.NXST_AGGREGATE)
3283 self.out_port = out_port
3284 self.table_id = table_id
3288 def _serialize_vendor_stats_body(self):
3289 if self.rule is not None:
3290 offset = ofproto.NX_STATS_MSG_SIZE + \
3291 ofproto.NX_AGGREGATE_STATS_REQUEST_SIZE
3292 self.match_len = nx_match.serialize_nxm_match(
3293 self.rule, self.buf, offset)
3296 ofproto.NX_AGGREGATE_STATS_REQUEST_PACK_STR,
3297 self.buf, ofproto.NX_STATS_MSG_SIZE, self.out_port,
3298 self.match_len, self.table_id)
3301 nx_actions.generate(
3302 'ryu.ofproto.ofproto_v1_0',
3303 'ryu.ofproto.ofproto_v1_0_parser'