esp32_bluetooth_classic_sni.../libs/scapy/contrib/openflow3.py
Matheus Eduardo Garbelini 86890704fd initial commit
todo: add documentation & wireshark dissector
2021-08-31 19:51:03 +08:00

3165 lines
124 KiB
Python
Executable file

# This file is part of Scapy
# See http://www.secdev.org/projects/scapy for more information
# Copyright (C) Philippe Biondi <phil@secdev.org>
# This program is published under a GPLv2 license
# Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr>
# OpenFlow is an open standard used in SDN deployments.
# Based on OpenFlow v1.3.4
# Specifications can be retrieved from https://www.opennetworking.org/
# scapy.contrib.description = OpenFlow v1.3
# scapy.contrib.status = loads
from __future__ import absolute_import
import copy
import struct
from scapy.compat import orb, raw
from scapy.config import conf
from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \
FieldLenField, FlagsField, IntEnumField, IntField, IPField, \
LongField, MACField, PacketField, PacketListField, ShortEnumField, \
ShortField, StrFixedLenField, X3BytesField, XBitField, XByteField, \
XIntField, XShortField, PacketLenField
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, Raw
from scapy.modules import six
from scapy.contrib.openflow import _ofp_header, _ofp_header_item, \
OFPacketField, OpenFlow, _UnknownOpenFlow
#####################################################
# Predefined values #
#####################################################
ofp_port_no = {0xfffffff8: "IN_PORT",
0xfffffff9: "TABLE",
0xfffffffa: "NORMAL",
0xfffffffb: "FLOOD",
0xfffffffc: "ALL",
0xfffffffd: "CONTROLLER",
0xfffffffe: "LOCAL",
0xffffffff: "ANY"}
ofp_group = {0xffffff00: "MAX",
0xfffffffc: "ALL",
0xffffffff: "ANY"}
ofp_table = {0xfe: "MAX",
0xff: "ALL"}
ofp_queue = {0xffffffff: "ALL"}
ofp_meter = {0xffff0000: "MAX",
0xfffffffd: "SLOWPATH",
0xfffffffe: "CONTROLLER",
0xffffffff: "ALL"}
ofp_buffer = {0xffffffff: "NO_BUFFER"}
ofp_max_len = {0xffff: "NO_BUFFER"}
#####################################################
# Common structures #
#####################################################
# The following structures will be used in different types
# of OpenFlow messages: ports, matches/OXMs, actions,
# instructions, buckets, queues, meter bands.
# Hello elements #
ofp_hello_elem_types = {1: "OFPHET_VERSIONBITMAP"}
class OFPHET(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_hello_elem_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPHETVersionBitmap(_ofp_header):
name = "OFPHET_VERSIONBITMAP"
fields_desc = [ShortEnumField("type", 1, ofp_hello_elem_types),
ShortField("len", 8),
FlagsField("bitmap", 0, 32, ["Type 0",
"OFv1.0",
"OFv1.1",
"OFv1.2",
"OFv1.3",
"OFv1.4",
"OFv1.5"])]
ofp_hello_elem_cls = {1: OFPHETVersionBitmap}
# Ports #
ofp_port_config = ["PORT_DOWN",
"NO_STP", # undefined in v1.3
"NO_RECV",
"NO_RECV_STP", # undefined in v1.3
"NO_FLOOD", # undefined in v1.3
"NO_FWD",
"NO_PACKET_IN"]
ofp_port_state = ["LINK_DOWN",
"BLOCKED",
"LIVE"]
ofp_port_features = ["10MB_HD",
"10MB_FD",
"100MB_HD",
"100MB_FD",
"1GB_HD",
"1GB_FD",
"10GB_FD",
"40GB_FD",
"100GB_FD",
"1TB_FD",
"OTHER",
"COPPER",
"FIBER",
"AUTONEG",
"PAUSE",
"PAUSE_ASYM"]
class OFPPort(Packet):
name = "OFP_PHY_PORT"
fields_desc = [IntEnumField("port_no", 0, ofp_port_no),
XIntField("pad1", 0),
MACField("hw_addr", "0"),
XShortField("pad2", 0),
StrFixedLenField("port_name", "", 16),
FlagsField("config", 0, 32, ofp_port_config),
FlagsField("state", 0, 32, ofp_port_state),
FlagsField("curr", 0, 32, ofp_port_features),
FlagsField("advertised", 0, 32, ofp_port_features),
FlagsField("supported", 0, 32, ofp_port_features),
FlagsField("peer", 0, 32, ofp_port_features),
IntField("curr_speed", 0),
IntField("max_speed", 0)]
def extract_padding(self, s):
return b"", s
# Matches & OXMs #
ofp_oxm_classes = {0: "OFPXMC_NXM_0",
1: "OFPXMC_NXM_1",
0x8000: "OFPXMC_OPENFLOW_BASIC",
0xffff: "OFPXMC_EXPERIMENTER"}
ofp_oxm_names = {0: "OFB_IN_PORT",
1: "OFB_IN_PHY_PORT",
2: "OFB_METADATA",
3: "OFB_ETH_DST",
4: "OFB_ETH_SRC",
5: "OFB_ETH_TYPE",
6: "OFB_VLAN_VID",
7: "OFB_VLAN_PCP",
8: "OFB_IP_DSCP",
9: "OFB_IP_ECN",
10: "OFB_IP_PROTO",
11: "OFB_IPV4_SRC",
12: "OFB_IPV4_DST",
13: "OFB_TCP_SRC",
14: "OFB_TCP_DST",
15: "OFB_UDP_SRC",
16: "OFB_UDP_DST",
17: "OFB_SCTP_SRC",
18: "OFB_SCTP_DST",
19: "OFB_ICMPV4_TYPE",
20: "OFB_ICMPV4_CODE",
21: "OFB_ARP_OP",
22: "OFB_ARP_SPA",
23: "OFB_ARP_TPA",
24: "OFB_ARP_SHA",
25: "OFB_ARP_THA",
26: "OFB_IPV6_SRC",
27: "OFB_IPV6_DST",
28: "OFB_IPV6_FLABEL",
29: "OFB_ICMPV6_TYPE",
30: "OFB_ICMPV6_CODE",
31: "OFB_IPV6_ND_TARGET",
32: "OFB_IPV6_ND_SLL",
33: "OFB_IPV6_ND_TLL",
34: "OFB_MPLS_LABEL",
35: "OFB_MPLS_TC",
36: "OFB_MPLS_BOS",
37: "OFB_PBB_ISID",
38: "OFB_TUNNEL_ID",
39: "OFB_IPV6_EXTHDR"}
ofp_oxm_constr = {0: ["OFBInPort", "in_port", 4],
1: ["OFBInPhyPort", "in_phy_port", 4],
2: ["OFBMetadata", "metadata", 8],
3: ["OFBEthDst", "eth_dst", 6],
4: ["OFBEthSrc", "eth_src", 6],
5: ["OFBEthType", "eth_type", 2],
6: ["OFBVLANVID", "vlan_vid", 2],
7: ["OFBVLANPCP", "vlan_pcp", 1],
8: ["OFBIPDSCP", "ip_dscp", 1],
9: ["OFBIPECN", "ip_ecn", 1],
10: ["OFBIPProto", "ip_proto", 1],
11: ["OFBIPv4Src", "ipv4_src", 4],
12: ["OFBIPv4Dst", "ipv4_dst", 4],
13: ["OFBTCPSrc", "tcp_src", 2],
14: ["OFBTCPDst", "tcp_dst", 2],
15: ["OFBUDPSrc", "udp_src", 2],
16: ["OFBUDPDst", "udp_dst", 2],
17: ["OFBSCTPSrc", "sctp_src", 2],
18: ["OFBSCTPDst", "sctp_dst", 2],
19: ["OFBICMPv4Type", "icmpv4_type", 1],
20: ["OFBICMPv4Code", "icmpv4_code", 1],
21: ["OFBARPOP", "arp_op", 2],
22: ["OFBARPSPA", "arp_spa", 4],
23: ["OFBARPTPA", "arp_tpa", 4],
24: ["OFBARPSHA", "arp_sha", 6],
25: ["OFBARPTHA", "arp_tha", 6],
26: ["OFBIPv6Src", "ipv6_src", 16],
27: ["OFBIPv6Dst", "ipv6_dst", 16],
28: ["OFBIPv6FLabel", "ipv6_flabel", 4],
29: ["OFBICMPv6Type", "icmpv6_type", 1],
30: ["OFBICMPv6Code", "icmpv6_code", 1],
31: ["OFBIPv6NDTarget", "ipv6_nd_target", 16],
32: ["OFBIPv6NDSLL", "ipv6_sll", 6],
33: ["OFBIPv6NDTLL", "ipv6_tll", 6],
34: ["OFBMPLSLabel", "mpls_label", 4],
35: ["OFBMPLSTC", "mpls_tc", 1],
36: ["OFBMPLSBoS", "mpls_bos", 1],
37: ["OFBPBBISID", "pbb_isid", 3],
38: ["OFBTunnelID", "tunnel_id", 8],
39: ["OFBIPv6ExtHdr", "ipv6_ext_hdr_flags", 2]}
# the ipv6flags array is useful only to the OFBIPv6ExtHdr class
ipv6flags = ["NONEXT",
"ESP",
"AUTH",
"DEST",
"FRAG",
"ROUTER",
"HOP",
"UNREP",
"UNSEQ"]
# here we fill ofp_oxm_fields with the fields that will be used
# to generate the various OXM classes
# e.g. the call to add_ofp_oxm_fields(0, ["OFBInPort", "in_port", 4])
# will add {0: [ShortEnumField("class",..), BitEnumField("field",..),..]}
ofp_oxm_fields = {}
def add_ofp_oxm_fields(i, org):
ofp_oxm_fields[i] = [ShortEnumField("class", "OFPXMC_OPENFLOW_BASIC", ofp_oxm_classes), # noqa: E501
BitEnumField("field", i // 2, 7, ofp_oxm_names),
BitField("hasmask", i % 2, 1)]
ofp_oxm_fields[i].append(ByteField("len", org[2] + org[2] * (i % 2)))
if i // 2 == 0: # OFBInPort
ofp_oxm_fields[i].append(IntEnumField(org[1], 0, ofp_port_no))
elif i // 2 == 3 or i // 2 == 4: # OFBEthSrc & OFBEthDst
ofp_oxm_fields[i].append(MACField(org[1], None))
elif i // 2 == 11 or i // 2 == 12: # OFBIPv4Src & OFBIPv4Dst
ofp_oxm_fields[i].append(IPField(org[1], "0"))
elif i // 2 == 39: # OFBIPv6ExtHdr
ofp_oxm_fields[i].append(FlagsField(org[1], 0, 8 * org[2], ipv6flags))
else:
ofp_oxm_fields[i].append(BitField(org[1], 0, 8 * org[2]))
if i % 2:
ofp_oxm_fields[i].append(BitField(org[1] + "_mask", 0, 8 * org[2]))
# some HM classes are not supported par OFv1.3 but we will create them anyway
for i, cls in ofp_oxm_constr.items():
add_ofp_oxm_fields(2 * i, cls)
add_ofp_oxm_fields(2 * i + 1, cls)
# now we create every OXM class with the same call,
# (except that static variable create_oxm_class.i is each time different)
# and we fill ofp_oxm_cls with them
ofp_oxm_cls = {}
ofp_oxm_id_cls = {}
def _create_oxm_cls():
# static variable initialization
if not hasattr(_create_oxm_cls, "i"):
_create_oxm_cls.i = 0
index = _create_oxm_cls.i
cls_name = ofp_oxm_constr[index // 4][0]
# we create standard OXM then OXM ID then OXM with mask then OXM-hasmask ID
if index % 4 == 2:
cls_name += "HM"
if index % 2:
cls_name += "ID"
oxm_name = ofp_oxm_names[index // 4]
oxm_fields = ofp_oxm_fields[index // 2]
# for ID classes we just want the first 4 fields (no payload)
if index % 2:
oxm_fields = oxm_fields[:4]
cls = type(cls_name, (Packet,), {"name": oxm_name, "fields_desc": oxm_fields}) # noqa: E501
# the first call to special function type will create the same class as in
# class OFBInPort(Packet):
# def __init__(self):
# self.name = "OFB_IN_PORT"
# self.fields_desc = [ ShortEnumField("class", 0x8000, ofp_oxm_classes),
# BitEnumField("field", 0, 7, ofp_oxm_names),
# BitField("hasmask", 0, 1),
# ByteField("len", 4),
# IntEnumField("in_port", 0, ofp_port_no) ]
if index % 2 == 0:
ofp_oxm_cls[index // 2] = cls
else:
ofp_oxm_id_cls[index // 2] = cls
_create_oxm_cls.i += 1
cls.extract_padding = lambda self, s: (b"", s)
return cls
OFBInPort = _create_oxm_cls()
OFBInPortID = _create_oxm_cls()
OFBInPortHM = _create_oxm_cls()
OFBInPortHMID = _create_oxm_cls()
OFBInPhyPort = _create_oxm_cls()
OFBInPhyPortID = _create_oxm_cls()
OFBInPhyPortHM = _create_oxm_cls()
OFBInPhyPortHMID = _create_oxm_cls()
OFBMetadata = _create_oxm_cls()
OFBMetadataID = _create_oxm_cls()
OFBMetadataHM = _create_oxm_cls()
OFBMetadataHMID = _create_oxm_cls()
OFBEthDst = _create_oxm_cls()
OFBEthDstID = _create_oxm_cls()
OFBEthDstHM = _create_oxm_cls()
OFBEthDstHMID = _create_oxm_cls()
OFBEthSrc = _create_oxm_cls()
OFBEthSrcID = _create_oxm_cls()
OFBEthSrcHM = _create_oxm_cls()
OFBEthSrcHMID = _create_oxm_cls()
OFBEthType = _create_oxm_cls()
OFBEthTypeID = _create_oxm_cls()
OFBEthTypeHM = _create_oxm_cls()
OFBEthTypeHMID = _create_oxm_cls()
OFBVLANVID = _create_oxm_cls()
OFBVLANVIDID = _create_oxm_cls()
OFBVLANVIDHM = _create_oxm_cls()
OFBVLANVIDHMID = _create_oxm_cls()
OFBVLANPCP = _create_oxm_cls()
OFBVLANPCPID = _create_oxm_cls()
OFBVLANPCPHM = _create_oxm_cls()
OFBVLANPCPHMID = _create_oxm_cls()
OFBIPDSCP = _create_oxm_cls()
OFBIPDSCPID = _create_oxm_cls()
OFBIPDSCPHM = _create_oxm_cls()
OFBIPDSCPHMID = _create_oxm_cls()
OFBIPECN = _create_oxm_cls()
OFBIPECNID = _create_oxm_cls()
OFBIPECNHM = _create_oxm_cls()
OFBIPECNHMID = _create_oxm_cls()
OFBIPProto = _create_oxm_cls()
OFBIPProtoID = _create_oxm_cls()
OFBIPProtoHM = _create_oxm_cls()
OFBIPProtoHMID = _create_oxm_cls()
OFBIPv4Src = _create_oxm_cls()
OFBIPv4SrcID = _create_oxm_cls()
OFBIPv4SrcHM = _create_oxm_cls()
OFBIPv4SrcHMID = _create_oxm_cls()
OFBIPv4Dst = _create_oxm_cls()
OFBIPv4DstID = _create_oxm_cls()
OFBIPv4DstHM = _create_oxm_cls()
OFBIPv4DstHMID = _create_oxm_cls()
OFBTCPSrc = _create_oxm_cls()
OFBTCPSrcID = _create_oxm_cls()
OFBTCPSrcHM = _create_oxm_cls()
OFBTCPSrcHMID = _create_oxm_cls()
OFBTCPDst = _create_oxm_cls()
OFBTCPDstID = _create_oxm_cls()
OFBTCPDstHM = _create_oxm_cls()
OFBTCPDstHMID = _create_oxm_cls()
OFBUDPSrc = _create_oxm_cls()
OFBUDPSrcID = _create_oxm_cls()
OFBUDPSrcHM = _create_oxm_cls()
OFBUDPSrcHMID = _create_oxm_cls()
OFBUDPDst = _create_oxm_cls()
OFBUDPDstID = _create_oxm_cls()
OFBUDPDstHM = _create_oxm_cls()
OFBUDPDstHMID = _create_oxm_cls()
OFBSCTPSrc = _create_oxm_cls()
OFBSCTPSrcID = _create_oxm_cls()
OFBSCTPSrcHM = _create_oxm_cls()
OFBSCTPSrcHMID = _create_oxm_cls()
OFBSCTPDst = _create_oxm_cls()
OFBSCTPDstID = _create_oxm_cls()
OFBSCTPDstHM = _create_oxm_cls()
OFBSCTPDstHMID = _create_oxm_cls()
OFBICMPv4Type = _create_oxm_cls()
OFBICMPv4TypeID = _create_oxm_cls()
OFBICMPv4TypeHM = _create_oxm_cls()
OFBICMPv4TypeHMID = _create_oxm_cls()
OFBICMPv4Code = _create_oxm_cls()
OFBICMPv4CodeID = _create_oxm_cls()
OFBICMPv4CodeHM = _create_oxm_cls()
OFBICMPv4CodeHMID = _create_oxm_cls()
OFBARPOP = _create_oxm_cls()
OFBARPOPID = _create_oxm_cls()
OFBARPOPHM = _create_oxm_cls()
OFBARPOPHMID = _create_oxm_cls()
OFBARPSPA = _create_oxm_cls()
OFBARPSPAID = _create_oxm_cls()
OFBARPSPAHM = _create_oxm_cls()
OFBARPSPAHMID = _create_oxm_cls()
OFBARPTPA = _create_oxm_cls()
OFBARPTPAID = _create_oxm_cls()
OFBARPTPAHM = _create_oxm_cls()
OFBARPTPAHMID = _create_oxm_cls()
OFBARPSHA = _create_oxm_cls()
OFBARPSHAID = _create_oxm_cls()
OFBARPSHAHM = _create_oxm_cls()
OFBARPSHAHMID = _create_oxm_cls()
OFBARPTHA = _create_oxm_cls()
OFBARPTHAID = _create_oxm_cls()
OFBARPTHAHM = _create_oxm_cls()
OFBARPTHAHMID = _create_oxm_cls()
OFBIPv6Src = _create_oxm_cls()
OFBIPv6SrcID = _create_oxm_cls()
OFBIPv6SrcHM = _create_oxm_cls()
OFBIPv6SrcHMID = _create_oxm_cls()
OFBIPv6Dst = _create_oxm_cls()
OFBIPv6DstID = _create_oxm_cls()
OFBIPv6DstHM = _create_oxm_cls()
OFBIPv6DstHMID = _create_oxm_cls()
OFBIPv6FLabel = _create_oxm_cls()
OFBIPv6FLabelID = _create_oxm_cls()
OFBIPv6FLabelHM = _create_oxm_cls()
OFBIPv6FLabelHMID = _create_oxm_cls()
OFBICMPv6Type = _create_oxm_cls()
OFBICMPv6TypeID = _create_oxm_cls()
OFBICMPv6TypeHM = _create_oxm_cls()
OFBICMPv6TypeHMID = _create_oxm_cls()
OFBICMPv6Code = _create_oxm_cls()
OFBICMPv6CodeID = _create_oxm_cls()
OFBICMPv6CodeHM = _create_oxm_cls()
OFBICMPv6CodeHMID = _create_oxm_cls()
OFBIPv6NDTarget = _create_oxm_cls()
OFBIPv6NDTargetID = _create_oxm_cls()
OFBIPv6NDTargetHM = _create_oxm_cls()
OFBIPv6NDTargetHMID = _create_oxm_cls()
OFBIPv6NDSLL = _create_oxm_cls()
OFBIPv6NDSLLID = _create_oxm_cls()
OFBIPv6NDSLLHM = _create_oxm_cls()
OFBIPv6NDSLLHMID = _create_oxm_cls()
OFBIPv6NDTLL = _create_oxm_cls()
OFBIPv6NDTLLID = _create_oxm_cls()
OFBIPv6NDTLLHM = _create_oxm_cls()
OFBIPv6NDTLLHMID = _create_oxm_cls()
OFBMPLSLabel = _create_oxm_cls()
OFBMPLSLabelID = _create_oxm_cls()
OFBMPLSLabelHM = _create_oxm_cls()
OFBMPLSLabelHMID = _create_oxm_cls()
OFBMPLSTC = _create_oxm_cls()
OFBMPLSTCID = _create_oxm_cls()
OFBMPLSTCHM = _create_oxm_cls()
OFBMPLSTCHMID = _create_oxm_cls()
OFBMPLSBoS = _create_oxm_cls()
OFBMPLSBoSID = _create_oxm_cls()
OFBMPLSBoSHM = _create_oxm_cls()
OFBMPLSBoSHMID = _create_oxm_cls()
OFBPBBISID = _create_oxm_cls()
OFBPBBISIDID = _create_oxm_cls()
OFBPBBISIDHM = _create_oxm_cls()
OFBPBBISIDHMID = _create_oxm_cls()
OFBTunnelID = _create_oxm_cls()
OFBTunnelIDID = _create_oxm_cls()
OFBTunnelIDHM = _create_oxm_cls()
OFBTunnelIDHMID = _create_oxm_cls()
OFBIPv6ExtHdr = _create_oxm_cls()
OFBIPv6ExtHdrID = _create_oxm_cls()
OFBIPv6ExtHdrHM = _create_oxm_cls()
OFBIPv6ExtHdrHMID = _create_oxm_cls()
# need_prereq holds a list of prerequisites defined in 7.2.3.8 of the specifications # noqa: E501
# e.g. if you want to use an OFBTCPSrc instance (code 26)
# you first need to declare an OFBIPProto instance (code 20) with value 6,
# and if you want to use an OFBIPProto instance (still code 20)
# you first need to declare an OFBEthType instance (code 10) with value 0x0800
# (0x0800 means IPv4 by default, but you might want to use 0x86dd with IPv6)
# need_prereq codes are two times higher than previous oxm classes codes,
# except for 21 which is sort of a proxy for IPv6 (see below)
need_prereq = {14: [12, 0x1000],
16: [10, 0x0800], # could be 0x86dd
18: [10, 0x0800], # could be 0x86dd
20: [10, 0x0800], # could be 0x86dd
21: [10, 0x86dd],
22: [10, 0x0800],
24: [10, 0x0800],
26: [20, 6],
28: [20, 6],
30: [20, 17],
32: [20, 17],
34: [20, 132],
36: [20, 132],
38: [20, 1],
40: [20, 1],
42: [10, 0x0806],
44: [10, 0x0806],
46: [10, 0x0806],
48: [10, 0x0806],
50: [10, 0x0806],
52: [10, 0x86dd],
54: [10, 0x86dd],
56: [10, 0x86dd],
58: [21, 58], # small trick here, we refer to normally non-
60: [21, 58], # existent field 21 to distinguish ipv6
62: [58, 135], # could be 136
64: [58, 135],
66: [58, 136],
68: [10, 0x8847], # could be 0x8848
70: [10, 0x8847], # could be 0x8848
72: [10, 0x8847], # could be 0x8848
74: [10, 0x88e7],
78: [10, 0x86dd]}
class OXMPacketListField(PacketListField):
__slots__ = ["autocomplete", "index"]
def __init__(self, name, default, cls, length_from=None, autocomplete=False): # noqa: E501
PacketListField.__init__(self, name, default, cls, length_from=length_from) # noqa: E501
self.autocomplete = autocomplete
self.index = []
def i2m(self, pkt, val):
# this part makes for a faster writing of specs-compliant matches
# expect some unwanted behaviour if you try incoherent associations
# you might want to set autocomplete=False in __init__ method
if self.autocomplete or conf.contribs['OPENFLOW']['prereq_autocomplete']: # noqa: E501
# val might be modified during the loop so we need a fixed copy
fix_val = copy.deepcopy(val)
for oxm in fix_val:
f = 2 * oxm.field
fix_index = list(self.index)
while f in need_prereq:
# this loop enables a small recursion
# e.g. ipv6_nd<--icmpv6<--ip_proto<--eth_type
prereq = need_prereq[f]
f = prereq[0]
f2 = 20 if f == 21 else f # ipv6 trick...
if f2 not in fix_index:
self.index.insert(0, f2)
prrq = ofp_oxm_cls[f2]() # never HM
setattr(prrq, ofp_oxm_constr[f2 // 2][1], prereq[1])
val.insert(0, prrq)
# we could do more complicated stuff to
# make sure prerequisite order is correct
# but it works well when presented with any coherent input
# e.g. you should not mix OFBTCPSrc with OFBICMPv6Code
# and expect to get coherent results...
# you can still go manual by setting prereq_autocomplete=False # noqa: E501
return val
def m2i(self, pkt, s):
t = orb(s[2])
nrm_t = t - t % 2
if nrm_t not in self.index:
self.index.append(nrm_t)
return ofp_oxm_cls.get(t, Raw)(s)
@staticmethod
def _get_oxm_length(s):
return orb(s[3])
def addfield(self, pkt, s, val):
return s + b"".join(raw(x) for x in self.i2m(pkt, val))
def getfield(self, pkt, s):
lst = []
lim = self.length_from(pkt)
ret = s[lim:]
remain = s[:lim]
while remain and len(remain) > 4:
tmp_len = OXMPacketListField._get_oxm_length(remain) + 4
# this could also be done by parsing oxm_fields (fixed lengths)
if tmp_len <= 4 or len(remain) < tmp_len:
# no incoherent length
break
current = remain[:tmp_len]
remain = remain[tmp_len:]
p = self.m2i(pkt, current)
lst.append(p)
self.index = []
# since OXMPacketListField is called only twice (when OFPMatch and OFPSetField # noqa: E501
# classes are created) and not when you want to instantiate an OFPMatch, # noqa: E501
# index needs to be reinitialized, otherwise there will be some conflicts # noqa: E501
# e.g. if you create OFPMatch with OFBTCPSrc and then change to OFBTCPDst, # noqa: E501
# index will already be filled with ethertype and nwproto codes,
# thus the corresponding fields will not be added to the packet
return remain + ret, lst
class OXMID(Packet):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = orb(_pkt[2])
return ofp_oxm_id_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPMatch(Packet):
name = "OFP_MATCH"
fields_desc = [ShortEnumField("type", 1, {0: "OFPMT_STANDARD",
1: "OFPMT_OXM"}),
ShortField("len", None),
OXMPacketListField("oxm_fields", [], Packet,
length_from=lambda pkt:pkt.len - 4)]
def post_build(self, p, pay):
tmp_len = self.len
if tmp_len is None:
tmp_len = len(p) + len(pay)
p = p[:2] + struct.pack("!H", tmp_len) + p[4:]
zero_bytes = (8 - tmp_len % 8) % 8
p += b"\x00" * zero_bytes
# message with user-defined length will not be automatically padded
return p + pay
def extract_padding(self, s):
tmp_len = self.len
zero_bytes = (8 - tmp_len % 8) % 8
return s[zero_bytes:], s[:zero_bytes]
# ofp_match is no longer a fixed-length structure in v1.3
# furthermore it may include variable padding
# we introduce to that end a subclass of PacketField
class MatchField(PacketField):
def __init__(self, name):
PacketField.__init__(self, name, OFPMatch(), OFPMatch)
def getfield(self, pkt, s):
i = self.m2i(pkt, s)
# i can be <OFPMatch> or <OFPMatch <Padding>>
# or <OFPMatch <Raw>> or <OFPMatch <Raw <Padding>>>
# and we want to return "", <OFPMatch> or "", <OFPMatch <Padding>>
# or raw(<Raw>), <OFPMatch> or raw(<Raw>), <OFPMatch <Padding>>
if Raw in i:
r = i[Raw]
if Padding in r:
p = r[Padding]
i.payload = p
del(r.payload)
return r.load, i
else:
return b"", i
# Actions #
class OpenFlow3(OpenFlow):
name = "OpenFlow v1.3 dissector"
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
# port 6653 has been allocated by IANA, port 6633 should no
# longer be used
# OpenFlow3 function may be called with None self in OFPPacketField
of_type = orb(_pkt[1])
if of_type == 1:
err_type = orb(_pkt[9])
# err_type is a short int, but last byte is enough
if err_type == 255:
err_type = 65535
return ofp_error_cls[err_type]
elif of_type == 18:
mp_type = orb(_pkt[9])
if mp_type == 255:
mp_type = 65535
return ofp_multipart_request_cls[mp_type]
elif of_type == 19:
mp_type = orb(_pkt[9])
if mp_type == 255:
mp_type = 65535
return ofp_multipart_reply_cls[mp_type]
else:
return ofpt_cls[of_type]
return _UnknownOpenFlow
ofp_action_types = {0: "OFPAT_OUTPUT",
1: "OFPAT_SET_VLAN_VID",
2: "OFPAT_SET_VLAN_PCP",
3: "OFPAT_STRIP_VLAN",
4: "OFPAT_SET_DL_SRC",
5: "OFPAT_SET_DL_DST",
6: "OFPAT_SET_NW_SRC",
7: "OFPAT_SET_NW_DST",
8: "OFPAT_SET_NW_TOS",
9: "OFPAT_SET_TP_SRC",
10: "OFPAT_SET_TP_DST",
# 11: "OFPAT_ENQUEUE",
11: "OFPAT_COPY_TTL_OUT",
12: "OFPAT_COPY_TTL_IN",
13: "OFPAT_SET_MPLS_LABEL",
14: "OFPAT_DEC_MPLS_TC",
15: "OFPAT_SET_MPLS_TTL",
16: "OFPAT_DEC_MPLS_TTL",
17: "OFPAT_PUSH_VLAN",
18: "OFPAT_POP_VLAN",
19: "OFPAT_PUSH_MPLS",
20: "OFPAT_POP_MPLS",
21: "OFPAT_SET_QUEUE",
22: "OFPAT_GROUP",
23: "OFPAT_SET_NW_TTL",
24: "OFPAT_DEC_NW_TTL",
25: "OFPAT_SET_FIELD",
26: "OFPAT_PUSH_PBB",
27: "OFPAT_POP_PBB",
65535: "OFPAT_EXPERIMENTER"}
class OFPAT(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_action_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPATOutput(OFPAT):
name = "OFPAT_OUTPUT"
fields_desc = [ShortEnumField("type", 0, ofp_action_types),
ShortField("len", 16),
IntEnumField("port", 0, ofp_port_no),
ShortEnumField("max_len", "NO_BUFFER", ofp_max_len),
XBitField("pad", 0, 48)]
# the following actions are not supported by OFv1.3
class OFPATSetVLANVID(OFPAT):
name = "OFPAT_SET_VLAN_VID"
fields_desc = [ShortEnumField("type", 1, ofp_action_types),
ShortField("len", 8),
ShortField("vlan_vid", 0),
XShortField("pad", 0)]
class OFPATSetVLANPCP(OFPAT):
name = "OFPAT_SET_VLAN_PCP"
fields_desc = [ShortEnumField("type", 2, ofp_action_types),
ShortField("len", 8),
ByteField("vlan_pcp", 0),
X3BytesField("pad", 0)]
class OFPATStripVLAN(OFPAT):
name = "OFPAT_STRIP_VLAN"
fields_desc = [ShortEnumField("type", 3, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATSetDlSrc(OFPAT):
name = "OFPAT_SET_DL_SRC"
fields_desc = [ShortEnumField("type", 4, ofp_action_types),
ShortField("len", 16),
MACField("dl_addr", "0"),
XBitField("pad", 0, 48)]
class OFPATSetDlDst(OFPAT):
name = "OFPAT_SET_DL_DST"
fields_desc = [ShortEnumField("type", 5, ofp_action_types),
ShortField("len", 16),
MACField("dl_addr", "0"),
XBitField("pad", 0, 48)]
class OFPATSetNwSrc(OFPAT):
name = "OFPAT_SET_NW_SRC"
fields_desc = [ShortEnumField("type", 6, ofp_action_types),
ShortField("len", 8),
IPField("nw_addr", "0")]
class OFPATSetNwDst(OFPAT):
name = "OFPAT_SET_NW_DST"
fields_desc = [ShortEnumField("type", 7, ofp_action_types),
ShortField("len", 8),
IPField("nw_addr", "0")]
class OFPATSetNwToS(OFPAT):
name = "OFPAT_SET_TP_TOS"
fields_desc = [ShortEnumField("type", 8, ofp_action_types),
ShortField("len", 8),
ByteField("nw_tos", 0),
X3BytesField("pad", 0)]
class OFPATSetTpSrc(OFPAT):
name = "OFPAT_SET_TP_SRC"
fields_desc = [ShortEnumField("type", 9, ofp_action_types),
ShortField("len", 8),
ShortField("tp_port", 0),
XShortField("pad", 0)]
class OFPATSetTpDst(OFPAT):
name = "OFPAT_SET_TP_DST"
fields_desc = [ShortEnumField("type", 10, ofp_action_types),
ShortField("len", 8),
ShortField("tp_port", 0),
XShortField("pad", 0)]
# class OFPATEnqueue(OFPAT):
# name = "OFPAT_ENQUEUE"
# fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
# ShortField("len", 16),
# ShortField("port", 0),
# XBitField("pad", 0, 48),
# IntEnumField("queue_id", 0, ofp_queue) ]
class OFPATSetMPLSLabel(OFPAT):
name = "OFPAT_SET_MPLS_LABEL"
fields_desc = [ShortEnumField("type", 13, ofp_action_types),
ShortField("len", 8),
IntField("mpls_label", 0)]
class OFPATSetMPLSTC(OFPAT):
name = "OFPAT_SET_MPLS_TC"
fields_desc = [ShortEnumField("type", 14, ofp_action_types),
ShortField("len", 8),
ByteField("mpls_tc", 0),
X3BytesField("pad", 0)]
# end of unsupported actions
class OFPATCopyTTLOut(OFPAT):
name = "OFPAT_COPY_TTL_OUT"
fields_desc = [ShortEnumField("type", 11, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATCopyTTLIn(OFPAT):
name = "OFPAT_COPY_TTL_IN"
fields_desc = [ShortEnumField("type", 12, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATSetMPLSTTL(OFPAT):
name = "OFPAT_SET_MPLS_TTL"
fields_desc = [ShortEnumField("type", 15, ofp_action_types),
ShortField("len", 8),
ByteField("mpls_ttl", 0),
X3BytesField("pad", 0)]
class OFPATDecMPLSTTL(OFPAT):
name = "OFPAT_DEC_MPLS_TTL"
fields_desc = [ShortEnumField("type", 16, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATPushVLAN(OFPAT):
name = "OFPAT_PUSH_VLAN"
fields_desc = [ShortEnumField("type", 17, ofp_action_types),
ShortField("len", 8),
ShortField("ethertype", 0x8100), # or 0x88a8
XShortField("pad", 0)]
class OFPATPopVLAN(OFPAT):
name = "OFPAT_POP_VLAN"
fields_desc = [ShortEnumField("type", 18, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATPushMPLS(OFPAT):
name = "OFPAT_PUSH_MPLS"
fields_desc = [ShortEnumField("type", 19, ofp_action_types),
ShortField("len", 8),
ShortField("ethertype", 0x8847), # or 0x8848
XShortField("pad", 0)]
class OFPATPopMPLS(OFPAT):
name = "OFPAT_POP_MPLS"
fields_desc = [ShortEnumField("type", 20, ofp_action_types),
ShortField("len", 8),
ShortField("ethertype", 0x8847), # or 0x8848
XShortField("pad", 0)]
class OFPATSetQueue(OFPAT):
name = "OFPAT_SET_QUEUE"
fields_desc = [ShortEnumField("type", 21, ofp_action_types),
ShortField("len", 8),
IntEnumField("queue_id", 0, ofp_queue)]
class OFPATGroup(OFPAT):
name = "OFPAT_GROUP"
fields_desc = [ShortEnumField("type", 22, ofp_action_types),
ShortField("len", 8),
IntEnumField("group_id", 0, ofp_group)]
class OFPATSetNwTTL(OFPAT):
name = "OFPAT_SET_NW_TTL"
fields_desc = [ShortEnumField("type", 23, ofp_action_types),
ShortField("len", 8),
ByteField("nw_ttl", 0),
X3BytesField("pad", 0)]
class OFPATDecNwTTL(OFPAT):
name = "OFPAT_DEC_NW_TTL"
fields_desc = [ShortEnumField("type", 24, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATSetField(OFPAT):
name = "OFPAT_SET_FIELD"
fields_desc = [ShortEnumField("type", 25, ofp_action_types),
ShortField("len", None),
# there should not be more than one oxm tlv
OXMPacketListField("field", [], Packet,
length_from=lambda pkt:pkt.len - 4,
# /!\ contains padding!
autocomplete=False)]
def post_build(self, p, pay):
tmp_len = self.len
zero_bytes = 0
if tmp_len is None:
tmp_len = len(p) + len(pay)
zero_bytes = (8 - tmp_len % 8) % 8
tmp_len = tmp_len + zero_bytes # add padding length
p = p[:2] + struct.pack("!H", tmp_len) + p[4:]
else:
zero_bytes = (8 - tmp_len % 8) % 8
# every message will be padded correctly
p += b"\x00" * zero_bytes
return p + pay
def extract_padding(self, s):
return b"", s
class OFPATPushPBB(OFPAT):
name = "OFPAT_PUSH_PBB"
fields_desc = [ShortEnumField("type", 26, ofp_action_types),
ShortField("len", 8),
ShortField("ethertype", 0x88e7),
XShortField("pad", 0)]
class OFPATPopPBB(OFPAT):
name = "OFPAT_POP_PBB"
fields_desc = [ShortEnumField("type", 27, ofp_action_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPATExperimenter(OFPAT):
name = "OFPAT_EXPERIMENTER"
fields_desc = [ShortEnumField("type", 65535, ofp_action_types),
ShortField("len", 8),
IntField("experimenter", 0)]
ofp_action_cls = {0: OFPATOutput,
1: OFPATSetVLANVID,
2: OFPATSetVLANPCP,
3: OFPATStripVLAN,
4: OFPATSetDlSrc,
5: OFPATSetDlDst,
6: OFPATSetNwSrc,
7: OFPATSetNwDst,
8: OFPATSetNwToS,
9: OFPATSetTpSrc,
10: OFPATSetTpDst,
# 11: OFPATEnqueue,
11: OFPATCopyTTLOut,
12: OFPATCopyTTLIn,
13: OFPATSetMPLSLabel,
14: OFPATSetMPLSTC,
15: OFPATSetMPLSTTL,
16: OFPATDecMPLSTTL,
17: OFPATPushVLAN,
18: OFPATPopVLAN,
19: OFPATPushMPLS,
20: OFPATPopMPLS,
21: OFPATSetQueue,
22: OFPATGroup,
23: OFPATSetNwTTL,
24: OFPATDecNwTTL,
25: OFPATSetField,
26: OFPATPushPBB,
27: OFPATPopPBB,
65535: OFPATExperimenter}
# Action IDs #
class OFPATID(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_action_id_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
# length is computed as in instruction structures,
# so we reuse _ofp_header
class OFPATOutputID(OFPATID):
name = "OFPAT_OUTPUT"
fields_desc = [ShortEnumField("type", 0, ofp_action_types),
ShortField("len", 4)]
# the following actions are not supported by OFv1.3
class OFPATSetVLANVIDID(OFPATID):
name = "OFPAT_SET_VLAN_VID"
fields_desc = [ShortEnumField("type", 1, ofp_action_types),
ShortField("len", 4)]
class OFPATSetVLANPCPID(OFPATID):
name = "OFPAT_SET_VLAN_PCP"
fields_desc = [ShortEnumField("type", 2, ofp_action_types),
ShortField("len", 4)]
class OFPATStripVLANID(OFPATID):
name = "OFPAT_STRIP_VLAN"
fields_desc = [ShortEnumField("type", 3, ofp_action_types),
ShortField("len", 4)]
class OFPATSetDlSrcID(OFPATID):
name = "OFPAT_SET_DL_SRC"
fields_desc = [ShortEnumField("type", 4, ofp_action_types),
ShortField("len", 4)]
class OFPATSetDlDstID(OFPATID):
name = "OFPAT_SET_DL_DST"
fields_desc = [ShortEnumField("type", 5, ofp_action_types),
ShortField("len", 4)]
class OFPATSetNwSrcID(OFPATID):
name = "OFPAT_SET_NW_SRC"
fields_desc = [ShortEnumField("type", 6, ofp_action_types),
ShortField("len", 4)]
class OFPATSetNwDstID(OFPATID):
name = "OFPAT_SET_NW_DST"
fields_desc = [ShortEnumField("type", 7, ofp_action_types),
ShortField("len", 4)]
class OFPATSetNwToSID(OFPATID):
name = "OFPAT_SET_TP_TOS"
fields_desc = [ShortEnumField("type", 8, ofp_action_types),
ShortField("len", 4)]
class OFPATSetTpSrcID(OFPATID):
name = "OFPAT_SET_TP_SRC"
fields_desc = [ShortEnumField("type", 9, ofp_action_types),
ShortField("len", 4)]
class OFPATSetTpDstID(OFPATID):
name = "OFPAT_SET_TP_DST"
fields_desc = [ShortEnumField("type", 10, ofp_action_types),
ShortField("len", 4)]
# class OFPATEnqueueID(OFPAT):
# name = "OFPAT_ENQUEUE"
# fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
# ShortField("len", 4) ]
class OFPATSetMPLSLabelID(OFPATID):
name = "OFPAT_SET_MPLS_LABEL"
fields_desc = [ShortEnumField("type", 13, ofp_action_types),
ShortField("len", 4)]
class OFPATSetMPLSTCID(OFPATID):
name = "OFPAT_SET_MPLS_TC"
fields_desc = [ShortEnumField("type", 14, ofp_action_types),
ShortField("len", 4)]
# end of unsupported actions
class OFPATCopyTTLOutID(OFPATID):
name = "OFPAT_COPY_TTL_OUT"
fields_desc = [ShortEnumField("type", 11, ofp_action_types),
ShortField("len", 4)]
class OFPATCopyTTLInID(OFPATID):
name = "OFPAT_COPY_TTL_IN"
fields_desc = [ShortEnumField("type", 12, ofp_action_types),
ShortField("len", 4)]
class OFPATSetMPLSTTLID(OFPATID):
name = "OFPAT_SET_MPLS_TTL"
fields_desc = [ShortEnumField("type", 15, ofp_action_types),
ShortField("len", 4)]
class OFPATDecMPLSTTLID(OFPATID):
name = "OFPAT_DEC_MPLS_TTL"
fields_desc = [ShortEnumField("type", 16, ofp_action_types),
ShortField("len", 4)]
class OFPATPushVLANID(OFPATID):
name = "OFPAT_PUSH_VLAN"
fields_desc = [ShortEnumField("type", 17, ofp_action_types),
ShortField("len", 4)]
class OFPATPopVLANID(OFPATID):
name = "OFPAT_POP_VLAN"
fields_desc = [ShortEnumField("type", 18, ofp_action_types),
ShortField("len", 4)]
class OFPATPushMPLSID(OFPATID):
name = "OFPAT_PUSH_MPLS"
fields_desc = [ShortEnumField("type", 19, ofp_action_types),
ShortField("len", 4)]
class OFPATPopMPLSID(OFPATID):
name = "OFPAT_POP_MPLS"
fields_desc = [ShortEnumField("type", 20, ofp_action_types),
ShortField("len", 4)]
class OFPATSetQueueID(OFPATID):
name = "OFPAT_SET_QUEUE"
fields_desc = [ShortEnumField("type", 21, ofp_action_types),
ShortField("len", 4)]
class OFPATGroupID(OFPATID):
name = "OFPAT_GROUP"
fields_desc = [ShortEnumField("type", 22, ofp_action_types),
ShortField("len", 4)]
class OFPATSetNwTTLID(OFPATID):
name = "OFPAT_SET_NW_TTL"
fields_desc = [ShortEnumField("type", 23, ofp_action_types),
ShortField("len", 4)]
class OFPATDecNwTTLID(OFPATID):
name = "OFPAT_DEC_NW_TTL"
fields_desc = [ShortEnumField("type", 24, ofp_action_types),
ShortField("len", 4)]
class OFPATSetFieldID(OFPATID):
name = "OFPAT_SET_FIELD"
fields_desc = [ShortEnumField("type", 25, ofp_action_types),
ShortField("len", 4)]
class OFPATPushPBBID(OFPATID):
name = "OFPAT_PUSH_PBB"
fields_desc = [ShortEnumField("type", 26, ofp_action_types),
ShortField("len", 4)]
class OFPATPopPBBID(OFPATID):
name = "OFPAT_POP_PBB"
fields_desc = [ShortEnumField("type", 27, ofp_action_types),
ShortField("len", 4)]
class OFPATExperimenterID(OFPATID):
name = "OFPAT_EXPERIMENTER"
fields_desc = [ShortEnumField("type", 65535, ofp_action_types),
ShortField("len", None)]
ofp_action_id_cls = {0: OFPATOutputID,
1: OFPATSetVLANVIDID,
2: OFPATSetVLANPCPID,
3: OFPATStripVLANID,
4: OFPATSetDlSrcID,
5: OFPATSetDlDstID,
6: OFPATSetNwSrcID,
7: OFPATSetNwDstID,
8: OFPATSetNwToSID,
9: OFPATSetTpSrcID,
10: OFPATSetTpDstID,
# 11: OFPATEnqueueID,
11: OFPATCopyTTLOutID,
12: OFPATCopyTTLInID,
13: OFPATSetMPLSLabelID,
14: OFPATSetMPLSTCID,
15: OFPATSetMPLSTTLID,
16: OFPATDecMPLSTTLID,
17: OFPATPushVLANID,
18: OFPATPopVLANID,
19: OFPATPushMPLSID,
20: OFPATPopMPLSID,
21: OFPATSetQueueID,
22: OFPATGroupID,
23: OFPATSetNwTTLID,
24: OFPATDecNwTTLID,
25: OFPATSetFieldID,
26: OFPATPushPBBID,
27: OFPATPopPBBID,
65535: OFPATExperimenterID}
# Instructions #
ofp_instruction_types = {1: "OFPIT_GOTO_TABLE",
2: "OFPIT_WRITE_METADATA",
3: "OFPIT_WRITE_ACTIONS",
4: "OFPIT_APPLY_ACTIONS",
5: "OFPIT_CLEAR_ACTIONS",
6: "OFPIT_METER",
65535: "OFPIT_EXPERIMENTER"}
class OFPIT(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_instruction_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPITGotoTable(OFPIT):
name = "OFPIT_GOTO_TABLE"
fields_desc = [ShortEnumField("type", 1, ofp_instruction_types),
ShortField("len", 8),
ByteEnumField("table_id", 0, ofp_table),
X3BytesField("pad", 0)]
class OFPITWriteMetadata(OFPIT):
name = "OFPIT_WRITE_METADATA"
fields_desc = [ShortEnumField("type", 2, ofp_instruction_types),
ShortField("len", 24),
XIntField("pad", 0),
LongField("metadata", 0),
LongField("metadata_mask", 0)]
class OFPITWriteActions(OFPIT):
name = "OFPIT_WRITE_ACTIONS"
fields_desc = [ShortEnumField("type", 3, ofp_instruction_types),
ShortField("len", None),
XIntField("pad", 0),
PacketListField("actions", [], OFPAT,
length_from=lambda pkt:pkt.len - 8)]
class OFPITApplyActions(OFPIT):
name = "OFPIT_APPLY_ACTIONS"
fields_desc = [ShortEnumField("type", 4, ofp_instruction_types),
ShortField("len", None),
XIntField("pad", 0),
PacketListField("actions", [], OFPAT,
length_from=lambda pkt:pkt.len - 8)]
class OFPITClearActions(OFPIT):
name = "OFPIT_CLEAR_ACTIONS"
fields_desc = [ShortEnumField("type", 5, ofp_instruction_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPITMeter(OFPIT):
name = "OFPIT_METER"
fields_desc = [ShortEnumField("type", 6, ofp_instruction_types),
ShortField("len", 8),
IntEnumField("meter_id", 1, ofp_meter)]
class OFPITExperimenter(OFPIT):
name = "OFPIT_EXPERIMENTER"
fields_desc = [ShortEnumField("type", 65535, ofp_instruction_types),
ShortField("len", None),
IntField("experimenter", 0)]
ofp_instruction_cls = {1: OFPITGotoTable,
2: OFPITWriteMetadata,
3: OFPITWriteActions,
4: OFPITApplyActions,
5: OFPITClearActions,
6: OFPITMeter,
65535: OFPITExperimenter}
# Instruction IDs #
# length is computed as in instruction structures,
# so we reuse _ofp_header
class OFPITID(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_instruction_id_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPITGotoTableID(OFPITID):
name = "OFPIT_GOTO_TABLE"
fields_desc = [ShortEnumField("type", 1, ofp_instruction_types),
ShortField("len", 4)]
class OFPITWriteMetadataID(OFPITID):
name = "OFPIT_WRITE_METADATA"
fields_desc = [ShortEnumField("type", 2, ofp_instruction_types),
ShortField("len", 4)]
class OFPITWriteActionsID(OFPITID):
name = "OFPIT_WRITE_ACTIONS"
fields_desc = [ShortEnumField("type", 3, ofp_instruction_types),
ShortField("len", 4)]
class OFPITApplyActionsID(OFPITID):
name = "OFPIT_APPLY_ACTIONS"
fields_desc = [ShortEnumField("type", 4, ofp_instruction_types),
ShortField("len", 4)]
class OFPITClearActionsID(OFPITID):
name = "OFPIT_CLEAR_ACTIONS"
fields_desc = [ShortEnumField("type", 5, ofp_instruction_types),
ShortField("len", 4)]
class OFPITMeterID(OFPITID):
name = "OFPIT_METER"
fields_desc = [ShortEnumField("type", 6, ofp_instruction_types),
ShortField("len", 4)]
class OFPITExperimenterID(OFPITID):
name = "OFPIT_EXPERIMENTER"
fields_desc = [ShortEnumField("type", 65535, ofp_instruction_types),
ShortField("len", None)]
ofp_instruction_id_cls = {1: OFPITGotoTableID,
2: OFPITWriteMetadataID,
3: OFPITWriteActionsID,
4: OFPITApplyActionsID,
5: OFPITClearActionsID,
6: OFPITMeterID,
65535: OFPITExperimenterID}
# Buckets #
class OFPBucket(_ofp_header_item):
name = "OFP_BUCKET"
fields_desc = [ShortField("len", None),
ShortField("weight", 0),
IntEnumField("watch_port", 0, ofp_port_no),
IntEnumField("watch_group", 0, ofp_group),
XIntField("pad", 0),
PacketListField("actions", [], OFPAT,
length_from=lambda pkt:pkt.len - 16)]
def extract_padding(self, s):
return b"", s
# Queues #
ofp_queue_property_types = {0: "OFPQT_NONE",
1: "OFPQT_MIN_RATE"}
class OFPQT(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_queue_property_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPQTNone(OFPQT):
name = "OFPQT_NONE"
fields_desc = [ShortEnumField("type", 0, ofp_queue_property_types),
ShortField("len", 8),
XIntField("pad", 0)]
class OFPQTMinRate(OFPQT):
name = "OFPQT_MIN_RATE"
fields_desc = [ShortEnumField("type", 1, ofp_queue_property_types),
ShortField("len", 16),
XIntField("pad1", 0),
ShortField("rate", 0),
XBitField("pad2", 0, 48)]
ofp_queue_property_cls = {0: OFPQTNone,
1: OFPQTMinRate}
class OFPPacketQueue(Packet):
name = "OFP_PACKET_QUEUE"
fields_desc = [IntEnumField("queue_id", 0, ofp_queue),
ShortField("len", None),
XShortField("pad", 0),
PacketListField("properties", [], OFPQT,
length_from=lambda pkt:pkt.len - 8)] # noqa: E501
def extract_padding(self, s):
return b"", s
def post_build(self, p, pay):
if self.properties == []:
p += raw(OFPQTNone())
if self.len is None:
tmp_len = len(p) + len(pay)
p = p[:4] + struct.pack("!H", tmp_len) + p[6:]
return p + pay
# Meter bands #
ofp_meter_band_types = {0: "OFPMBT_DROP",
1: "OFPMBT_DSCP_REMARK",
65535: "OFPMBT_EXPERIMENTER"}
class OFPMBT(_ofp_header):
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_meter_band_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPMBTDrop(OFPMBT):
name = "OFPMBT_DROP"
fields_desc = [ShortEnumField("type", 0, ofp_queue_property_types),
ShortField("len", 16),
IntField("rate", 0),
IntField("burst_size", 0),
XIntField("pad", 0)]
class OFPMBTDSCPRemark(OFPMBT):
name = "OFPMBT_DSCP_REMARK"
fields_desc = [ShortEnumField("type", 1, ofp_queue_property_types),
ShortField("len", 16),
IntField("rate", 0),
IntField("burst_size", 0),
ByteField("prec_level", 0),
X3BytesField("pad", 0)]
class OFPMBTExperimenter(OFPMBT):
name = "OFPMBT_EXPERIMENTER"
fields_desc = [ShortEnumField("type", 65535, ofp_queue_property_types),
ShortField("len", 16),
IntField("rate", 0),
IntField("burst_size", 0),
IntField("experimenter", 0)]
ofp_meter_band_cls = {0: OFPMBTDrop,
1: OFPMBTDSCPRemark,
2: OFPMBTExperimenter}
#####################################################
# OpenFlow 1.3 Messages #
#####################################################
ofp_version = {0x01: "OpenFlow 1.0",
0x02: "OpenFlow 1.1",
0x03: "OpenFlow 1.2",
0x04: "OpenFlow 1.3",
0x05: "OpenFlow 1.4"}
ofp_type = {0: "OFPT_HELLO",
1: "OFPT_ERROR",
2: "OFPT_ECHO_REQUEST",
3: "OFPT_ECHO_REPLY",
4: "OFPT_EXPERIMENTER",
5: "OFPT_FEATURES_REQUEST",
6: "OFPT_FEATURES_REPLY",
7: "OFPT_GET_CONFIG_REQUEST",
8: "OFPT_GET_CONFIG_REPLY",
9: "OFPT_SET_CONFIG",
10: "OFPT_PACKET_IN",
11: "OFPT_FLOW_REMOVED",
12: "OFPT_PORT_STATUS",
13: "OFPT_PACKET_OUT",
14: "OFPT_FLOW_MOD",
15: "OFPT_GROUP_MOD",
16: "OFPT_PORT_MOD",
17: "OFPT_TABLE_MOD",
18: "OFPT_MULTIPART_REQUEST",
19: "OFPT_MULTIPART_REPLY",
20: "OFPT_BARRIER_REQUEST",
21: "OFPT_BARRIER_REPLY",
22: "OFPT_QUEUE_GET_CONFIG_REQUEST",
23: "OFPT_QUEUE_GET_CONFIG_REPLY",
24: "OFPT_ROLE_REQUEST",
25: "OFPT_ROLE_REPLY",
26: "OFPT_GET_ASYNC_REQUEST",
27: "OFPT_GET_ASYNC_REPLY",
28: "OFPT_SET_ASYNC",
29: "OFPT_METER_MOD"}
class OFPTHello(_ofp_header):
name = "OFPT_HELLO"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 0, ofp_type),
ShortField("len", None),
IntField("xid", 0),
PacketListField("elements", [], OFPHET,
length_from=lambda pkt: pkt.len - 8)]
#####################################################
# OFPT_ERROR #
#####################################################
ofp_error_type = {0: "OFPET_HELLO_FAILED",
1: "OFPET_BAD_REQUEST",
2: "OFPET_BAD_ACTION",
3: "OFPET_BAD_INSTRUCTION",
4: "OFPET_BAD_MATCH",
5: "OFPET_FLOW_MOD_FAILED",
6: "OFPET_GROUP_MOD_FAILED",
7: "OFPET_PORT_MOD_FAILED",
8: "OFPET_TABLE_MOD_FAILED",
9: "OFPET_QUEUE_OP_FAILED",
10: "OFPET_SWITCH_CONFIG_FAILED",
11: "OFPET_ROLE_REQUEST_FAILED",
12: "OFPET_METER_MOD_FAILED",
13: "OFPET_TABLE_FEATURES_FAILED",
65535: "OFPET_EXPERIMENTER"}
class OFPETHelloFailed(_ofp_header):
name = "OFPET_HELLO_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 0, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPHFC_INCOMPATIBLE",
1: "OFPHFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETBadRequest(_ofp_header):
name = "OFPET_BAD_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 1, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPBRC_BAD_VERSION",
1: "OFPBRC_BAD_TYPE",
2: "OFPBRC_BAD_MULTIPART",
3: "OFPBRC_BAD_EXPERIMENTER",
4: "OFPBRC_BAD_EXP_TYPE",
5: "OFPBRC_EPERM",
6: "OFPBRC_BAD_LEN",
7: "OFPBRC_BUFFER_EMPTY",
8: "OFPBRC_BUFFER_UNKNOWN",
9: "OFPBRC_BAD_TABLE_ID",
10: "OFPBRC_IS_SLAVE",
11: "OFPBRC_BAD_PORT",
12: "OFPBRC_BAD_PACKET",
13: "OFPBRC_MULTIPART_BUFFER_OVERFLOW"}), # noqa: E501
OFPacketField("data", "", Raw)]
class OFPETBadAction(_ofp_header):
name = "OFPET_BAD_ACTION"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 2, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPBAC_BAD_TYPE",
1: "OFPBAC_BAD_LEN",
2: "OFPBAC_BAD_EXPERIMENTER",
3: "OFPBAC_BAD_EXP_TYPE",
4: "OFPBAC_BAD_OUT_PORT",
5: "OFPBAC_BAD_ARGUMENT",
6: "OFPBAC_EPERM",
7: "OFPBAC_TOO_MANY",
8: "OFPBAC_BAD_QUEUE",
9: "OFPBAC_BAD_OUT_GROUP",
10: "OFPBAC_MATCH_INCONSISTENT", # noqa: E501
11: "OFPBAC_UNSUPPORTED_ORDER", # noqa: E501
12: "OFPBAC_BAD_TAG",
13: "OFPBAC_BAD_SET_TYPE",
14: "OFPBAC_BAD_SET_LEN",
15: "OFPBAC_BAD_SET_ARGUMENT"}), # noqa: E501
OFPacketField("data", "", Raw)]
class OFPETBadInstruction(_ofp_header):
name = "OFPET_BAD_INSTRUCTION"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 3, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPBIC_UNKNOWN_INST",
1: "OFPBIC_UNSUP_INST",
2: "OFPBIC_BAD_TABLE_ID",
3: "OFPBIC_UNSUP_METADATA",
4: "OFPBIC_UNSUP_METADATA_MASK", # noqa: E501
5: "OFPBIC_BAD_EXPERIMENTER",
6: "OFPBIC_BAD_EXP_TYPE",
7: "OFPBIC_BAD_LEN",
8: "OFPBIC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETBadMatch(_ofp_header):
name = "OFPET_BAD_MATCH"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 4, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPBMC_BAD_TYPE",
1: "OFPBMC_BAD_LEN",
2: "OFPBMC_BAD_TAG",
3: "OFPBMC_BAD_DL_ADDR_MASK",
4: "OFPBMC_BAD_NW_ADDR_MASK",
5: "OFPBMC_BAD_WILDCARDS",
6: "OFPBMC_BAD_FIELD",
7: "OFPBMC_BAD_VALUE",
8: "OFPBMC_BAD_MASK",
9: "OFPBMC_BAD_PREREQ",
10: "OFPBMC_DUP_FIELD",
11: "OFPBMC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETFlowModFailed(_ofp_header):
name = "OFPET_FLOW_MOD_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 5, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPFMFC_UNKNOWN",
1: "OFPFMFC_TABLE_FULL",
2: "OFPFMFC_BAD_TABLE_ID",
3: "OFPFMFC_OVERLAP",
4: "OFPFMFC_EPERM",
5: "OFPFMFC_BAD_TIMEOUT",
6: "OFPFMFC_BAD_COMMAND",
7: "OFPFMFC_BAD_FLAGS"}),
OFPacketField("data", "", Raw)]
class OFPETGroupModFailed(_ofp_header):
name = "OFPET_GROUP_MOD_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 6, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPGMFC_GROUP_EXISTS",
1: "OFPGMFC_INVALID_GROUP",
2: "OFPGMFC_WEIGHT_UNSUPPORTED", # noqa: E501
3: "OFPGMFC_OUT_OF_GROUPS",
4: "OFPGMFC_OUT_OF_BUCKETS",
5: "OFPGMFC_CHAINING_UNSUPPORTED", # noqa: E501
6: "OFPGMFC_WATCH_UNSUPPORTED", # noqa: E501
7: "OFPGMFC_LOOP",
8: "OFPGMFC_UNKNOWN_GROUP",
9: "OFPGMFC_CHAINED_GROUP",
10: "OFPGMFC_BAD_TYPE",
11: "OFPGMFC_BAD_COMMAND",
12: "OFPGMFC_BAD_BUCKET",
13: "OFPGMFC_BAD_WATCH",
14: "OFPFMFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETPortModFailed(_ofp_header):
name = "OFPET_PORT_MOD_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 7, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPPMFC_BAD_PORT",
1: "OFPPMFC_BAD_HW_ADDR",
2: "OFPPMFC_BAD_CONFIG",
3: "OFPPMFC_BAD_ADVERTISE",
4: "OFPPMFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETTableModFailed(_ofp_header):
name = "OFPET_TABLE_MOD_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 8, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPTMFC_BAD_TABLE",
1: "OFPTMFC_BAD_CONFIG",
2: "OFPTMFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETQueueOpFailed(_ofp_header):
name = "OFPET_QUEUE_OP_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 9, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPQOFC_BAD_PORT",
1: "OFPQOFC_BAD_QUEUE",
2: "OFPQOFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETSwitchConfigFailed(_ofp_header):
name = "OFPET_SWITCH_CONFIG_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 10, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPSCFC_BAD_FLAGS",
1: "OFPSCFC_BAD_LEN",
2: "OFPSCFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETRoleRequestFailed(_ofp_header):
name = "OFPET_ROLE_REQUEST_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 11, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPRRFC_STALE",
1: "OFPRRFC_UNSUP",
2: "OFPRRFC_BAD_ROLE"}),
OFPacketField("data", "", Raw)]
class OFPETMeterModFailed(_ofp_header):
name = "OFPET_METER_MOD_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 12, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPMMFC_UNKNOWN",
1: "OFPMMFC_METER_EXISTS",
2: "OFPMMFC_INVALID_METER",
3: "OFPMMFC_UNKNOWN_METER",
4: "OFPMMFC_BAD_COMMAND",
5: "OFPMMFC_BAD_FLAGS",
6: "OFPMMFC_BAD_RATE",
7: "OFPMMFC_BAD_BURST",
8: "OFPMMFC_BAD_BAND",
9: "OFPMMFC_BAD_BAND_VALUE",
10: "OFPMMFC_OUT_OF_METERS",
11: "OFPMMFC_OUT_OF_BANDS"}),
OFPacketField("data", "", Raw)]
class OFPETTableFeaturesFailed(_ofp_header):
name = "OFPET_TABLE_FEATURES_FAILED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", 13, ofp_error_type),
ShortEnumField("errcode", 0, {0: "OFPTFFC_BAD_TABLE",
1: "OFPTFFC_BAD_METADATA",
2: "OFPTFFC_BAD_TYPE",
3: "OFPTFFC_BAD_LEN",
4: "OFPTFFC_BAD_ARGUMENT",
5: "OFPTFFC_EPERM"}),
OFPacketField("data", "", Raw)]
class OFPETExperimenter(_ofp_header):
name = "OFPET_EXPERIMENTER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 1, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("errtype", "OFPET_EXPERIMENTER", ofp_error_type), # noqa: E501
ShortField("exp_type", None),
IntField("experimenter", None),
OFPacketField("data", "", Raw)]
# ofp_error_cls allows generic method OpenFlow3()
# to choose the right class for dissection
ofp_error_cls = {0: OFPETHelloFailed,
1: OFPETBadRequest,
2: OFPETBadAction,
3: OFPETBadInstruction,
4: OFPETBadMatch,
5: OFPETFlowModFailed,
6: OFPETGroupModFailed,
7: OFPETPortModFailed,
8: OFPETTableModFailed,
9: OFPETQueueOpFailed,
10: OFPETSwitchConfigFailed,
11: OFPETRoleRequestFailed,
12: OFPETMeterModFailed,
13: OFPETTableFeaturesFailed,
65535: OFPETExperimenter}
# end of OFPT_ERRORS #
class OFPTEchoRequest(_ofp_header):
name = "OFPT_ECHO_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 2, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTEchoReply(_ofp_header):
name = "OFPT_ECHO_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 3, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTExperimenter(_ofp_header):
name = "OFPT_EXPERIMENTER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 4, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntField("experimenter", 0),
IntField("exp_type", 0)]
class OFPTFeaturesRequest(_ofp_header):
name = "OFPT_FEATURES_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 5, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTFeaturesReply(_ofp_header):
name = "OFPT_FEATURES_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 6, ofp_type),
ShortField("len", None),
IntField("xid", 0),
LongField("datapath_id", 0),
IntField("n_buffers", 0),
ByteField("n_tables", 1),
ByteField("auxiliary_id", 0),
XShortField("pad", 0),
FlagsField("capabilities", 0, 32, ["FLOW_STATS",
"TABLE_STATS",
"PORT_STATS",
"GROUP_STATS",
"RESERVED", # undefined
"IP_REASM",
"QUEUE_STATS",
"ARP_MATCH_IP", # undefined # noqa: E501
"PORT_BLOCKED"]),
IntField("reserved", 0)]
class OFPTGetConfigRequest(_ofp_header):
name = "OFPT_GET_CONFIG_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 7, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTGetConfigReply(_ofp_header):
name = "OFPT_GET_CONFIG_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 8, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("flags", 0, {0: "FRAG_NORMAL",
1: "FRAG_DROP",
2: "FRAG_REASM",
3: "FRAG_MASK"}),
ShortField("miss_send_len", 0)]
class OFPTSetConfig(_ofp_header):
name = "OFPT_SET_CONFIG"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 9, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("flags", 0, {0: "FRAG_NORMAL",
1: "FRAG_DROP",
2: "FRAG_REASM",
3: "FRAG_MASK"}),
ShortField("miss_send_len", 128)]
class OFPTPacketIn(_ofp_header):
name = "OFPT_PACKET_IN"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 10, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
ShortField("total_len", 0),
ByteEnumField("reason", 0, {0: "OFPR_NO_MATCH",
1: "OFPR_ACTION",
2: "OFPR_INVALID_TTL"}),
ByteEnumField("table_id", 0, ofp_table),
LongField("cookie", 0),
MatchField("match"),
XShortField("pad", 0),
PacketField("data", "", Ether)]
class OFPTFlowRemoved(_ofp_header):
name = "OFPT_FLOW_REMOVED"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 11, ofp_type),
ShortField("len", None),
IntField("xid", 0),
LongField("cookie", 0),
ShortField("priority", 0),
ByteEnumField("reason", 0, {0: "OFPRR_IDLE_TIMEOUT",
1: "OFPRR_HARD_TIMEOUT",
2: "OFPRR_DELETE",
3: "OFPRR_GROUP_DELETE"}),
ByteEnumField("table_id", 0, ofp_table),
IntField("duration_sec", 0),
IntField("duration_nsec", 0),
ShortField("idle_timeout", 0),
ShortField("hard_timeout", 0),
LongField("packet_count", 0),
LongField("byte_count", 0),
MatchField("match")]
class OFPTPortStatus(_ofp_header):
name = "OFPT_PORT_STATUS"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 12, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ByteEnumField("reason", 0, {0: "OFPPR_ADD",
1: "OFPPR_DELETE",
2: "OFPPR_MODIFY"}),
XBitField("pad", 0, 56),
PacketField("desc", OFPPort(), OFPPort)]
class OFPTPacketOut(_ofp_header):
name = "OFPT_PACKET_OUT"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 13, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
IntEnumField("in_port", "CONTROLLER", ofp_port_no),
FieldLenField("actions_len", None, fmt="H", length_of="actions"), # noqa: E501
XBitField("pad", 0, 48),
PacketListField("actions", [], OFPAT,
OFPAT,
length_from=lambda pkt:pkt.actions_len),
PacketField("data", "", Ether)]
class OFPTFlowMod(_ofp_header):
name = "OFPT_FLOW_MOD"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 14, ofp_type),
ShortField("len", None),
IntField("xid", 0),
LongField("cookie", 0),
LongField("cookie_mask", 0),
ByteEnumField("table_id", 0, ofp_table),
ByteEnumField("cmd", 0, {0: "OFPFC_ADD",
1: "OFPFC_MODIFY",
2: "OFPFC_MODIFY_STRICT",
3: "OFPFC_DELETE",
4: "OFPFC_DELETE_STRICT"}),
ShortField("idle_timeout", 0),
ShortField("hard_timeout", 0),
ShortField("priority", 0),
IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
IntEnumField("out_port", "ANY", ofp_port_no),
IntEnumField("out_group", "ANY", ofp_group),
FlagsField("flags", 0, 16, ["SEND_FLOW_REM",
"CHECK_OVERLAP",
"RESET_COUNTS",
"NO_PKT_COUNTS",
"NO_BYT_COUNTS"]),
XShortField("pad", 0),
MatchField("match"),
PacketListField("instructions", [], OFPIT,
length_from=lambda pkt:pkt.len - 48 - (pkt.match.len + (8 - pkt.match.len % 8) % 8))] # noqa: E501
# include match padding to match.len
class OFPTGroupMod(_ofp_header):
name = "OFPT_GROUP_MOD"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 15, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("cmd", 0, {0: "OFPGC_ADD",
1: "OFPGC_MODIFY",
2: "OFPGC_DELETE"}),
ByteEnumField("group_type", 0, {0: "OFPGT_ALL",
1: "OFPGT_SELECT",
2: "OFPGT_INDIRECT",
3: "OFPGT_FF"}),
XByteField("pad", 0),
IntEnumField("group_id", 0, ofp_group),
PacketListField("buckets", [], OFPBucket,
length_from=lambda pkt:pkt.len - 16)]
class OFPTPortMod(_ofp_header):
name = "OFPT_PORT_MOD"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 16, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("port_no", 0, ofp_port_no),
XIntField("pad1", 0),
MACField("hw_addr", "0"),
XShortField("pad2", 0),
FlagsField("config", 0, 32, ofp_port_config),
FlagsField("mask", 0, 32, ofp_port_config),
FlagsField("advertise", 0, 32, ofp_port_features),
XIntField("pad3", 0)]
class OFPTTableMod(_ofp_header):
name = "OFPT_TABLE_MOD"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 17, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ByteEnumField("table_id", 0, ofp_table),
X3BytesField("pad", 0),
IntEnumField("config", 0, {3: "OFPTC_DEPRECATED_MASK"})]
#####################################################
# OFPT_MULTIPART #
#####################################################
ofp_multipart_types = {0: "OFPMP_DESC",
1: "OFPMP_FLOW",
2: "OFPMP_AGGREGATE",
3: "OFPMP_TABLE",
4: "OFPMP_PORT_STATS",
5: "OFPMP_QUEUE",
6: "OFPMP_GROUP",
7: "OFPMP_GROUP_DESC",
8: "OFPMP_GROUP_FEATURES",
9: "OFPMP_METER",
10: "OFPMP_METER_CONFIG",
11: "OFPMP_METER_FEATURES",
12: "OFPMP_TABLE_FEATURES",
13: "OFPMP_PORT_DESC",
65535: "OFPST_VENDOR"}
ofpmp_request_flags = ["REQ_MORE"]
ofpmp_reply_flags = ["REPLY_MORE"]
class OFPMPRequestDesc(_ofp_header):
name = "OFPMP_REQUEST_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 0, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad", 0)]
class OFPMPReplyDesc(_ofp_header):
name = "OFPMP_REPLY_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 0, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad", 0),
StrFixedLenField("mfr_desc", "", 256),
StrFixedLenField("hw_desc", "", 256),
StrFixedLenField("sw_desc", "", 256),
StrFixedLenField("serial_num", "", 32),
StrFixedLenField("dp_desc", "", 256)]
class OFPMPRequestFlow(_ofp_header):
name = "OFPMP_REQUEST_FLOW"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 1, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
ByteEnumField("table_id", "ALL", ofp_table),
X3BytesField("pad2", 0),
IntEnumField("out_port", "ANY", ofp_port_no),
IntEnumField("out_group", "ANY", ofp_group),
IntField("pad3", 0),
LongField("cookie", 0),
LongField("cookie_mask", 0),
MatchField("match")]
class OFPFlowStats(_ofp_header_item):
name = "OFP_FLOW_STATS"
fields_desc = [ShortField("len", None),
ByteEnumField("table_id", 0, ofp_table),
XByteField("pad1", 0),
IntField("duration_sec", 0),
IntField("duration_nsec", 0),
ShortField("priority", 0),
ShortField("idle_timeout", 0),
ShortField("hard_timeout", 0),
FlagsField("flags", 0, 16, ["SEND_FLOW_REM",
"CHECK_OVERLAP",
"RESET_COUNTS",
"NO_PKT_COUNTS",
"NO_BYT_COUNTS"]),
IntField("pad2", 0),
LongField("cookie", 0),
LongField("packet_count", 0),
LongField("byte_count", 0),
MatchField("match"),
PacketListField("instructions", [], OFPIT,
length_from=lambda pkt:pkt.len - 56 - pkt.match.len)] # noqa: E501
def extract_padding(self, s):
return b"", s
class OFPMPReplyFlow(_ofp_header):
name = "OFPMP_REPLY_FLOW"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 1, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("flow_stats", [], OFPFlowStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestAggregate(OFPMPRequestFlow):
name = "OFPMP_REQUEST_AGGREGATE"
mp_type = 2
class OFPMPReplyAggregate(_ofp_header):
name = "OFPMP_REPLY_AGGREGATE"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 2, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
LongField("packet_count", 0),
LongField("byte_count", 0),
IntField("flow_count", 0),
XIntField("pad2", 0)]
class OFPMPRequestTable(_ofp_header):
name = "OFPMP_REQUEST_TABLE"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 3, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0)]
class OFPTableStats(Packet):
name = "OFP_TABLE_STATS"
fields_desc = [ByteEnumField("table_id", 0, ofp_table),
X3BytesField("pad1", 0),
IntField("active_count", 0),
LongField("lookup_count", 0),
LongField("matched_count", 0)]
def extract_padding(self, s):
return b"", s
class OFPMPReplyTable(_ofp_header):
name = "OFPMP_REPLY_TABLE"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 3, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("table_stats", None, OFPTableStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestPortStats(_ofp_header):
name = "OFPMP_REQUEST_PORT_STATS"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 4, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("port_no", "ANY", ofp_port_no),
XIntField("pad", 0)]
class OFPPortStats(Packet):
def extract_padding(self, s):
return b"", s
name = "OFP_PORT_STATS"
fields_desc = [IntEnumField("port_no", 0, ofp_port_no),
XIntField("pad", 0),
LongField("rx_packets", 0),
LongField("tx_packets", 0),
LongField("rx_bytes", 0),
LongField("tx_bytes", 0),
LongField("rx_dropped", 0),
LongField("tx_dropped", 0),
LongField("rx_errors", 0),
LongField("tx_errors", 0),
LongField("rx_frame_err", 0),
LongField("rx_over_err", 0),
LongField("rx_crc_err", 0),
LongField("collisions", 0),
IntField("duration_sec", 0),
IntField("duration_nsec", 0)]
class OFPMPReplyPortStats(_ofp_header):
name = "OFPMP_REPLY_PORT_STATS"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 4, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("port_stats", None, OFPPortStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestQueue(_ofp_header):
name = "OFPMP_REQUEST_QUEUE"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 5, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("port_no", "ANY", ofp_port_no),
IntEnumField("queue_id", "ALL", ofp_queue)]
class OFPQueueStats(Packet):
name = "OFP_QUEUE_STATS"
fields_desc = [IntEnumField("port_no", 0, ofp_port_no),
IntEnumField("queue_id", 0, ofp_queue),
LongField("tx_bytes", 0),
LongField("tx_packets", 0),
LongField("tx_errors", 0),
IntField("duration_sec", 0),
IntField("duration_nsec", 0)]
def extract_padding(self, s):
return b"", s
class OFPMPReplyQueue(_ofp_header):
name = "OFPMP_REPLY_QUEUE"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 5, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("queue_stats", None, OFPQueueStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestGroup(_ofp_header):
name = "OFPMP_REQUEST_GROUP"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 6, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("group_id", "ANY", ofp_group),
XIntField("pad2", 0)]
class OFPBucketStats(Packet):
name = "OFP_BUCKET_STATS"
fields_desc = [LongField("packet_count", 0),
LongField("byte_count", 0)]
def extract_padding(self, s):
return b"", s
class OFPGroupStats(_ofp_header_item):
name = "OFP_GROUP_STATS"
fields_desc = [ShortField("len", None),
XShortField("pad1", 0),
IntEnumField("group_id", 0, ofp_group),
IntField("ref_count", 0),
IntField("pad2", 0),
LongField("packet_count", 0),
LongField("byte_count", 0),
IntField("duration_sec", 0),
IntField("duration_nsec", 0),
PacketListField("bucket_stats", None, OFPBucketStats,
length_from=lambda pkt:pkt.len - 40)]
def extract_padding(self, s):
return b"", s
class OFPMPReplyGroup(_ofp_header):
name = "OFPMP_REPLY_GROUP"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 6, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("group_stats", [], OFPGroupStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestGroupDesc(_ofp_header):
name = "OFPMP_REQUEST_GROUP_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 7, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0)]
class OFPGroupDesc(_ofp_header_item):
name = "OFP_GROUP_DESC"
fields_desc = [ShortField("len", None),
ByteEnumField("type", 0, {0: "OFPGT_ALL",
1: "OFPGT_SELECT",
2: "OFPGT_INDIRECT",
3: "OFPGT_FF"}),
XByteField("pad", 0),
IntEnumField("group_id", 0, ofp_group),
PacketListField("buckets", None, OFPBucket,
length_from=lambda pkt: pkt.len - 8)]
def extract_padding(self, s):
return b"", s
class OFPMPReplyGroupDesc(_ofp_header):
name = "OFPMP_REPLY_GROUP_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 7, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("group_descs", [], OFPGroupDesc,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestGroupFeatures(_ofp_header):
name = "OFPMP_REQUEST_GROUP_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 8, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0)]
ofp_action_types_flags = [v for v in six.itervalues(ofp_action_types)
if v != 'OFPAT_EXPERIMENTER']
class OFPMPReplyGroupFeatures(_ofp_header):
name = "OFPMP_REPLY_GROUP_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 8, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
FlagsField("types", 0, 32, ["ALL",
"SELECT",
"INDIRECT",
"FF"]),
FlagsField("capabilities", 0, 32, ["SELECT_WEIGHT",
"SELECT_LIVENESS",
"CHAINING",
"CHAINING_CHECKS"]),
IntField("max_group_all", 0),
IntField("max_group_select", 0),
IntField("max_group_indirect", 0),
IntField("max_group_ff", 0),
# no ofpat_experimenter flag
FlagsField("actions_all", 0, 32, ofp_action_types_flags),
FlagsField("actions_select", 0, 32, ofp_action_types_flags),
FlagsField("actions_indirect", 0, 32, ofp_action_types_flags), # noqa: E501
FlagsField("actions_ff", 0, 32, ofp_action_types_flags)]
class OFPMPRequestMeter(_ofp_header):
name = "OFPMP_REQUEST_METER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 9, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("meter_id", "ALL", ofp_meter),
XIntField("pad2", 0)]
class OFPMeterBandStats(Packet):
name = "OFP_METER_BAND_STATS"
fields_desc = [LongField("packet_band_count", 0),
LongField("byte_band_count", 0)]
def extract_padding(self, s):
return b"", s
class OFPMeterStats(Packet):
name = "OFP_GROUP_STATS"
fields_desc = [IntEnumField("meter_id", 1, ofp_meter),
ShortField("len", None),
XBitField("pad", 0, 48),
IntField("flow_count", 0),
LongField("packet_in_count", 0),
LongField("byte_in_count", 0),
IntField("duration_sec", 0),
IntField("duration_nsec", 0),
PacketListField("band_stats", None, OFPMeterBandStats,
length_from=lambda pkt:pkt.len - 40)]
def post_build(self, p, pay):
if self.len is None:
tmp_len = len(p) + len(pay)
p = p[:4] + struct.pack("!H", tmp_len) + p[6:]
return p + pay
def extract_padding(self, s):
return b"", s
class OFPMPReplyMeter(_ofp_header):
name = "OFPMP_REPLY_METER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 9, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("meter_stats", [], OFPMeterStats,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestMeterConfig(_ofp_header):
name = "OFPMP_REQUEST_METER_CONFIG"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 10, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("meter_id", "ALL", ofp_meter),
XIntField("pad2", 0)]
class OFPMeterConfig(_ofp_header_item):
name = "OFP_METER_CONFIG"
fields_desc = [ShortField("len", None),
FlagsField("flags", 0, 16, ["KBPS",
"PKTPS",
"BURST",
"STATS"]),
IntEnumField("meter_id", 1, ofp_meter),
PacketListField("bands", [], OFPMBT,
length_from=lambda pkt:pkt.len - 8)]
def extract_padding(self, s):
return b"", s
class OFPMPReplyMeterConfig(_ofp_header):
name = "OFPMP_REPLY_METER_CONFIG"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 10, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("meter_configs", [], OFPMeterConfig,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestMeterFeatures(_ofp_header):
name = "OFPMP_REQUEST_METER_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 11, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0)]
class OFPMPReplyMeterFeatures(_ofp_header):
name = "OFPMP_REPLY_METER_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 11, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
IntField("max_meter", 0),
FlagsField("band_types", 0, 32, ["DROP",
"DSCP_REMARK",
"EXPERIMENTER"]),
FlagsField("capabilities", 0, 32, ["KPBS",
"PKTPS",
"BURST",
"STATS"]),
ByteField("max_bands", 0),
ByteField("max_color", 0),
XShortField("pad2", 0)]
# table features for multipart messages #
class OFPTFPT(Packet):
name = "Dummy OpenFlow3 Table Features Properties Header"
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_table_features_prop_cls.get(t, Raw)
return Raw
def post_build(self, p, pay):
tmp_len = self.len
if tmp_len is None:
tmp_len = len(p) + len(pay)
p = p[:2] + struct.pack("!H", tmp_len) + p[4:]
# every message will be padded correctly
zero_bytes = (8 - tmp_len % 8) % 8
p += b"\x00" * zero_bytes
return p + pay
def extract_padding(self, s):
return b"", s
ofp_table_features_prop_types = {0: "OFPTFPT_INSTRUCTIONS",
1: "OFPTFPT_INSTRUCTIONS_MISS",
2: "OFPTFPT_NEXT_TABLES",
3: "OFPTFPT_NEXT_TABLES_MISS",
4: "OFPTFPT_WRITE_ACTIONS",
5: "OFPTFPT_WRITE_ACTIONS_MISS",
6: "OFPTFPT_APPLY_ACTIONS",
7: "OFPTFPT_APPLY_ACTIONS_MISS",
8: "OFPTFPT_MATCH",
10: "OFPTFPT_WILDCARDS",
12: "OFPTFPT_WRITE_SETFIELD",
13: "OFPTFPT_WRITE_SETFIELD_MISS",
14: "OFPTFPT_APPLY_SETFIELD",
15: "OFPTFPT_APPLY_SETFIELD_MISS",
65534: "OFPTFPT_EXPERIMENTER",
65535: "OFPTFPT_EXPERIMENTER_MISS"}
class OFPTFPTInstructions(OFPTFPT):
name = "OFPTFPT_INSTRUCTIONS"
fields_desc = [ShortField("type", 0),
ShortField("len", None),
PacketListField("instruction_ids", [], OFPITID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTInstructionsMiss(OFPTFPT):
name = "OFPTFPT_INSTRUCTIONS_MISS"
fields_desc = [ShortField("type", 1),
ShortField("len", None),
PacketListField("instruction_ids", [], OFPITID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTableID(Packet):
name = "OFP_TABLE_ID"
fields_desc = [ByteEnumField("table_id", 0, ofp_table)]
def extract_padding(self, s):
return b"", s
class OFPTFPTNextTables(OFPTFPT):
name = "OFPTFPT_NEXT_TABLES"
fields_desc = [ShortField("type", 2),
ShortField("len", None),
PacketListField("next_table_ids", None, OFPTableID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTNextTablesMiss(OFPTFPT):
name = "OFPTFPT_NEXT_TABLES_MISS"
fields_desc = [ShortField("type", 3),
ShortField("len", None),
PacketListField("next_table_ids", None, OFPTableID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTWriteActions(OFPTFPT):
name = "OFPTFPT_WRITE_ACTIONS"
fields_desc = [ShortField("type", 4),
ShortField("len", None),
PacketListField("action_ids", [], OFPATID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTWriteActionsMiss(OFPTFPT):
name = "OFPTFPT_WRITE_ACTIONS_MISS"
fields_desc = [ShortField("type", 5),
ShortField("len", None),
PacketListField("action_ids", [], OFPATID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTApplyActions(OFPTFPT):
name = "OFPTFPT_APPLY_ACTIONS"
fields_desc = [ShortField("type", 6),
ShortField("len", None),
PacketListField("action_ids", [], OFPATID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTApplyActionsMiss(OFPTFPT):
name = "OFPTFPT_APPLY_ACTIONS_MISS"
fields_desc = [ShortField("type", 7),
ShortField("len", None),
PacketListField("action_ids", [], OFPATID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTMatch(OFPTFPT):
name = "OFPTFPT_MATCH"
fields_desc = [ShortField("type", 8),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTWildcards(OFPTFPT):
name = "OFPTFPT_WILDCARDS"
fields_desc = [ShortField("type", 10),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTWriteSetField(OFPTFPT):
name = "OFPTFPT_WRITE_SETFIELD"
fields_desc = [ShortField("type", 12),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTWriteSetFieldMiss(OFPTFPT):
name = "OFPTFPT_WRITE_SETFIELD_MISS"
fields_desc = [ShortField("type", 13),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTApplySetField(OFPTFPT):
name = "OFPTFPT_APPLY_SETFIELD"
fields_desc = [ShortField("type", 14),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTApplySetFieldMiss(OFPTFPT):
name = "OFPTFPT_APPLY_SETFIELD_MISS"
fields_desc = [ShortField("type", 15),
ShortField("len", None),
PacketListField("oxm_ids", [], OXMID,
length_from=lambda pkt:pkt.len - 4)]
class OFPTFPTExperimenter(OFPTFPT):
name = "OFPTFPT_EXPERIMENTER"
fields_desc = [ShortField("type", 65534),
ShortField("len", None),
IntField("experimenter", 0),
IntField("exp_type", 0),
PacketLenField("experimenter_data", None, Raw,
length_from=lambda pkt: pkt.len - 12)]
class OFPTFPTExperimenterMiss(OFPTFPT):
name = "OFPTFPT_EXPERIMENTER_MISS"
fields_desc = [ShortField("type", 65535),
ShortField("len", None),
IntField("experimenter", 0),
IntField("exp_type", 0),
PacketLenField("experimenter_data", None, Raw,
length_from=lambda pkt: pkt.len - 12)]
ofp_table_features_prop_cls = {0: OFPTFPTInstructions,
1: OFPTFPTInstructionsMiss,
2: OFPTFPTNextTables,
3: OFPTFPTNextTablesMiss,
4: OFPTFPTWriteActions,
5: OFPTFPTWriteActionsMiss,
6: OFPTFPTApplyActions,
7: OFPTFPTApplyActionsMiss,
8: OFPTFPTMatch,
10: OFPTFPTWildcards,
12: OFPTFPTWriteSetField,
13: OFPTFPTWriteSetFieldMiss,
14: OFPTFPTApplySetField,
15: OFPTFPTApplySetFieldMiss,
65534: OFPTFPTExperimenter,
65535: OFPTFPTExperimenterMiss}
class OFPTableFeatures(_ofp_header_item):
name = "OFP_TABLE_FEATURES"
fields_desc = [ShortField("len", None),
ByteEnumField("table_id", 0, ofp_table),
XBitField("pad", 0, 40),
StrFixedLenField("table_name", "", 32),
LongField("metadata_match", 0),
LongField("metadata_write", 0),
IntEnumField("config", 0, {0: "OFPTC_NO_MASK",
3: "OFPTC_DEPRECATED_MASK"}),
IntField("max_entries", 0),
PacketListField("properties", [], OFPTFPT,
length_from=lambda pkt:pkt.len - 64)]
def extract_padding(self, s):
return b"", s
class OFPMPRequestTableFeatures(_ofp_header):
name = "OFPMP_REQUEST_TABLE_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 12, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
PacketListField("table_features", [], OFPTableFeatures,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPReplyTableFeatures(_ofp_header):
name = "OFPMP_REPLY_TABLE_FEATURES"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 12, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("table_features", [], OFPTableFeatures,
length_from=lambda pkt:pkt.len - 16)]
# end of table features #
class OFPMPRequestPortDesc(_ofp_header):
name = "OFPMP_REQUEST_PORT_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 13, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntEnumField("port_no", 0, ofp_port_no),
XIntField("pad", 0)]
class OFPMPReplyPortDesc(_ofp_header):
name = "OFPMP_REPLY_PORT_DESC"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 13, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
PacketListField("ports", None, OFPPort,
length_from=lambda pkt:pkt.len - 16)]
class OFPMPRequestExperimenter(_ofp_header):
name = "OFPST_REQUEST_EXPERIMENTER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 18, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 65535, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_request_flags),
XIntField("pad1", 0),
IntField("experimenter", 0),
IntField("exp_type", 0)]
class OFPMPReplyExperimenter(_ofp_header):
name = "OFPST_REPLY_EXPERIMENTER"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 19, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("mp_type", 65535, ofp_multipart_types),
FlagsField("flags", 0, 16, ofpmp_reply_flags),
XIntField("pad1", 0),
IntField("experimenter", 0),
IntField("exp_type", 0)]
# ofp_multipart_request/reply_cls allows generic method OpenFlow3()
# to choose the right class for dissection
ofp_multipart_request_cls = {0: OFPMPRequestDesc,
1: OFPMPRequestFlow,
2: OFPMPRequestAggregate,
3: OFPMPRequestTable,
4: OFPMPRequestPortStats,
5: OFPMPRequestQueue,
6: OFPMPRequestGroup,
7: OFPMPRequestGroupDesc,
8: OFPMPRequestGroupFeatures,
9: OFPMPRequestMeter,
10: OFPMPRequestMeterConfig,
11: OFPMPRequestMeterFeatures,
12: OFPMPRequestTableFeatures,
13: OFPMPRequestPortDesc,
65535: OFPMPRequestExperimenter}
ofp_multipart_reply_cls = {0: OFPMPReplyDesc,
1: OFPMPReplyFlow,
2: OFPMPReplyAggregate,
3: OFPMPReplyTable,
4: OFPMPReplyPortStats,
5: OFPMPReplyQueue,
6: OFPMPReplyGroup,
7: OFPMPReplyGroupDesc,
8: OFPMPReplyGroupFeatures,
9: OFPMPReplyMeter,
10: OFPMPReplyMeterConfig,
11: OFPMPReplyMeterFeatures,
12: OFPMPReplyTableFeatures,
13: OFPMPReplyPortDesc,
65535: OFPMPReplyExperimenter}
# end of OFPT_MULTIPART #
class OFPTBarrierRequest(_ofp_header):
name = "OFPT_BARRIER_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 20, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTBarrierReply(_ofp_header):
name = "OFPT_BARRIER_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 21, ofp_type),
ShortField("len", None),
IntField("xid", 0)]
class OFPTQueueGetConfigRequest(_ofp_header):
name = "OFPT_QUEUE_GET_CONFIG_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 22, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("port_no", "ANY", ofp_port_no),
XIntField("pad", 0)]
class OFPTQueueGetConfigReply(_ofp_header):
name = "OFPT_QUEUE_GET_CONFIG_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 23, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("port", 0, ofp_port_no),
XIntField("pad", 0),
PacketListField("queues", [], OFPPacketQueue,
length_from=lambda pkt:pkt.len - 16)]
class OFPTRoleRequest(_ofp_header):
name = "OFPT_ROLE_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 24, ofp_type),
ShortField("len", None),
IntField("xid", 0),
IntEnumField("role", 0, {0: "OFPCR_ROLE_NOCHANGE",
1: "OFPCR_ROLE_EQUAL",
2: "OFPCR_ROLE_MASTER",
3: "OFPCR_ROLE_SLAVE"}),
XIntField("pad", 0),
LongField("generation_id", 0)]
class OFPTRoleReply(OFPTRoleRequest):
name = "OFPT_ROLE_REPLY"
type = 25
class OFPTGetAsyncRequest(_ofp_header):
name = "OFPT_GET_ASYNC_REQUEST"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 26, ofp_type),
ShortField("len", 8),
IntField("xid", 0)]
ofp_packet_in_reason = ["NO_MATCH",
"ACTION",
"INVALID_TTL"]
ofp_port_reason = ["ADD",
"DELETE",
"MODIFY"]
ofp_flow_removed_reason = ["IDLE_TIMEOUT",
"HARD_TIMEOUT",
"DELETE",
"GROUP_DELETE"]
class OFPTGetAsyncReply(_ofp_header):
name = "OFPT_GET_ASYNC_REPLY"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 27, ofp_type),
ShortField("len", 32),
IntField("xid", 0),
FlagsField("packet_in_mask_master", 0, 32, ofp_packet_in_reason), # noqa: E501
FlagsField("packet_in_mask_slave", 0, 32, ofp_packet_in_reason), # noqa: E501
FlagsField("port_status_mask_master", 0, 32, ofp_port_reason), # noqa: E501
FlagsField("port_status_mask_slave", 0, 32, ofp_port_reason), # noqa: E501
FlagsField("flow_removed_mask_master", 0, 32, ofp_flow_removed_reason), # noqa: E501
FlagsField("flow_removed_mask_slave", 0, 32, ofp_flow_removed_reason)] # noqa: E501
class OFPTSetAsync(OFPTGetAsyncReply):
name = "OFPT_SET_ASYNC"
type = 28
class OFPTMeterMod(_ofp_header):
name = "OFPT_METER_MOD"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 29, ofp_type),
ShortField("len", None),
IntField("xid", 0),
ShortEnumField("cmd", 0, {0: "OFPMC_ADD",
1: "OFPMC_MODIFY",
2: "OFPMC_DELETE"}),
FlagsField("flags", 0, 16, ["KBPS",
"PKTPS",
"BURST",
"STATS"]),
IntEnumField("meter_id", 1, ofp_meter),
PacketListField("bands", [], OFPMBT,
length_from=lambda pkt:pkt.len - 16)]
# ofpt_cls allows generic method OpenFlow3() to choose the right class for dissection # noqa: E501
ofpt_cls = {0: OFPTHello,
# 1: OFPTError,
2: OFPTEchoRequest,
3: OFPTEchoReply,
4: OFPTExperimenter,
5: OFPTFeaturesRequest,
6: OFPTFeaturesReply,
7: OFPTGetConfigRequest,
8: OFPTGetConfigReply,
9: OFPTSetConfig,
10: OFPTPacketIn,
11: OFPTFlowRemoved,
12: OFPTPortStatus,
13: OFPTPacketOut,
14: OFPTFlowMod,
15: OFPTGroupMod,
16: OFPTPortMod,
17: OFPTTableMod,
# 18: OFPTMultipartRequest,
# 19: OFPTMultipartReply,
20: OFPTBarrierRequest,
21: OFPTBarrierReply,
22: OFPTQueueGetConfigRequest,
23: OFPTQueueGetConfigReply,
24: OFPTRoleRequest,
25: OFPTRoleReply,
26: OFPTGetAsyncRequest,
27: OFPTGetAsyncReply,
28: OFPTSetAsync,
29: OFPTMeterMod}