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