class PortStatsPropOptical(PortStatsPropHeader): """ Optical port stats property. """ pad = Pad(4) flags = UBInt32() tx_freq_lmda = UBInt32() tx_offset = UBInt32() tx_grid_span = UBInt32() rx_freq_lmda = UBInt32() rx_offset = UBInt32() rx_grid_span = UBInt32() tx_pwr = UBInt16() rx_pwr = UBInt16() bias_current = UBInt16() temperature = UBInt16() def __init__(self, flags=None, tx_freq_lmda=None, tx_offset=None, tx_grid_span=None, rx_freq_lmda=None, rx_offset=None, rx_grid_span=None, tx_pwr=None, rx_pwr=None, bias_current=None, temperature=None): """ Create the optical port stats property. :param flags: Features enabled by the port. :param tx_freq_lmda: Current TX Frequency/Wavelength :param tx_offset: TX Offset :param tx_grid_span: TX Grid Spacing :param rx_freq_lmda: Current RX Frequency/Wavelength :param rx_offset: RX Offset :param rx_grid_span: RX Grid Spacing :param tx_pwr: Current TX power :param rx_pwr: Current RX power :param bias_current: TX Bias Current :param temperature: TX Laser Temperature """ super().type = PortStatsPropType.OFPPSPT_OPTICAL self.flags = flags self.tx_freq_lmda = tx_freq_lmda self.tx_offset = tx_offset self.tx_grid_span = tx_grid_span self.rx_freq_lmda = rx_freq_lmda self.rx_offset = rx_offset self.rx_grid_span = rx_grid_span self.tx_pwr = tx_pwr self.rx_pwr = rx_pwr self.bias_current = bias_current self.temperature = temperature super().length = self.__sizeof__()
class Bucket(GenericStruct): """Bucket for use in groups.""" length = UBInt16() weight = UBInt16() watch_port = UBInt32() watch_group = UBInt32() pad = Pad(4) actions = FixedTypeList(ActionHeader) def __init__(self, length=None, weight=None, watch_port=None, watch_group=None, actions=None): """Initialize all instance variables. Args: length (int): Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. weight (int): Relative weight of bucket. Only defined for select groups. watch_port (int): Port whose state affects whether this bucket is live. Only required for fast failover groups. watch_group (int): Group whose state affects whether this bucket is live. Only required for fast failover groups. actions (~pyof.v0x04.common.action.ListOfActions): The action length is inferred from the length field in the header. """ super().__init__() self.length = length self.weight = weight self.watch_port = watch_port self.watch_group = watch_group self.actions = actions def __repr__(self): return f"{type(self).__name__}(actions={self.actions!r})" def unpack(self, buff, offset=0): """Unpack bucket. Bucket has a dynamic content with length as first field. The length is needed to compute the total buffer offset. """ length = UBInt16() length.unpack(buff, offset=offset) super().unpack(buff[:offset + length.value], offset=offset) def get_size(self, value=None): """ Return the Bucket length. If the object length is None, returns the minimum size. """ if self.length is None: return super().get_size() return self.length
class PortMod(GenericMessage): """Implement messages to modify the physical port behavior.""" header = Header(message_type=Type.OFPT_PORT_MOD) port_no = UBInt32() pad = Pad(4) hw_addr = HWAddress() pad2 = Pad(2) config = UBInt32(enum_ref=PortConfig) mask = UBInt32(enum_ref=PortConfig) advertise = UBInt32(enum_ref=PortFeatures) #: Pad to 64-bits. pad3 = Pad(4) def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None): """Create a PortMod with the optional parameters below. Args: xid (int): OpenFlow xid to the header. port_no (int): Physical port number. hw_addr (HWAddress): The hardware address is not configurable. This is used to sanity-check the request, so it must be the same as returned in an ofp_phy_port struct. config (~pyof.v0x04.common.port.PortConfig): Bitmap of OFPPC_* flags mask (~pyof.v0x04.common.port.PortConfig): Bitmap of OFPPC_* flags to be changed advertise (~pyof.v0x04.common.port.PortFeatures): Bitmap of OFPPF_*. Zero all bits to prevent any action taking place. """ super().__init__(xid) self.port_no = port_no self.hw_addr = hw_addr self.config = config self.mask = mask self.advertise = advertise
class ActionPopPBB(ActionHeader): """Action structure for OFPAT_POP_PBB.""" pad = Pad(4) _allowed_types = (ActionType.OFPAT_POP_PBB, ) def __init__(self): """Create an ActionPopPBB.""" super().__init__(action_type=ActionType.OFPAT_POP_PBB, length=8)
class ActionDecNWTTL(ActionHeader): """Action structure for OFPAT_DEC_NW_TTL.""" pad = Pad(4) _allowed_types = (ActionType.OFPAT_DEC_NW_TTL, ) def __init__(self): """Create a ActionDecNWTTL.""" super().__init__(action_type=ActionType.OFPAT_DEC_NW_TTL, length=8)
class FlowStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_FLOW.""" table_id = UBInt8() #: Align to 32 bits. pad = Pad(3) out_port = UBInt32() out_group = UBInt32() pad2 = Pad(4) cookie = UBInt64() cookie_mask = UBInt64() match = Match() def __init__(self, table_id=Table.OFPTT_ALL, out_port=PortNo.OFPP_ANY, out_group=Group.OFPG_ANY, cookie=0, cookie_mask=0, match=None): """Create a FlowStatsRequest with the optional parameters below. Args: table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (:class:`int`, :class:`~pyof.v0x04.common.port.PortNo`): Require matching entries to include this as an output port. A value of :attr:`.PortNo.OFPP_ANY` indicates no restriction. out_group: Require matching entries to include this as an output group. A value of :attr:`Group.OFPG_ANY` indicates no restriction. cookie: Requires matching entries to contain this cookie value cookie_mask: Mask used to restrict the cookie bits that must match. A value of 0 indicates no restriction. match (~pyof.v0x04.common.flow_match.Match): Fields to match. """ super().__init__() self.table_id = table_id self.out_port = out_port self.out_group = out_group self.cookie = cookie self.cookie_mask = cookie_mask self.match = Match() if match is None else match
class ActionCopyTTLOut(ActionHeader): """Action structure for OFPAT_COPY_TTL_OUT.""" pad = Pad(4) _allowed_types = (ActionType.OFPAT_COPY_TTL_OUT, ) def __init__(self): """Create an ActionCopyTTLOut.""" super().__init__(action_type=ActionType.OFPAT_COPY_TTL_OUT, length=8)
class GroupStats(GenericStruct): """Body of reply to OFPMP_GROUP request.""" length = UBInt16() #: Align to 64 bits. pad = Pad(2) group_id = UBInt32() ref_count = UBInt32() #: Align to 64 bits. pad2 = Pad(4) packet_count = UBInt64() byte_count = UBInt64() duration_sec = UBInt32() duration_nsec = UBInt32() bucket_stats = ListOfBucketCounter() def __init__(self, length=None, group_id=None, ref_count=None, packet_count=None, byte_count=None, duration_sec=None, duration_nsec=None, bucket_stats=None): """Create a GroupStats with the optional parameters below. Args: length: Length of this entry group_id: Group identifier ref_count: Number of flows or groups that directly forward to this group. packet_count: Number of packets processed by group byte_count: Number of bytes processed by group duration_sec: Time group has been alive in seconds duration_nsec: Time group has been alive in nanoseconds bucket_stats: List of stats of group buckets """ super().__init__() self.length = length self.group_id = group_id self.ref_count = ref_count self.packet_count = packet_count self.byte_count = byte_count self.duration_sec = duration_sec self.duration_nsec = duration_nsec self.bucket_stats = bucket_stats
def unpack(self, buff, offset=0): """Discard padding bytes using the unpacked length attribute.""" begin = offset size = 0 for name, value in list(self.get_class_attributes())[:-1]: size = self._unpack_attribute(name, value, buff, begin) begin += size self._unpack_attribute('oxm_match_fields', type(self).oxm_match_fields, buff[:offset + self.length - len(Pad(4))], begin - size)
class MeterBandDrop(MeterBandHeader): """OFPMBT_DROP band - drop packets.""" pad = Pad(4) def __init__(self, rate=None, burst_size=None): """Create a MeterBandDrop with the optional parameters below. Args: rate (int): Rate for dropping packets. burst_size (int): Size of bursts. """ super().__init__(MeterBandType.OFPMBT_DROP, rate, burst_size)
class PacketIn(GenericMessage): """Packet received on port (datapath -> controller).""" #: :class:`~.header.Header`: OpenFlow Header header = Header(message_type=Type.OFPT_PACKET_IN) #: ID assigned by datapath. buffer_id = UBInt32() #: Full length of frame. total_len = UBInt16() #: Reason packet is being sent (one of OFPR_*), reason = UBInt8(enum_ref=PacketInReason) #: ID of the table that was looked up. table_id = UBInt8() #: Cookie of the flow entry that was looked up. cookie = UBInt64() #: Packet metadata. Variable size. match = Match() #: Align to 64 bit + 16 bit pad = Pad(2) #: Ethernet frame whose length is inferred from header.length. #: The padding bytes preceding the Ethernet frame ensure that the IP #: header (if any) following the Ethernet header is 32-bit aligned. data = BinaryData() def __init__(self, xid=None, buffer_id=None, total_len=None, reason=None, table_id=None, cookie=None, match=None, data=b''): """Assign parameters to object attributes. Args: xid (int): Header's xid. buffer_id (int): ID assigned by datapath. total_len (int): Full length of frame. reason (PacketInReason): The reason why the packet is being sent table_id (int): ID of the table that was looked up cookie (int): Cookie of the flow entry that was looked up match (:class:`~.common.flow_match.Match`): Packet metadata. Variable size. data (bytes): Ethernet frame, halfway through 32-bit word, so the IP header is 32-bit aligned. The amount of data is inferred from the length field in the header. Because of padding, offsetof(struct ofp_packet_in, data) == sizeof(struct ofp_packet_in) - 2. """ super().__init__(xid) self.buffer_id = buffer_id self.total_len = total_len self.reason = reason self.table_id = table_id self.cookie = cookie self.match = match self.data = data
class PortDescPropOptical(PortDescPropHeader): """ Optical port description property. """ # Align to 64 bits. pad4 = Pad(4) # Features supported by the port. supported = UBInt32() # Minimum TX Frequency/Wavelength. tx_min_freq_lmda = UBInt32() # Maximum TX Frequency/Wavelength. tx_max_freq_lmda = UBInt32() # TX Grid Spacing Frequency/Wavelength. tx_grid_freq_lmda = UBInt32() # Minimum RX Frequency/Wavelength. rx_min_freq_lmda = UBInt32() # Maximum RX Frequency/Wavelength. rx_max_freq_lmda = UBInt32() # RX Grid Spacing Frequency/Wavelength rx_grid_freq_lmda = UBInt32() # Minimum TX power tx_pwr_min = UBInt16() # Maximun TX power tx_pwr_max = UBInt16() def __init__(self, supported=None, tx_min_freq_lmda=None, tx_max_freq_lmda=None, tx_grid_freq_lmda=None, rx_min_freq_lmda=None, rx_max_freq_lmda=None, rx_grid_freq_lmda=None, tx_pwr_min=None, tx_pwr_max=None): """ Create the Port Description Property for Optical. :param supported: Features supported by the port. :param tx_min_freq_lmda: Minimum TX Frequency/Wavelength. :param tx_max_freq_lmda: Maximum TX Frequency/Wavelength. :param tx_grid_freq_lmda: TX Grid Spacing Frequency/Wavelength. :param rx_min_freq_lmda: Minimum RX Frequency/Wavelength. :param rx_max_freq_lmda: Maximum RX Frequency/Wavelength. :param rx_grid_freq_lmda: RX Grid Spacing Frequency/Wavelength :param tx_pwr_min: Minimum TX power :param tx_pwr_max: Maximun TX power """ super().__init__(type=PortDescPropType.OFPPDPT_OPTICAL) self.supported = supported self.tx_min_freq_lmda = tx_min_freq_lmda self.tx_max_freq_lmda = tx_max_freq_lmda self.tx_grid_freq_lmda = tx_grid_freq_lmda self.rx_grid_freq_lmda = rx_grid_freq_lmda self.rx_min_freq_lmda = rx_min_freq_lmda self.rx_max_freq_lmda = rx_max_freq_lmda self.tx_pwr_min = tx_pwr_min self.tx_pwr_max = tx_pwr_max self.length = self.__sizeof__()
class SwitchFeatures(GenericMessage): """Message sent by the switch device to the controller. This message is the response for a features_request message, sent by the controller to the switch device. The 'OFPT_FEATURES_REPLY' message inherits from this class, despite the strange name. """ header = Header(message_type=Type.OFPT_FEATURES_REPLY) datapath_id = UBInt64() n_buffers = UBInt32() n_tables = UBInt8() auxiliary_id = UBInt8() #: Align to 64-bits. pad = Pad(2) # Features capabilities = UBInt32(enum_ref=Capabilities) reserved = UBInt32() def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, auxiliary_id=None, capabilities=None, reserved=None): """The constructor just assings parameters to object attributes. Args: xid (int): xid to be used on the message header. datapath_id (int): Datapath unique ID. The lower 48-bits are for MAC address, while the upper 16-bits are implementer-defined. n_buffers (int): Max packets buffered at once. n_tables (int): Number of tables supported by datapath. auxiliary_id (int): Identify auxiliary connections. capabilities (int): bitmap of supported capabilities. reserved (int): Reserved. """ super().__init__(xid) self.datapath_id = datapath_id self.n_buffers = n_buffers self.n_tables = n_tables self.auxiliary_id = auxiliary_id self.capabilities = capabilities self.reserved = reserved
class FlowStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_FLOW.""" table_id = UBInt8() #: Align to 32 bits. pad = Pad(3) out_port = UBInt32() out_group = UBInt32() pad2 = Pad(4) cookie = UBInt64() cookie_mask = UBInt64() match = Match() def __init__(self, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None): """The constructor just assings parameters to object attributes. Args: table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (:class:`int`, :class:`.Port`): Require matching entries to include this as an output port. A value of :attr:`.Port.OFPP_NONE` indicates no restriction. out_group: Require matching entries to include this as an output group. A value of OFPG_ANY indicates no restriction. cookie: Requires matching entries to contain this cookie value cookie_mask: Mask used to restrict the cookie bits that must match. A value of 0 indicates no restriction. match (Match): Fields to match. """ super().__init__() self.table_id = table_id self.out_port = out_port self.out_group = out_group self.cookie = cookie self.cookie_mask = cookie_mask self.match = match
class InstructionClearAction(GenericStruct): """Instruction structure for OFPIT_CLEAR_ACTIONS. This structure does not contain any actions. """ #: OFPIT_CLEAR_ACTIONS instruction_type = UBInt16(InstructionType.OFPIT_CLEAR_ACTIONS, enum_ref=InstructionType) #: Length of this struct in bytes. length = UBInt16(8) #: Align to 64-bits pad = Pad(4) #: OFPIT_CLEAR_ACTIONS does not have any action on the list of actions. actions = ListOfActions()
class ActionPopMPLS(ActionHeader): """Action structure for OFPAT_POP_MPLS.""" ethertype = UBInt16() pad = Pad(2) _allowed_types = (ActionType.OFPAT_POP_MPLS, ) def __init__(self, ethertype=None): """Create an ActionPopMPLS with the optional parameters below. Args: ethertype (int): indicates the Ethertype of the payload. """ super().__init__(action_type=ActionType.OFPAT_POP_MPLS) self.ethertype = ethertype
class ActionSetNWTTL(ActionHeader): """Action structure for OFPAT_SET_NW_TTL.""" nw_ttl = UBInt8() pad = Pad(3) _allowed_types = (ActionType.OFPAT_SET_NW_TTL, ) def __init__(self, nw_ttl=None): """Create an ActionSetNWTTL with the optional parameters below. Args: nw_ttl (int): the TTL address to set in the IP header. """ super().__init__(action_type=ActionType.OFPAT_SET_NW_TTL, length=8) self.nw_ttl = nw_ttl
class MeterBandDscpRemark(MeterBandHeader): """OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header.""" prec_level = UBInt8() pad = Pad(3) def __init__(self, rate=None, burst_size=None, prec_level=None): """Create a MeterBandDscpRemark with the optional parameters below. Args: rate (int): Rate for remarking packets. burst_size (int): Size of bursts. prec_level (int): Number of precendence level to substract. """ super().__init__(MeterBandType.OFPMBT_DSCP_REMARK, rate, burst_size) self.prec_level = prec_level
class ActionSetMPLSTTL(ActionHeader): """Action structure for OFPAT_SET_MPLS_TTL.""" mpls_ttl = UBInt8() pad = Pad(3) _allowed_types = (ActionType.OFPAT_SET_MPLS_TTL, ) def __init__(self, mpls_ttl=None): """Create an ActionSetMPLSTTL with the optional parameters below. Args: mpls_ttl (int): The mpls_ttl field is the MPLS TTL to set. """ super().__init__(action_type=ActionType.OFPAT_SET_MPLS_TTL, length=8) self.mpls_ttl = mpls_ttl
class GroupStatsRequest(GenericStruct): """Body of OFPMP_GROUP request.""" #: Group id. All groups is OFPG_ALL group_id = UBInt32() #: Align to 64 bits pad = Pad(4) def __init__(self, group_id=Group.OFPG_ALL): """Create a GroupStatsRequest with the optional parameters below. Args: group_id(int): ID of group to read. OFPG_ALL to request informatio for all groups. """ super().__init__() self.group_id = group_id
class ActionStripVlan(ActionHeader): """Strips VLAN information from packets. Action defined for switches to remove the 802.1q VLAN information from packets. """ pad = Pad(4) _allowed_types = (ActionType.OFPAT_STRIP_VLAN, ) def __init__(self): """Construct the ActionHeader with the appropriate ActionType. No parameters need to be specified. """ super().__init__(action_type=ActionType.OFPAT_STRIP_VLAN, length=8)
class QueueGetConfigRequest(GenericMessage): """Query structure for configured queues on a port.""" header = Header(message_type=Type.OFPT_QUEUE_GET_CONFIG_REQUEST) port = UBInt16(enum_ref=Port) #: Pad to 64-bits pad = Pad(2) def __init__(self, xid=None, port=None): """Create a QueueGetConfigRequest with the optional parameters below. Args: xid (int): xid of OpenFlow header port (~pyof.v0x01.common.phy_port.Port): Target port for the query """ super().__init__(xid) self.port = port
class QueueGetConfigRequest(GenericMessage): """Query structure for configured queues on a port.""" header = Header(message_type=Type.OFPT_GET_CONFIG_REQUEST) port = UBInt16(enum_ref=Port) #: Pad to 64-bits pad = Pad(2) def __init__(self, xid=None, port=None): """The constructor just assings parameters to object attributes. Args: xid (int): xid of OpenFlow header port (Port): Target port for the query """ super().__init__(xid) self.port = port
class InstructionGotoTable(Instruction): """Instruction structure for OFPIT_GOTO_TABLE.""" #: Set next table in the lookup pipeline. table_id = UBInt8() #: Pad to 64 bits. pad = Pad(3) def __init__(self, table_id=Meter.OFPM_ALL): """Create a InstructionGotoTable with the optional parameters below. Args: length (int): Length of this struct in bytes. table_id (int): set next table in the lookup pipeline. """ super().__init__(InstructionType.OFPIT_GOTO_TABLE) self.table_id = table_id
class QueuePropMinRate(GenericStruct): """Define the minimum-rate type queue.""" prop_header = QueuePropHeader( queue_property=QueueProperties.OFPQT_MIN_RATE, length=16) rate = UBInt16() #: 64-bit alignmet. pad = Pad(6) def __init__(self, rate=None): """Create a QueuePropMinRate with the optional parameters below. Args: rate (int): In 1/10 of a percent (1000 -> 100%); >1000 -> disabled. """ super().__init__() self.rate = rate
class QueuePropHeader(GenericStruct): """Describe the header of each queue property.""" property = UBInt16(enum_ref=QueueProperties) len = UBInt16() #: 64-bit alignment pad = Pad(4) def __init__(self, prop=None, length=None): """The contructor takes the paremeters below. Args: property (QueueProperties): The queue property. len (int): Length of property, including this header. """ super().__init__() self.property = prop self.len = length
class QueuePropMinRate(GenericStruct): """Minimum-rate queue property uses the following structure and fields.""" prop_header = QueuePropHeader(property=QueueProperties.OFPQT_MIN_RATE, length=16) #: In 1/10 of a percent; >1000 -> disabled. rate = UBInt16() #: 64-bit alignmet. pad = Pad(6) def __init__(self, rate=None): """The contructor takes the paremeters below. Args: rate (int): In 1/10 of a percent (1000 -> 100%); >1000 -> disabled. """ super().__init__() self.rate = rate
class QueuePropMaxRate(GenericStruct): """Maximum-rate queue property uses the following structure and fields.""" prop_header = QueuePropHeader( queue_property=QueueProperties.OFPQT_MAX_RATE, length=16) #: In 1/10 of a percent; >1000 -> disabled. rate = UBInt16() #: 64-bit alignmet. pad = Pad(6) def __init__(self, rate=None): """Create a QueuePropMaxRate with the optional parameters below. Args: rate (int): In 1/10 of a percent (1000 -> 100%); >1000 -> disabled. """ super().__init__() self.rate = rate
class PortStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_PORT.""" port_no = UBInt16() #: Align to 64-bits. pad = Pad(6) def __init__(self, port_no=None): """The constructor just assings parameters to object attributes. Args: port_no (:class:`int`, :class:`.Port`): OFPST_PORT message must request statistics either for a single port (specified in ``port_no``) or for all ports (if port_no == :attr:`.Port.OFPP_NONE`). """ super().__init__() self.port_no = port_no
class PortStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_PORT.""" port_no = UBInt16() #: Align to 64-bits. pad = Pad(6) def __init__(self, port_no=Port.OFPP_NONE): """Create a PortStatsRequest with the optional parameters below. Args: port_no (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`): OFPST_PORT message must request statistics either for a single port (specified in ``port_no``) or for all ports (if ``port_no`` == :attr:`.Port.OFPP_NONE`). """ super().__init__() self.port_no = port_no