1# Copyright (C) 2011, 2012 Nippon Telegraph and Telephone Corporation. 2# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp> 3# 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 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 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 13# implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17""" 18Decoder/Encoder implementations of OpenFlow 1.0. 19""" 20 21import struct 22import base64 23 24import six 25import netaddr 26 27from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase 28from ryu.lib import addrconv 29from ryu.lib import ip 30from ryu.lib import mac 31from ryu.lib.packet import packet 32from ryu.lib.pack_utils import msg_pack_into 33from ryu.ofproto import nx_match 34from ryu.ofproto import ofproto_common 35from ryu.ofproto import ofproto_parser 36from ryu.ofproto import ofproto_v1_0 as ofproto 37from ryu.ofproto import nx_actions 38from ryu import utils 39 40import logging 41LOG = logging.getLogger('ryu.ofproto.ofproto_v1_0_parser') 42 43_MSG_PARSERS = {} 44 45 46def _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 50 return cls 51 return _set_cls_msg_type 52 53 54def _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 59 return cls 60 61 62@ofproto_parser.register_msg_parser(ofproto.OFP_VERSION) 63def 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) 66 67 68# OFP_MSG_REPLY = { 69# OFPFeaturesRequest: OFPSwitchFeatures, 70# OFPBarrierRequest: OFPBarrierReply, 71# OFPQueueGetConfigRequest: OFPQueueGetConfigReply, 72# 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, 81# } 82def _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 86 return cls 87 return _set_cls_msg_reply 88 89 90# 91# common structures 92# 93 94class OFPPhyPort(ofproto_parser.namedtuple('OFPPhyPort', ( 95 'port_no', 'hw_addr', 'name', 'config', 'state', 'curr', 'advertised', 96 'supported', 'peer'))): 97 """ 98 Description of a port 99 100 ========== ========================================================= 101 Attribute Description 102 ========== ========================================================= 103 port_no Port number and it uniquely identifies a port within 104 a switch. 105 hw_addr MAC address for the port. 106 name Null-terminated string containing a human-readable name 107 for the interface. 108 config Bitmap of port configration flags. 109 110 | OFPPC_PORT_DOWN 111 | OFPPC_NO_STP 112 | OFPPC_NO_RECV 113 | OFPPC_NO_RECV_STP 114 | OFPPC_NO_FLOOD 115 | OFPPC_NO_FWD 116 | OFPPC_NO_PACKET_IN 117 state Bitmap of port state flags. 118 119 | OFPPS_LINK_DOWN 120 | OFPPS_STP_LISTEN 121 | OFPPS_STP_LEARN 122 | OFPPS_STP_FORWARD 123 | OFPPS_STP_BLOCK 124 | OFPPS_STP_MASK 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 ========== ========================================================= 130 """ 131 _TYPE = { 132 'ascii': [ 133 'hw_addr', 134 ], 135 'utf-8': [ 136 # OF spec is unclear about the encoding of name. 137 # we assumes UTF-8, which is used by OVS. 138 'name', 139 ] 140 } 141 142 @classmethod 143 def parser(cls, buf, offset): 144 port = struct.unpack_from(ofproto.OFP_PHY_PORT_PACK_STR, 145 buf, offset) 146 port = list(port) 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') 151 return cls(*port) 152 153 154class OFPMatch(StringifyMixin): 155 """ 156 Flow Match Structure 157 158 This class is implementation of the flow match structure having 159 compose/query API. 160 161 ================ ================================================== 162 Attribute Description 163 ================ ================================================== 164 wildcards Wildcard fields. 165 (match fields) For the available match fields, 166 please refer to the following. 167 ================ ================================================== 168 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 180 ARP opcode. 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 ================ =============== ================================== 190 191 Example:: 192 193 >>> # compose 194 >>> match = parser.OFPMatch( 195 ... in_port=1, 196 ... dl_type=0x0800, 197 ... dl_src='aa:bb:cc:dd:ee:ff', 198 ... nw_src='192.168.0.1') 199 >>> # query 200 >>> if 'nw_src' in match: 201 ... print match['nw_src'] 202 ... 203 '192.168.0.1' 204 """ 205 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 212 if in_port is None: 213 self.in_port = 0 214 else: 215 wc &= ~ofproto.OFPFW_IN_PORT 216 self.in_port = in_port 217 218 if dl_src is None: 219 self.dl_src = mac.DONTCARE 220 else: 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) 225 if dl_src == 0: 226 self.dl_src = mac.DONTCARE 227 else: 228 self.dl_src = dl_src 229 230 if dl_dst is None: 231 self.dl_dst = mac.DONTCARE 232 else: 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) 237 if dl_dst == 0: 238 self.dl_dst = mac.DONTCARE 239 else: 240 self.dl_dst = dl_dst 241 242 if dl_vlan is None: 243 self.dl_vlan = 0 244 else: 245 wc &= ~ofproto.OFPFW_DL_VLAN 246 self.dl_vlan = dl_vlan 247 248 if dl_vlan_pcp is None: 249 self.dl_vlan_pcp = 0 250 else: 251 wc &= ~ofproto.OFPFW_DL_VLAN_PCP 252 self.dl_vlan_pcp = dl_vlan_pcp 253 254 if dl_type is None: 255 self.dl_type = 0 256 else: 257 wc &= ~ofproto.OFPFW_DL_TYPE 258 self.dl_type = dl_type 259 260 if nw_tos is None: 261 self.nw_tos = 0 262 else: 263 wc &= ~ofproto.OFPFW_NW_TOS 264 self.nw_tos = nw_tos 265 266 if nw_proto is None: 267 self.nw_proto = 0 268 else: 269 wc &= ~ofproto.OFPFW_NW_PROTO 270 self.nw_proto = nw_proto 271 272 if nw_src is None: 273 self.nw_src = 0 274 else: 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) 279 self.nw_src = nw_src 280 281 if nw_dst is None: 282 self.nw_dst = 0 283 else: 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) 288 self.nw_dst = nw_dst 289 290 if tp_src is None: 291 self.tp_src = 0 292 else: 293 wc &= ~ofproto.OFPFW_TP_SRC 294 self.tp_src = tp_src 295 296 if tp_dst is None: 297 self.tp_dst = 0 298 else: 299 wc &= ~ofproto.OFPFW_TP_DST 300 self.tp_dst = tp_dst 301 302 if wildcards is None: 303 self.wildcards = wc 304 else: 305 self.wildcards = wildcards 306 307 def __getitem__(self, name): 308 if not isinstance(name, str): 309 raise KeyError(name) 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 320 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) 328 return value 329 else: 330 raise KeyError(name) 331 332 def __contains__(self, name): 333 wc = getattr(ofproto, 'OFPFW_' + name.upper(), 0) 334 return ~self.wildcards & wc 335 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) 342 343 @classmethod 344 def parse(cls, buf, offset): 345 match = struct.unpack_from(ofproto.OFP_MATCH_PACK_STR, 346 buf, offset) 347 return cls(*match) 348 349 def to_jsondict(self): 350 fields = {} 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) 357 else: 358 fields[k] = v 359 return {self.__class__.__name__: fields} 360 361 @classmethod 362 def from_jsondict(cls, dict_): 363 return cls(**dict_) 364 365 366class OFPActionHeader(StringifyMixin): 367 _base_attributes = ['type', 'len'] 368 369 def __init__(self, type_, len_): 370 self.type = type_ 371 self.len = len_ 372 373 def serialize(self, buf, offset): 374 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR, 375 buf, offset, self.type, self.len) 376 377 378class OFPAction(OFPActionHeader): 379 _ACTION_TYPES = {} 380 381 @staticmethod 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 387 return cls 388 return _register_action_type 389 390 def __init__(self): 391 cls = self.__class__ 392 super(OFPAction, self).__init__(cls.cls_action_type, 393 cls.cls_action_len) 394 395 @classmethod 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) 402 403 404@OFPAction.register_action_type(ofproto.OFPAT_OUTPUT, 405 ofproto.OFP_ACTION_OUTPUT_SIZE) 406class OFPActionOutput(OFPAction): 407 """ 408 Output action 409 410 This action indicates output a packet to the switch port. 411 412 ================ ====================================================== 413 Attribute Description 414 ================ ====================================================== 415 port Output port. 416 max_len Max length to send to controller. 417 ================ ====================================================== 418 419 Note:: 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. 423 """ 424 425 def __init__(self, port, max_len=0xffe5): 426 super(OFPActionOutput, self).__init__() 427 self.port = port 428 self.max_len = max_len 429 430 @classmethod 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) 437 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) 441 442 443@OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_VID, 444 ofproto.OFP_ACTION_VLAN_VID_SIZE) 445class OFPActionVlanVid(OFPAction): 446 """ 447 Set the 802.1q VLAN id action 448 449 This action indicates the 802.1q VLAN id to be set. 450 451 ================ ====================================================== 452 Attribute Description 453 ================ ====================================================== 454 vlan_vid VLAN id. 455 ================ ====================================================== 456 """ 457 458 def __init__(self, vlan_vid): 459 super(OFPActionVlanVid, self).__init__() 460 self.vlan_vid = vlan_vid 461 462 @classmethod 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 468 return cls(vlan_vid) 469 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) 473 474 475@OFPAction.register_action_type(ofproto.OFPAT_SET_VLAN_PCP, 476 ofproto.OFP_ACTION_VLAN_PCP_SIZE) 477class OFPActionVlanPcp(OFPAction): 478 """ 479 Set the 802.1q priority action 480 481 This action indicates the 802.1q priority to be set. 482 483 ================ ====================================================== 484 Attribute Description 485 ================ ====================================================== 486 vlan_pcp VLAN priority. 487 ================ ====================================================== 488 """ 489 490 def __init__(self, vlan_pcp): 491 super(OFPActionVlanPcp, self).__init__() 492 self.vlan_pcp = vlan_pcp 493 494 @classmethod 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 500 return cls(vlan_pcp) 501 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) 505 506 507@OFPAction.register_action_type(ofproto.OFPAT_STRIP_VLAN, 508 ofproto.OFP_ACTION_HEADER_SIZE) 509class OFPActionStripVlan(OFPAction): 510 """ 511 Strip the 802.1q header action 512 513 This action indicates the 802.1q priority to be striped. 514 """ 515 516 def __init__(self): 517 super(OFPActionStripVlan, self).__init__() 518 519 @classmethod 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 525 return cls() 526 527 528class 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 535 536 @classmethod 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 543 return cls(dl_addr) 544 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) 548 549 def to_jsondict(self): 550 body = {"dl_addr": addrconv.mac.bin_to_text(self.dl_addr)} 551 return {self.__class__.__name__: body} 552 553 @classmethod 554 def from_jsondict(cls, dict_): 555 return cls(**dict_) 556 557 558@OFPAction.register_action_type(ofproto.OFPAT_SET_DL_SRC, 559 ofproto.OFP_ACTION_DL_ADDR_SIZE) 560class OFPActionSetDlSrc(OFPActionDlAddr): 561 """ 562 Set the ethernet source address action 563 564 This action indicates the ethernet source address to be set. 565 566 ================ ====================================================== 567 Attribute Description 568 ================ ====================================================== 569 dl_addr Ethernet address. 570 ================ ====================================================== 571 """ 572 573 def __init__(self, dl_addr): 574 super(OFPActionSetDlSrc, self).__init__(dl_addr) 575 576 577@OFPAction.register_action_type(ofproto.OFPAT_SET_DL_DST, 578 ofproto.OFP_ACTION_DL_ADDR_SIZE) 579class OFPActionSetDlDst(OFPActionDlAddr): 580 """ 581 Set the ethernet destination address action 582 583 This action indicates the ethernet destination address to be set. 584 585 ================ ====================================================== 586 Attribute Description 587 ================ ====================================================== 588 dl_addr Ethernet address. 589 ================ ====================================================== 590 """ 591 592 def __init__(self, dl_addr): 593 super(OFPActionSetDlDst, self).__init__(dl_addr) 594 595 596class 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 602 603 @classmethod 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 610 return cls(nw_addr) 611 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) 615 616 def to_jsondict(self): 617 body = {"nw_addr": ip.ipv4_to_str(self.nw_addr)} 618 return {self.__class__.__name__: body} 619 620 @classmethod 621 def from_jsondict(cls, dict_): 622 return cls(**dict_) 623 624 625@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_SRC, 626 ofproto.OFP_ACTION_NW_ADDR_SIZE) 627class OFPActionSetNwSrc(OFPActionNwAddr): 628 """ 629 Set the IP source address action 630 631 This action indicates the IP source address to be set. 632 633 ================ ====================================================== 634 Attribute Description 635 ================ ====================================================== 636 nw_addr IP address. 637 ================ ====================================================== 638 """ 639 640 def __init__(self, nw_addr): 641 super(OFPActionSetNwSrc, self).__init__(nw_addr) 642 643 644@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_DST, 645 ofproto.OFP_ACTION_NW_ADDR_SIZE) 646class OFPActionSetNwDst(OFPActionNwAddr): 647 """ 648 Set the IP destination address action 649 650 This action indicates the IP destination address to be set. 651 652 ================ ====================================================== 653 Attribute Description 654 ================ ====================================================== 655 nw_addr IP address. 656 ================ ====================================================== 657 """ 658 659 def __init__(self, nw_addr): 660 super(OFPActionSetNwDst, self).__init__(nw_addr) 661 662 663@OFPAction.register_action_type(ofproto.OFPAT_SET_NW_TOS, 664 ofproto.OFP_ACTION_NW_TOS_SIZE) 665class OFPActionSetNwTos(OFPAction): 666 """ 667 Set the IP ToS action 668 669 This action indicates the IP ToS (DSCP field, 6 bits) to be set. 670 671 ================ ====================================================== 672 Attribute Description 673 ================ ====================================================== 674 tos IP ToS (DSCP field, 6 bits). 675 ================ ====================================================== 676 """ 677 678 def __init__(self, tos): 679 super(OFPActionSetNwTos, self).__init__() 680 self.tos = tos 681 682 @classmethod 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 688 return cls(tos) 689 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) 693 694 695class OFPActionTpPort(OFPAction): 696 def __init__(self, tp): 697 super(OFPActionTpPort, self).__init__() 698 self.tp = tp 699 700 @classmethod 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 707 return cls(tp) 708 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) 712 713 714@OFPAction.register_action_type(ofproto.OFPAT_SET_TP_SRC, 715 ofproto.OFP_ACTION_TP_PORT_SIZE) 716class OFPActionSetTpSrc(OFPActionTpPort): 717 """ 718 Set the TCP/UDP source port action 719 720 This action indicates the TCP/UDP source port to be set. 721 722 ================ ====================================================== 723 Attribute Description 724 ================ ====================================================== 725 tp TCP/UDP port. 726 ================ ====================================================== 727 """ 728 729 def __init__(self, tp): 730 super(OFPActionSetTpSrc, self).__init__(tp) 731 732 733@OFPAction.register_action_type(ofproto.OFPAT_SET_TP_DST, 734 ofproto.OFP_ACTION_TP_PORT_SIZE) 735class OFPActionSetTpDst(OFPActionTpPort): 736 """ 737 Set the TCP/UDP destination port action 738 739 This action indicates the TCP/UDP destination port to be set. 740 741 ================ ====================================================== 742 Attribute Description 743 ================ ====================================================== 744 tp TCP/UDP port. 745 ================ ====================================================== 746 """ 747 748 def __init__(self, tp): 749 super(OFPActionSetTpDst, self).__init__(tp) 750 751 752@OFPAction.register_action_type(ofproto.OFPAT_ENQUEUE, 753 ofproto.OFP_ACTION_ENQUEUE_SIZE) 754class OFPActionEnqueue(OFPAction): 755 """ 756 Output to queue action 757 758 This action indicates send packets to given queue on port. 759 760 ================ ====================================================== 761 Attribute Description 762 ================ ====================================================== 763 port Port that queue belongs. 764 queue_id Where to enqueue the packets. 765 ================ ====================================================== 766 """ 767 768 def __init__(self, port, queue_id): 769 super(OFPActionEnqueue, self).__init__() 770 self.port = port 771 self.queue_id = queue_id 772 773 @classmethod 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) 780 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) 784 785 786@OFPAction.register_action_type(ofproto.OFPAT_VENDOR, 0) 787class OFPActionVendor(OFPAction): 788 """ 789 Vendor action 790 791 This action is an extensible action for the vendor. 792 """ 793 _ACTION_VENDORS = {} 794 795 @staticmethod 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 800 return cls 801 return _register_action_vendor 802 803 def __init__(self, vendor=None): 804 super(OFPActionVendor, self).__init__() 805 self.type = ofproto.OFPAT_VENDOR 806 self.len = None 807 808 if vendor is None: 809 self.vendor = self.cls_vendor 810 else: 811 self.vendor = vendor 812 813 @classmethod 814 def parser(cls, buf, offset): 815 type_, len_, vendor = struct.unpack_from( 816 ofproto.OFP_ACTION_VENDOR_HEADER_PACK_STR, buf, offset) 817 818 data = buf[(offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE 819 ): offset + len_] 820 821 if vendor == ofproto_common.NX_EXPERIMENTER_ID: 822 obj = NXAction.parse(data) # noqa 823 else: 824 cls_ = cls._ACTION_VENDORS.get(vendor, None) 825 826 if cls_ is None: 827 obj = OFPActionVendorUnknown(vendor, data) 828 else: 829 obj = cls_.parser(buf, offset) 830 831 obj.len = len_ 832 return obj 833 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) 837 838 839# OpenFlow1.2 or later compatible 840OFPActionExperimenter = OFPActionVendor 841 842 843class OFPActionVendorUnknown(OFPActionVendor): 844 def __init__(self, vendor, data=None, type_=None, len_=None): 845 super(OFPActionVendorUnknown, 846 self).__init__(vendor=vendor) 847 self.data = data 848 849 def serialize(self, buf, offset): 850 # fixup 851 data = self.data 852 if data is None: 853 data = bytearray() 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), 858 buf, 859 offset + ofproto.OFP_ACTION_VENDOR_HEADER_SIZE, 860 self.data) 861 862 863@OFPActionVendor.register_action_vendor(ofproto_common.NX_EXPERIMENTER_ID) 864class NXActionHeader(OFPActionVendor): 865 _NX_ACTION_SUBTYPES = {} 866 867 @staticmethod 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 873 return cls 874 return _register_nx_action_subtype 875 876 def __init__(self): 877 super(NXActionHeader, self).__init__() 878 self.subtype = self.cls_subtype 879 880 def serialize(self, buf, offset): 881 msg_pack_into(ofproto.OFP_ACTION_HEADER_PACK_STR, 882 buf, offset, self.type, self.len) 883 884 @classmethod 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) 890 891 892class OFPDescStats(ofproto_parser.namedtuple('OFPDescStats', ( 893 'mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))): 894 895 _TYPE = { 896 'ascii': [ 897 'mfr_desc', 898 'hw_desc', 899 'sw_desc', 900 'serial_num', 901 'dp_desc', 902 ] 903 } 904 905 @classmethod 906 def parser(cls, buf, offset): 907 desc = struct.unpack_from(ofproto.OFP_DESC_STATS_PACK_STR, 908 buf, offset) 909 desc = list(desc) 910 desc = [x.rstrip(b'\0') for x in desc] 911 stats = cls(*desc) 912 stats.length = ofproto.OFP_DESC_STATS_SIZE 913 return stats 914 915 916class OFPFlowStats(StringifyMixin): 917 def __init__(self): 918 super(OFPFlowStats, self).__init__() 919 self.length = None 920 self.table_id = None 921 self.match = None 922 self.duration_sec = None 923 self.duration_nsec = None 924 self.priority = None 925 self.idle_timeout = None 926 self.hard_timeout = None 927 self.cookie = None 928 self.packet_count = None 929 self.byte_count = None 930 self.actions = None 931 932 @classmethod 933 def parser(cls, buf, offset): 934 flow_stats = cls() 935 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 939 940 flow_stats.match = OFPMatch.parse(buf, offset) 941 offset += ofproto.OFP_MATCH_SIZE 942 943 (flow_stats.duration_sec, 944 flow_stats.duration_nsec, 945 flow_stats.priority, 946 flow_stats.idle_timeout, 947 flow_stats.hard_timeout, 948 flow_stats.cookie, 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 953 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) 959 960 offset += action.len 961 length += action.len 962 963 return flow_stats 964 965 966class OFPAggregateStats(ofproto_parser.namedtuple('OFPAggregateStats', ( 967 'packet_count', 'byte_count', 'flow_count'))): 968 @classmethod 969 def parser(cls, buf, offset): 970 agg = struct.unpack_from( 971 ofproto.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset) 972 stats = cls(*agg) 973 stats.length = ofproto.OFP_AGGREGATE_STATS_REPLY_SIZE 974 return stats 975 976 977class OFPTableStats(ofproto_parser.namedtuple('OFPTableStats', ( 978 'table_id', 'name', 'wildcards', 'max_entries', 'active_count', 979 'lookup_count', 'matched_count'))): 980 981 _TYPE = { 982 'utf-8': [ 983 # OF spec is unclear about the encoding of name. 984 # we assumes UTF-8. 985 'name', 986 ] 987 } 988 989 @classmethod 990 def parser(cls, buf, offset): 991 tbl = struct.unpack_from(ofproto.OFP_TABLE_STATS_PACK_STR, 992 buf, offset) 993 tbl = list(tbl) 994 i = cls._fields.index('name') 995 tbl[i] = tbl[i].rstrip(b'\0') 996 stats = cls(*tbl) 997 stats.length = ofproto.OFP_TABLE_STATS_SIZE 998 return stats 999 1000 1001class 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'))): 1005 @classmethod 1006 def parser(cls, buf, offset): 1007 port = struct.unpack_from(ofproto.OFP_PORT_STATS_PACK_STR, 1008 buf, offset) 1009 stats = cls(*port) 1010 stats.length = ofproto.OFP_PORT_STATS_SIZE 1011 return stats 1012 1013 1014class OFPQueueStats(ofproto_parser.namedtuple('OFPQueueStats', ( 1015 'port_no', 'queue_id', 'tx_bytes', 'tx_packets', 'tx_errors'))): 1016 @classmethod 1017 def parser(cls, buf, offset): 1018 queue = struct.unpack_from(ofproto.OFP_QUEUE_STATS_PACK_STR, 1019 buf, offset) 1020 stats = cls(*queue) 1021 stats.length = ofproto.OFP_QUEUE_STATS_SIZE 1022 return stats 1023 1024 1025class OFPVendorStats(ofproto_parser.namedtuple('OFPVendorStats', 1026 ('specific_data'))): 1027 @classmethod 1028 def parser(cls, buf, offset): 1029 stats = cls(buf[offset:]) 1030 stats.length = len(stats.specific_data) 1031 return stats 1032 1033 1034class NXFlowStats(StringifyMixin): 1035 def __init__(self): 1036 super(NXFlowStats, self).__init__() 1037 self.length = None 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 1047 self.cookie = None 1048 self.packet_count = None 1049 self.byte_count = None 1050 1051 @classmethod 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 1064 1065 fields = [] 1066 match_len = nxflow_stats.match_len 1067 match_len -= 4 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 1074 1075 actions = [] 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 1084 1085 return nxflow_stats 1086 1087 1088class NXAggregateStats(ofproto_parser.namedtuple('NXAggregateStats', ( 1089 'packet_count', 'byte_count', 'flow_count'))): 1090 @classmethod 1091 def parser(cls, buf, offset): 1092 agg = struct.unpack_from( 1093 ofproto.NX_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset) 1094 stats = cls(*agg) 1095 stats.length = ofproto.NX_AGGREGATE_STATS_REPLY_SIZE 1096 1097 return stats 1098 1099 1100class OFPQueuePropHeader(StringifyMixin): 1101 _QUEUE_PROPERTIES = {} 1102 1103 @staticmethod 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 1109 return cls 1110 return _register_queue_propery 1111 1112 def __init__(self): 1113 self.property = self.cls_prop_type 1114 self.len = self.cls_prop_len 1115 1116 @classmethod 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 1123 1124 offset += ofproto.OFP_QUEUE_PROP_HEADER_SIZE 1125 return prop_cls.parser(buf, offset) 1126 1127 1128@OFPQueuePropHeader.register_queue_property( 1129 ofproto.OFPQT_NONE, ofproto.OFP_QUEUE_PROP_HEADER_SIZE) 1130class OFPQueuePropNone(OFPQueuePropHeader): 1131 def __init__(self): 1132 super(OFPQueuePropNone, self).__init__() 1133 1134 @classmethod 1135 def parser(cls, buf, offset): 1136 return cls() 1137 1138 1139@OFPQueuePropHeader.register_queue_property( 1140 ofproto.OFPQT_MIN_RATE, ofproto.OFP_QUEUE_PROP_MIN_RATE_SIZE) 1141class OFPQueuePropMinRate(OFPQueuePropHeader): 1142 def __init__(self, rate): 1143 super(OFPQueuePropMinRate, self).__init__() 1144 self.rate = rate 1145 1146 @classmethod 1147 def parser(cls, buf, offset): 1148 (rate,) = struct.unpack_from( 1149 ofproto.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, 1150 buf, offset) 1151 return cls(rate) 1152 1153 1154class OFPPacketQueue(StringifyMixin): 1155 """ 1156 Description of a queue 1157 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 ========== ========================================================= 1165 """ 1166 1167 def __init__(self, queue_id, len_): 1168 self.queue_id = queue_id 1169 self.len = len_ 1170 self.properties = None 1171 1172 @classmethod 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_) 1177 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 <= 1182 packet_queue.len): 1183 prop = OFPQueuePropHeader.parser(buf, offset) 1184 packet_queue.properties.append(prop) 1185 1186 cur_len += prop.len 1187 offset += prop.len 1188 1189 return packet_queue 1190 1191# 1192# Symmetric messages 1193# parser + serializer 1194# 1195 1196 1197@_register_parser 1198@_set_msg_type(ofproto.OFPT_HELLO) 1199class OFPHello(MsgBase): 1200 """ 1201 Hello message 1202 1203 When connection is started, the hello message is exchanged between a 1204 switch and a controller. 1205 1206 This message is handled by the Ryu framework, so the Ryu application 1207 do not need to process this typically. 1208 """ 1209 1210 def __init__(self, datapath): 1211 super(OFPHello, self).__init__(datapath) 1212 1213 1214@_register_parser 1215@_set_msg_type(ofproto.OFPT_ERROR) 1216class OFPErrorMsg(MsgBase): 1217 """ 1218 Error message 1219 1220 The switch notifies controller of problems by this message. 1221 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 ========== ========================================================= 1229 1230 ``type`` attribute corresponds to ``type_`` parameter of __init__. 1231 1232 Types and codes are defined in ``ryu.ofproto.ofproto``. 1233 1234 =========================== =========== 1235 Type Code 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 =========================== =========== 1244 1245 Example:: 1246 1247 @set_ev_cls(ofp_event.EventOFPErrorMsg, 1248 [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER]) 1249 def error_msg_handler(self, ev): 1250 msg = ev.msg 1251 1252 self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x ' 1253 'message=%s', 1254 msg.type, msg.code, utils.hex_array(msg.data)) 1255 """ 1256 1257 def __init__(self, datapath, type_=None, code=None, data=None): 1258 super(OFPErrorMsg, self).__init__(datapath) 1259 self.type = type_ 1260 self.code = code 1261 if isinstance(data, six.string_types): 1262 data = data.encode('ascii') 1263 self.data = data 1264 1265 @classmethod 1266 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1267 msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type, 1268 msg_len, xid, buf) 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:] 1273 return msg 1274 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 1280 1281 1282@_register_parser 1283@_set_msg_type(ofproto.OFPT_ECHO_REQUEST) 1284class OFPEchoRequest(MsgBase): 1285 """ 1286 Echo request message 1287 1288 This message is handled by the Ryu framework, so the Ryu application 1289 do not need to process this typically. 1290 1291 ========== ========================================================= 1292 Attribute Description 1293 ========== ========================================================= 1294 data An arbitrary length data. 1295 ========== ========================================================= 1296 1297 Example:: 1298 1299 def send_echo_request(self, datapath, data): 1300 ofp_parser = datapath.ofproto_parser 1301 1302 req = ofp_parser.OFPEchoRequest(datapath, data) 1303 datapath.send_msg(req) 1304 """ 1305 1306 def __init__(self, datapath, data=None): 1307 super(OFPEchoRequest, self).__init__(datapath) 1308 self.data = data 1309 1310 @classmethod 1311 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1312 msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type, 1313 msg_len, xid, buf) 1314 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:] 1315 return msg 1316 1317 def _serialize_body(self): 1318 if self.data is not None: 1319 self.buf += self.data 1320 1321 1322@_register_parser 1323@_set_msg_type(ofproto.OFPT_ECHO_REPLY) 1324class OFPEchoReply(MsgBase): 1325 """ 1326 Echo reply message 1327 1328 This message is handled by the Ryu framework, so the Ryu application 1329 do not need to process this typically. 1330 1331 ========== ========================================================= 1332 Attribute Description 1333 ========== ========================================================= 1334 data An arbitrary length data. 1335 ========== ========================================================= 1336 1337 Example:: 1338 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)) 1344 """ 1345 1346 def __init__(self, datapath, data=None): 1347 super(OFPEchoReply, self).__init__(datapath) 1348 self.data = data 1349 1350 @classmethod 1351 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1352 msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type, 1353 msg_len, xid, buf) 1354 msg.data = msg.buf[ofproto.OFP_HEADER_SIZE:] 1355 return msg 1356 1357 def _serialize_body(self): 1358 assert self.data is not None 1359 self.buf += self.data 1360 1361 1362@_register_parser 1363@_set_msg_type(ofproto.OFPT_VENDOR) 1364class OFPVendor(MsgBase): 1365 """ 1366 Vendor message 1367 1368 The controller send this message to send the vendor-specific 1369 information to a switch. 1370 """ 1371 _VENDORS = {} 1372 1373 @staticmethod 1374 def register_vendor(id_): 1375 def _register_vendor(cls): 1376 OFPVendor._VENDORS[id_] = cls 1377 return cls 1378 return _register_vendor 1379 1380 def __init__(self, datapath): 1381 super(OFPVendor, self).__init__(datapath) 1382 self.data = None 1383 self.vendor = None 1384 1385 @classmethod 1386 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1387 msg = super(OFPVendor, cls).parser(datapath, version, msg_type, 1388 msg_len, xid, buf) 1389 (msg.vendor,) = struct.unpack_from( 1390 ofproto.OFP_VENDOR_HEADER_PACK_STR, msg.buf, 1391 ofproto.OFP_HEADER_SIZE) 1392 1393 cls_ = cls._VENDORS.get(msg.vendor) 1394 if cls_: 1395 msg.data = cls_.parser(datapath, msg.buf, 0) 1396 else: 1397 msg.data = msg.buf[ofproto.OFP_VENDOR_HEADER_SIZE:] 1398 1399 return msg 1400 1401 def serialize_header(self): 1402 msg_pack_into(ofproto.OFP_VENDOR_HEADER_PACK_STR, 1403 self.buf, ofproto.OFP_HEADER_SIZE, self.vendor) 1404 1405 def _serialize_body(self): 1406 assert self.data is not None 1407 self.serialize_header() 1408 self.buf += self.data 1409 1410 1411@OFPVendor.register_vendor(ofproto_common.NX_EXPERIMENTER_ID) 1412class NiciraHeader(OFPVendor): 1413 _NX_SUBTYPES = {} 1414 1415 @staticmethod 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 1420 return cls 1421 return _register_nx_subtype 1422 1423 def __init__(self, datapath, subtype): 1424 super(NiciraHeader, self).__init__(datapath) 1425 self.vendor = ofproto_common.NX_EXPERIMENTER_ID 1426 self.subtype = subtype 1427 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) 1433 1434 @classmethod 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) 1442 1443 1444class 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 1449 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) 1454 1455 1456class 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): 1462 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 1468 1469 if actions is None: 1470 actions = [] 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 1479 self.flags = flags 1480 self.rule = rule 1481 self.actions = actions 1482 1483 def _serialize_body(self): 1484 self.serialize_header() 1485 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) 1489 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) 1495 1496 if self.actions is not None: 1497 for a in self.actions: 1498 a.serialize(self.buf, offset) 1499 offset += a.len 1500 1501 1502class NXTRoleRequest(NiciraHeader): 1503 def __init__(self, datapath, role): 1504 super(NXTRoleRequest, self).__init__( 1505 datapath, ofproto.NXT_ROLE_REQUEST) 1506 self.role = role 1507 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) 1512 1513 1514@NiciraHeader.register_nx_subtype(ofproto.NXT_ROLE_REPLY) 1515class NXTRoleReply(NiciraHeader): 1516 def __init__(self, datapath, role): 1517 super(NXTRoleReply, self).__init__( 1518 datapath, ofproto.NXT_ROLE_REPLY) 1519 self.role = role 1520 1521 @classmethod 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) 1526 1527 1528class NXTFlowModTableId(NiciraHeader): 1529 def __init__(self, datapath, set_): 1530 super(NXTFlowModTableId, self).__init__( 1531 datapath, ofproto.NXT_FLOW_MOD_TABLE_ID) 1532 self.set = set_ 1533 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, 1538 self.set) 1539 1540 1541@NiciraHeader.register_nx_subtype(ofproto.NXT_FLOW_REMOVED) 1542class 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 1557 self.match = match 1558 1559 @classmethod 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, 1570 byte_count, match) 1571 1572 1573class 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 1578 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, 1583 self.format) 1584 1585 1586@NiciraHeader.register_nx_subtype(ofproto.NXT_PACKET_IN) 1587class 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 1598 self.match = match 1599 self.frame = frame 1600 1601 @classmethod 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) 1606 1607 offset += (ofproto.NX_PACKET_IN_SIZE - 1608 ofproto.NICIRA_HEADER_SIZE) 1609 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) 1617 1618 1619class NXTFlowAge(NiciraHeader): 1620 def __init__(self, datapath): 1621 super(NXTFlowAge, self).__init__( 1622 datapath, ofproto.NXT_FLOW_AGE) 1623 1624 def _serialize_body(self): 1625 self.serialize_header() 1626 1627 1628class NXTSetAsyncConfig(NiciraHeader): 1629 def __init__(self, datapath, packet_in_mask, port_status_mask, 1630 flow_removed_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 1636 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]) 1644 1645 1646class 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 1651 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, 1656 self.controller_id) 1657 1658 1659# 1660# asymmetric message (datapath -> controller) 1661# parser only 1662# 1663 1664 1665@_register_parser 1666@_set_msg_type(ofproto.OFPT_FEATURES_REPLY) 1667class OFPSwitchFeatures(MsgBase): 1668 """ 1669 Features reply message 1670 1671 The switch responds with a features reply message to a features 1672 request. 1673 1674 This message is handled by the Ryu framework, so the Ryu application 1675 do not need to process this typically. 1676 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. 1684 1685 | OFPC_FLOW_STATS 1686 | OFPC_TABLE_STATS 1687 | OFPC_PORT_STATS 1688 | OFPC_STP 1689 | OFPC_RESERVED 1690 | OFPC_IP_REASM 1691 | OFPC_QUEUE_STATS 1692 | OFPC_ARP_MATCH_IP 1693 actions Bitmap of supported OFPAT_*. 1694 ports List of ``OFPPhyPort`` instances. 1695 ================ ====================================================== 1696 1697 Example:: 1698 1699 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) 1700 def switch_features_handler(self, ev): 1701 msg = ev.msg 1702 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) 1708 """ 1709 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 1718 self.ports = ports 1719 1720 @classmethod 1721 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1722 msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type, 1723 msg_len, xid, buf) 1724 (msg.datapath_id, 1725 msg.n_buffers, 1726 msg.n_tables, 1727 msg.capabilities, 1728 msg.actions) = struct.unpack_from( 1729 ofproto.OFP_SWITCH_FEATURES_PACK_STR, msg.buf, 1730 ofproto.OFP_HEADER_SIZE) 1731 1732 msg.ports = {} 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 1741 1742 return msg 1743 1744 1745@_register_parser 1746@_set_msg_type(ofproto.OFPT_PORT_STATUS) 1747class OFPPortStatus(MsgBase): 1748 """ 1749 Port status message 1750 1751 The switch notifies controller of change of ports. 1752 1753 ================ ====================================================== 1754 Attribute Description 1755 ================ ====================================================== 1756 reason One of the following values. 1757 1758 | OFPPR_ADD 1759 | OFPPR_DELETE 1760 | OFPPR_MODIFY 1761 desc instance of ``OFPPhyPort`` 1762 ================ ====================================================== 1763 1764 Example:: 1765 1766 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER) 1767 def port_status_handler(self, ev): 1768 msg = ev.msg 1769 dp = msg.datapath 1770 ofp = dp.ofproto 1771 1772 if msg.reason == ofp.OFPPR_ADD: 1773 reason = 'ADD' 1774 elif msg.reason == ofp.OFPPR_DELETE: 1775 reason = 'DELETE' 1776 elif msg.reason == ofp.OFPPR_MODIFY: 1777 reason = 'MODIFY' 1778 else: 1779 reason = 'unknown' 1780 1781 self.logger.debug('OFPPortStatus received: reason=%s desc=%s', 1782 reason, msg.desc) 1783 """ 1784 1785 def __init__(self, datapath, reason=None, desc=None): 1786 super(OFPPortStatus, self).__init__(datapath) 1787 self.reason = reason 1788 self.desc = desc 1789 1790 @classmethod 1791 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1792 msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type, 1793 msg_len, xid, buf) 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) 1799 return msg 1800 1801 1802@_register_parser 1803@_set_msg_type(ofproto.OFPT_PACKET_IN) 1804class OFPPacketIn(MsgBase): 1805 """ 1806 Packet-In message 1807 1808 The switch sends the packet that received to the controller by this 1809 message. 1810 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. 1818 1819 | OFPR_NO_MATCH 1820 | OFPR_ACTION 1821 | OFPR_INVALID_TTL 1822 data Ethernet frame. 1823 ============= ========================================================= 1824 1825 Example:: 1826 1827 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) 1828 def packet_in_handler(self, ev): 1829 msg = ev.msg 1830 dp = msg.datapath 1831 ofp = dp.ofproto 1832 1833 if msg.reason == ofp.OFPR_NO_MATCH: 1834 reason = 'NO MATCH' 1835 elif msg.reason == ofp.OFPR_ACTION: 1836 reason = 'ACTION' 1837 elif msg.reason == ofp.OFPR_INVALID_TTL: 1838 reason = 'INVALID TTL' 1839 else: 1840 reason = 'unknown' 1841 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)) 1847 """ 1848 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 1856 self.data = data 1857 1858 @classmethod 1859 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1860 msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type, 1861 msg_len, xid, buf) 1862 (msg.buffer_id, 1863 msg.total_len, 1864 msg.in_port, 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] 1872 return msg 1873 1874 1875@_register_parser 1876@_set_msg_type(ofproto.OFPT_GET_CONFIG_REPLY) 1877class OFPGetConfigReply(MsgBase): 1878 """ 1879 Get config reply message 1880 1881 The switch responds to a configuration request with a get config reply 1882 message. 1883 1884 ============= ========================================================= 1885 Attribute Description 1886 ============= ========================================================= 1887 flags One of the following configuration flags. 1888 1889 | OFPC_FRAG_NORMAL 1890 | OFPC_FRAG_DROP 1891 | OFPC_FRAG_REASM 1892 | OFPC_FRAG_MASK 1893 miss_send_len Max bytes of new flow that datapath should send to the 1894 controller. 1895 ============= ========================================================= 1896 1897 Example:: 1898 1899 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER) 1900 def get_config_reply_handler(self, ev): 1901 msg = ev.msg 1902 dp = msg.datapath 1903 ofp = dp.ofproto 1904 1905 if msg.flags == ofp.OFPC_FRAG_NORMAL: 1906 flags = 'NORMAL' 1907 elif msg.flags == ofp.OFPC_FRAG_DROP: 1908 flags = 'DROP' 1909 elif msg.flags == ofp.OFPC_FRAG_REASM: 1910 flags = 'REASM' 1911 elif msg.flags == ofp.OFPC_FRAG_MASK: 1912 flags = 'MASK' 1913 else: 1914 flags = 'unknown' 1915 self.logger.debug('OFPGetConfigReply received: ' 1916 'flags=%s miss_send_len=%d', 1917 flags, msg.miss_send_len) 1918 """ 1919 1920 def __init__(self, datapath): 1921 super(OFPGetConfigReply, self).__init__(datapath) 1922 1923 @classmethod 1924 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 1925 msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type, 1926 msg_len, xid, buf) 1927 (msg.flags, msg.miss_send_len) = struct.unpack_from( 1928 ofproto.OFP_SWITCH_CONFIG_PACK_STR, 1929 msg.buf, ofproto.OFP_HEADER_SIZE) 1930 return msg 1931 1932 1933@_register_parser 1934@_set_msg_type(ofproto.OFPT_BARRIER_REPLY) 1935class OFPBarrierReply(MsgBase): 1936 """ 1937 Barrier reply message 1938 1939 The switch responds with this message to a barrier request. 1940 1941 Example:: 1942 1943 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER) 1944 def barrier_reply_handler(self, ev): 1945 self.logger.debug('OFPBarrierReply received') 1946 """ 1947 1948 def __init__(self, datapath): 1949 super(OFPBarrierReply, self).__init__(datapath) 1950 1951 1952@_register_parser 1953@_set_msg_type(ofproto.OFPT_FLOW_REMOVED) 1954class OFPFlowRemoved(MsgBase): 1955 """ 1956 Flow removed message 1957 1958 When flow entries time out or are deleted, the switch notifies controller 1959 with this message. 1960 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. 1968 1969 | OFPRR_IDLE_TIMEOUT 1970 | OFPRR_HARD_TIMEOUT 1971 | OFPRR_DELETE 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 ================ ====================================================== 1979 1980 Example:: 1981 1982 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER) 1983 def flow_removed_handler(self, ev): 1984 msg = ev.msg 1985 dp = msg.datapath 1986 ofp = dp.ofproto 1987 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: 1993 reason = 'DELETE' 1994 elif msg.reason == ofp.OFPRR_GROUP_DELETE: 1995 reason = 'GROUP DELETE' 1996 else: 1997 reason = 'unknown' 1998 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, 2006 msg.byte_count) 2007 """ 2008 2009 def __init__(self, datapath): 2010 super(OFPFlowRemoved, self).__init__(datapath) 2011 2012 @classmethod 2013 def parser(cls, datapath, version, msg_type, msg_len, xid, buf): 2014 msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type, 2015 msg_len, xid, buf) 2016 2017 msg.match = OFPMatch.parse(msg.buf, ofproto.OFP_HEADER_SIZE) 2018 2019 (msg.cookie, 2020 msg.priority, 2021 msg.reason, 2022 msg.duration_sec, 2023 msg.duration_nsec, 2024 msg.idle_timeout, 2025 msg.packet_count, 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) 2029 2030 return msg 2031 2032 2033@_register_parser 2034@_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REPLY) 2035class OFPQueueGetConfigReply(MsgBase): 2036 """ 2037 Queue configuration reply message 2038 2039 The switch responds with this message to a queue configuration request. 2040 2041 ================ ====================================================== 2042 Attribute Description 2043 ================ ====================================================== 2044 port Port to be queried. 2045 queues List of ``OFPPacketQueue`` instance. 2046 ================ ====================================================== 2047 2048 Example:: 2049 2050 @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER) 2051 def queue_get_config_reply_handler(self, ev): 2052 msg = ev.msg 2053 2054 self.logger.debug('OFPQueueGetConfigReply received: ' 2055 'port=%s queues=%s', 2056 msg.port, msg.queues) 2057 """ 2058 2059 def __init__(self, datapath): 2060 super(OFPQueueGetConfigReply, self).__init__(datapath) 2061 2062 @classmethod 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) 2066 2067 offset = ofproto.OFP_HEADER_SIZE 2068 (msg.port,) = struct.unpack_from( 2069 ofproto.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf, offset) 2070 2071 msg.queues = [] 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) 2076 2077 offset += queue.len 2078 2079 return msg 2080 2081 2082def _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 2086 return cls 2087 return _set_cls_stats_type 2088 2089 2090@_register_parser 2091@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2092class OFPStatsReply(MsgBase): 2093 _STATS_MSG_TYPES = {} 2094 2095 @staticmethod 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 2103 return cls 2104 return _register_stats_type 2105 2106 def __init__(self, datapath): 2107 super(OFPStatsReply, self).__init__(datapath) 2108 self.type = None 2109 self.flags = None 2110 self.body = None 2111 2112 @classmethod 2113 def parser_stats_body(cls, buf, msg_len, offset): 2114 body_cls = cls.cls_stats_body_cls 2115 body = [] 2116 while offset < msg_len: 2117 entry = body_cls.parser(buf, offset) 2118 body.append(entry) 2119 offset += entry.length 2120 2121 if cls.cls_body_single_struct: 2122 return body[0] 2123 return body 2124 2125 @classmethod 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) 2132 return msg 2133 2134 @classmethod 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) 2142 msg.type = type_ 2143 msg.flags = flags 2144 return msg 2145 2146 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) 2150class OFPDescStatsReply(OFPStatsReply): 2151 """ 2152 Description statistics reply message 2153 2154 The switch responds with a stats reply that include this message to 2155 a description statistics request. 2156 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 ================ ====================================================== 2166 2167 Example:: 2168 2169 @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER) 2170 def desc_stats_reply_handler(self, ev): 2171 msg = ev.msg 2172 ofp = msg.datapath.ofproto 2173 body = ev.msg.body 2174 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) 2179 """ 2180 2181 def __init__(self, datapath): 2182 super(OFPDescStatsReply, self).__init__(datapath) 2183 2184 2185@OFPStatsReply.register_stats_type() 2186@_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats) 2187@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2188class OFPFlowStatsReply(OFPStatsReply): 2189 """ 2190 Individual flow statistics reply message 2191 2192 The switch responds with a stats reply that include this message to 2193 an individual flow statistics request. 2194 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 2202 duration_sec. 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 ================ ====================================================== 2212 2213 Example:: 2214 2215 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 2216 def flow_stats_reply_handler(self, ev): 2217 msg = ev.msg 2218 ofp = msg.datapath.ofproto 2219 body = ev.msg.body 2220 2221 flows = [] 2222 for stat in body: 2223 flows.append('table_id=%s match=%s ' 2224 'duration_sec=%d duration_nsec=%d ' 2225 'priority=%d ' 2226 'idle_timeout=%d hard_timeout=%d ' 2227 'cookie=%d packet_count=%d byte_count=%d ' 2228 'actions=%s' % 2229 (stat.table_id, stat.match, 2230 stat.duration_sec, stat.duration_nsec, 2231 stat.priority, 2232 stat.idle_timeout, stat.hard_timeout, 2233 stat.cookie, stat.packet_count, stat.byte_count, 2234 stat.actions)) 2235 self.logger.debug('FlowStats: %s', flows) 2236 """ 2237 2238 def __init__(self, datapath): 2239 super(OFPFlowStatsReply, self).__init__(datapath) 2240 2241 2242@OFPStatsReply.register_stats_type() 2243@_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats) 2244@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2245class OFPAggregateStatsReply(OFPStatsReply): 2246 """ 2247 Aggregate flow statistics reply message 2248 2249 The switch responds with a stats reply that include this message to 2250 an aggregate flow statistics request. 2251 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 ================ ====================================================== 2259 2260 Example:: 2261 2262 @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER) 2263 def aggregate_stats_reply_handler(self, ev): 2264 msg = ev.msg 2265 ofp = msg.datapath.ofproto 2266 body = ev.msg.body 2267 2268 self.logger.debug('AggregateStats: packet_count=%d byte_count=%d ' 2269 'flow_count=%d', 2270 body.packet_count, body.byte_count, 2271 body.flow_count) 2272 """ 2273 2274 def __init__(self, datapath): 2275 super(OFPAggregateStatsReply, self).__init__(datapath) 2276 2277 2278@OFPStatsReply.register_stats_type() 2279@_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats) 2280@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2281class OFPTableStatsReply(OFPStatsReply): 2282 """ 2283 Table statistics reply message 2284 2285 The switch responds with a stats reply that include this message to 2286 a table statistics request. 2287 2288 ================ ====================================================== 2289 Attribute Description 2290 ================ ====================================================== 2291 table_id ID of table. 2292 name table name. 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 ================ ====================================================== 2300 2301 Example:: 2302 2303 @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER) 2304 def stats_reply_handler(self, ev): 2305 msg = ev.msg 2306 ofp = msg.datapath.ofproto 2307 body = ev.msg.body 2308 2309 tables = [] 2310 for stat in body: 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) 2318 """ 2319 2320 def __init__(self, datapath): 2321 super(OFPTableStatsReply, self).__init__(datapath) 2322 2323 2324@OFPStatsReply.register_stats_type() 2325@_set_stats_type(ofproto.OFPST_PORT, OFPPortStats) 2326@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2327class OFPPortStatsReply(OFPStatsReply): 2328 """ 2329 Port statistics reply message 2330 2331 The switch responds with a stats reply that include this message to 2332 a port statistics request. 2333 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 ================ ====================================================== 2351 2352 Example:: 2353 2354 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) 2355 def port_stats_reply_handler(self, ev): 2356 msg = ev.msg 2357 ofp = msg.datapath.ofproto 2358 body = ev.msg.body 2359 2360 ports = [] 2361 for stat in body: 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 ' 2368 'collisions=%d' % 2369 (stat.port_no, 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) 2377 """ 2378 2379 def __init__(self, datapath): 2380 super(OFPPortStatsReply, self).__init__(datapath) 2381 2382 2383@OFPStatsReply.register_stats_type() 2384@_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats) 2385@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2386class OFPQueueStatsReply(OFPStatsReply): 2387 """ 2388 Queue statistics reply message 2389 2390 The switch responds with a stats reply that include this message to 2391 an aggregate flow statistics request. 2392 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 ================ ====================================================== 2402 2403 Example:: 2404 2405 @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER) 2406 def stats_reply_handler(self, ev): 2407 msg = ev.msg 2408 ofp = msg.datapath.ofproto 2409 body = ev.msg.body 2410 2411 queues = [] 2412 for stat in body: 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) 2418 """ 2419 2420 def __init__(self, datapath): 2421 super(OFPQueueStatsReply, self).__init__(datapath) 2422 2423 2424@OFPStatsReply.register_stats_type() 2425@_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats) 2426@_set_msg_type(ofproto.OFPT_STATS_REPLY) 2427class OFPVendorStatsReply(OFPStatsReply): 2428 """ 2429 Vendor statistics reply message 2430 2431 The switch responds with a stats reply that include this message to 2432 an vendor statistics request. 2433 """ 2434 _STATS_VENDORS = {} 2435 2436 @staticmethod 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 2441 return cls 2442 return _register_stats_vendor 2443 2444 def __init__(self, datapath): 2445 super(OFPVendorStatsReply, self).__init__(datapath) 2446 2447 @classmethod 2448 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, 2449 buf): 2450 (type_,) = struct.unpack_from( 2451 ofproto.OFP_VENDOR_STATS_MSG_PACK_STR, six.binary_type(buf), 2452 ofproto.OFP_STATS_MSG_SIZE) 2453 2454 cls_ = cls._STATS_VENDORS.get(type_) 2455 2456 if cls_ is None: 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) 2462 msg.body = body 2463 return msg 2464 2465 return cls_.parser( 2466 datapath, version, msg_type, msg_len, xid, buf, 2467 ofproto.OFP_VENDOR_STATS_MSG_SIZE) 2468 2469 2470@OFPVendorStatsReply.register_stats_vendor(ofproto_common.NX_EXPERIMENTER_ID) 2471class NXStatsReply(OFPStatsReply): 2472 _NX_STATS_TYPES = {} 2473 2474 @staticmethod 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 2483 return cls 2484 return _register_nx_stats_type 2485 2486 @classmethod 2487 def parser_stats_body(cls, buf, msg_len, offset): 2488 body_cls = cls.cls_stats_body_cls 2489 body = [] 2490 while offset < msg_len: 2491 entry = body_cls.parser(buf, offset) 2492 body.append(entry) 2493 offset += entry.length 2494 2495 if cls.cls_body_single_struct: 2496 return body[0] 2497 return body 2498 2499 @classmethod 2500 def parser_stats(cls, datapath, version, msg_type, msg_len, xid, 2501 buf, offset): 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) 2505 2506 return msg 2507 2508 @classmethod 2509 def parser(cls, datapath, version, msg_type, msg_len, xid, buf, 2510 offset): 2511 (type_,) = struct.unpack_from( 2512 ofproto.NX_STATS_MSG_PACK_STR, six.binary_type(buf), offset) 2513 offset += ofproto.NX_STATS_MSG0_SIZE 2514 2515 cls_ = cls._NX_STATS_TYPES.get(type_) 2516 2517 msg = cls_.parser_stats( 2518 datapath, version, msg_type, msg_len, xid, buf, offset) 2519 2520 return msg 2521 2522 2523@NXStatsReply.register_nx_stats_type() 2524@_set_stats_type(ofproto.NXST_FLOW, NXFlowStats) 2525class NXFlowStatsReply(NXStatsReply): 2526 def __init__(self, datapath): 2527 super(NXFlowStatsReply, self).__init__(datapath) 2528 2529 2530@NXStatsReply.register_nx_stats_type() 2531@_set_stats_type(ofproto.NXST_AGGREGATE, NXAggregateStats) 2532class NXAggregateStatsReply(NXStatsReply): 2533 def __init__(self, datapath): 2534 super(NXAggregateStatsReply, self).__init__(datapath) 2535 2536 2537# 2538# controller-to-switch message 2539# serializer only 2540# 2541 2542 2543@_set_msg_reply(OFPSwitchFeatures) 2544@_set_msg_type(ofproto.OFPT_FEATURES_REQUEST) 2545class OFPFeaturesRequest(MsgBase): 2546 """ 2547 Features request message 2548 2549 The controller sends a feature request to the switch upon session 2550 establishment. 2551 2552 This message is handled by the Ryu framework, so the Ryu application 2553 do not need to process this typically. 2554 2555 Example:: 2556 2557 def send_features_request(self, datapath): 2558 ofp_parser = datapath.ofproto_parser 2559 2560 req = ofp_parser.OFPFeaturesRequest(datapath) 2561 datapath.send_msg(req) 2562 """ 2563 2564 def __init__(self, datapath): 2565 super(OFPFeaturesRequest, self).__init__(datapath) 2566 2567 2568@_set_msg_type(ofproto.OFPT_GET_CONFIG_REQUEST) 2569class OFPGetConfigRequest(MsgBase): 2570 """ 2571 Get config request message 2572 2573 The controller sends a get config request to query configuration 2574 parameters in the switch. 2575 2576 Example:: 2577 2578 def send_get_config_request(self, datapath): 2579 ofp_parser = datapath.ofproto_parser 2580 2581 req = ofp_parser.OFPGetConfigRequest(datapath) 2582 datapath.send_msg(req) 2583 """ 2584 2585 def __init__(self, datapath): 2586 super(OFPGetConfigRequest, self).__init__(datapath) 2587 2588 2589@_set_msg_type(ofproto.OFPT_SET_CONFIG) 2590class OFPSetConfig(MsgBase): 2591 """ 2592 Set config request message 2593 2594 The controller sends a set config request message to set configuraion 2595 parameters. 2596 2597 ============= ========================================================= 2598 Attribute Description 2599 ============= ========================================================= 2600 flags One of the following configuration flags. 2601 2602 | OFPC_FRAG_NORMAL 2603 | OFPC_FRAG_DROP 2604 | OFPC_FRAG_REASM 2605 | OFPC_FRAG_MASK 2606 miss_send_len Max bytes of new flow that datapath should send to the 2607 controller. 2608 ============= ========================================================= 2609 2610 Example:: 2611 2612 def send_set_config(self, datapath): 2613 ofp = datapath.ofproto 2614 ofp_parser = datapath.ofproto_parser 2615 2616 req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256) 2617 datapath.send_msg(req) 2618 """ 2619 2620 def __init__(self, datapath, flags=None, miss_send_len=None): 2621 super(OFPSetConfig, self).__init__(datapath) 2622 self.flags = flags 2623 self.miss_send_len = miss_send_len 2624 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) 2631 2632 2633@_set_msg_type(ofproto.OFPT_PACKET_OUT) 2634class OFPPacketOut(MsgBase): 2635 """ 2636 Packet-Out message 2637 2638 The controller uses this message to send a packet out throught the 2639 switch. 2640 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 ================ ====================================================== 2650 2651 Example:: 2652 2653 def send_packet_out(self, datapath): 2654 ofp = datapath.ofproto 2655 ofp_parser = datapath.ofproto_parser 2656 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, 2661 in_port, actions) 2662 datapath.send_msg(req) 2663 """ 2664 2665 def __init__(self, datapath, buffer_id=None, in_port=None, actions=None, 2666 data=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 2672 self.data = data 2673 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 2678 2679 self._actions_len = 0 2680 offset = ofproto.OFP_PACKET_OUT_SIZE 2681 for a in self.actions: 2682 a.serialize(self.buf, offset) 2683 offset += a.len 2684 self._actions_len += a.len 2685 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 2691 else: 2692 self.buf += self.data 2693 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) 2697 2698 @classmethod 2699 def from_jsondict(cls, dict_, decode_string=base64.b64decode, 2700 **additional_args): 2701 if isinstance(dict_['data'], dict): 2702 data = dict_.pop('data') 2703 ins = super(OFPPacketOut, cls).from_jsondict(dict_, 2704 decode_string, 2705 **additional_args) 2706 ins.data = packet.Packet.from_jsondict(data['Packet']) 2707 dict_['data'] = data 2708 else: 2709 ins = super(OFPPacketOut, cls).from_jsondict(dict_, 2710 decode_string, 2711 **additional_args) 2712 2713 return ins 2714 2715 2716@_register_parser 2717@_set_msg_type(ofproto.OFPT_FLOW_MOD) 2718class OFPFlowMod(MsgBase): 2719 """ 2720 Modify Flow entry message 2721 2722 The controller sends this message to modify the flow table. 2723 2724 ================ ====================================================== 2725 Attribute Description 2726 ================ ====================================================== 2727 match Instance of ``OFPMatch``. 2728 cookie Opaque controller-issued identifier. 2729 command One of the following values. 2730 2731 | OFPFC_ADD 2732 | OFPFC_MODIFY 2733 | OFPFC_MODIFY_STRICT 2734 | OFPFC_DELETE 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. 2746 2747 | OFPFF_SEND_FLOW_REM 2748 | OFPFF_CHECK_OVERLAP 2749 | OFPFF_EMERG 2750 actions List of ``OFPAction*`` instance. 2751 ================ ====================================================== 2752 2753 Example:: 2754 2755 def send_flow_mod(self, datapath): 2756 ofp = datapath.ofproto 2757 ofp_parser = datapath.ofproto_parser 2758 2759 match = ofp_parser.OFPMatch(in_port=1) 2760 cookie = 0 2761 command = ofp.OFPFC_ADD 2762 idle_timeout = hard_timeout = 0 2763 priority = 32768 2764 buffer_id = 0xffffffff 2765 out_port = ofproto.OFPP_NONE 2766 flags = 0 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) 2772 """ 2773 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 2789 self.flags = flags 2790 self.actions = [] if actions is None else actions 2791 2792 def _serialize_body(self): 2793 offset = ofproto.OFP_HEADER_SIZE 2794 self.match.serialize(self.buf, offset) 2795 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, 2801 self.flags) 2802 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) 2807 offset += a.len 2808 2809 @classmethod 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 2814 2815 msg.match = OFPMatch.parse(msg.buf, offset) 2816 offset += ofproto.OFP_MATCH_SIZE 2817 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 2823 2824 actions = [] 2825 while offset < msg_len: 2826 a = OFPAction.parser(buf, offset) 2827 actions.append(a) 2828 offset += a.len 2829 msg.actions = actions 2830 2831 return msg 2832 2833 2834@_set_msg_type(ofproto.OFPT_PORT_MOD) 2835class OFPPortMod(MsgBase): 2836 """ 2837 Port modification message 2838 2839 The controller send this message to modify the behavior of the port. 2840 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. 2848 2849 | OFPPC_PORT_DOWN 2850 | OFPPC_NO_STP 2851 | OFPPC_NO_RECV 2852 | OFPPC_NO_RECV_STP 2853 | OFPPC_NO_FLOOD 2854 | OFPPC_NO_FWD 2855 | OFPPC_NO_PACKET_IN 2856 mask Bitmap of configuration flags above to be changed 2857 advertise Bitmap of the following flags. 2858 2859 | OFPPF_10MB_HD 2860 | OFPPF_10MB_FD 2861 | OFPPF_100MB_HD 2862 | OFPPF_100MB_FD 2863 | OFPPF_1GB_HD 2864 | OFPPF_1GB_FD 2865 | OFPPF_10GB_FD 2866 | OFPPF_COPPER 2867 | OFPPF_FIBER 2868 | OFPPF_AUTONEG 2869 | OFPPF_PAUSE 2870 | OFPPF_PAUSE_ASYM 2871 ================ ====================================================== 2872 2873 Example:: 2874 2875 def send_port_mod(self, datapath): 2876 ofp = datapath.ofproto 2877 ofp_parser = datapath.ofproto_parser 2878 2879 port_no = 3 2880 hw_addr = 'fa:c8:e8:76:1d:7e' 2881 config = 0 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, 2889 mask, advertise) 2890 datapath.send_msg(req) 2891 """ 2892 _TYPE = { 2893 'ascii': [ 2894 'hw_addr', 2895 ] 2896 } 2897 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 2904 self.mask = mask 2905 self.advertise = advertise 2906 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) 2912 2913 2914@_set_msg_reply(OFPBarrierReply) 2915@_set_msg_type(ofproto.OFPT_BARRIER_REQUEST) 2916class OFPBarrierRequest(MsgBase): 2917 """ 2918 Barrier request message 2919 2920 The controller sends this message to ensure message dependencies have 2921 been met or receive notifications for completed operations. 2922 2923 Example:: 2924 2925 def send_barrier_request(self, datapath): 2926 ofp_parser = datapath.ofproto_parser 2927 2928 req = ofp_parser.OFPBarrierRequest(datapath) 2929 datapath.send_msg(req) 2930 """ 2931 2932 def __init__(self, datapath): 2933 super(OFPBarrierRequest, self).__init__(datapath) 2934 2935 2936@_set_msg_reply(OFPQueueGetConfigReply) 2937@_set_msg_type(ofproto.OFPT_QUEUE_GET_CONFIG_REQUEST) 2938class OFPQueueGetConfigRequest(MsgBase): 2939 """ 2940 Queue configuration request message 2941 2942 ================ ====================================================== 2943 Attribute Description 2944 ================ ====================================================== 2945 port Port to be queried. Should refer 2946 to a valid physical port (i.e. < OFPP_MAX). 2947 ================ ====================================================== 2948 2949 Example:: 2950 2951 def send_queue_get_config_request(self, datapath): 2952 ofp = datapath.ofproto 2953 ofp_parser = datapath.ofproto_parser 2954 2955 req = ofp_parser.OFPQueueGetConfigRequest(datapath, 2956 ofp.OFPP_NONE) 2957 datapath.send_msg(req) 2958 """ 2959 2960 def __init__(self, datapath, port): 2961 super(OFPQueueGetConfigRequest, self).__init__(datapath) 2962 self.port = port 2963 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) 2967 2968 2969class OFPStatsRequest(MsgBase): 2970 def __init__(self, datapath, flags): 2971 assert flags == 0 # none yet defined 2972 2973 super(OFPStatsRequest, self).__init__(datapath) 2974 self.type = self.__class__.cls_stats_type 2975 self.flags = flags 2976 2977 def _serialize_stats_body(self): 2978 pass 2979 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() 2985 2986 2987@_set_msg_reply(OFPDescStatsReply) 2988@_set_stats_type(ofproto.OFPST_DESC, OFPDescStats) 2989@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 2990class OFPDescStatsRequest(OFPStatsRequest): 2991 """ 2992 Description statistics request message 2993 2994 The controller uses this message to query description of the switch. 2995 2996 ================ ====================================================== 2997 Attribute Description 2998 ================ ====================================================== 2999 flags Zero (none yet defined in the spec). 3000 ================ ====================================================== 3001 3002 Example:: 3003 3004 def send_desc_stats_request(self, datapath): 3005 ofp_parser = datapath.ofproto_parser 3006 3007 req = ofp_parser.OFPDescStatsRequest(datapath) 3008 datapath.send_msg(req) 3009 """ 3010 3011 def __init__(self, datapath, flags): 3012 super(OFPDescStatsRequest, self).__init__(datapath, flags) 3013 3014 3015class OFPFlowStatsRequestBase(OFPStatsRequest): 3016 def __init__(self, datapath, flags, match, table_id, out_port): 3017 super(OFPFlowStatsRequestBase, self).__init__(datapath, flags) 3018 self.match = match 3019 self.table_id = table_id 3020 self.out_port = out_port 3021 3022 def _serialize_stats_body(self): 3023 offset = ofproto.OFP_STATS_MSG_SIZE 3024 self.match.serialize(self.buf, offset) 3025 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) 3029 3030 3031@_set_msg_reply(OFPFlowStatsReply) 3032@_set_stats_type(ofproto.OFPST_FLOW, OFPFlowStats) 3033@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3034class OFPFlowStatsRequest(OFPFlowStatsRequestBase): 3035 """ 3036 Individual flow statistics request message 3037 3038 The controller uses this message to query individual flow statistics. 3039 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 ================ ====================================================== 3051 3052 Example:: 3053 3054 def send_flow_stats_request(self, datapath): 3055 ofp = datapath.ofproto 3056 ofp_parser = datapath.ofproto_parser 3057 3058 match = ofp_parser.OFPMatch(in_port=1) 3059 table_id = 0xff 3060 out_port = ofp.OFPP_NONE 3061 req = ofp_parser.OFPFlowStatsRequest( 3062 datapath, 0, match, table_id, out_port) 3063 3064 datapath.send_msg(req) 3065 """ 3066 3067 def __init__(self, datapath, flags, match, table_id, out_port): 3068 super(OFPFlowStatsRequest, self).__init__( 3069 datapath, flags, match, table_id, out_port) 3070 3071 3072@_set_msg_reply(OFPAggregateStatsReply) 3073@_set_stats_type(ofproto.OFPST_AGGREGATE, OFPAggregateStats) 3074@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3075class OFPAggregateStatsRequest(OFPFlowStatsRequestBase): 3076 """ 3077 Aggregate flow statistics request message 3078 3079 The controller uses this message to query aggregate flow statictics. 3080 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 ================ ====================================================== 3092 3093 Example:: 3094 3095 def send_aggregate_stats_request(self, datapath): 3096 ofp = datapath.ofproto 3097 ofp_parser = datapath.ofproto_parser 3098 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) 3103 3104 datapath.send_msg(req) 3105 """ 3106 3107 def __init__(self, datapath, flags, match, table_id, out_port): 3108 super(OFPAggregateStatsRequest, self).__init__( 3109 datapath, flags, match, table_id, out_port) 3110 3111 3112@_set_msg_reply(OFPTableStatsReply) 3113@_set_stats_type(ofproto.OFPST_TABLE, OFPTableStats) 3114@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3115class OFPTableStatsRequest(OFPStatsRequest): 3116 """ 3117 Table statistics request message 3118 3119 The controller uses this message to query flow table statictics. 3120 3121 ================ ====================================================== 3122 Attribute Description 3123 ================ ====================================================== 3124 flags Zero (none yet defined in the spec). 3125 ================ ====================================================== 3126 3127 Example:: 3128 3129 def send_table_stats_request(self, datapath): 3130 ofp_parser = datapath.ofproto_parser 3131 3132 req = ofp_parser.OFPTableStatsRequest(datapath) 3133 datapath.send_msg(req) 3134 """ 3135 3136 def __init__(self, datapath, flags): 3137 super(OFPTableStatsRequest, self).__init__(datapath, flags) 3138 3139 3140@_set_msg_reply(OFPPortStatsReply) 3141@_set_stats_type(ofproto.OFPST_PORT, OFPPortStats) 3142@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3143class OFPPortStatsRequest(OFPStatsRequest): 3144 """ 3145 Port statistics request message 3146 3147 The controller uses this message to query information about ports 3148 statistics. 3149 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 ================ ====================================================== 3156 3157 Example:: 3158 3159 def send_port_stats_request(self, datapath): 3160 ofp = datapath.ofproto 3161 ofp_parser = datapath.ofproto_parser 3162 3163 req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_ANY) 3164 datapath.send_msg(req) 3165 """ 3166 3167 def __init__(self, datapath, flags, port_no): 3168 super(OFPPortStatsRequest, self).__init__(datapath, flags) 3169 self.port_no = port_no 3170 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) 3174 3175 3176@_set_msg_reply(OFPQueueStatsReply) 3177@_set_stats_type(ofproto.OFPST_QUEUE, OFPQueueStats) 3178@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3179class OFPQueueStatsRequest(OFPStatsRequest): 3180 """ 3181 Queue statistics request message 3182 3183 The controller uses this message to query queue statictics. 3184 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 ================ ====================================================== 3192 3193 Example:: 3194 3195 def send_queue_stats_request(self, datapath): 3196 ofp = datapath.ofproto 3197 ofp_parser = datapath.ofproto_parser 3198 3199 req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPT_ALL, 3200 ofp.OFPQ_ALL) 3201 datapath.send_msg(req) 3202 """ 3203 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 3208 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) 3213 3214 3215@_set_msg_reply(OFPVendorStatsReply) 3216@_set_stats_type(ofproto.OFPST_VENDOR, OFPVendorStats) 3217@_set_msg_type(ofproto.OFPT_STATS_REQUEST) 3218class OFPVendorStatsRequest(OFPStatsRequest): 3219 """ 3220 Vendor statistics request message 3221 3222 The controller uses this message to query vendor-specific information 3223 of a switch. 3224 """ 3225 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 3230 3231 def _serialize_vendor_stats(self): 3232 self.buf += self.specific_data 3233 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, 3237 self.vendor) 3238 self._serialize_vendor_stats() 3239 3240 3241class 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 3246 3247 def _serialize_vendor_stats_body(self): 3248 pass 3249 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, 3253 self.subtype) 3254 self._serialize_vendor_stats_body() 3255 3256 3257class NXFlowStatsRequest(NXStatsRequest): 3258 def __init__(self, datapath, flags, out_port, table_id, rule=None): 3259 super(NXFlowStatsRequest, self).__init__(datapath, flags, 3260 ofproto.NXST_FLOW) 3261 self.out_port = out_port 3262 self.table_id = table_id 3263 self.rule = rule 3264 self.match_len = 0 3265 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) 3272 3273 msg_pack_into( 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) 3277 3278 3279class 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 3285 self.rule = rule 3286 self.match_len = 0 3287 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) 3294 3295 msg_pack_into( 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) 3299 3300 3301nx_actions.generate( 3302 'ryu.ofproto.ofproto_v1_0', 3303 'ryu.ofproto.ofproto_v1_0_parser' 3304) 3305