예제 #1
0
class StatsRequest(GenericMessage):
    """Request statistics to switch."""

    #: OpenFlow :class:`~pyof.v0x01.common.header.Header`
    header = Header(message_type=Type.OFPT_STATS_REQUEST)
    body_type = UBInt16(enum_ref=StatsType)
    flags = UBInt16()
    body = BinaryData()

    def __init__(self, xid=None, body_type=None, flags=0, body=b''):
        """Create a StatsRequest with the optional parameters below.

        Args:
            xid (int): xid to be used on the message header.
            body_type (StatsType): One of the OFPST_* constants.
            flags (int): OFPSF_REQ_* flags (none yet defined).
            body (BinaryData): Body of the request.
        """
        super().__init__(xid)
        self.body_type = body_type
        self.flags = flags
        self.body = body

    def pack(self, value=None):
        """Pack according to :attr:`body_type`.

        Make `body` a binary pack before packing this object. Then, restore
        body.
        """
        backup = self.body
        if not value:
            value = self.body

        if hasattr(value, 'pack'):
            self.body = value.pack()
        stats_request_packed = super().pack()

        self.body = backup
        return stats_request_packed

    def unpack(self, buff, offset=0):
        """Unpack according to :attr:`body_type`."""
        super().unpack(buff)

        class_name = self._get_body_class()
        buff = self.body.value
        self.body = FixedTypeList(pyof_class=class_name)
        self.body.unpack(buff)

    def _get_body_class(self):
        if isinstance(self.body_type, (int, UBInt16)):
            self.body_type = self.body_type.enum_ref(self.body_type.value)

        module = import_module('pyof.v0x01.controller2switch.common')
        body_name = self.body_type.name.replace('OFPST_', '').title()

        for class_name in module.__all__:
            if 'Request' in class_name and body_name in class_name:
                return getattr(module, class_name)
        return None
예제 #2
0
class StatsRequest(GenericMessage):
    """Request statistics to switch."""

    #: OpenFlow :class:`~pyof.v0x01.common.header.Header`
    header = Header(message_type=Type.OFPT_STATS_REQUEST)
    body_type = UBInt16(enum_ref=StatsTypes)
    flags = UBInt16()
    body = BinaryData()

    def __init__(self, xid=None, body_type=None, flags=0, body=b''):
        """Create a StatsRequest with the optional parameters below.

        Args:
            xid (int): xid to be used on the message header.
            body_type (StatsTypes): One of the OFPST_* constants.
            flags (int): OFPSF_REQ_* flags (none yet defined).
            body (BinaryData): Body of the request.
        """
        super().__init__(xid)
        self.body_type = body_type
        self.flags = flags
        self.body = body

    def pack(self, value=None):
        """Pack according to :attr:`body_type`.

        Make `body` a binary pack before packing this object. Then, restore
        body.
        """
        backup = self.body
        if not value:
            value = self.body

        if hasattr(value, 'pack'):
            self.body = value.pack()
        stats_request_packed = super().pack()

        self.body = backup
        return stats_request_packed

    def unpack(self, buff, offset=0):
        """Unpack according to :attr:`body_type`."""
        super().unpack(buff)

        class_name = self._get_body_class()
        buff = self.body.value
        self.body = FixedTypeList(pyof_class=class_name)
        self.body.unpack(buff)

    def _get_body_class(self):
        if isinstance(self.body_type, (int, UBInt16)):
            self.body_type = self.body_type.enum_ref(self.body_type.value)

        module = import_module('pyof.v0x01.controller2switch.common')
        body_name = self.body_type.name.replace('OFPST_', '').title()

        for class_name in module.__all__:
            if 'Request' in class_name and body_name in class_name:
                return getattr(module, class_name)
        return None
예제 #3
0
    def unpack(self, buff, offset=0):
        """Unpack according to :attr:`body_type`."""
        super().unpack(buff)

        class_name = self._get_body_class()
        buff = self.body.value
        self.body = FixedTypeList(pyof_class=class_name)
        self.body.unpack(buff)
예제 #4
0
class GroupDescStats(GenericStruct):
    """Body of reply to OFPMP_GROUP_DESC request."""

    length = UBInt16()
    group_type = UBInt8()
    #: Pad to 64 bits.
    pad = Pad(1)
    group_id = UBInt32()
    buckets = FixedTypeList(Bucket)

    def __init__(self,
                 length=None,
                 group_type=None,
                 group_id=None,
                 buckets=None):
        """Create a GroupDescStats with the optional parameters below.

        Args:
            length (int): Length of this entry.
            group_type (|GroupType_v0x05|): One of OFPGT_*.
            group_id (int): Group identifier.
            buckets (|ListOfBuckets_v0x05|): List of buckets in group.
        """
        super().__init__()
        self.length = length
        self.group_type = group_type
        self.group_id = group_id
        self.buckets = buckets
예제 #5
0
    def _get_body_instance(self):
        """Return the body instance."""
        exp_header = ExperimenterMultipartHeader
        simple_body = {MultipartType.OFPMP_DESC: Desc,
                       MultipartType.OFPMP_GROUP_FEATURES: GroupFeatures,
                       MultipartType.OFPMP_METER_FEATURES: MeterFeatures,
                       MultipartType.OFPMP_EXPERIMENTER: exp_header}

        array_of_bodies = {MultipartType.OFPMP_FLOW: FlowStats,
                           MultipartType.OFPMP_AGGREGATE: AggregateStatsReply,
                           MultipartType.OFPMP_TABLE: TableStats,
                           MultipartType.OFPMP_PORT_STATS: PortStats,
                           MultipartType.OFPMP_QUEUE: QueueStats,
                           MultipartType.OFPMP_GROUP: GroupStats,
                           MultipartType.OFPMP_GROUP_DESC: GroupDescStats,
                           MultipartType.OFPMP_METER: MeterStats,
                           MultipartType.OFPMP_METER_CONFIG: MeterConfig,
                           MultipartType.OFPMP_TABLE_FEATURES: TableFeatures,
                           MultipartType.OFPMP_PORT_DESC: Port}

        if isinstance(self.multipart_type, UBInt16):
            self.multipart_type = self.multipart_type.enum_ref(
                self.multipart_type.value)

        pyof_class = simple_body.get(self.multipart_type, None)
        if pyof_class:
            return pyof_class()

        array_of_class = array_of_bodies.get(self.multipart_type, None)
        if array_of_class:
            return FixedTypeList(pyof_class=array_of_class)

        return BinaryData(b'')
예제 #6
0
class TableMod(GenericMessage):
    """Configure/Modify behavior of a flow table."""

    #: class:`~pyof.v0x05.common.action.ActionHeader`: OpenFlow Header
    header = Header(message_type=Type.OFPT_TABLE_MOD)
    #: ID of the table, OFPTT_ALL indicates all tables
    table_id = UBInt8()
    #: Pad to 32 bits
    pad = Pad(3)
    #: Bitmap of OFPTC_* flags
    config = UBInt32()
    #: Table Mod Property list
    properties = FixedTypeList(TableModPropHeader)

    def __init__(self, xid=None, table_id=Table.OFPTT_ALL, config=3, properties=None):
        """Assing parameters to object attributes.

        Args:
            xid (int): :class:`~pyof.v0x05.common.header.Header`'s xid.
                Defaults to random.
            table_id (int): ID of the table, OFPTT_ALL indicates all tables.
            config (int): Bitmap of OFPTC_* flags
        """

        super().__init__(xid)
        self.table_id = table_id
        # This is reserved for future used. The default value is the only valid
        # one from the Enum.
        self.config = config
        self.properties = properties
예제 #7
0
    def _get_body_instance(self):
        """Return the body instance."""
        simple_body = {
            MultipartTypes.OFPMP_FLOW: FlowStatsRequest,
            MultipartTypes.OFPMP_AGGREGATE: AggregateStatsRequest,
            MultipartTypes.OFPMP_PORT_STATS: PortStatsRequest,
            MultipartTypes.OFPMP_QUEUE: QueueStatsRequest,
            MultipartTypes.OFPMP_GROUP: GroupStatsRequest,
            MultipartTypes.OFPMP_METER: MeterMultipartRequest,
            MultipartTypes.OFPMP_EXPERIMENTER: ExperimenterMultipartHeader
        }

        array_of_bodies = {MultipartTypes.OFPMP_TABLE_FEATURES: TableFeatures}

        if isinstance(self.multipart_type, UBInt16):
            self.multipart_type = self.multipart_type.enum_ref(
                self.multipart_type.value)

        pyof_class = simple_body.get(self.multipart_type, None)
        if pyof_class:
            return pyof_class()

        array_of_class = array_of_bodies.get(self.multipart_type, None)
        if array_of_class:
            return FixedTypeList(pyof_class=array_of_class)

        return BinaryData(b'')
예제 #8
0
class MeterMod(GenericMessage):
    """Meter configuration."""

    header = Header(message_type=Type.OFPT_METER_MOD)
    command = UBInt16(enum_ref=MeterModCommand)
    flags = UBInt16(enum_ref=MeterFlags)
    meter_id = UBInt32()
    bands = FixedTypeList(MeterBandHeader)

    def __init__(self,
                 xid=None,
                 command=None,
                 flags=None,
                 meter_id=None,
                 bands=None):
        """Instance attributes assignment.

        Args:
            xid (int): Headers transaction id. Defaults to random.
            command (MeterModCommand): One of OFPMC_*.
            flags (MeterFlags): One of OFPMF_*.
            meter_id (int): Meter instance.
            bands (MeterBandHeader): The bands length is inferred from the
                length field in the header.
        """
        super().__init__(xid)
        self.command = command
        self.flags = flags
        self.meter_id = meter_id
        self.bands = bands
예제 #9
0
    def __init__(self,
                 xid=None,
                 port_no=None,
                 hw_addr=None,
                 config=None,
                 mask=None,
                 properties=FixedTypeList(pyof_class=PortModPropHeader)):
        """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.v0x05.common.port.PortConfig):
                Bitmap of OFPPC_* flags
            mask (~pyof.v0x05.common.port.PortConfig):
                Bitmap of OFPPC_* flags to be changed
            properties (FixedTypeList(pyof_class=PortModPropHeader)):
                Port mod property list - 0 or more properties
        """
        super().__init__(xid)
        self.port_no = port_no
        self.hw_addr = hw_addr
        self.config = config
        self.mask = mask
        self.properties = properties
예제 #10
0
class MeterMod(GenericMessage):
    """Meter configuration."""

    header = Header(message_type=Type.OFPT_METER_MOD)
    #: One of OFPMC_*.
    command = UBInt16(enum_ref=MeterModCommand)
    #: Bitmap of OFPMF_* flags.
    flags = UBInt16(enum_ref=MeterFlags)
    #: Meter instance.
    meter_id = UBInt32()
    #: The band list length field in the header.
    bands = FixedTypeList(MeterBandHeader)

    def __init__(self,
                 xid=None,
                 command=None,
                 flags=None,
                 meter_id=None,
                 bands=None):
        """Create a MeterMod with the optional parameters below.

        Args:
            xid (int): Headers transaction id. Defaults to random.
            command (MeterModCommand): One of OFPMC_*.
            flags (MeterFlags): One of OFPMF_*.
            meter_id (int): Meter instance.
            bands (MeterBandHeader): The bands length is inferred from the
                length field in the header.
        """
        super().__init__(xid)
        self.command = command
        self.flags = flags
        self.meter_id = meter_id
        self.bands = bands
예제 #11
0
    def unpack(self, buff, offset=0):
        """Unpack according to :attr:`body_type`."""
        super().unpack(buff)

        class_name = self._get_body_class()
        buff = self.body.value
        self.body = FixedTypeList(pyof_class=class_name)
        self.body.unpack(buff)
예제 #12
0
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 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
예제 #13
0
    def _get_body_instance(self):
        """Return the body instance."""
        pyof_class = self._get_body_class()

        if pyof_class is None:
            return BinaryData(b'')
        elif pyof_class is DescStats:
            return pyof_class()

        return FixedTypeList(pyof_class=pyof_class)
예제 #14
0
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 = FixedTypeList(BucketCounter)

    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
예제 #15
0
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)
    #: The hardware address is not configurable. This is used to
    #: sanity-check the request, so it must be the same as returned in an port struct.
    hw_addr = HWAddress()
    #: Pad to 64 bits.
    pad2 = Pad(2)
    #: Bitmap of OFPPC_* flags.
    config = UBInt32(enum_ref=PortConfig)
    #: Bitmap of OFPPC_* flags to be changed.
    mask = UBInt32(enum_ref=PortConfig)
    #: Port mod property list - 0 or more properties
    properties = FixedTypeList(pyof_class=PortModPropHeader)

    def __init__(self,
                 xid=None,
                 port_no=None,
                 hw_addr=None,
                 config=None,
                 mask=None,
                 properties=FixedTypeList(pyof_class=PortModPropHeader)):
        """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.v0x05.common.port.PortConfig):
                Bitmap of OFPPC_* flags
            mask (~pyof.v0x05.common.port.PortConfig):
                Bitmap of OFPPC_* flags to be changed
            properties (FixedTypeList(pyof_class=PortModPropHeader)):
                Port mod property list - 0 or more properties
        """
        super().__init__(xid)
        self.port_no = port_no
        self.hw_addr = hw_addr
        self.config = config
        self.mask = mask
        self.properties = properties
예제 #16
0
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