1# SPDX-License-Identifier: GPL-2.0-only 2# This file is part of Scapy 3# See https://scapy.net/ for more information 4# Copyright (C) Philippe Biondi <phil@secdev.org> 5# Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr> 6 7""" 8OpenFlow v1.3.4 9 10OpenFlow is an open standard used in SDN deployments. 11Specifications can be retrieved from https://www.opennetworking.org/ 12""" 13 14 15# scapy.contrib.description = OpenFlow v1.3 16# scapy.contrib.status = loads 17 18import copy 19import struct 20 21 22from scapy.compat import orb, raw 23from scapy.config import conf 24from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \ 25 FieldLenField, FlagsField, IntEnumField, IntField, IPField, \ 26 LongField, MACField, PacketField, PacketListField, ShortEnumField, \ 27 ShortField, StrFixedLenField, X3BytesField, XBitField, XByteField, \ 28 XIntField, XShortField, PacketLenField 29from scapy.layers.l2 import Ether 30from scapy.packet import Packet, Padding, Raw 31 32from scapy.contrib.openflow import _ofp_header, _ofp_header_item, \ 33 OFPacketField, OpenFlow, _UnknownOpenFlow 34 35##################################################### 36# Predefined values # 37##################################################### 38 39ofp_port_no = {0xfffffff8: "IN_PORT", 40 0xfffffff9: "TABLE", 41 0xfffffffa: "NORMAL", 42 0xfffffffb: "FLOOD", 43 0xfffffffc: "ALL", 44 0xfffffffd: "CONTROLLER", 45 0xfffffffe: "LOCAL", 46 0xffffffff: "ANY"} 47 48ofp_group = {0xffffff00: "MAX", 49 0xfffffffc: "ALL", 50 0xffffffff: "ANY"} 51 52ofp_table = {0xfe: "MAX", 53 0xff: "ALL"} 54 55ofp_queue = {0xffffffff: "ALL"} 56 57ofp_meter = {0xffff0000: "MAX", 58 0xfffffffd: "SLOWPATH", 59 0xfffffffe: "CONTROLLER", 60 0xffffffff: "ALL"} 61 62ofp_buffer = {0xffffffff: "NO_BUFFER"} 63 64ofp_max_len = {0xffff: "NO_BUFFER"} 65 66 67##################################################### 68# Common structures # 69##################################################### 70 71# The following structures will be used in different types 72# of OpenFlow messages: ports, matches/OXMs, actions, 73# instructions, buckets, queues, meter bands. 74 75 76# Hello elements # 77 78 79ofp_hello_elem_types = {1: "OFPHET_VERSIONBITMAP"} 80 81 82class OFPHET(_ofp_header): 83 @classmethod 84 def dispatch_hook(cls, _pkt=None, *args, **kargs): 85 if _pkt and len(_pkt) >= 2: 86 t = struct.unpack("!H", _pkt[:2])[0] 87 return ofp_hello_elem_cls.get(t, Raw) 88 return Raw 89 90 def extract_padding(self, s): 91 return b"", s 92 93 94class OFPHETVersionBitmap(_ofp_header): 95 name = "OFPHET_VERSIONBITMAP" 96 fields_desc = [ShortEnumField("type", 1, ofp_hello_elem_types), 97 ShortField("len", 8), 98 FlagsField("bitmap", 0, 32, ["Type 0", 99 "OFv1.0", 100 "OFv1.1", 101 "OFv1.2", 102 "OFv1.3", 103 "OFv1.4", 104 "OFv1.5"])] 105 106 107ofp_hello_elem_cls = {1: OFPHETVersionBitmap} 108 109 110# Ports # 111 112ofp_port_config = ["PORT_DOWN", 113 "NO_STP", # undefined in v1.3 114 "NO_RECV", 115 "NO_RECV_STP", # undefined in v1.3 116 "NO_FLOOD", # undefined in v1.3 117 "NO_FWD", 118 "NO_PACKET_IN"] 119 120ofp_port_state = ["LINK_DOWN", 121 "BLOCKED", 122 "LIVE"] 123 124ofp_port_features = ["10MB_HD", 125 "10MB_FD", 126 "100MB_HD", 127 "100MB_FD", 128 "1GB_HD", 129 "1GB_FD", 130 "10GB_FD", 131 "40GB_FD", 132 "100GB_FD", 133 "1TB_FD", 134 "OTHER", 135 "COPPER", 136 "FIBER", 137 "AUTONEG", 138 "PAUSE", 139 "PAUSE_ASYM"] 140 141 142class OFPPort(Packet): 143 name = "OFP_PHY_PORT" 144 fields_desc = [IntEnumField("port_no", 0, ofp_port_no), 145 XIntField("pad1", 0), 146 MACField("hw_addr", "0"), 147 XShortField("pad2", 0), 148 StrFixedLenField("port_name", "", 16), 149 FlagsField("config", 0, 32, ofp_port_config), 150 FlagsField("state", 0, 32, ofp_port_state), 151 FlagsField("curr", 0, 32, ofp_port_features), 152 FlagsField("advertised", 0, 32, ofp_port_features), 153 FlagsField("supported", 0, 32, ofp_port_features), 154 FlagsField("peer", 0, 32, ofp_port_features), 155 IntField("curr_speed", 0), 156 IntField("max_speed", 0)] 157 158 def extract_padding(self, s): 159 return b"", s 160 161 162# Matches & OXMs # 163 164ofp_oxm_classes = {0: "OFPXMC_NXM_0", 165 1: "OFPXMC_NXM_1", 166 0x8000: "OFPXMC_OPENFLOW_BASIC", 167 0xffff: "OFPXMC_EXPERIMENTER"} 168 169ofp_oxm_names = {0: "OFB_IN_PORT", 170 1: "OFB_IN_PHY_PORT", 171 2: "OFB_METADATA", 172 3: "OFB_ETH_DST", 173 4: "OFB_ETH_SRC", 174 5: "OFB_ETH_TYPE", 175 6: "OFB_VLAN_VID", 176 7: "OFB_VLAN_PCP", 177 8: "OFB_IP_DSCP", 178 9: "OFB_IP_ECN", 179 10: "OFB_IP_PROTO", 180 11: "OFB_IPV4_SRC", 181 12: "OFB_IPV4_DST", 182 13: "OFB_TCP_SRC", 183 14: "OFB_TCP_DST", 184 15: "OFB_UDP_SRC", 185 16: "OFB_UDP_DST", 186 17: "OFB_SCTP_SRC", 187 18: "OFB_SCTP_DST", 188 19: "OFB_ICMPV4_TYPE", 189 20: "OFB_ICMPV4_CODE", 190 21: "OFB_ARP_OP", 191 22: "OFB_ARP_SPA", 192 23: "OFB_ARP_TPA", 193 24: "OFB_ARP_SHA", 194 25: "OFB_ARP_THA", 195 26: "OFB_IPV6_SRC", 196 27: "OFB_IPV6_DST", 197 28: "OFB_IPV6_FLABEL", 198 29: "OFB_ICMPV6_TYPE", 199 30: "OFB_ICMPV6_CODE", 200 31: "OFB_IPV6_ND_TARGET", 201 32: "OFB_IPV6_ND_SLL", 202 33: "OFB_IPV6_ND_TLL", 203 34: "OFB_MPLS_LABEL", 204 35: "OFB_MPLS_TC", 205 36: "OFB_MPLS_BOS", 206 37: "OFB_PBB_ISID", 207 38: "OFB_TUNNEL_ID", 208 39: "OFB_IPV6_EXTHDR"} 209 210ofp_oxm_constr = {0: ["OFBInPort", "in_port", 4], 211 1: ["OFBInPhyPort", "in_phy_port", 4], 212 2: ["OFBMetadata", "metadata", 8], 213 3: ["OFBEthDst", "eth_dst", 6], 214 4: ["OFBEthSrc", "eth_src", 6], 215 5: ["OFBEthType", "eth_type", 2], 216 6: ["OFBVLANVID", "vlan_vid", 2], 217 7: ["OFBVLANPCP", "vlan_pcp", 1], 218 8: ["OFBIPDSCP", "ip_dscp", 1], 219 9: ["OFBIPECN", "ip_ecn", 1], 220 10: ["OFBIPProto", "ip_proto", 1], 221 11: ["OFBIPv4Src", "ipv4_src", 4], 222 12: ["OFBIPv4Dst", "ipv4_dst", 4], 223 13: ["OFBTCPSrc", "tcp_src", 2], 224 14: ["OFBTCPDst", "tcp_dst", 2], 225 15: ["OFBUDPSrc", "udp_src", 2], 226 16: ["OFBUDPDst", "udp_dst", 2], 227 17: ["OFBSCTPSrc", "sctp_src", 2], 228 18: ["OFBSCTPDst", "sctp_dst", 2], 229 19: ["OFBICMPv4Type", "icmpv4_type", 1], 230 20: ["OFBICMPv4Code", "icmpv4_code", 1], 231 21: ["OFBARPOP", "arp_op", 2], 232 22: ["OFBARPSPA", "arp_spa", 4], 233 23: ["OFBARPTPA", "arp_tpa", 4], 234 24: ["OFBARPSHA", "arp_sha", 6], 235 25: ["OFBARPTHA", "arp_tha", 6], 236 26: ["OFBIPv6Src", "ipv6_src", 16], 237 27: ["OFBIPv6Dst", "ipv6_dst", 16], 238 28: ["OFBIPv6FLabel", "ipv6_flabel", 4], 239 29: ["OFBICMPv6Type", "icmpv6_type", 1], 240 30: ["OFBICMPv6Code", "icmpv6_code", 1], 241 31: ["OFBIPv6NDTarget", "ipv6_nd_target", 16], 242 32: ["OFBIPv6NDSLL", "ipv6_sll", 6], 243 33: ["OFBIPv6NDTLL", "ipv6_tll", 6], 244 34: ["OFBMPLSLabel", "mpls_label", 4], 245 35: ["OFBMPLSTC", "mpls_tc", 1], 246 36: ["OFBMPLSBoS", "mpls_bos", 1], 247 37: ["OFBPBBISID", "pbb_isid", 3], 248 38: ["OFBTunnelID", "tunnel_id", 8], 249 39: ["OFBIPv6ExtHdr", "ipv6_ext_hdr_flags", 2]} 250 251# the ipv6flags array is useful only to the OFBIPv6ExtHdr class 252ipv6flags = ["NONEXT", 253 "ESP", 254 "AUTH", 255 "DEST", 256 "FRAG", 257 "ROUTER", 258 "HOP", 259 "UNREP", 260 "UNSEQ"] 261 262# here we fill ofp_oxm_fields with the fields that will be used 263# to generate the various OXM classes 264# e.g. the call to add_ofp_oxm_fields(0, ["OFBInPort", "in_port", 4]) 265# will add {0: [ShortEnumField("class",..), BitEnumField("field",..),..]} 266ofp_oxm_fields = {} 267 268 269def add_ofp_oxm_fields(i, org): 270 ofp_oxm_fields[i] = [ShortEnumField("class_", "OFPXMC_OPENFLOW_BASIC", ofp_oxm_classes), # noqa: E501 271 BitEnumField("field", i // 2, 7, ofp_oxm_names), 272 BitField("hasmask", i % 2, 1)] 273 ofp_oxm_fields[i].append(ByteField("len", org[2] + org[2] * (i % 2))) 274 if i // 2 == 0: # OFBInPort 275 ofp_oxm_fields[i].append(IntEnumField(org[1], 0, ofp_port_no)) 276 elif i // 2 == 3 or i // 2 == 4: # OFBEthSrc & OFBEthDst 277 ofp_oxm_fields[i].append(MACField(org[1], None)) 278 elif i // 2 == 11 or i // 2 == 12: # OFBIPv4Src & OFBIPv4Dst 279 ofp_oxm_fields[i].append(IPField(org[1], "0")) 280 elif i // 2 == 39: # OFBIPv6ExtHdr 281 ofp_oxm_fields[i].append(FlagsField(org[1], 0, 8 * org[2], ipv6flags)) 282 else: 283 ofp_oxm_fields[i].append(BitField(org[1], 0, 8 * org[2])) 284 if i % 2: 285 ofp_oxm_fields[i].append(BitField(org[1] + "_mask", 0, 8 * org[2])) 286 287 288# some HM classes are not supported par OFv1.3 but we will create them anyway 289for i, cls in ofp_oxm_constr.items(): 290 add_ofp_oxm_fields(2 * i, cls) 291 add_ofp_oxm_fields(2 * i + 1, cls) 292 293# now we create every OXM class with the same call, 294# (except that static variable create_oxm_class.i is each time different) 295# and we fill ofp_oxm_cls with them 296ofp_oxm_cls = {} 297ofp_oxm_id_cls = {} 298 299 300def _create_oxm_cls(): 301 # static variable initialization 302 if not hasattr(_create_oxm_cls, "i"): 303 _create_oxm_cls.i = 0 304 305 index = _create_oxm_cls.i 306 cls_name = ofp_oxm_constr[index // 4][0] 307 # we create standard OXM then OXM ID then OXM with mask then OXM-hasmask ID 308 if index % 4 == 2: 309 cls_name += "HM" 310 if index % 2: 311 cls_name += "ID" 312 313 oxm_name = ofp_oxm_names[index // 4] 314 oxm_fields = ofp_oxm_fields[index // 2] 315 # for ID classes we just want the first 4 fields (no payload) 316 if index % 2: 317 oxm_fields = oxm_fields[:4] 318 319 cls = type(cls_name, (Packet,), {"name": oxm_name, "fields_desc": oxm_fields}) # noqa: E501 320 # the first call to special function type will create the same class as in 321 # class OFBInPort(Packet): 322 # def __init__(self): 323 # self.name = "OFB_IN_PORT" 324 # self.fields_desc = [ ShortEnumField("class", 0x8000, ofp_oxm_classes), 325 # BitEnumField("field", 0, 7, ofp_oxm_names), 326 # BitField("hasmask", 0, 1), 327 # ByteField("len", 4), 328 # IntEnumField("in_port", 0, ofp_port_no) ] 329 330 if index % 2 == 0: 331 ofp_oxm_cls[index // 2] = cls 332 else: 333 ofp_oxm_id_cls[index // 2] = cls 334 _create_oxm_cls.i += 1 335 cls.extract_padding = lambda self, s: (b"", s) 336 return cls 337 338 339OFBInPort = _create_oxm_cls() 340OFBInPortID = _create_oxm_cls() 341OFBInPortHM = _create_oxm_cls() 342OFBInPortHMID = _create_oxm_cls() 343OFBInPhyPort = _create_oxm_cls() 344OFBInPhyPortID = _create_oxm_cls() 345OFBInPhyPortHM = _create_oxm_cls() 346OFBInPhyPortHMID = _create_oxm_cls() 347OFBMetadata = _create_oxm_cls() 348OFBMetadataID = _create_oxm_cls() 349OFBMetadataHM = _create_oxm_cls() 350OFBMetadataHMID = _create_oxm_cls() 351OFBEthDst = _create_oxm_cls() 352OFBEthDstID = _create_oxm_cls() 353OFBEthDstHM = _create_oxm_cls() 354OFBEthDstHMID = _create_oxm_cls() 355OFBEthSrc = _create_oxm_cls() 356OFBEthSrcID = _create_oxm_cls() 357OFBEthSrcHM = _create_oxm_cls() 358OFBEthSrcHMID = _create_oxm_cls() 359OFBEthType = _create_oxm_cls() 360OFBEthTypeID = _create_oxm_cls() 361OFBEthTypeHM = _create_oxm_cls() 362OFBEthTypeHMID = _create_oxm_cls() 363OFBVLANVID = _create_oxm_cls() 364OFBVLANVIDID = _create_oxm_cls() 365OFBVLANVIDHM = _create_oxm_cls() 366OFBVLANVIDHMID = _create_oxm_cls() 367OFBVLANPCP = _create_oxm_cls() 368OFBVLANPCPID = _create_oxm_cls() 369OFBVLANPCPHM = _create_oxm_cls() 370OFBVLANPCPHMID = _create_oxm_cls() 371OFBIPDSCP = _create_oxm_cls() 372OFBIPDSCPID = _create_oxm_cls() 373OFBIPDSCPHM = _create_oxm_cls() 374OFBIPDSCPHMID = _create_oxm_cls() 375OFBIPECN = _create_oxm_cls() 376OFBIPECNID = _create_oxm_cls() 377OFBIPECNHM = _create_oxm_cls() 378OFBIPECNHMID = _create_oxm_cls() 379OFBIPProto = _create_oxm_cls() 380OFBIPProtoID = _create_oxm_cls() 381OFBIPProtoHM = _create_oxm_cls() 382OFBIPProtoHMID = _create_oxm_cls() 383OFBIPv4Src = _create_oxm_cls() 384OFBIPv4SrcID = _create_oxm_cls() 385OFBIPv4SrcHM = _create_oxm_cls() 386OFBIPv4SrcHMID = _create_oxm_cls() 387OFBIPv4Dst = _create_oxm_cls() 388OFBIPv4DstID = _create_oxm_cls() 389OFBIPv4DstHM = _create_oxm_cls() 390OFBIPv4DstHMID = _create_oxm_cls() 391OFBTCPSrc = _create_oxm_cls() 392OFBTCPSrcID = _create_oxm_cls() 393OFBTCPSrcHM = _create_oxm_cls() 394OFBTCPSrcHMID = _create_oxm_cls() 395OFBTCPDst = _create_oxm_cls() 396OFBTCPDstID = _create_oxm_cls() 397OFBTCPDstHM = _create_oxm_cls() 398OFBTCPDstHMID = _create_oxm_cls() 399OFBUDPSrc = _create_oxm_cls() 400OFBUDPSrcID = _create_oxm_cls() 401OFBUDPSrcHM = _create_oxm_cls() 402OFBUDPSrcHMID = _create_oxm_cls() 403OFBUDPDst = _create_oxm_cls() 404OFBUDPDstID = _create_oxm_cls() 405OFBUDPDstHM = _create_oxm_cls() 406OFBUDPDstHMID = _create_oxm_cls() 407OFBSCTPSrc = _create_oxm_cls() 408OFBSCTPSrcID = _create_oxm_cls() 409OFBSCTPSrcHM = _create_oxm_cls() 410OFBSCTPSrcHMID = _create_oxm_cls() 411OFBSCTPDst = _create_oxm_cls() 412OFBSCTPDstID = _create_oxm_cls() 413OFBSCTPDstHM = _create_oxm_cls() 414OFBSCTPDstHMID = _create_oxm_cls() 415OFBICMPv4Type = _create_oxm_cls() 416OFBICMPv4TypeID = _create_oxm_cls() 417OFBICMPv4TypeHM = _create_oxm_cls() 418OFBICMPv4TypeHMID = _create_oxm_cls() 419OFBICMPv4Code = _create_oxm_cls() 420OFBICMPv4CodeID = _create_oxm_cls() 421OFBICMPv4CodeHM = _create_oxm_cls() 422OFBICMPv4CodeHMID = _create_oxm_cls() 423OFBARPOP = _create_oxm_cls() 424OFBARPOPID = _create_oxm_cls() 425OFBARPOPHM = _create_oxm_cls() 426OFBARPOPHMID = _create_oxm_cls() 427OFBARPSPA = _create_oxm_cls() 428OFBARPSPAID = _create_oxm_cls() 429OFBARPSPAHM = _create_oxm_cls() 430OFBARPSPAHMID = _create_oxm_cls() 431OFBARPTPA = _create_oxm_cls() 432OFBARPTPAID = _create_oxm_cls() 433OFBARPTPAHM = _create_oxm_cls() 434OFBARPTPAHMID = _create_oxm_cls() 435OFBARPSHA = _create_oxm_cls() 436OFBARPSHAID = _create_oxm_cls() 437OFBARPSHAHM = _create_oxm_cls() 438OFBARPSHAHMID = _create_oxm_cls() 439OFBARPTHA = _create_oxm_cls() 440OFBARPTHAID = _create_oxm_cls() 441OFBARPTHAHM = _create_oxm_cls() 442OFBARPTHAHMID = _create_oxm_cls() 443OFBIPv6Src = _create_oxm_cls() 444OFBIPv6SrcID = _create_oxm_cls() 445OFBIPv6SrcHM = _create_oxm_cls() 446OFBIPv6SrcHMID = _create_oxm_cls() 447OFBIPv6Dst = _create_oxm_cls() 448OFBIPv6DstID = _create_oxm_cls() 449OFBIPv6DstHM = _create_oxm_cls() 450OFBIPv6DstHMID = _create_oxm_cls() 451OFBIPv6FLabel = _create_oxm_cls() 452OFBIPv6FLabelID = _create_oxm_cls() 453OFBIPv6FLabelHM = _create_oxm_cls() 454OFBIPv6FLabelHMID = _create_oxm_cls() 455OFBICMPv6Type = _create_oxm_cls() 456OFBICMPv6TypeID = _create_oxm_cls() 457OFBICMPv6TypeHM = _create_oxm_cls() 458OFBICMPv6TypeHMID = _create_oxm_cls() 459OFBICMPv6Code = _create_oxm_cls() 460OFBICMPv6CodeID = _create_oxm_cls() 461OFBICMPv6CodeHM = _create_oxm_cls() 462OFBICMPv6CodeHMID = _create_oxm_cls() 463OFBIPv6NDTarget = _create_oxm_cls() 464OFBIPv6NDTargetID = _create_oxm_cls() 465OFBIPv6NDTargetHM = _create_oxm_cls() 466OFBIPv6NDTargetHMID = _create_oxm_cls() 467OFBIPv6NDSLL = _create_oxm_cls() 468OFBIPv6NDSLLID = _create_oxm_cls() 469OFBIPv6NDSLLHM = _create_oxm_cls() 470OFBIPv6NDSLLHMID = _create_oxm_cls() 471OFBIPv6NDTLL = _create_oxm_cls() 472OFBIPv6NDTLLID = _create_oxm_cls() 473OFBIPv6NDTLLHM = _create_oxm_cls() 474OFBIPv6NDTLLHMID = _create_oxm_cls() 475OFBMPLSLabel = _create_oxm_cls() 476OFBMPLSLabelID = _create_oxm_cls() 477OFBMPLSLabelHM = _create_oxm_cls() 478OFBMPLSLabelHMID = _create_oxm_cls() 479OFBMPLSTC = _create_oxm_cls() 480OFBMPLSTCID = _create_oxm_cls() 481OFBMPLSTCHM = _create_oxm_cls() 482OFBMPLSTCHMID = _create_oxm_cls() 483OFBMPLSBoS = _create_oxm_cls() 484OFBMPLSBoSID = _create_oxm_cls() 485OFBMPLSBoSHM = _create_oxm_cls() 486OFBMPLSBoSHMID = _create_oxm_cls() 487OFBPBBISID = _create_oxm_cls() 488OFBPBBISIDID = _create_oxm_cls() 489OFBPBBISIDHM = _create_oxm_cls() 490OFBPBBISIDHMID = _create_oxm_cls() 491OFBTunnelID = _create_oxm_cls() 492OFBTunnelIDID = _create_oxm_cls() 493OFBTunnelIDHM = _create_oxm_cls() 494OFBTunnelIDHMID = _create_oxm_cls() 495OFBIPv6ExtHdr = _create_oxm_cls() 496OFBIPv6ExtHdrID = _create_oxm_cls() 497OFBIPv6ExtHdrHM = _create_oxm_cls() 498OFBIPv6ExtHdrHMID = _create_oxm_cls() 499 500# need_prereq holds a list of prerequisites defined in 7.2.3.8 of the specifications # noqa: E501 501# e.g. if you want to use an OFBTCPSrc instance (code 26) 502# you first need to declare an OFBIPProto instance (code 20) with value 6, 503# and if you want to use an OFBIPProto instance (still code 20) 504# you first need to declare an OFBEthType instance (code 10) with value 0x0800 505# (0x0800 means IPv4 by default, but you might want to use 0x86dd with IPv6) 506# need_prereq codes are two times higher than previous oxm classes codes, 507# except for 21 which is sort of a proxy for IPv6 (see below) 508need_prereq = {14: [12, 0x1000], 509 16: [10, 0x0800], # could be 0x86dd 510 18: [10, 0x0800], # could be 0x86dd 511 20: [10, 0x0800], # could be 0x86dd 512 21: [10, 0x86dd], 513 22: [10, 0x0800], 514 24: [10, 0x0800], 515 26: [20, 6], 516 28: [20, 6], 517 30: [20, 17], 518 32: [20, 17], 519 34: [20, 132], 520 36: [20, 132], 521 38: [20, 1], 522 40: [20, 1], 523 42: [10, 0x0806], 524 44: [10, 0x0806], 525 46: [10, 0x0806], 526 48: [10, 0x0806], 527 50: [10, 0x0806], 528 52: [10, 0x86dd], 529 54: [10, 0x86dd], 530 56: [10, 0x86dd], 531 58: [21, 58], # small trick here, we refer to normally non- 532 60: [21, 58], # existent field 21 to distinguish ipv6 533 62: [58, 135], # could be 136 534 64: [58, 135], 535 66: [58, 136], 536 68: [10, 0x8847], # could be 0x8848 537 70: [10, 0x8847], # could be 0x8848 538 72: [10, 0x8847], # could be 0x8848 539 74: [10, 0x88e7], 540 78: [10, 0x86dd]} 541 542 543class OXMPacketListField(PacketListField): 544 545 __slots__ = ["autocomplete", "index"] 546 547 def __init__(self, name, default, cls, length_from=None, autocomplete=False): # noqa: E501 548 PacketListField.__init__(self, name, default, cls, length_from=length_from) # noqa: E501 549 self.autocomplete = autocomplete 550 self.index = [] 551 552 def i2m(self, pkt, val): 553 # this part makes for a faster writing of specs-compliant matches 554 # expect some unwanted behaviour if you try incoherent associations 555 # you might want to set autocomplete=False in __init__ method 556 if self.autocomplete or conf.contribs['OPENFLOW']['prereq_autocomplete']: # noqa: E501 557 # val might be modified during the loop so we need a fixed copy 558 fix_val = copy.deepcopy(val) 559 for oxm in fix_val: 560 f = 2 * oxm.field 561 fix_index = list(self.index) 562 while f in need_prereq: 563 # this loop enables a small recursion 564 # e.g. ipv6_nd<--icmpv6<--ip_proto<--eth_type 565 prereq = need_prereq[f] 566 f = prereq[0] 567 f2 = 20 if f == 21 else f # ipv6 trick... 568 if f2 not in fix_index: 569 self.index.insert(0, f2) 570 prrq = ofp_oxm_cls[f2]() # never HM 571 setattr(prrq, ofp_oxm_constr[f2 // 2][1], prereq[1]) 572 val.insert(0, prrq) 573 # we could do more complicated stuff to 574 # make sure prerequisite order is correct 575 # but it works well when presented with any coherent input 576 # e.g. you should not mix OFBTCPSrc with OFBICMPv6Code 577 # and expect to get coherent results... 578 # you can still go manual by setting prereq_autocomplete=False # noqa: E501 579 return val 580 581 def m2i(self, pkt, s): 582 t = orb(s[2]) 583 nrm_t = t - t % 2 584 if nrm_t not in self.index: 585 self.index.append(nrm_t) 586 return ofp_oxm_cls.get(t, Raw)(s) 587 588 @staticmethod 589 def _get_oxm_length(s): 590 return orb(s[3]) 591 592 def addfield(self, pkt, s, val): 593 return s + b"".join(raw(x) for x in self.i2m(pkt, val)) 594 595 def getfield(self, pkt, s): 596 lst = [] 597 lim = self.length_from(pkt) 598 ret = s[lim:] 599 remain = s[:lim] 600 601 while remain and len(remain) > 4: 602 tmp_len = OXMPacketListField._get_oxm_length(remain) + 4 603 # this could also be done by parsing oxm_fields (fixed lengths) 604 if tmp_len <= 4 or len(remain) < tmp_len: 605 # no incoherent length 606 break 607 current = remain[:tmp_len] 608 remain = remain[tmp_len:] 609 p = self.m2i(pkt, current) 610 lst.append(p) 611 612 self.index = [] 613 # since OXMPacketListField is called only twice (when OFPMatch and OFPSetField # noqa: E501 614 # classes are created) and not when you want to instantiate an OFPMatch, # noqa: E501 615 # index needs to be reinitialized, otherwise there will be some conflicts # noqa: E501 616 # e.g. if you create OFPMatch with OFBTCPSrc and then change to OFBTCPDst, # noqa: E501 617 # index will already be filled with ethertype and nwproto codes, 618 # thus the corresponding fields will not be added to the packet 619 return remain + ret, lst 620 621 622class OXMID(Packet): 623 @classmethod 624 def dispatch_hook(cls, _pkt=None, *args, **kargs): 625 if _pkt and len(_pkt) >= 2: 626 t = orb(_pkt[2]) 627 return ofp_oxm_id_cls.get(t, Raw) 628 return Raw 629 630 def extract_padding(self, s): 631 return b"", s 632 633 634class OFPMatch(Packet): 635 name = "OFP_MATCH" 636 fields_desc = [ShortEnumField("type", 1, {0: "OFPMT_STANDARD", 637 1: "OFPMT_OXM"}), 638 ShortField("len", None), 639 OXMPacketListField("oxm_fields", [], Packet, 640 length_from=lambda pkt:pkt.len - 4)] 641 642 def post_build(self, p, pay): 643 tmp_len = self.len 644 if tmp_len is None: 645 tmp_len = len(p) + len(pay) 646 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] 647 zero_bytes = (8 - tmp_len % 8) % 8 648 p += b"\x00" * zero_bytes 649 # message with user-defined length will not be automatically padded 650 return p + pay 651 652 def extract_padding(self, s): 653 tmp_len = self.len 654 zero_bytes = (8 - tmp_len % 8) % 8 655 return s[zero_bytes:], s[:zero_bytes] 656 657# ofp_match is no longer a fixed-length structure in v1.3 658# furthermore it may include variable padding 659# we introduce to that end a subclass of PacketField 660 661 662class MatchField(PacketField): 663 def __init__(self, name): 664 PacketField.__init__(self, name, OFPMatch(), OFPMatch) 665 666 def getfield(self, pkt, s): 667 i = self.m2i(pkt, s) 668 # i can be <OFPMatch> or <OFPMatch <Padding>> 669 # or <OFPMatch <Raw>> or <OFPMatch <Raw <Padding>>> 670 # and we want to return "", <OFPMatch> or "", <OFPMatch <Padding>> 671 # or raw(<Raw>), <OFPMatch> or raw(<Raw>), <OFPMatch <Padding>> 672 if Raw in i: 673 r = i[Raw] 674 if Padding in r: 675 p = r[Padding] 676 i.payload = p 677 del r.payload 678 return r.load, i 679 else: 680 return b"", i 681 682 683# Actions # 684 685 686class OpenFlow3(OpenFlow): 687 name = "OpenFlow v1.3 dissector" 688 689 @classmethod 690 def dispatch_hook(cls, _pkt=None, *args, **kargs): 691 if _pkt and len(_pkt) >= 2: 692 # port 6653 has been allocated by IANA, port 6633 should no 693 # longer be used 694 # OpenFlow3 function may be called with None self in OFPPacketField 695 of_type = orb(_pkt[1]) 696 if of_type == 1: 697 err_type = orb(_pkt[9]) 698 # err_type is a short int, but last byte is enough 699 if err_type == 255: 700 err_type = 65535 701 return ofp_error_cls[err_type] 702 elif of_type == 18: 703 mp_type = orb(_pkt[9]) 704 if mp_type == 255: 705 mp_type = 65535 706 return ofp_multipart_request_cls[mp_type] 707 elif of_type == 19: 708 mp_type = orb(_pkt[9]) 709 if mp_type == 255: 710 mp_type = 65535 711 return ofp_multipart_reply_cls[mp_type] 712 else: 713 return ofpt_cls[of_type] 714 return _UnknownOpenFlow 715 716 717ofp_action_types = {0: "OFPAT_OUTPUT", 718 1: "OFPAT_SET_VLAN_VID", 719 2: "OFPAT_SET_VLAN_PCP", 720 3: "OFPAT_STRIP_VLAN", 721 4: "OFPAT_SET_DL_SRC", 722 5: "OFPAT_SET_DL_DST", 723 6: "OFPAT_SET_NW_SRC", 724 7: "OFPAT_SET_NW_DST", 725 8: "OFPAT_SET_NW_TOS", 726 9: "OFPAT_SET_TP_SRC", 727 10: "OFPAT_SET_TP_DST", 728 # 11: "OFPAT_ENQUEUE", 729 11: "OFPAT_COPY_TTL_OUT", 730 12: "OFPAT_COPY_TTL_IN", 731 13: "OFPAT_SET_MPLS_LABEL", 732 14: "OFPAT_DEC_MPLS_TC", 733 15: "OFPAT_SET_MPLS_TTL", 734 16: "OFPAT_DEC_MPLS_TTL", 735 17: "OFPAT_PUSH_VLAN", 736 18: "OFPAT_POP_VLAN", 737 19: "OFPAT_PUSH_MPLS", 738 20: "OFPAT_POP_MPLS", 739 21: "OFPAT_SET_QUEUE", 740 22: "OFPAT_GROUP", 741 23: "OFPAT_SET_NW_TTL", 742 24: "OFPAT_DEC_NW_TTL", 743 25: "OFPAT_SET_FIELD", 744 26: "OFPAT_PUSH_PBB", 745 27: "OFPAT_POP_PBB", 746 65535: "OFPAT_EXPERIMENTER"} 747 748 749class OFPAT(_ofp_header): 750 @classmethod 751 def dispatch_hook(cls, _pkt=None, *args, **kargs): 752 if _pkt and len(_pkt) >= 2: 753 t = struct.unpack("!H", _pkt[:2])[0] 754 return ofp_action_cls.get(t, Raw) 755 return Raw 756 757 def extract_padding(self, s): 758 return b"", s 759 760 761class OFPATOutput(OFPAT): 762 name = "OFPAT_OUTPUT" 763 fields_desc = [ShortEnumField("type", 0, ofp_action_types), 764 ShortField("len", 16), 765 IntEnumField("port", 0, ofp_port_no), 766 ShortEnumField("max_len", "NO_BUFFER", ofp_max_len), 767 XBitField("pad", 0, 48)] 768 769 770# the following actions are not supported by OFv1.3 771 772 773class OFPATSetVLANVID(OFPAT): 774 name = "OFPAT_SET_VLAN_VID" 775 fields_desc = [ShortEnumField("type", 1, ofp_action_types), 776 ShortField("len", 8), 777 ShortField("vlan_vid", 0), 778 XShortField("pad", 0)] 779 780 781class OFPATSetVLANPCP(OFPAT): 782 name = "OFPAT_SET_VLAN_PCP" 783 fields_desc = [ShortEnumField("type", 2, ofp_action_types), 784 ShortField("len", 8), 785 ByteField("vlan_pcp", 0), 786 X3BytesField("pad", 0)] 787 788 789class OFPATStripVLAN(OFPAT): 790 name = "OFPAT_STRIP_VLAN" 791 fields_desc = [ShortEnumField("type", 3, ofp_action_types), 792 ShortField("len", 8), 793 XIntField("pad", 0)] 794 795 796class OFPATSetDlSrc(OFPAT): 797 name = "OFPAT_SET_DL_SRC" 798 fields_desc = [ShortEnumField("type", 4, ofp_action_types), 799 ShortField("len", 16), 800 MACField("dl_addr", "0"), 801 XBitField("pad", 0, 48)] 802 803 804class OFPATSetDlDst(OFPAT): 805 name = "OFPAT_SET_DL_DST" 806 fields_desc = [ShortEnumField("type", 5, ofp_action_types), 807 ShortField("len", 16), 808 MACField("dl_addr", "0"), 809 XBitField("pad", 0, 48)] 810 811 812class OFPATSetNwSrc(OFPAT): 813 name = "OFPAT_SET_NW_SRC" 814 fields_desc = [ShortEnumField("type", 6, ofp_action_types), 815 ShortField("len", 8), 816 IPField("nw_addr", "0")] 817 818 819class OFPATSetNwDst(OFPAT): 820 name = "OFPAT_SET_NW_DST" 821 fields_desc = [ShortEnumField("type", 7, ofp_action_types), 822 ShortField("len", 8), 823 IPField("nw_addr", "0")] 824 825 826class OFPATSetNwToS(OFPAT): 827 name = "OFPAT_SET_TP_TOS" 828 fields_desc = [ShortEnumField("type", 8, ofp_action_types), 829 ShortField("len", 8), 830 ByteField("nw_tos", 0), 831 X3BytesField("pad", 0)] 832 833 834class OFPATSetTpSrc(OFPAT): 835 name = "OFPAT_SET_TP_SRC" 836 fields_desc = [ShortEnumField("type", 9, ofp_action_types), 837 ShortField("len", 8), 838 ShortField("tp_port", 0), 839 XShortField("pad", 0)] 840 841 842class OFPATSetTpDst(OFPAT): 843 name = "OFPAT_SET_TP_DST" 844 fields_desc = [ShortEnumField("type", 10, ofp_action_types), 845 ShortField("len", 8), 846 ShortField("tp_port", 0), 847 XShortField("pad", 0)] 848 849# class OFPATEnqueue(OFPAT): 850# name = "OFPAT_ENQUEUE" 851# fields_desc = [ ShortEnumField("type", 11, ofp_action_types), 852# ShortField("len", 16), 853# ShortField("port", 0), 854# XBitField("pad", 0, 48), 855# IntEnumField("queue_id", 0, ofp_queue) ] 856 857 858class OFPATSetMPLSLabel(OFPAT): 859 name = "OFPAT_SET_MPLS_LABEL" 860 fields_desc = [ShortEnumField("type", 13, ofp_action_types), 861 ShortField("len", 8), 862 IntField("mpls_label", 0)] 863 864 865class OFPATSetMPLSTC(OFPAT): 866 name = "OFPAT_SET_MPLS_TC" 867 fields_desc = [ShortEnumField("type", 14, ofp_action_types), 868 ShortField("len", 8), 869 ByteField("mpls_tc", 0), 870 X3BytesField("pad", 0)] 871 872# end of unsupported actions 873 874 875class OFPATCopyTTLOut(OFPAT): 876 name = "OFPAT_COPY_TTL_OUT" 877 fields_desc = [ShortEnumField("type", 11, ofp_action_types), 878 ShortField("len", 8), 879 XIntField("pad", 0)] 880 881 882class OFPATCopyTTLIn(OFPAT): 883 name = "OFPAT_COPY_TTL_IN" 884 fields_desc = [ShortEnumField("type", 12, ofp_action_types), 885 ShortField("len", 8), 886 XIntField("pad", 0)] 887 888 889class OFPATSetMPLSTTL(OFPAT): 890 name = "OFPAT_SET_MPLS_TTL" 891 fields_desc = [ShortEnumField("type", 15, ofp_action_types), 892 ShortField("len", 8), 893 ByteField("mpls_ttl", 0), 894 X3BytesField("pad", 0)] 895 896 897class OFPATDecMPLSTTL(OFPAT): 898 name = "OFPAT_DEC_MPLS_TTL" 899 fields_desc = [ShortEnumField("type", 16, ofp_action_types), 900 ShortField("len", 8), 901 XIntField("pad", 0)] 902 903 904class OFPATPushVLAN(OFPAT): 905 name = "OFPAT_PUSH_VLAN" 906 fields_desc = [ShortEnumField("type", 17, ofp_action_types), 907 ShortField("len", 8), 908 ShortField("ethertype", 0x8100), # or 0x88a8 909 XShortField("pad", 0)] 910 911 912class OFPATPopVLAN(OFPAT): 913 name = "OFPAT_POP_VLAN" 914 fields_desc = [ShortEnumField("type", 18, ofp_action_types), 915 ShortField("len", 8), 916 XIntField("pad", 0)] 917 918 919class OFPATPushMPLS(OFPAT): 920 name = "OFPAT_PUSH_MPLS" 921 fields_desc = [ShortEnumField("type", 19, ofp_action_types), 922 ShortField("len", 8), 923 ShortField("ethertype", 0x8847), # or 0x8848 924 XShortField("pad", 0)] 925 926 927class OFPATPopMPLS(OFPAT): 928 name = "OFPAT_POP_MPLS" 929 fields_desc = [ShortEnumField("type", 20, ofp_action_types), 930 ShortField("len", 8), 931 ShortField("ethertype", 0x8847), # or 0x8848 932 XShortField("pad", 0)] 933 934 935class OFPATSetQueue(OFPAT): 936 name = "OFPAT_SET_QUEUE" 937 fields_desc = [ShortEnumField("type", 21, ofp_action_types), 938 ShortField("len", 8), 939 IntEnumField("queue_id", 0, ofp_queue)] 940 941 942class OFPATGroup(OFPAT): 943 name = "OFPAT_GROUP" 944 fields_desc = [ShortEnumField("type", 22, ofp_action_types), 945 ShortField("len", 8), 946 IntEnumField("group_id", 0, ofp_group)] 947 948 949class OFPATSetNwTTL(OFPAT): 950 name = "OFPAT_SET_NW_TTL" 951 fields_desc = [ShortEnumField("type", 23, ofp_action_types), 952 ShortField("len", 8), 953 ByteField("nw_ttl", 0), 954 X3BytesField("pad", 0)] 955 956 957class OFPATDecNwTTL(OFPAT): 958 name = "OFPAT_DEC_NW_TTL" 959 fields_desc = [ShortEnumField("type", 24, ofp_action_types), 960 ShortField("len", 8), 961 XIntField("pad", 0)] 962 963 964class OFPATSetField(OFPAT): 965 name = "OFPAT_SET_FIELD" 966 fields_desc = [ShortEnumField("type", 25, ofp_action_types), 967 ShortField("len", None), 968 # there should not be more than one oxm tlv 969 OXMPacketListField("field", [], Packet, 970 length_from=lambda pkt:pkt.len - 4, 971 # /!\ contains padding! 972 autocomplete=False)] 973 974 def post_build(self, p, pay): 975 tmp_len = self.len 976 zero_bytes = 0 977 if tmp_len is None: 978 tmp_len = len(p) + len(pay) 979 zero_bytes = (8 - tmp_len % 8) % 8 980 tmp_len = tmp_len + zero_bytes # add padding length 981 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] 982 p += b"\x00" * zero_bytes 983 # message with user-defined length will not be automatically padded 984 return p + pay 985 986 def extract_padding(self, s): 987 return b"", s 988 989 990class OFPATPushPBB(OFPAT): 991 name = "OFPAT_PUSH_PBB" 992 fields_desc = [ShortEnumField("type", 26, ofp_action_types), 993 ShortField("len", 8), 994 ShortField("ethertype", 0x88e7), 995 XShortField("pad", 0)] 996 997 998class OFPATPopPBB(OFPAT): 999 name = "OFPAT_POP_PBB" 1000 fields_desc = [ShortEnumField("type", 27, ofp_action_types), 1001 ShortField("len", 8), 1002 XIntField("pad", 0)] 1003 1004 1005class OFPATExperimenter(OFPAT): 1006 name = "OFPAT_EXPERIMENTER" 1007 fields_desc = [ShortEnumField("type", 65535, ofp_action_types), 1008 ShortField("len", 8), 1009 IntField("experimenter", 0)] 1010 1011 1012ofp_action_cls = {0: OFPATOutput, 1013 1: OFPATSetVLANVID, 1014 2: OFPATSetVLANPCP, 1015 3: OFPATStripVLAN, 1016 4: OFPATSetDlSrc, 1017 5: OFPATSetDlDst, 1018 6: OFPATSetNwSrc, 1019 7: OFPATSetNwDst, 1020 8: OFPATSetNwToS, 1021 9: OFPATSetTpSrc, 1022 10: OFPATSetTpDst, 1023 # 11: OFPATEnqueue, 1024 11: OFPATCopyTTLOut, 1025 12: OFPATCopyTTLIn, 1026 13: OFPATSetMPLSLabel, 1027 14: OFPATSetMPLSTC, 1028 15: OFPATSetMPLSTTL, 1029 16: OFPATDecMPLSTTL, 1030 17: OFPATPushVLAN, 1031 18: OFPATPopVLAN, 1032 19: OFPATPushMPLS, 1033 20: OFPATPopMPLS, 1034 21: OFPATSetQueue, 1035 22: OFPATGroup, 1036 23: OFPATSetNwTTL, 1037 24: OFPATDecNwTTL, 1038 25: OFPATSetField, 1039 26: OFPATPushPBB, 1040 27: OFPATPopPBB, 1041 65535: OFPATExperimenter} 1042 1043 1044# Action IDs # 1045 1046class OFPATID(_ofp_header): 1047 @classmethod 1048 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1049 if _pkt and len(_pkt) >= 2: 1050 t = struct.unpack("!H", _pkt[:2])[0] 1051 return ofp_action_id_cls.get(t, Raw) 1052 return Raw 1053 1054 def extract_padding(self, s): 1055 return b"", s 1056 1057# length is computed as in instruction structures, 1058# so we reuse _ofp_header 1059 1060 1061class OFPATOutputID(OFPATID): 1062 name = "OFPAT_OUTPUT" 1063 fields_desc = [ShortEnumField("type", 0, ofp_action_types), 1064 ShortField("len", 4)] 1065 1066# the following actions are not supported by OFv1.3 1067 1068 1069class OFPATSetVLANVIDID(OFPATID): 1070 name = "OFPAT_SET_VLAN_VID" 1071 fields_desc = [ShortEnumField("type", 1, ofp_action_types), 1072 ShortField("len", 4)] 1073 1074 1075class OFPATSetVLANPCPID(OFPATID): 1076 name = "OFPAT_SET_VLAN_PCP" 1077 fields_desc = [ShortEnumField("type", 2, ofp_action_types), 1078 ShortField("len", 4)] 1079 1080 1081class OFPATStripVLANID(OFPATID): 1082 name = "OFPAT_STRIP_VLAN" 1083 fields_desc = [ShortEnumField("type", 3, ofp_action_types), 1084 ShortField("len", 4)] 1085 1086 1087class OFPATSetDlSrcID(OFPATID): 1088 name = "OFPAT_SET_DL_SRC" 1089 fields_desc = [ShortEnumField("type", 4, ofp_action_types), 1090 ShortField("len", 4)] 1091 1092 1093class OFPATSetDlDstID(OFPATID): 1094 name = "OFPAT_SET_DL_DST" 1095 fields_desc = [ShortEnumField("type", 5, ofp_action_types), 1096 ShortField("len", 4)] 1097 1098 1099class OFPATSetNwSrcID(OFPATID): 1100 name = "OFPAT_SET_NW_SRC" 1101 fields_desc = [ShortEnumField("type", 6, ofp_action_types), 1102 ShortField("len", 4)] 1103 1104 1105class OFPATSetNwDstID(OFPATID): 1106 name = "OFPAT_SET_NW_DST" 1107 fields_desc = [ShortEnumField("type", 7, ofp_action_types), 1108 ShortField("len", 4)] 1109 1110 1111class OFPATSetNwToSID(OFPATID): 1112 name = "OFPAT_SET_TP_TOS" 1113 fields_desc = [ShortEnumField("type", 8, ofp_action_types), 1114 ShortField("len", 4)] 1115 1116 1117class OFPATSetTpSrcID(OFPATID): 1118 name = "OFPAT_SET_TP_SRC" 1119 fields_desc = [ShortEnumField("type", 9, ofp_action_types), 1120 ShortField("len", 4)] 1121 1122 1123class OFPATSetTpDstID(OFPATID): 1124 name = "OFPAT_SET_TP_DST" 1125 fields_desc = [ShortEnumField("type", 10, ofp_action_types), 1126 ShortField("len", 4)] 1127 1128# class OFPATEnqueueID(OFPAT): 1129# name = "OFPAT_ENQUEUE" 1130# fields_desc = [ ShortEnumField("type", 11, ofp_action_types), 1131# ShortField("len", 4) ] 1132 1133 1134class OFPATSetMPLSLabelID(OFPATID): 1135 name = "OFPAT_SET_MPLS_LABEL" 1136 fields_desc = [ShortEnumField("type", 13, ofp_action_types), 1137 ShortField("len", 4)] 1138 1139 1140class OFPATSetMPLSTCID(OFPATID): 1141 name = "OFPAT_SET_MPLS_TC" 1142 fields_desc = [ShortEnumField("type", 14, ofp_action_types), 1143 ShortField("len", 4)] 1144 1145# end of unsupported actions 1146 1147 1148class OFPATCopyTTLOutID(OFPATID): 1149 name = "OFPAT_COPY_TTL_OUT" 1150 fields_desc = [ShortEnumField("type", 11, ofp_action_types), 1151 ShortField("len", 4)] 1152 1153 1154class OFPATCopyTTLInID(OFPATID): 1155 name = "OFPAT_COPY_TTL_IN" 1156 fields_desc = [ShortEnumField("type", 12, ofp_action_types), 1157 ShortField("len", 4)] 1158 1159 1160class OFPATSetMPLSTTLID(OFPATID): 1161 name = "OFPAT_SET_MPLS_TTL" 1162 fields_desc = [ShortEnumField("type", 15, ofp_action_types), 1163 ShortField("len", 4)] 1164 1165 1166class OFPATDecMPLSTTLID(OFPATID): 1167 name = "OFPAT_DEC_MPLS_TTL" 1168 fields_desc = [ShortEnumField("type", 16, ofp_action_types), 1169 ShortField("len", 4)] 1170 1171 1172class OFPATPushVLANID(OFPATID): 1173 name = "OFPAT_PUSH_VLAN" 1174 fields_desc = [ShortEnumField("type", 17, ofp_action_types), 1175 ShortField("len", 4)] 1176 1177 1178class OFPATPopVLANID(OFPATID): 1179 name = "OFPAT_POP_VLAN" 1180 fields_desc = [ShortEnumField("type", 18, ofp_action_types), 1181 ShortField("len", 4)] 1182 1183 1184class OFPATPushMPLSID(OFPATID): 1185 name = "OFPAT_PUSH_MPLS" 1186 fields_desc = [ShortEnumField("type", 19, ofp_action_types), 1187 ShortField("len", 4)] 1188 1189 1190class OFPATPopMPLSID(OFPATID): 1191 name = "OFPAT_POP_MPLS" 1192 fields_desc = [ShortEnumField("type", 20, ofp_action_types), 1193 ShortField("len", 4)] 1194 1195 1196class OFPATSetQueueID(OFPATID): 1197 name = "OFPAT_SET_QUEUE" 1198 fields_desc = [ShortEnumField("type", 21, ofp_action_types), 1199 ShortField("len", 4)] 1200 1201 1202class OFPATGroupID(OFPATID): 1203 name = "OFPAT_GROUP" 1204 fields_desc = [ShortEnumField("type", 22, ofp_action_types), 1205 ShortField("len", 4)] 1206 1207 1208class OFPATSetNwTTLID(OFPATID): 1209 name = "OFPAT_SET_NW_TTL" 1210 fields_desc = [ShortEnumField("type", 23, ofp_action_types), 1211 ShortField("len", 4)] 1212 1213 1214class OFPATDecNwTTLID(OFPATID): 1215 name = "OFPAT_DEC_NW_TTL" 1216 fields_desc = [ShortEnumField("type", 24, ofp_action_types), 1217 ShortField("len", 4)] 1218 1219 1220class OFPATSetFieldID(OFPATID): 1221 name = "OFPAT_SET_FIELD" 1222 fields_desc = [ShortEnumField("type", 25, ofp_action_types), 1223 ShortField("len", 4)] 1224 1225 1226class OFPATPushPBBID(OFPATID): 1227 name = "OFPAT_PUSH_PBB" 1228 fields_desc = [ShortEnumField("type", 26, ofp_action_types), 1229 ShortField("len", 4)] 1230 1231 1232class OFPATPopPBBID(OFPATID): 1233 name = "OFPAT_POP_PBB" 1234 fields_desc = [ShortEnumField("type", 27, ofp_action_types), 1235 ShortField("len", 4)] 1236 1237 1238class OFPATExperimenterID(OFPATID): 1239 name = "OFPAT_EXPERIMENTER" 1240 fields_desc = [ShortEnumField("type", 65535, ofp_action_types), 1241 ShortField("len", None)] 1242 1243 1244ofp_action_id_cls = {0: OFPATOutputID, 1245 1: OFPATSetVLANVIDID, 1246 2: OFPATSetVLANPCPID, 1247 3: OFPATStripVLANID, 1248 4: OFPATSetDlSrcID, 1249 5: OFPATSetDlDstID, 1250 6: OFPATSetNwSrcID, 1251 7: OFPATSetNwDstID, 1252 8: OFPATSetNwToSID, 1253 9: OFPATSetTpSrcID, 1254 10: OFPATSetTpDstID, 1255 # 11: OFPATEnqueueID, 1256 11: OFPATCopyTTLOutID, 1257 12: OFPATCopyTTLInID, 1258 13: OFPATSetMPLSLabelID, 1259 14: OFPATSetMPLSTCID, 1260 15: OFPATSetMPLSTTLID, 1261 16: OFPATDecMPLSTTLID, 1262 17: OFPATPushVLANID, 1263 18: OFPATPopVLANID, 1264 19: OFPATPushMPLSID, 1265 20: OFPATPopMPLSID, 1266 21: OFPATSetQueueID, 1267 22: OFPATGroupID, 1268 23: OFPATSetNwTTLID, 1269 24: OFPATDecNwTTLID, 1270 25: OFPATSetFieldID, 1271 26: OFPATPushPBBID, 1272 27: OFPATPopPBBID, 1273 65535: OFPATExperimenterID} 1274 1275 1276# Instructions # 1277 1278 1279ofp_instruction_types = {1: "OFPIT_GOTO_TABLE", 1280 2: "OFPIT_WRITE_METADATA", 1281 3: "OFPIT_WRITE_ACTIONS", 1282 4: "OFPIT_APPLY_ACTIONS", 1283 5: "OFPIT_CLEAR_ACTIONS", 1284 6: "OFPIT_METER", 1285 65535: "OFPIT_EXPERIMENTER"} 1286 1287 1288class OFPIT(_ofp_header): 1289 @classmethod 1290 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1291 if _pkt and len(_pkt) >= 2: 1292 t = struct.unpack("!H", _pkt[:2])[0] 1293 return ofp_instruction_cls.get(t, Raw) 1294 return Raw 1295 1296 def extract_padding(self, s): 1297 return b"", s 1298 1299 1300class OFPITGotoTable(OFPIT): 1301 name = "OFPIT_GOTO_TABLE" 1302 fields_desc = [ShortEnumField("type", 1, ofp_instruction_types), 1303 ShortField("len", 8), 1304 ByteEnumField("table_id", 0, ofp_table), 1305 X3BytesField("pad", 0)] 1306 1307 1308class OFPITWriteMetadata(OFPIT): 1309 name = "OFPIT_WRITE_METADATA" 1310 fields_desc = [ShortEnumField("type", 2, ofp_instruction_types), 1311 ShortField("len", 24), 1312 XIntField("pad", 0), 1313 LongField("metadata", 0), 1314 LongField("metadata_mask", 0)] 1315 1316 1317class OFPITWriteActions(OFPIT): 1318 name = "OFPIT_WRITE_ACTIONS" 1319 fields_desc = [ShortEnumField("type", 3, ofp_instruction_types), 1320 ShortField("len", None), 1321 XIntField("pad", 0), 1322 PacketListField("actions", [], OFPAT, 1323 length_from=lambda pkt:pkt.len - 8)] 1324 1325 1326class OFPITApplyActions(OFPIT): 1327 name = "OFPIT_APPLY_ACTIONS" 1328 fields_desc = [ShortEnumField("type", 4, ofp_instruction_types), 1329 ShortField("len", None), 1330 XIntField("pad", 0), 1331 PacketListField("actions", [], OFPAT, 1332 length_from=lambda pkt:pkt.len - 8)] 1333 1334 1335class OFPITClearActions(OFPIT): 1336 name = "OFPIT_CLEAR_ACTIONS" 1337 fields_desc = [ShortEnumField("type", 5, ofp_instruction_types), 1338 ShortField("len", 8), 1339 XIntField("pad", 0)] 1340 1341 1342class OFPITMeter(OFPIT): 1343 name = "OFPIT_METER" 1344 fields_desc = [ShortEnumField("type", 6, ofp_instruction_types), 1345 ShortField("len", 8), 1346 IntEnumField("meter_id", 1, ofp_meter)] 1347 1348 1349class OFPITExperimenter(OFPIT): 1350 name = "OFPIT_EXPERIMENTER" 1351 fields_desc = [ShortEnumField("type", 65535, ofp_instruction_types), 1352 ShortField("len", None), 1353 IntField("experimenter", 0)] 1354 1355 1356ofp_instruction_cls = {1: OFPITGotoTable, 1357 2: OFPITWriteMetadata, 1358 3: OFPITWriteActions, 1359 4: OFPITApplyActions, 1360 5: OFPITClearActions, 1361 6: OFPITMeter, 1362 65535: OFPITExperimenter} 1363 1364 1365# Instruction IDs # 1366 1367# length is computed as in instruction structures, 1368# so we reuse _ofp_header 1369 1370class OFPITID(_ofp_header): 1371 @classmethod 1372 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1373 if _pkt and len(_pkt) >= 2: 1374 t = struct.unpack("!H", _pkt[:2])[0] 1375 return ofp_instruction_id_cls.get(t, Raw) 1376 return Raw 1377 1378 def extract_padding(self, s): 1379 return b"", s 1380 1381 1382class OFPITGotoTableID(OFPITID): 1383 name = "OFPIT_GOTO_TABLE" 1384 fields_desc = [ShortEnumField("type", 1, ofp_instruction_types), 1385 ShortField("len", 4)] 1386 1387 1388class OFPITWriteMetadataID(OFPITID): 1389 name = "OFPIT_WRITE_METADATA" 1390 fields_desc = [ShortEnumField("type", 2, ofp_instruction_types), 1391 ShortField("len", 4)] 1392 1393 1394class OFPITWriteActionsID(OFPITID): 1395 name = "OFPIT_WRITE_ACTIONS" 1396 fields_desc = [ShortEnumField("type", 3, ofp_instruction_types), 1397 ShortField("len", 4)] 1398 1399 1400class OFPITApplyActionsID(OFPITID): 1401 name = "OFPIT_APPLY_ACTIONS" 1402 fields_desc = [ShortEnumField("type", 4, ofp_instruction_types), 1403 ShortField("len", 4)] 1404 1405 1406class OFPITClearActionsID(OFPITID): 1407 name = "OFPIT_CLEAR_ACTIONS" 1408 fields_desc = [ShortEnumField("type", 5, ofp_instruction_types), 1409 ShortField("len", 4)] 1410 1411 1412class OFPITMeterID(OFPITID): 1413 name = "OFPIT_METER" 1414 fields_desc = [ShortEnumField("type", 6, ofp_instruction_types), 1415 ShortField("len", 4)] 1416 1417 1418class OFPITExperimenterID(OFPITID): 1419 name = "OFPIT_EXPERIMENTER" 1420 fields_desc = [ShortEnumField("type", 65535, ofp_instruction_types), 1421 ShortField("len", None)] 1422 1423 1424ofp_instruction_id_cls = {1: OFPITGotoTableID, 1425 2: OFPITWriteMetadataID, 1426 3: OFPITWriteActionsID, 1427 4: OFPITApplyActionsID, 1428 5: OFPITClearActionsID, 1429 6: OFPITMeterID, 1430 65535: OFPITExperimenterID} 1431 1432 1433# Buckets # 1434 1435class OFPBucket(_ofp_header_item): 1436 name = "OFP_BUCKET" 1437 fields_desc = [ShortField("len", None), 1438 ShortField("weight", 0), 1439 IntEnumField("watch_port", 0, ofp_port_no), 1440 IntEnumField("watch_group", 0, ofp_group), 1441 XIntField("pad", 0), 1442 PacketListField("actions", [], OFPAT, 1443 length_from=lambda pkt:pkt.len - 16)] 1444 1445 def extract_padding(self, s): 1446 return b"", s 1447 1448 1449# Queues # 1450 1451 1452ofp_queue_property_types = {0: "OFPQT_NONE", 1453 1: "OFPQT_MIN_RATE"} 1454 1455 1456class OFPQT(_ofp_header): 1457 @classmethod 1458 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1459 if _pkt and len(_pkt) >= 2: 1460 t = struct.unpack("!H", _pkt[:2])[0] 1461 return ofp_queue_property_cls.get(t, Raw) 1462 return Raw 1463 1464 def extract_padding(self, s): 1465 return b"", s 1466 1467 1468class OFPQTNone(OFPQT): 1469 name = "OFPQT_NONE" 1470 fields_desc = [ShortEnumField("type", 0, ofp_queue_property_types), 1471 ShortField("len", 8), 1472 XIntField("pad", 0)] 1473 1474 1475class OFPQTMinRate(OFPQT): 1476 name = "OFPQT_MIN_RATE" 1477 fields_desc = [ShortEnumField("type", 1, ofp_queue_property_types), 1478 ShortField("len", 16), 1479 XIntField("pad1", 0), 1480 ShortField("rate", 0), 1481 XBitField("pad2", 0, 48)] 1482 1483 1484ofp_queue_property_cls = {0: OFPQTNone, 1485 1: OFPQTMinRate} 1486 1487 1488class OFPPacketQueue(Packet): 1489 name = "OFP_PACKET_QUEUE" 1490 fields_desc = [IntEnumField("queue_id", 0, ofp_queue), 1491 ShortField("len", None), 1492 XShortField("pad", 0), 1493 PacketListField("properties", [], OFPQT, 1494 length_from=lambda pkt:pkt.len - 8)] # noqa: E501 1495 1496 def extract_padding(self, s): 1497 return b"", s 1498 1499 def post_build(self, p, pay): 1500 if self.properties == []: 1501 p += raw(OFPQTNone()) 1502 if self.len is None: 1503 tmp_len = len(p) + len(pay) 1504 p = p[:4] + struct.pack("!H", tmp_len) + p[6:] 1505 return p + pay 1506 1507 1508# Meter bands # 1509 1510ofp_meter_band_types = {0: "OFPMBT_DROP", 1511 1: "OFPMBT_DSCP_REMARK", 1512 65535: "OFPMBT_EXPERIMENTER"} 1513 1514 1515class OFPMBT(_ofp_header): 1516 @classmethod 1517 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1518 if _pkt and len(_pkt) >= 2: 1519 t = struct.unpack("!H", _pkt[:2])[0] 1520 return ofp_meter_band_cls.get(t, Raw) 1521 return Raw 1522 1523 def extract_padding(self, s): 1524 return b"", s 1525 1526 1527class OFPMBTDrop(OFPMBT): 1528 name = "OFPMBT_DROP" 1529 fields_desc = [ShortEnumField("type", 0, ofp_queue_property_types), 1530 ShortField("len", 16), 1531 IntField("rate", 0), 1532 IntField("burst_size", 0), 1533 XIntField("pad", 0)] 1534 1535 1536class OFPMBTDSCPRemark(OFPMBT): 1537 name = "OFPMBT_DSCP_REMARK" 1538 fields_desc = [ShortEnumField("type", 1, ofp_queue_property_types), 1539 ShortField("len", 16), 1540 IntField("rate", 0), 1541 IntField("burst_size", 0), 1542 ByteField("prec_level", 0), 1543 X3BytesField("pad", 0)] 1544 1545 1546class OFPMBTExperimenter(OFPMBT): 1547 name = "OFPMBT_EXPERIMENTER" 1548 fields_desc = [ShortEnumField("type", 65535, ofp_queue_property_types), 1549 ShortField("len", 16), 1550 IntField("rate", 0), 1551 IntField("burst_size", 0), 1552 IntField("experimenter", 0)] 1553 1554 1555ofp_meter_band_cls = {0: OFPMBTDrop, 1556 1: OFPMBTDSCPRemark, 1557 2: OFPMBTExperimenter} 1558 1559 1560##################################################### 1561# OpenFlow 1.3 Messages # 1562##################################################### 1563 1564ofp_version = {0x01: "OpenFlow 1.0", 1565 0x02: "OpenFlow 1.1", 1566 0x03: "OpenFlow 1.2", 1567 0x04: "OpenFlow 1.3", 1568 0x05: "OpenFlow 1.4"} 1569 1570ofp_type = {0: "OFPT_HELLO", 1571 1: "OFPT_ERROR", 1572 2: "OFPT_ECHO_REQUEST", 1573 3: "OFPT_ECHO_REPLY", 1574 4: "OFPT_EXPERIMENTER", 1575 5: "OFPT_FEATURES_REQUEST", 1576 6: "OFPT_FEATURES_REPLY", 1577 7: "OFPT_GET_CONFIG_REQUEST", 1578 8: "OFPT_GET_CONFIG_REPLY", 1579 9: "OFPT_SET_CONFIG", 1580 10: "OFPT_PACKET_IN", 1581 11: "OFPT_FLOW_REMOVED", 1582 12: "OFPT_PORT_STATUS", 1583 13: "OFPT_PACKET_OUT", 1584 14: "OFPT_FLOW_MOD", 1585 15: "OFPT_GROUP_MOD", 1586 16: "OFPT_PORT_MOD", 1587 17: "OFPT_TABLE_MOD", 1588 18: "OFPT_MULTIPART_REQUEST", 1589 19: "OFPT_MULTIPART_REPLY", 1590 20: "OFPT_BARRIER_REQUEST", 1591 21: "OFPT_BARRIER_REPLY", 1592 22: "OFPT_QUEUE_GET_CONFIG_REQUEST", 1593 23: "OFPT_QUEUE_GET_CONFIG_REPLY", 1594 24: "OFPT_ROLE_REQUEST", 1595 25: "OFPT_ROLE_REPLY", 1596 26: "OFPT_GET_ASYNC_REQUEST", 1597 27: "OFPT_GET_ASYNC_REPLY", 1598 28: "OFPT_SET_ASYNC", 1599 29: "OFPT_METER_MOD"} 1600 1601 1602class OFPTHello(_ofp_header): 1603 name = "OFPT_HELLO" 1604 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1605 ByteEnumField("type", 0, ofp_type), 1606 ShortField("len", None), 1607 IntField("xid", 0), 1608 PacketListField("elements", [], OFPHET, 1609 length_from=lambda pkt: pkt.len - 8)] 1610 1611 1612##################################################### 1613# OFPT_ERROR # 1614##################################################### 1615 1616 1617ofp_error_type = {0: "OFPET_HELLO_FAILED", 1618 1: "OFPET_BAD_REQUEST", 1619 2: "OFPET_BAD_ACTION", 1620 3: "OFPET_BAD_INSTRUCTION", 1621 4: "OFPET_BAD_MATCH", 1622 5: "OFPET_FLOW_MOD_FAILED", 1623 6: "OFPET_GROUP_MOD_FAILED", 1624 7: "OFPET_PORT_MOD_FAILED", 1625 8: "OFPET_TABLE_MOD_FAILED", 1626 9: "OFPET_QUEUE_OP_FAILED", 1627 10: "OFPET_SWITCH_CONFIG_FAILED", 1628 11: "OFPET_ROLE_REQUEST_FAILED", 1629 12: "OFPET_METER_MOD_FAILED", 1630 13: "OFPET_TABLE_FEATURES_FAILED", 1631 65535: "OFPET_EXPERIMENTER"} 1632 1633 1634class OFPETHelloFailed(_ofp_header): 1635 name = "OFPET_HELLO_FAILED" 1636 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1637 ByteEnumField("type", 1, ofp_type), 1638 ShortField("len", None), 1639 IntField("xid", 0), 1640 ShortEnumField("errtype", 0, ofp_error_type), 1641 ShortEnumField("errcode", 0, {0: "OFPHFC_INCOMPATIBLE", 1642 1: "OFPHFC_EPERM"}), 1643 OFPacketField("data", "", Raw)] 1644 1645 1646class OFPETBadRequest(_ofp_header): 1647 name = "OFPET_BAD_REQUEST" 1648 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1649 ByteEnumField("type", 1, ofp_type), 1650 ShortField("len", None), 1651 IntField("xid", 0), 1652 ShortEnumField("errtype", 1, ofp_error_type), 1653 ShortEnumField("errcode", 0, {0: "OFPBRC_BAD_VERSION", 1654 1: "OFPBRC_BAD_TYPE", 1655 2: "OFPBRC_BAD_MULTIPART", 1656 3: "OFPBRC_BAD_EXPERIMENTER", 1657 4: "OFPBRC_BAD_EXP_TYPE", 1658 5: "OFPBRC_EPERM", 1659 6: "OFPBRC_BAD_LEN", 1660 7: "OFPBRC_BUFFER_EMPTY", 1661 8: "OFPBRC_BUFFER_UNKNOWN", 1662 9: "OFPBRC_BAD_TABLE_ID", 1663 10: "OFPBRC_IS_SLAVE", 1664 11: "OFPBRC_BAD_PORT", 1665 12: "OFPBRC_BAD_PACKET", 1666 13: "OFPBRC_MULTIPART_BUFFER_OVERFLOW"}), # noqa: E501 1667 OFPacketField("data", "", Raw)] 1668 1669 1670class OFPETBadAction(_ofp_header): 1671 name = "OFPET_BAD_ACTION" 1672 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1673 ByteEnumField("type", 1, ofp_type), 1674 ShortField("len", None), 1675 IntField("xid", 0), 1676 ShortEnumField("errtype", 2, ofp_error_type), 1677 ShortEnumField("errcode", 0, {0: "OFPBAC_BAD_TYPE", 1678 1: "OFPBAC_BAD_LEN", 1679 2: "OFPBAC_BAD_EXPERIMENTER", 1680 3: "OFPBAC_BAD_EXP_TYPE", 1681 4: "OFPBAC_BAD_OUT_PORT", 1682 5: "OFPBAC_BAD_ARGUMENT", 1683 6: "OFPBAC_EPERM", 1684 7: "OFPBAC_TOO_MANY", 1685 8: "OFPBAC_BAD_QUEUE", 1686 9: "OFPBAC_BAD_OUT_GROUP", 1687 10: "OFPBAC_MATCH_INCONSISTENT", # noqa: E501 1688 11: "OFPBAC_UNSUPPORTED_ORDER", # noqa: E501 1689 12: "OFPBAC_BAD_TAG", 1690 13: "OFPBAC_BAD_SET_TYPE", 1691 14: "OFPBAC_BAD_SET_LEN", 1692 15: "OFPBAC_BAD_SET_ARGUMENT"}), # noqa: E501 1693 OFPacketField("data", "", Raw)] 1694 1695 1696class OFPETBadInstruction(_ofp_header): 1697 name = "OFPET_BAD_INSTRUCTION" 1698 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1699 ByteEnumField("type", 1, ofp_type), 1700 ShortField("len", None), 1701 IntField("xid", 0), 1702 ShortEnumField("errtype", 3, ofp_error_type), 1703 ShortEnumField("errcode", 0, {0: "OFPBIC_UNKNOWN_INST", 1704 1: "OFPBIC_UNSUP_INST", 1705 2: "OFPBIC_BAD_TABLE_ID", 1706 3: "OFPBIC_UNSUP_METADATA", 1707 4: "OFPBIC_UNSUP_METADATA_MASK", # noqa: E501 1708 5: "OFPBIC_BAD_EXPERIMENTER", 1709 6: "OFPBIC_BAD_EXP_TYPE", 1710 7: "OFPBIC_BAD_LEN", 1711 8: "OFPBIC_EPERM"}), 1712 OFPacketField("data", "", Raw)] 1713 1714 1715class OFPETBadMatch(_ofp_header): 1716 name = "OFPET_BAD_MATCH" 1717 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1718 ByteEnumField("type", 1, ofp_type), 1719 ShortField("len", None), 1720 IntField("xid", 0), 1721 ShortEnumField("errtype", 4, ofp_error_type), 1722 ShortEnumField("errcode", 0, {0: "OFPBMC_BAD_TYPE", 1723 1: "OFPBMC_BAD_LEN", 1724 2: "OFPBMC_BAD_TAG", 1725 3: "OFPBMC_BAD_DL_ADDR_MASK", 1726 4: "OFPBMC_BAD_NW_ADDR_MASK", 1727 5: "OFPBMC_BAD_WILDCARDS", 1728 6: "OFPBMC_BAD_FIELD", 1729 7: "OFPBMC_BAD_VALUE", 1730 8: "OFPBMC_BAD_MASK", 1731 9: "OFPBMC_BAD_PREREQ", 1732 10: "OFPBMC_DUP_FIELD", 1733 11: "OFPBMC_EPERM"}), 1734 OFPacketField("data", "", Raw)] 1735 1736 1737class OFPETFlowModFailed(_ofp_header): 1738 name = "OFPET_FLOW_MOD_FAILED" 1739 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1740 ByteEnumField("type", 1, ofp_type), 1741 ShortField("len", None), 1742 IntField("xid", 0), 1743 ShortEnumField("errtype", 5, ofp_error_type), 1744 ShortEnumField("errcode", 0, {0: "OFPFMFC_UNKNOWN", 1745 1: "OFPFMFC_TABLE_FULL", 1746 2: "OFPFMFC_BAD_TABLE_ID", 1747 3: "OFPFMFC_OVERLAP", 1748 4: "OFPFMFC_EPERM", 1749 5: "OFPFMFC_BAD_TIMEOUT", 1750 6: "OFPFMFC_BAD_COMMAND", 1751 7: "OFPFMFC_BAD_FLAGS"}), 1752 OFPacketField("data", "", Raw)] 1753 1754 1755class OFPETGroupModFailed(_ofp_header): 1756 name = "OFPET_GROUP_MOD_FAILED" 1757 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1758 ByteEnumField("type", 1, ofp_type), 1759 ShortField("len", None), 1760 IntField("xid", 0), 1761 ShortEnumField("errtype", 6, ofp_error_type), 1762 ShortEnumField("errcode", 0, {0: "OFPGMFC_GROUP_EXISTS", 1763 1: "OFPGMFC_INVALID_GROUP", 1764 2: "OFPGMFC_WEIGHT_UNSUPPORTED", # noqa: E501 1765 3: "OFPGMFC_OUT_OF_GROUPS", 1766 4: "OFPGMFC_OUT_OF_BUCKETS", 1767 5: "OFPGMFC_CHAINING_UNSUPPORTED", # noqa: E501 1768 6: "OFPGMFC_WATCH_UNSUPPORTED", # noqa: E501 1769 7: "OFPGMFC_LOOP", 1770 8: "OFPGMFC_UNKNOWN_GROUP", 1771 9: "OFPGMFC_CHAINED_GROUP", 1772 10: "OFPGMFC_BAD_TYPE", 1773 11: "OFPGMFC_BAD_COMMAND", 1774 12: "OFPGMFC_BAD_BUCKET", 1775 13: "OFPGMFC_BAD_WATCH", 1776 14: "OFPFMFC_EPERM"}), 1777 OFPacketField("data", "", Raw)] 1778 1779 1780class OFPETPortModFailed(_ofp_header): 1781 name = "OFPET_PORT_MOD_FAILED" 1782 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1783 ByteEnumField("type", 1, ofp_type), 1784 ShortField("len", None), 1785 IntField("xid", 0), 1786 ShortEnumField("errtype", 7, ofp_error_type), 1787 ShortEnumField("errcode", 0, {0: "OFPPMFC_BAD_PORT", 1788 1: "OFPPMFC_BAD_HW_ADDR", 1789 2: "OFPPMFC_BAD_CONFIG", 1790 3: "OFPPMFC_BAD_ADVERTISE", 1791 4: "OFPPMFC_EPERM"}), 1792 OFPacketField("data", "", Raw)] 1793 1794 1795class OFPETTableModFailed(_ofp_header): 1796 name = "OFPET_TABLE_MOD_FAILED" 1797 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1798 ByteEnumField("type", 1, ofp_type), 1799 ShortField("len", None), 1800 IntField("xid", 0), 1801 ShortEnumField("errtype", 8, ofp_error_type), 1802 ShortEnumField("errcode", 0, {0: "OFPTMFC_BAD_TABLE", 1803 1: "OFPTMFC_BAD_CONFIG", 1804 2: "OFPTMFC_EPERM"}), 1805 OFPacketField("data", "", Raw)] 1806 1807 1808class OFPETQueueOpFailed(_ofp_header): 1809 name = "OFPET_QUEUE_OP_FAILED" 1810 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1811 ByteEnumField("type", 1, ofp_type), 1812 ShortField("len", None), 1813 IntField("xid", 0), 1814 ShortEnumField("errtype", 9, ofp_error_type), 1815 ShortEnumField("errcode", 0, {0: "OFPQOFC_BAD_PORT", 1816 1: "OFPQOFC_BAD_QUEUE", 1817 2: "OFPQOFC_EPERM"}), 1818 OFPacketField("data", "", Raw)] 1819 1820 1821class OFPETSwitchConfigFailed(_ofp_header): 1822 name = "OFPET_SWITCH_CONFIG_FAILED" 1823 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1824 ByteEnumField("type", 1, ofp_type), 1825 ShortField("len", None), 1826 IntField("xid", 0), 1827 ShortEnumField("errtype", 10, ofp_error_type), 1828 ShortEnumField("errcode", 0, {0: "OFPSCFC_BAD_FLAGS", 1829 1: "OFPSCFC_BAD_LEN", 1830 2: "OFPSCFC_EPERM"}), 1831 OFPacketField("data", "", Raw)] 1832 1833 1834class OFPETRoleRequestFailed(_ofp_header): 1835 name = "OFPET_ROLE_REQUEST_FAILED" 1836 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1837 ByteEnumField("type", 1, ofp_type), 1838 ShortField("len", None), 1839 IntField("xid", 0), 1840 ShortEnumField("errtype", 11, ofp_error_type), 1841 ShortEnumField("errcode", 0, {0: "OFPRRFC_STALE", 1842 1: "OFPRRFC_UNSUP", 1843 2: "OFPRRFC_BAD_ROLE"}), 1844 OFPacketField("data", "", Raw)] 1845 1846 1847class OFPETMeterModFailed(_ofp_header): 1848 name = "OFPET_METER_MOD_FAILED" 1849 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1850 ByteEnumField("type", 1, ofp_type), 1851 ShortField("len", None), 1852 IntField("xid", 0), 1853 ShortEnumField("errtype", 12, ofp_error_type), 1854 ShortEnumField("errcode", 0, {0: "OFPMMFC_UNKNOWN", 1855 1: "OFPMMFC_METER_EXISTS", 1856 2: "OFPMMFC_INVALID_METER", 1857 3: "OFPMMFC_UNKNOWN_METER", 1858 4: "OFPMMFC_BAD_COMMAND", 1859 5: "OFPMMFC_BAD_FLAGS", 1860 6: "OFPMMFC_BAD_RATE", 1861 7: "OFPMMFC_BAD_BURST", 1862 8: "OFPMMFC_BAD_BAND", 1863 9: "OFPMMFC_BAD_BAND_VALUE", 1864 10: "OFPMMFC_OUT_OF_METERS", 1865 11: "OFPMMFC_OUT_OF_BANDS"}), 1866 OFPacketField("data", "", Raw)] 1867 1868 1869class OFPETTableFeaturesFailed(_ofp_header): 1870 name = "OFPET_TABLE_FEATURES_FAILED" 1871 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1872 ByteEnumField("type", 1, ofp_type), 1873 ShortField("len", None), 1874 IntField("xid", 0), 1875 ShortEnumField("errtype", 13, ofp_error_type), 1876 ShortEnumField("errcode", 0, {0: "OFPTFFC_BAD_TABLE", 1877 1: "OFPTFFC_BAD_METADATA", 1878 2: "OFPTFFC_BAD_TYPE", 1879 3: "OFPTFFC_BAD_LEN", 1880 4: "OFPTFFC_BAD_ARGUMENT", 1881 5: "OFPTFFC_EPERM"}), 1882 OFPacketField("data", "", Raw)] 1883 1884 1885class OFPETExperimenter(_ofp_header): 1886 name = "OFPET_EXPERIMENTER" 1887 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1888 ByteEnumField("type", 1, ofp_type), 1889 ShortField("len", None), 1890 IntField("xid", 0), 1891 ShortEnumField("errtype", "OFPET_EXPERIMENTER", ofp_error_type), # noqa: E501 1892 ShortField("exp_type", None), 1893 IntField("experimenter", None), 1894 OFPacketField("data", "", Raw)] 1895 1896 1897# ofp_error_cls allows generic method OpenFlow3() 1898# to choose the right class for dissection 1899ofp_error_cls = {0: OFPETHelloFailed, 1900 1: OFPETBadRequest, 1901 2: OFPETBadAction, 1902 3: OFPETBadInstruction, 1903 4: OFPETBadMatch, 1904 5: OFPETFlowModFailed, 1905 6: OFPETGroupModFailed, 1906 7: OFPETPortModFailed, 1907 8: OFPETTableModFailed, 1908 9: OFPETQueueOpFailed, 1909 10: OFPETSwitchConfigFailed, 1910 11: OFPETRoleRequestFailed, 1911 12: OFPETMeterModFailed, 1912 13: OFPETTableFeaturesFailed, 1913 65535: OFPETExperimenter} 1914 1915# end of OFPT_ERRORS # 1916 1917 1918class OFPTEchoRequest(_ofp_header): 1919 name = "OFPT_ECHO_REQUEST" 1920 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1921 ByteEnumField("type", 2, ofp_type), 1922 ShortField("len", None), 1923 IntField("xid", 0)] 1924 1925 1926class OFPTEchoReply(_ofp_header): 1927 name = "OFPT_ECHO_REPLY" 1928 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1929 ByteEnumField("type", 3, ofp_type), 1930 ShortField("len", None), 1931 IntField("xid", 0)] 1932 1933 1934class OFPTExperimenter(_ofp_header): 1935 name = "OFPT_EXPERIMENTER" 1936 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1937 ByteEnumField("type", 4, ofp_type), 1938 ShortField("len", None), 1939 IntField("xid", 0), 1940 IntField("experimenter", 0), 1941 IntField("exp_type", 0)] 1942 1943 1944class OFPTFeaturesRequest(_ofp_header): 1945 name = "OFPT_FEATURES_REQUEST" 1946 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1947 ByteEnumField("type", 5, ofp_type), 1948 ShortField("len", None), 1949 IntField("xid", 0)] 1950 1951 1952class OFPTFeaturesReply(_ofp_header): 1953 name = "OFPT_FEATURES_REPLY" 1954 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1955 ByteEnumField("type", 6, ofp_type), 1956 ShortField("len", None), 1957 IntField("xid", 0), 1958 LongField("datapath_id", 0), 1959 IntField("n_buffers", 0), 1960 ByteField("n_tables", 1), 1961 ByteField("auxiliary_id", 0), 1962 XShortField("pad", 0), 1963 FlagsField("capabilities", 0, 32, ["FLOW_STATS", 1964 "TABLE_STATS", 1965 "PORT_STATS", 1966 "GROUP_STATS", 1967 "RESERVED", # undefined 1968 "IP_REASM", 1969 "QUEUE_STATS", 1970 "ARP_MATCH_IP", # undefined # noqa: E501 1971 "PORT_BLOCKED"]), 1972 IntField("reserved", 0)] 1973 1974 1975class OFPTGetConfigRequest(_ofp_header): 1976 name = "OFPT_GET_CONFIG_REQUEST" 1977 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1978 ByteEnumField("type", 7, ofp_type), 1979 ShortField("len", None), 1980 IntField("xid", 0)] 1981 1982 1983class OFPTGetConfigReply(_ofp_header): 1984 name = "OFPT_GET_CONFIG_REPLY" 1985 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1986 ByteEnumField("type", 8, ofp_type), 1987 ShortField("len", None), 1988 IntField("xid", 0), 1989 ShortEnumField("flags", 0, {0: "FRAG_NORMAL", 1990 1: "FRAG_DROP", 1991 2: "FRAG_REASM", 1992 3: "FRAG_MASK"}), 1993 ShortField("miss_send_len", 0)] 1994 1995 1996class OFPTSetConfig(_ofp_header): 1997 name = "OFPT_SET_CONFIG" 1998 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 1999 ByteEnumField("type", 9, ofp_type), 2000 ShortField("len", None), 2001 IntField("xid", 0), 2002 ShortEnumField("flags", 0, {0: "FRAG_NORMAL", 2003 1: "FRAG_DROP", 2004 2: "FRAG_REASM", 2005 3: "FRAG_MASK"}), 2006 ShortField("miss_send_len", 128)] 2007 2008 2009class OFPTPacketIn(_ofp_header): 2010 name = "OFPT_PACKET_IN" 2011 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2012 ByteEnumField("type", 10, ofp_type), 2013 ShortField("len", None), 2014 IntField("xid", 0), 2015 IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer), 2016 ShortField("total_len", 0), 2017 ByteEnumField("reason", 0, {0: "OFPR_NO_MATCH", 2018 1: "OFPR_ACTION", 2019 2: "OFPR_INVALID_TTL"}), 2020 ByteEnumField("table_id", 0, ofp_table), 2021 LongField("cookie", 0), 2022 MatchField("match"), 2023 XShortField("pad", 0), 2024 PacketField("data", "", Ether)] 2025 2026 2027class OFPTFlowRemoved(_ofp_header): 2028 name = "OFPT_FLOW_REMOVED" 2029 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2030 ByteEnumField("type", 11, ofp_type), 2031 ShortField("len", None), 2032 IntField("xid", 0), 2033 LongField("cookie", 0), 2034 ShortField("priority", 0), 2035 ByteEnumField("reason", 0, {0: "OFPRR_IDLE_TIMEOUT", 2036 1: "OFPRR_HARD_TIMEOUT", 2037 2: "OFPRR_DELETE", 2038 3: "OFPRR_GROUP_DELETE"}), 2039 ByteEnumField("table_id", 0, ofp_table), 2040 IntField("duration_sec", 0), 2041 IntField("duration_nsec", 0), 2042 ShortField("idle_timeout", 0), 2043 ShortField("hard_timeout", 0), 2044 LongField("packet_count", 0), 2045 LongField("byte_count", 0), 2046 MatchField("match")] 2047 2048 2049class OFPTPortStatus(_ofp_header): 2050 name = "OFPT_PORT_STATUS" 2051 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2052 ByteEnumField("type", 12, ofp_type), 2053 ShortField("len", None), 2054 IntField("xid", 0), 2055 ByteEnumField("reason", 0, {0: "OFPPR_ADD", 2056 1: "OFPPR_DELETE", 2057 2: "OFPPR_MODIFY"}), 2058 XBitField("pad", 0, 56), 2059 PacketField("desc", OFPPort(), OFPPort)] 2060 2061 2062class OFPTPacketOut(_ofp_header): 2063 name = "OFPT_PACKET_OUT" 2064 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2065 ByteEnumField("type", 13, ofp_type), 2066 ShortField("len", None), 2067 IntField("xid", 0), 2068 IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer), 2069 IntEnumField("in_port", "CONTROLLER", ofp_port_no), 2070 FieldLenField("actions_len", None, fmt="H", length_of="actions"), # noqa: E501 2071 XBitField("pad", 0, 48), 2072 PacketListField("actions", [], OFPAT, 2073 OFPAT, 2074 length_from=lambda pkt:pkt.actions_len), 2075 PacketField("data", "", Ether)] 2076 2077 2078class OFPTFlowMod(_ofp_header): 2079 name = "OFPT_FLOW_MOD" 2080 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2081 ByteEnumField("type", 14, ofp_type), 2082 ShortField("len", None), 2083 IntField("xid", 0), 2084 LongField("cookie", 0), 2085 LongField("cookie_mask", 0), 2086 ByteEnumField("table_id", 0, ofp_table), 2087 ByteEnumField("cmd", 0, {0: "OFPFC_ADD", 2088 1: "OFPFC_MODIFY", 2089 2: "OFPFC_MODIFY_STRICT", 2090 3: "OFPFC_DELETE", 2091 4: "OFPFC_DELETE_STRICT"}), 2092 ShortField("idle_timeout", 0), 2093 ShortField("hard_timeout", 0), 2094 ShortField("priority", 0), 2095 IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer), 2096 IntEnumField("out_port", "ANY", ofp_port_no), 2097 IntEnumField("out_group", "ANY", ofp_group), 2098 FlagsField("flags", 0, 16, ["SEND_FLOW_REM", 2099 "CHECK_OVERLAP", 2100 "RESET_COUNTS", 2101 "NO_PKT_COUNTS", 2102 "NO_BYT_COUNTS"]), 2103 XShortField("pad", 0), 2104 MatchField("match"), 2105 PacketListField("instructions", [], OFPIT, 2106 length_from=lambda pkt:pkt.len - 48 - (pkt.match.len + (8 - pkt.match.len % 8) % 8))] # noqa: E501 2107 # include match padding to match.len 2108 2109 2110class OFPTGroupMod(_ofp_header): 2111 name = "OFPT_GROUP_MOD" 2112 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2113 ByteEnumField("type", 15, ofp_type), 2114 ShortField("len", None), 2115 IntField("xid", 0), 2116 ShortEnumField("cmd", 0, {0: "OFPGC_ADD", 2117 1: "OFPGC_MODIFY", 2118 2: "OFPGC_DELETE"}), 2119 ByteEnumField("group_type", 0, {0: "OFPGT_ALL", 2120 1: "OFPGT_SELECT", 2121 2: "OFPGT_INDIRECT", 2122 3: "OFPGT_FF"}), 2123 XByteField("pad", 0), 2124 IntEnumField("group_id", 0, ofp_group), 2125 PacketListField("buckets", [], OFPBucket, 2126 length_from=lambda pkt:pkt.len - 16)] 2127 2128 2129class OFPTPortMod(_ofp_header): 2130 name = "OFPT_PORT_MOD" 2131 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2132 ByteEnumField("type", 16, ofp_type), 2133 ShortField("len", None), 2134 IntField("xid", 0), 2135 IntEnumField("port_no", 0, ofp_port_no), 2136 XIntField("pad1", 0), 2137 MACField("hw_addr", "0"), 2138 XShortField("pad2", 0), 2139 FlagsField("config", 0, 32, ofp_port_config), 2140 FlagsField("mask", 0, 32, ofp_port_config), 2141 FlagsField("advertise", 0, 32, ofp_port_features), 2142 XIntField("pad3", 0)] 2143 2144 2145class OFPTTableMod(_ofp_header): 2146 name = "OFPT_TABLE_MOD" 2147 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2148 ByteEnumField("type", 17, ofp_type), 2149 ShortField("len", None), 2150 IntField("xid", 0), 2151 ByteEnumField("table_id", 0, ofp_table), 2152 X3BytesField("pad", 0), 2153 IntEnumField("config", 0, {3: "OFPTC_DEPRECATED_MASK"})] 2154 2155 2156##################################################### 2157# OFPT_MULTIPART # 2158##################################################### 2159 2160 2161ofp_multipart_types = {0: "OFPMP_DESC", 2162 1: "OFPMP_FLOW", 2163 2: "OFPMP_AGGREGATE", 2164 3: "OFPMP_TABLE", 2165 4: "OFPMP_PORT_STATS", 2166 5: "OFPMP_QUEUE", 2167 6: "OFPMP_GROUP", 2168 7: "OFPMP_GROUP_DESC", 2169 8: "OFPMP_GROUP_FEATURES", 2170 9: "OFPMP_METER", 2171 10: "OFPMP_METER_CONFIG", 2172 11: "OFPMP_METER_FEATURES", 2173 12: "OFPMP_TABLE_FEATURES", 2174 13: "OFPMP_PORT_DESC", 2175 65535: "OFPST_VENDOR"} 2176 2177ofpmp_request_flags = ["REQ_MORE"] 2178 2179ofpmp_reply_flags = ["REPLY_MORE"] 2180 2181 2182class OFPMPRequestDesc(_ofp_header): 2183 name = "OFPMP_REQUEST_DESC" 2184 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2185 ByteEnumField("type", 18, ofp_type), 2186 ShortField("len", None), 2187 IntField("xid", 0), 2188 ShortEnumField("mp_type", 0, ofp_multipart_types), 2189 FlagsField("flags", 0, 16, ofpmp_request_flags), 2190 XIntField("pad", 0)] 2191 2192 2193class OFPMPReplyDesc(_ofp_header): 2194 name = "OFPMP_REPLY_DESC" 2195 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2196 ByteEnumField("type", 19, ofp_type), 2197 ShortField("len", None), 2198 IntField("xid", 0), 2199 ShortEnumField("mp_type", 0, ofp_multipart_types), 2200 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2201 XIntField("pad", 0), 2202 StrFixedLenField("mfr_desc", "", 256), 2203 StrFixedLenField("hw_desc", "", 256), 2204 StrFixedLenField("sw_desc", "", 256), 2205 StrFixedLenField("serial_num", "", 32), 2206 StrFixedLenField("dp_desc", "", 256)] 2207 2208 2209class OFPMPRequestFlow(_ofp_header): 2210 name = "OFPMP_REQUEST_FLOW" 2211 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2212 ByteEnumField("type", 18, ofp_type), 2213 ShortField("len", None), 2214 IntField("xid", 0), 2215 ShortEnumField("mp_type", 1, ofp_multipart_types), 2216 FlagsField("flags", 0, 16, ofpmp_request_flags), 2217 XIntField("pad1", 0), 2218 ByteEnumField("table_id", "ALL", ofp_table), 2219 X3BytesField("pad2", 0), 2220 IntEnumField("out_port", "ANY", ofp_port_no), 2221 IntEnumField("out_group", "ANY", ofp_group), 2222 IntField("pad3", 0), 2223 LongField("cookie", 0), 2224 LongField("cookie_mask", 0), 2225 MatchField("match")] 2226 2227 2228class OFPFlowStats(_ofp_header_item): 2229 name = "OFP_FLOW_STATS" 2230 fields_desc = [ShortField("len", None), 2231 ByteEnumField("table_id", 0, ofp_table), 2232 XByteField("pad1", 0), 2233 IntField("duration_sec", 0), 2234 IntField("duration_nsec", 0), 2235 ShortField("priority", 0), 2236 ShortField("idle_timeout", 0), 2237 ShortField("hard_timeout", 0), 2238 FlagsField("flags", 0, 16, ["SEND_FLOW_REM", 2239 "CHECK_OVERLAP", 2240 "RESET_COUNTS", 2241 "NO_PKT_COUNTS", 2242 "NO_BYT_COUNTS"]), 2243 IntField("pad2", 0), 2244 LongField("cookie", 0), 2245 LongField("packet_count", 0), 2246 LongField("byte_count", 0), 2247 MatchField("match"), 2248 PacketListField("instructions", [], OFPIT, 2249 length_from=lambda pkt:pkt.len - 52 - pkt.match.len)] # noqa: E501 2250 2251 def extract_padding(self, s): 2252 return b"", s 2253 2254 2255class OFPMPReplyFlow(_ofp_header): 2256 name = "OFPMP_REPLY_FLOW" 2257 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2258 ByteEnumField("type", 19, ofp_type), 2259 ShortField("len", None), 2260 IntField("xid", 0), 2261 ShortEnumField("mp_type", 1, ofp_multipart_types), 2262 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2263 XIntField("pad1", 0), 2264 PacketListField("flow_stats", [], OFPFlowStats, 2265 length_from=lambda pkt:pkt.len - 16)] 2266 2267 2268class OFPMPRequestAggregate(OFPMPRequestFlow): 2269 name = "OFPMP_REQUEST_AGGREGATE" 2270 mp_type = 2 2271 2272 2273class OFPMPReplyAggregate(_ofp_header): 2274 name = "OFPMP_REPLY_AGGREGATE" 2275 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2276 ByteEnumField("type", 19, ofp_type), 2277 ShortField("len", None), 2278 IntField("xid", 0), 2279 ShortEnumField("mp_type", 2, ofp_multipart_types), 2280 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2281 XIntField("pad1", 0), 2282 LongField("packet_count", 0), 2283 LongField("byte_count", 0), 2284 IntField("flow_count", 0), 2285 XIntField("pad2", 0)] 2286 2287 2288class OFPMPRequestTable(_ofp_header): 2289 name = "OFPMP_REQUEST_TABLE" 2290 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2291 ByteEnumField("type", 18, ofp_type), 2292 ShortField("len", None), 2293 IntField("xid", 0), 2294 ShortEnumField("mp_type", 3, ofp_multipart_types), 2295 FlagsField("flags", 0, 16, ofpmp_request_flags), 2296 XIntField("pad1", 0)] 2297 2298 2299class OFPTableStats(Packet): 2300 name = "OFP_TABLE_STATS" 2301 fields_desc = [ByteEnumField("table_id", 0, ofp_table), 2302 X3BytesField("pad1", 0), 2303 IntField("active_count", 0), 2304 LongField("lookup_count", 0), 2305 LongField("matched_count", 0)] 2306 2307 def extract_padding(self, s): 2308 return b"", s 2309 2310 2311class OFPMPReplyTable(_ofp_header): 2312 name = "OFPMP_REPLY_TABLE" 2313 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2314 ByteEnumField("type", 19, ofp_type), 2315 ShortField("len", None), 2316 IntField("xid", 0), 2317 ShortEnumField("mp_type", 3, ofp_multipart_types), 2318 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2319 XIntField("pad1", 0), 2320 PacketListField("table_stats", None, OFPTableStats, 2321 length_from=lambda pkt:pkt.len - 16)] 2322 2323 2324class OFPMPRequestPortStats(_ofp_header): 2325 name = "OFPMP_REQUEST_PORT_STATS" 2326 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2327 ByteEnumField("type", 18, ofp_type), 2328 ShortField("len", None), 2329 IntField("xid", 0), 2330 ShortEnumField("mp_type", 4, ofp_multipart_types), 2331 FlagsField("flags", 0, 16, ofpmp_request_flags), 2332 XIntField("pad1", 0), 2333 IntEnumField("port_no", "ANY", ofp_port_no), 2334 XIntField("pad", 0)] 2335 2336 2337class OFPPortStats(Packet): 2338 def extract_padding(self, s): 2339 return b"", s 2340 name = "OFP_PORT_STATS" 2341 fields_desc = [IntEnumField("port_no", 0, ofp_port_no), 2342 XIntField("pad", 0), 2343 LongField("rx_packets", 0), 2344 LongField("tx_packets", 0), 2345 LongField("rx_bytes", 0), 2346 LongField("tx_bytes", 0), 2347 LongField("rx_dropped", 0), 2348 LongField("tx_dropped", 0), 2349 LongField("rx_errors", 0), 2350 LongField("tx_errors", 0), 2351 LongField("rx_frame_err", 0), 2352 LongField("rx_over_err", 0), 2353 LongField("rx_crc_err", 0), 2354 LongField("collisions", 0), 2355 IntField("duration_sec", 0), 2356 IntField("duration_nsec", 0)] 2357 2358 2359class OFPMPReplyPortStats(_ofp_header): 2360 name = "OFPMP_REPLY_PORT_STATS" 2361 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2362 ByteEnumField("type", 19, ofp_type), 2363 ShortField("len", None), 2364 IntField("xid", 0), 2365 ShortEnumField("mp_type", 4, ofp_multipart_types), 2366 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2367 XIntField("pad1", 0), 2368 PacketListField("port_stats", None, OFPPortStats, 2369 length_from=lambda pkt:pkt.len - 16)] 2370 2371 2372class OFPMPRequestQueue(_ofp_header): 2373 name = "OFPMP_REQUEST_QUEUE" 2374 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2375 ByteEnumField("type", 18, ofp_type), 2376 ShortField("len", None), 2377 IntField("xid", 0), 2378 ShortEnumField("mp_type", 5, ofp_multipart_types), 2379 FlagsField("flags", 0, 16, ofpmp_request_flags), 2380 XIntField("pad1", 0), 2381 IntEnumField("port_no", "ANY", ofp_port_no), 2382 IntEnumField("queue_id", "ALL", ofp_queue)] 2383 2384 2385class OFPQueueStats(Packet): 2386 name = "OFP_QUEUE_STATS" 2387 fields_desc = [IntEnumField("port_no", 0, ofp_port_no), 2388 IntEnumField("queue_id", 0, ofp_queue), 2389 LongField("tx_bytes", 0), 2390 LongField("tx_packets", 0), 2391 LongField("tx_errors", 0), 2392 IntField("duration_sec", 0), 2393 IntField("duration_nsec", 0)] 2394 2395 def extract_padding(self, s): 2396 return b"", s 2397 2398 2399class OFPMPReplyQueue(_ofp_header): 2400 name = "OFPMP_REPLY_QUEUE" 2401 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2402 ByteEnumField("type", 19, ofp_type), 2403 ShortField("len", None), 2404 IntField("xid", 0), 2405 ShortEnumField("mp_type", 5, ofp_multipart_types), 2406 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2407 XIntField("pad1", 0), 2408 PacketListField("queue_stats", None, OFPQueueStats, 2409 length_from=lambda pkt:pkt.len - 16)] 2410 2411 2412class OFPMPRequestGroup(_ofp_header): 2413 name = "OFPMP_REQUEST_GROUP" 2414 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2415 ByteEnumField("type", 18, ofp_type), 2416 ShortField("len", None), 2417 IntField("xid", 0), 2418 ShortEnumField("mp_type", 6, ofp_multipart_types), 2419 FlagsField("flags", 0, 16, ofpmp_request_flags), 2420 XIntField("pad1", 0), 2421 IntEnumField("group_id", "ANY", ofp_group), 2422 XIntField("pad2", 0)] 2423 2424 2425class OFPBucketStats(Packet): 2426 name = "OFP_BUCKET_STATS" 2427 fields_desc = [LongField("packet_count", 0), 2428 LongField("byte_count", 0)] 2429 2430 def extract_padding(self, s): 2431 return b"", s 2432 2433 2434class OFPGroupStats(_ofp_header_item): 2435 name = "OFP_GROUP_STATS" 2436 fields_desc = [ShortField("len", None), 2437 XShortField("pad1", 0), 2438 IntEnumField("group_id", 0, ofp_group), 2439 IntField("ref_count", 0), 2440 IntField("pad2", 0), 2441 LongField("packet_count", 0), 2442 LongField("byte_count", 0), 2443 IntField("duration_sec", 0), 2444 IntField("duration_nsec", 0), 2445 PacketListField("bucket_stats", None, OFPBucketStats, 2446 length_from=lambda pkt:pkt.len - 40)] 2447 2448 def extract_padding(self, s): 2449 return b"", s 2450 2451 2452class OFPMPReplyGroup(_ofp_header): 2453 name = "OFPMP_REPLY_GROUP" 2454 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2455 ByteEnumField("type", 19, ofp_type), 2456 ShortField("len", None), 2457 IntField("xid", 0), 2458 ShortEnumField("mp_type", 6, ofp_multipart_types), 2459 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2460 XIntField("pad1", 0), 2461 PacketListField("group_stats", [], OFPGroupStats, 2462 length_from=lambda pkt:pkt.len - 16)] 2463 2464 2465class OFPMPRequestGroupDesc(_ofp_header): 2466 name = "OFPMP_REQUEST_GROUP_DESC" 2467 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2468 ByteEnumField("type", 18, ofp_type), 2469 ShortField("len", None), 2470 IntField("xid", 0), 2471 ShortEnumField("mp_type", 7, ofp_multipart_types), 2472 FlagsField("flags", 0, 16, ofpmp_request_flags), 2473 XIntField("pad1", 0)] 2474 2475 2476class OFPGroupDesc(_ofp_header_item): 2477 name = "OFP_GROUP_DESC" 2478 fields_desc = [ShortField("len", None), 2479 ByteEnumField("type", 0, {0: "OFPGT_ALL", 2480 1: "OFPGT_SELECT", 2481 2: "OFPGT_INDIRECT", 2482 3: "OFPGT_FF"}), 2483 XByteField("pad", 0), 2484 IntEnumField("group_id", 0, ofp_group), 2485 PacketListField("buckets", None, OFPBucket, 2486 length_from=lambda pkt: pkt.len - 8)] 2487 2488 def extract_padding(self, s): 2489 return b"", s 2490 2491 2492class OFPMPReplyGroupDesc(_ofp_header): 2493 name = "OFPMP_REPLY_GROUP_DESC" 2494 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2495 ByteEnumField("type", 19, ofp_type), 2496 ShortField("len", None), 2497 IntField("xid", 0), 2498 ShortEnumField("mp_type", 7, ofp_multipart_types), 2499 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2500 XIntField("pad1", 0), 2501 PacketListField("group_descs", [], OFPGroupDesc, 2502 length_from=lambda pkt:pkt.len - 16)] 2503 2504 2505class OFPMPRequestGroupFeatures(_ofp_header): 2506 name = "OFPMP_REQUEST_GROUP_FEATURES" 2507 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2508 ByteEnumField("type", 18, ofp_type), 2509 ShortField("len", None), 2510 IntField("xid", 0), 2511 ShortEnumField("mp_type", 8, ofp_multipart_types), 2512 FlagsField("flags", 0, 16, ofpmp_request_flags), 2513 XIntField("pad1", 0)] 2514 2515 2516ofp_action_types_flags = [v for v in ofp_action_types.values() 2517 if v != 'OFPAT_EXPERIMENTER'] 2518 2519 2520class OFPMPReplyGroupFeatures(_ofp_header): 2521 name = "OFPMP_REPLY_GROUP_FEATURES" 2522 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2523 ByteEnumField("type", 19, ofp_type), 2524 ShortField("len", None), 2525 IntField("xid", 0), 2526 ShortEnumField("mp_type", 8, ofp_multipart_types), 2527 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2528 XIntField("pad1", 0), 2529 FlagsField("types", 0, 32, ["ALL", 2530 "SELECT", 2531 "INDIRECT", 2532 "FF"]), 2533 FlagsField("capabilities", 0, 32, ["SELECT_WEIGHT", 2534 "SELECT_LIVENESS", 2535 "CHAINING", 2536 "CHAINING_CHECKS"]), 2537 IntField("max_group_all", 0), 2538 IntField("max_group_select", 0), 2539 IntField("max_group_indirect", 0), 2540 IntField("max_group_ff", 0), 2541 # no ofpat_experimenter flag 2542 FlagsField("actions_all", 0, 32, ofp_action_types_flags), 2543 FlagsField("actions_select", 0, 32, ofp_action_types_flags), 2544 FlagsField("actions_indirect", 0, 32, ofp_action_types_flags), # noqa: E501 2545 FlagsField("actions_ff", 0, 32, ofp_action_types_flags)] 2546 2547 2548class OFPMPRequestMeter(_ofp_header): 2549 name = "OFPMP_REQUEST_METER" 2550 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2551 ByteEnumField("type", 18, ofp_type), 2552 ShortField("len", None), 2553 IntField("xid", 0), 2554 ShortEnumField("mp_type", 9, ofp_multipart_types), 2555 FlagsField("flags", 0, 16, ofpmp_request_flags), 2556 XIntField("pad1", 0), 2557 IntEnumField("meter_id", "ALL", ofp_meter), 2558 XIntField("pad2", 0)] 2559 2560 2561class OFPMeterBandStats(Packet): 2562 name = "OFP_METER_BAND_STATS" 2563 fields_desc = [LongField("packet_band_count", 0), 2564 LongField("byte_band_count", 0)] 2565 2566 def extract_padding(self, s): 2567 return b"", s 2568 2569 2570class OFPMeterStats(Packet): 2571 name = "OFP_GROUP_STATS" 2572 fields_desc = [IntEnumField("meter_id", 1, ofp_meter), 2573 ShortField("len", None), 2574 XBitField("pad", 0, 48), 2575 IntField("flow_count", 0), 2576 LongField("packet_in_count", 0), 2577 LongField("byte_in_count", 0), 2578 IntField("duration_sec", 0), 2579 IntField("duration_nsec", 0), 2580 PacketListField("band_stats", None, OFPMeterBandStats, 2581 length_from=lambda pkt:pkt.len - 40)] 2582 2583 def post_build(self, p, pay): 2584 if self.len is None: 2585 tmp_len = len(p) + len(pay) 2586 p = p[:4] + struct.pack("!H", tmp_len) + p[6:] 2587 return p + pay 2588 2589 def extract_padding(self, s): 2590 return b"", s 2591 2592 2593class OFPMPReplyMeter(_ofp_header): 2594 name = "OFPMP_REPLY_METER" 2595 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2596 ByteEnumField("type", 19, ofp_type), 2597 ShortField("len", None), 2598 IntField("xid", 0), 2599 ShortEnumField("mp_type", 9, ofp_multipart_types), 2600 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2601 XIntField("pad1", 0), 2602 PacketListField("meter_stats", [], OFPMeterStats, 2603 length_from=lambda pkt:pkt.len - 16)] 2604 2605 2606class OFPMPRequestMeterConfig(_ofp_header): 2607 name = "OFPMP_REQUEST_METER_CONFIG" 2608 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2609 ByteEnumField("type", 18, ofp_type), 2610 ShortField("len", None), 2611 IntField("xid", 0), 2612 ShortEnumField("mp_type", 10, ofp_multipart_types), 2613 FlagsField("flags", 0, 16, ofpmp_request_flags), 2614 XIntField("pad1", 0), 2615 IntEnumField("meter_id", "ALL", ofp_meter), 2616 XIntField("pad2", 0)] 2617 2618 2619class OFPMeterConfig(_ofp_header_item): 2620 name = "OFP_METER_CONFIG" 2621 fields_desc = [ShortField("len", None), 2622 FlagsField("flags", 0, 16, ["KBPS", 2623 "PKTPS", 2624 "BURST", 2625 "STATS"]), 2626 IntEnumField("meter_id", 1, ofp_meter), 2627 PacketListField("bands", [], OFPMBT, 2628 length_from=lambda pkt:pkt.len - 8)] 2629 2630 def extract_padding(self, s): 2631 return b"", s 2632 2633 2634class OFPMPReplyMeterConfig(_ofp_header): 2635 name = "OFPMP_REPLY_METER_CONFIG" 2636 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2637 ByteEnumField("type", 19, ofp_type), 2638 ShortField("len", None), 2639 IntField("xid", 0), 2640 ShortEnumField("mp_type", 10, ofp_multipart_types), 2641 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2642 XIntField("pad1", 0), 2643 PacketListField("meter_configs", [], OFPMeterConfig, 2644 length_from=lambda pkt:pkt.len - 16)] 2645 2646 2647class OFPMPRequestMeterFeatures(_ofp_header): 2648 name = "OFPMP_REQUEST_METER_FEATURES" 2649 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2650 ByteEnumField("type", 18, ofp_type), 2651 ShortField("len", None), 2652 IntField("xid", 0), 2653 ShortEnumField("mp_type", 11, ofp_multipart_types), 2654 FlagsField("flags", 0, 16, ofpmp_request_flags), 2655 XIntField("pad1", 0)] 2656 2657 2658class OFPMPReplyMeterFeatures(_ofp_header): 2659 name = "OFPMP_REPLY_METER_FEATURES" 2660 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2661 ByteEnumField("type", 19, ofp_type), 2662 ShortField("len", None), 2663 IntField("xid", 0), 2664 ShortEnumField("mp_type", 11, ofp_multipart_types), 2665 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2666 XIntField("pad1", 0), 2667 IntField("max_meter", 0), 2668 FlagsField("band_types", 0, 32, ["DROP", 2669 "DSCP_REMARK", 2670 "EXPERIMENTER"]), 2671 FlagsField("capabilities", 0, 32, ["KPBS", 2672 "PKTPS", 2673 "BURST", 2674 "STATS"]), 2675 ByteField("max_bands", 0), 2676 ByteField("max_color", 0), 2677 XShortField("pad2", 0)] 2678 2679 2680# table features for multipart messages # 2681 2682 2683class OFPTFPT(Packet): 2684 name = "Dummy OpenFlow3 Table Features Properties Header" 2685 2686 @classmethod 2687 def dispatch_hook(cls, _pkt=None, *args, **kargs): 2688 if _pkt and len(_pkt) >= 2: 2689 t = struct.unpack("!H", _pkt[:2])[0] 2690 return ofp_table_features_prop_cls.get(t, Raw) 2691 return Raw 2692 2693 def post_build(self, p, pay): 2694 tmp_len = self.len 2695 if tmp_len is None: 2696 tmp_len = len(p) + len(pay) 2697 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] 2698 zero_bytes = (8 - tmp_len % 8) % 8 2699 p += b"\x00" * zero_bytes 2700 # message with user-defined length will not be automatically padded 2701 return p + pay 2702 2703 def extract_padding(self, s): 2704 return b"", s 2705 2706 2707ofp_table_features_prop_types = {0: "OFPTFPT_INSTRUCTIONS", 2708 1: "OFPTFPT_INSTRUCTIONS_MISS", 2709 2: "OFPTFPT_NEXT_TABLES", 2710 3: "OFPTFPT_NEXT_TABLES_MISS", 2711 4: "OFPTFPT_WRITE_ACTIONS", 2712 5: "OFPTFPT_WRITE_ACTIONS_MISS", 2713 6: "OFPTFPT_APPLY_ACTIONS", 2714 7: "OFPTFPT_APPLY_ACTIONS_MISS", 2715 8: "OFPTFPT_MATCH", 2716 10: "OFPTFPT_WILDCARDS", 2717 12: "OFPTFPT_WRITE_SETFIELD", 2718 13: "OFPTFPT_WRITE_SETFIELD_MISS", 2719 14: "OFPTFPT_APPLY_SETFIELD", 2720 15: "OFPTFPT_APPLY_SETFIELD_MISS", 2721 65534: "OFPTFPT_EXPERIMENTER", 2722 65535: "OFPTFPT_EXPERIMENTER_MISS"} 2723 2724 2725class OFPTFPTInstructions(OFPTFPT): 2726 name = "OFPTFPT_INSTRUCTIONS" 2727 fields_desc = [ShortField("type", 0), 2728 ShortField("len", None), 2729 PacketListField("instruction_ids", [], OFPITID, 2730 length_from=lambda pkt:pkt.len - 4)] 2731 2732 2733class OFPTFPTInstructionsMiss(OFPTFPT): 2734 name = "OFPTFPT_INSTRUCTIONS_MISS" 2735 fields_desc = [ShortField("type", 1), 2736 ShortField("len", None), 2737 PacketListField("instruction_ids", [], OFPITID, 2738 length_from=lambda pkt:pkt.len - 4)] 2739 2740 2741class OFPTableID(Packet): 2742 name = "OFP_TABLE_ID" 2743 fields_desc = [ByteEnumField("table_id", 0, ofp_table)] 2744 2745 def extract_padding(self, s): 2746 return b"", s 2747 2748 2749class OFPTFPTNextTables(OFPTFPT): 2750 name = "OFPTFPT_NEXT_TABLES" 2751 fields_desc = [ShortField("type", 2), 2752 ShortField("len", None), 2753 PacketListField("next_table_ids", None, OFPTableID, 2754 length_from=lambda pkt:pkt.len - 4)] 2755 2756 2757class OFPTFPTNextTablesMiss(OFPTFPT): 2758 name = "OFPTFPT_NEXT_TABLES_MISS" 2759 fields_desc = [ShortField("type", 3), 2760 ShortField("len", None), 2761 PacketListField("next_table_ids", None, OFPTableID, 2762 length_from=lambda pkt:pkt.len - 4)] 2763 2764 2765class OFPTFPTWriteActions(OFPTFPT): 2766 name = "OFPTFPT_WRITE_ACTIONS" 2767 fields_desc = [ShortField("type", 4), 2768 ShortField("len", None), 2769 PacketListField("action_ids", [], OFPATID, 2770 length_from=lambda pkt:pkt.len - 4)] 2771 2772 2773class OFPTFPTWriteActionsMiss(OFPTFPT): 2774 name = "OFPTFPT_WRITE_ACTIONS_MISS" 2775 fields_desc = [ShortField("type", 5), 2776 ShortField("len", None), 2777 PacketListField("action_ids", [], OFPATID, 2778 length_from=lambda pkt:pkt.len - 4)] 2779 2780 2781class OFPTFPTApplyActions(OFPTFPT): 2782 name = "OFPTFPT_APPLY_ACTIONS" 2783 fields_desc = [ShortField("type", 6), 2784 ShortField("len", None), 2785 PacketListField("action_ids", [], OFPATID, 2786 length_from=lambda pkt:pkt.len - 4)] 2787 2788 2789class OFPTFPTApplyActionsMiss(OFPTFPT): 2790 name = "OFPTFPT_APPLY_ACTIONS_MISS" 2791 fields_desc = [ShortField("type", 7), 2792 ShortField("len", None), 2793 PacketListField("action_ids", [], OFPATID, 2794 length_from=lambda pkt:pkt.len - 4)] 2795 2796 2797class OFPTFPTMatch(OFPTFPT): 2798 name = "OFPTFPT_MATCH" 2799 fields_desc = [ShortField("type", 8), 2800 ShortField("len", None), 2801 PacketListField("oxm_ids", [], OXMID, 2802 length_from=lambda pkt:pkt.len - 4)] 2803 2804 2805class OFPTFPTWildcards(OFPTFPT): 2806 name = "OFPTFPT_WILDCARDS" 2807 fields_desc = [ShortField("type", 10), 2808 ShortField("len", None), 2809 PacketListField("oxm_ids", [], OXMID, 2810 length_from=lambda pkt:pkt.len - 4)] 2811 2812 2813class OFPTFPTWriteSetField(OFPTFPT): 2814 name = "OFPTFPT_WRITE_SETFIELD" 2815 fields_desc = [ShortField("type", 12), 2816 ShortField("len", None), 2817 PacketListField("oxm_ids", [], OXMID, 2818 length_from=lambda pkt:pkt.len - 4)] 2819 2820 2821class OFPTFPTWriteSetFieldMiss(OFPTFPT): 2822 name = "OFPTFPT_WRITE_SETFIELD_MISS" 2823 fields_desc = [ShortField("type", 13), 2824 ShortField("len", None), 2825 PacketListField("oxm_ids", [], OXMID, 2826 length_from=lambda pkt:pkt.len - 4)] 2827 2828 2829class OFPTFPTApplySetField(OFPTFPT): 2830 name = "OFPTFPT_APPLY_SETFIELD" 2831 fields_desc = [ShortField("type", 14), 2832 ShortField("len", None), 2833 PacketListField("oxm_ids", [], OXMID, 2834 length_from=lambda pkt:pkt.len - 4)] 2835 2836 2837class OFPTFPTApplySetFieldMiss(OFPTFPT): 2838 name = "OFPTFPT_APPLY_SETFIELD_MISS" 2839 fields_desc = [ShortField("type", 15), 2840 ShortField("len", None), 2841 PacketListField("oxm_ids", [], OXMID, 2842 length_from=lambda pkt:pkt.len - 4)] 2843 2844 2845class OFPTFPTExperimenter(OFPTFPT): 2846 name = "OFPTFPT_EXPERIMENTER" 2847 fields_desc = [ShortField("type", 65534), 2848 ShortField("len", None), 2849 IntField("experimenter", 0), 2850 IntField("exp_type", 0), 2851 PacketLenField("experimenter_data", None, Raw, 2852 length_from=lambda pkt: pkt.len - 12)] 2853 2854 2855class OFPTFPTExperimenterMiss(OFPTFPT): 2856 name = "OFPTFPT_EXPERIMENTER_MISS" 2857 fields_desc = [ShortField("type", 65535), 2858 ShortField("len", None), 2859 IntField("experimenter", 0), 2860 IntField("exp_type", 0), 2861 PacketLenField("experimenter_data", None, Raw, 2862 length_from=lambda pkt: pkt.len - 12)] 2863 2864 2865ofp_table_features_prop_cls = {0: OFPTFPTInstructions, 2866 1: OFPTFPTInstructionsMiss, 2867 2: OFPTFPTNextTables, 2868 3: OFPTFPTNextTablesMiss, 2869 4: OFPTFPTWriteActions, 2870 5: OFPTFPTWriteActionsMiss, 2871 6: OFPTFPTApplyActions, 2872 7: OFPTFPTApplyActionsMiss, 2873 8: OFPTFPTMatch, 2874 10: OFPTFPTWildcards, 2875 12: OFPTFPTWriteSetField, 2876 13: OFPTFPTWriteSetFieldMiss, 2877 14: OFPTFPTApplySetField, 2878 15: OFPTFPTApplySetFieldMiss, 2879 65534: OFPTFPTExperimenter, 2880 65535: OFPTFPTExperimenterMiss} 2881 2882 2883class OFPTableFeatures(_ofp_header_item): 2884 name = "OFP_TABLE_FEATURES" 2885 fields_desc = [ShortField("len", None), 2886 ByteEnumField("table_id", 0, ofp_table), 2887 XBitField("pad", 0, 40), 2888 StrFixedLenField("table_name", "", 32), 2889 LongField("metadata_match", 0), 2890 LongField("metadata_write", 0), 2891 IntEnumField("config", 0, {0: "OFPTC_NO_MASK", 2892 3: "OFPTC_DEPRECATED_MASK"}), 2893 IntField("max_entries", 0), 2894 PacketListField("properties", [], OFPTFPT, 2895 length_from=lambda pkt:pkt.len - 64)] 2896 2897 def extract_padding(self, s): 2898 return b"", s 2899 2900 2901class OFPMPRequestTableFeatures(_ofp_header): 2902 name = "OFPMP_REQUEST_TABLE_FEATURES" 2903 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2904 ByteEnumField("type", 18, ofp_type), 2905 ShortField("len", None), 2906 IntField("xid", 0), 2907 ShortEnumField("mp_type", 12, ofp_multipart_types), 2908 FlagsField("flags", 0, 16, ofpmp_request_flags), 2909 XIntField("pad1", 0), 2910 PacketListField("table_features", [], OFPTableFeatures, 2911 length_from=lambda pkt:pkt.len - 16)] 2912 2913 2914class OFPMPReplyTableFeatures(_ofp_header): 2915 name = "OFPMP_REPLY_TABLE_FEATURES" 2916 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2917 ByteEnumField("type", 19, ofp_type), 2918 ShortField("len", None), 2919 IntField("xid", 0), 2920 ShortEnumField("mp_type", 12, ofp_multipart_types), 2921 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2922 XIntField("pad1", 0), 2923 PacketListField("table_features", [], OFPTableFeatures, 2924 length_from=lambda pkt:pkt.len - 16)] 2925 2926 2927# end of table features # 2928 2929 2930class OFPMPRequestPortDesc(_ofp_header): 2931 name = "OFPMP_REQUEST_PORT_DESC" 2932 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2933 ByteEnumField("type", 18, ofp_type), 2934 ShortField("len", None), 2935 IntField("xid", 0), 2936 ShortEnumField("mp_type", 13, ofp_multipart_types), 2937 FlagsField("flags", 0, 16, ofpmp_request_flags), 2938 XIntField("pad1", 0), 2939 IntEnumField("port_no", 0, ofp_port_no), 2940 XIntField("pad", 0)] 2941 2942 2943class OFPMPReplyPortDesc(_ofp_header): 2944 name = "OFPMP_REPLY_PORT_DESC" 2945 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2946 ByteEnumField("type", 19, ofp_type), 2947 ShortField("len", None), 2948 IntField("xid", 0), 2949 ShortEnumField("mp_type", 13, ofp_multipart_types), 2950 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2951 XIntField("pad1", 0), 2952 PacketListField("ports", None, OFPPort, 2953 length_from=lambda pkt:pkt.len - 16)] 2954 2955 2956class OFPMPRequestExperimenter(_ofp_header): 2957 name = "OFPST_REQUEST_EXPERIMENTER" 2958 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2959 ByteEnumField("type", 18, ofp_type), 2960 ShortField("len", None), 2961 IntField("xid", 0), 2962 ShortEnumField("mp_type", 65535, ofp_multipart_types), 2963 FlagsField("flags", 0, 16, ofpmp_request_flags), 2964 XIntField("pad1", 0), 2965 IntField("experimenter", 0), 2966 IntField("exp_type", 0)] 2967 2968 2969class OFPMPReplyExperimenter(_ofp_header): 2970 name = "OFPST_REPLY_EXPERIMENTER" 2971 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 2972 ByteEnumField("type", 19, ofp_type), 2973 ShortField("len", None), 2974 IntField("xid", 0), 2975 ShortEnumField("mp_type", 65535, ofp_multipart_types), 2976 FlagsField("flags", 0, 16, ofpmp_reply_flags), 2977 XIntField("pad1", 0), 2978 IntField("experimenter", 0), 2979 IntField("exp_type", 0)] 2980 2981 2982# ofp_multipart_request/reply_cls allows generic method OpenFlow3() 2983# to choose the right class for dissection 2984ofp_multipart_request_cls = {0: OFPMPRequestDesc, 2985 1: OFPMPRequestFlow, 2986 2: OFPMPRequestAggregate, 2987 3: OFPMPRequestTable, 2988 4: OFPMPRequestPortStats, 2989 5: OFPMPRequestQueue, 2990 6: OFPMPRequestGroup, 2991 7: OFPMPRequestGroupDesc, 2992 8: OFPMPRequestGroupFeatures, 2993 9: OFPMPRequestMeter, 2994 10: OFPMPRequestMeterConfig, 2995 11: OFPMPRequestMeterFeatures, 2996 12: OFPMPRequestTableFeatures, 2997 13: OFPMPRequestPortDesc, 2998 65535: OFPMPRequestExperimenter} 2999 3000ofp_multipart_reply_cls = {0: OFPMPReplyDesc, 3001 1: OFPMPReplyFlow, 3002 2: OFPMPReplyAggregate, 3003 3: OFPMPReplyTable, 3004 4: OFPMPReplyPortStats, 3005 5: OFPMPReplyQueue, 3006 6: OFPMPReplyGroup, 3007 7: OFPMPReplyGroupDesc, 3008 8: OFPMPReplyGroupFeatures, 3009 9: OFPMPReplyMeter, 3010 10: OFPMPReplyMeterConfig, 3011 11: OFPMPReplyMeterFeatures, 3012 12: OFPMPReplyTableFeatures, 3013 13: OFPMPReplyPortDesc, 3014 65535: OFPMPReplyExperimenter} 3015 3016# end of OFPT_MULTIPART # 3017 3018 3019class OFPTBarrierRequest(_ofp_header): 3020 name = "OFPT_BARRIER_REQUEST" 3021 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3022 ByteEnumField("type", 20, ofp_type), 3023 ShortField("len", None), 3024 IntField("xid", 0)] 3025 3026 3027class OFPTBarrierReply(_ofp_header): 3028 name = "OFPT_BARRIER_REPLY" 3029 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3030 ByteEnumField("type", 21, ofp_type), 3031 ShortField("len", None), 3032 IntField("xid", 0)] 3033 3034 3035class OFPTQueueGetConfigRequest(_ofp_header): 3036 name = "OFPT_QUEUE_GET_CONFIG_REQUEST" 3037 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3038 ByteEnumField("type", 22, ofp_type), 3039 ShortField("len", None), 3040 IntField("xid", 0), 3041 IntEnumField("port_no", "ANY", ofp_port_no), 3042 XIntField("pad", 0)] 3043 3044 3045class OFPTQueueGetConfigReply(_ofp_header): 3046 name = "OFPT_QUEUE_GET_CONFIG_REPLY" 3047 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3048 ByteEnumField("type", 23, ofp_type), 3049 ShortField("len", None), 3050 IntField("xid", 0), 3051 IntEnumField("port", 0, ofp_port_no), 3052 XIntField("pad", 0), 3053 PacketListField("queues", [], OFPPacketQueue, 3054 length_from=lambda pkt:pkt.len - 16)] 3055 3056 3057class OFPTRoleRequest(_ofp_header): 3058 name = "OFPT_ROLE_REQUEST" 3059 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3060 ByteEnumField("type", 24, ofp_type), 3061 ShortField("len", None), 3062 IntField("xid", 0), 3063 IntEnumField("role", 0, {0: "OFPCR_ROLE_NOCHANGE", 3064 1: "OFPCR_ROLE_EQUAL", 3065 2: "OFPCR_ROLE_MASTER", 3066 3: "OFPCR_ROLE_SLAVE"}), 3067 XIntField("pad", 0), 3068 LongField("generation_id", 0)] 3069 3070 3071class OFPTRoleReply(OFPTRoleRequest): 3072 name = "OFPT_ROLE_REPLY" 3073 type = 25 3074 3075 3076class OFPTGetAsyncRequest(_ofp_header): 3077 name = "OFPT_GET_ASYNC_REQUEST" 3078 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3079 ByteEnumField("type", 26, ofp_type), 3080 ShortField("len", 8), 3081 IntField("xid", 0)] 3082 3083 3084ofp_packet_in_reason = ["NO_MATCH", 3085 "ACTION", 3086 "INVALID_TTL"] 3087 3088ofp_port_reason = ["ADD", 3089 "DELETE", 3090 "MODIFY"] 3091 3092ofp_flow_removed_reason = ["IDLE_TIMEOUT", 3093 "HARD_TIMEOUT", 3094 "DELETE", 3095 "GROUP_DELETE"] 3096 3097 3098class OFPTGetAsyncReply(_ofp_header): 3099 name = "OFPT_GET_ASYNC_REPLY" 3100 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3101 ByteEnumField("type", 27, ofp_type), 3102 ShortField("len", 32), 3103 IntField("xid", 0), 3104 FlagsField("packet_in_mask_master", 0, 32, ofp_packet_in_reason), # noqa: E501 3105 FlagsField("packet_in_mask_slave", 0, 32, ofp_packet_in_reason), # noqa: E501 3106 FlagsField("port_status_mask_master", 0, 32, ofp_port_reason), # noqa: E501 3107 FlagsField("port_status_mask_slave", 0, 32, ofp_port_reason), # noqa: E501 3108 FlagsField("flow_removed_mask_master", 0, 32, ofp_flow_removed_reason), # noqa: E501 3109 FlagsField("flow_removed_mask_slave", 0, 32, ofp_flow_removed_reason)] # noqa: E501 3110 3111 3112class OFPTSetAsync(OFPTGetAsyncReply): 3113 name = "OFPT_SET_ASYNC" 3114 type = 28 3115 3116 3117class OFPTMeterMod(_ofp_header): 3118 name = "OFPT_METER_MOD" 3119 fields_desc = [ByteEnumField("version", 0x04, ofp_version), 3120 ByteEnumField("type", 29, ofp_type), 3121 ShortField("len", None), 3122 IntField("xid", 0), 3123 ShortEnumField("cmd", 0, {0: "OFPMC_ADD", 3124 1: "OFPMC_MODIFY", 3125 2: "OFPMC_DELETE"}), 3126 FlagsField("flags", 0, 16, ["KBPS", 3127 "PKTPS", 3128 "BURST", 3129 "STATS"]), 3130 IntEnumField("meter_id", 1, ofp_meter), 3131 PacketListField("bands", [], OFPMBT, 3132 length_from=lambda pkt:pkt.len - 16)] 3133 3134 3135# ofpt_cls allows generic method OpenFlow3() to choose the right class for dissection # noqa: E501 3136ofpt_cls = {0: OFPTHello, 3137 # 1: OFPTError, 3138 2: OFPTEchoRequest, 3139 3: OFPTEchoReply, 3140 4: OFPTExperimenter, 3141 5: OFPTFeaturesRequest, 3142 6: OFPTFeaturesReply, 3143 7: OFPTGetConfigRequest, 3144 8: OFPTGetConfigReply, 3145 9: OFPTSetConfig, 3146 10: OFPTPacketIn, 3147 11: OFPTFlowRemoved, 3148 12: OFPTPortStatus, 3149 13: OFPTPacketOut, 3150 14: OFPTFlowMod, 3151 15: OFPTGroupMod, 3152 16: OFPTPortMod, 3153 17: OFPTTableMod, 3154 # 18: OFPTMultipartRequest, 3155 # 19: OFPTMultipartReply, 3156 20: OFPTBarrierRequest, 3157 21: OFPTBarrierReply, 3158 22: OFPTQueueGetConfigRequest, 3159 23: OFPTQueueGetConfigReply, 3160 24: OFPTRoleRequest, 3161 25: OFPTRoleReply, 3162 26: OFPTGetAsyncRequest, 3163 27: OFPTGetAsyncReply, 3164 28: OFPTSetAsync, 3165 29: OFPTMeterMod} 3166