Пример #1
0
 def test_max_field_value(self):
     """Use all bits of oxm_field."""
     self.tlv.oxm_class = OxmClass.OFPXMC_EXPERIMENTER
     self.tlv.oxm_field = 127
     unpacked = OxmTLV()
     unpacked.unpack(self.tlv.pack())
     self.assertEqual(self.tlv, unpacked)
Пример #2
0
    def test_unpack_invalid_field(self):
        """Raise UnpackException if field is invalid for a class.

        Example: field 42 is invalid for oxm_class OFPXMC_OPENFLOW_BASIC.
        """
        field42 = b'\x80\x00T\x00'
        tlv = OxmTLV()
        with self.assertRaises(UnpackException):
            tlv.unpack(field42)
Пример #3
0
    def __init__(self, field=None):
        """Create a ActionSetField with the optional parameters below.

        Args:
            length (int): length padded to 64 bits, followed by exactly
                          oxm_len bytes containing a single OXM TLV, then
                          exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4)
                          (between 0 and 7) bytes of all-zero bytes
            field (:class:`OxmTLV`): OXM field and value.
        """
        super().__init__(action_type=ActionType.OFPAT_SET_FIELD)
        self.field = OxmTLV() if field is None else field
Пример #4
0
class ActionSetField(ActionHeader):
    """Action structure for OFPAT_SET_FIELD."""

    field = OxmTLV()

    _allowed_types = ActionType.OFPAT_SET_FIELD,

    def __init__(self, field=None):
        """Create a ActionSetField with the optional parameters below.

        Args:
            length (int): length padded to 64 bits, followed by exactly
                          oxm_len bytes containing a single OXM TLV, then
                          exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4)
                          (between 0 and 7) bytes of all-zero bytes
            field (:class:`OxmTLV`): OXM field and value.
        """
        super().__init__(action_type=ActionType.OFPAT_SET_FIELD)
        self.field = OxmTLV() if field is None else field

    def pack(self, value=None):
        """Pack this structure updating the length and padding it."""
        self._update_length()
        packet = super().pack()
        return self._complete_last_byte(packet)

    def _update_length(self):
        """Update the length field of the struct."""
        action_length = 4 + len(self.field.pack())
        overflow = action_length % 8
        self.length = action_length
        if overflow:
            self.length = action_length + 8 - overflow

    def _complete_last_byte(self, packet):
        """Pad until the packet length is a multiple of 8 (bytes)."""
        padded_size = self.length
        padding_bytes = padded_size - len(packet)
        if padding_bytes > 0:
            packet += Pad(padding_bytes).pack()
        return packet
Пример #5
0
 def _create_from_pack(self):
     """Return a new instance by unpacking self.tlv.pack()."""
     unpacked = OxmTLV()
     unpacked.unpack(self.tlv.pack())
     return unpacked
Пример #6
0
 def setUp(self):
     """Instantiate an OXM TLV struct."""
     self.tlv = OxmTLV(oxm_class=OxmClass.OFPXMC_OPENFLOW_BASIC,
                       oxm_field=OxmOfbMatchField.OFPXMT_OFB_IN_PHY_PORT,
                       oxm_hasmask=False, oxm_value=b'')
Пример #7
0
class TestOxmTLV(TestCase):
    """Test OXM TLV pack and unpack."""

    def setUp(self):
        """Instantiate an OXM TLV struct."""
        self.tlv = OxmTLV(oxm_class=OxmClass.OFPXMC_OPENFLOW_BASIC,
                          oxm_field=OxmOfbMatchField.OFPXMT_OFB_IN_PHY_PORT,
                          oxm_hasmask=False, oxm_value=b'')

    def test_different_class_types(self):
        """Pack, unpack the result and assert the values are equal."""
        for oxm_class in (OxmClass.OFPXMC_OPENFLOW_BASIC,
                          OxmClass.OFPXMC_EXPERIMENTER):
            self.tlv.oxm_class = oxm_class
            unpacked = self._create_from_pack()
            self.assertEqual(oxm_class, unpacked.oxm_class)

    def test_different_fields(self):
        """Pack, unpack the result and assert the values are equal."""
        for oxm_field in (OxmOfbMatchField.OFPXMT_OFB_IN_PORT,
                          OxmOfbMatchField.OFPXMT_OFB_IPV6_EXTHDR):
            self.tlv.oxm_field = oxm_field
            unpacked = self._create_from_pack()
            self.assertEqual(oxm_field, unpacked.oxm_field)

    def test_hasmask_bit(self):
        """Pack, unpack the result and assert the values are equal."""
        for oxm_hasmask in True, False:
            self.tlv.oxm_hasmask = oxm_hasmask
            unpacked = self._create_from_pack()
            self.assertEqual(oxm_hasmask, unpacked.oxm_hasmask)

    def test_different_values(self):
        """Pack, unpack the result and assert the values are equal."""
        for oxm_value in b'', b'abc':
            self.tlv.oxm_value = oxm_value
            unpacked = self._create_from_pack()
            self.assertEqual(oxm_value, unpacked.oxm_value)

    def _create_from_pack(self):
        """Return a new instance by unpacking self.tlv.pack()."""
        unpacked = OxmTLV()
        unpacked.unpack(self.tlv.pack())
        return unpacked

    def test_pack_overflowed_field(self):
        """Raise PackException if field is bigger than 7 bit."""
        self.tlv.oxm_class = OxmClass.OFPXMC_EXPERIMENTER
        self.tlv.oxm_field = 2**7
        with self.assertRaises(PackException):
            self.tlv.pack()

    def test_pack_invalid_field(self):
        """Raise PackException if field is invalid for a class.

        Example: field 42 is invalid for oxm_class OFPXMC_OPENFLOW_BASIC.
        """
        self.tlv.oxm_class = OxmClass.OFPXMC_OPENFLOW_BASIC
        self.tlv.oxm_field = 42
        with self.assertRaises(PackException):
            self.tlv.pack()

    def test_unpack_invalid_field(self):
        """Raise UnpackException if field is invalid for a class.

        Example: field 42 is invalid for oxm_class OFPXMC_OPENFLOW_BASIC.
        """
        field42 = b'\x80\x00T\x00'
        tlv = OxmTLV()
        with self.assertRaises(UnpackException):
            tlv.unpack(field42)

    def test_max_field_value(self):
        """Use all bits of oxm_field."""
        self.tlv.oxm_class = OxmClass.OFPXMC_EXPERIMENTER
        self.tlv.oxm_field = 127
        unpacked = OxmTLV()
        unpacked.unpack(self.tlv.pack())
        self.assertEqual(self.tlv, unpacked)
Пример #8
0
 def as_of_tlv(self):
     """Return a pyof OXM TLV instance."""
     value_bytes = HWAddress(self.value).pack()
     return OxmTLV(oxm_field=self.oxm_field, oxm_value=value_bytes)
Пример #9
0
 def as_of_tlv(self):
     """Return a pyof OXM TLV instance."""
     value_bytes = self.value.to_bytes(1, 'big')
     return OxmTLV(oxm_field=self.oxm_field, oxm_value=value_bytes)
Пример #10
0
 def _create_vlan_tlv(vlan_id):
     tlv = OxmTLV()
     tlv.oxm_field = OxmOfbMatchField.OFPXMT_OFB_VLAN_VID
     oxm_value = vlan_id | VlanId.OFPVID_PRESENT
     tlv.oxm_value = oxm_value.to_bytes(2, 'big')
     return tlv
Пример #11
0
 def as_of_tlv(self):
     """Return a pyof OXM TLV instance."""
     value = self.value | VlanId.OFPVID_PRESENT
     value_bytes = value.to_bytes(2, 'big')
     return OxmTLV(oxm_field=self.oxm_field, oxm_value=value_bytes)
Пример #12
0
    def _create_flow_mod(version, packet, port):
        """Create a FlowMod message with the appropriate version and data."""
        if version == '0x01':
            flow_mod = FlowMod10()
            flow_mod.match.dl_src = packet.source.value
            flow_mod.match.dl_dst = packet.destination.value
            flow_mod.match.dl_type = packet.ether_type
            flow_mod.actions.append(Output10(port=port))

        else:
            flow_mod = FlowMod13()

            match_dl_type = OxmTLV()
            match_dl_type.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE
            match_dl_type.oxm_value = packet.ether_type.value.to_bytes(
                2, 'big')
            flow_mod.match.oxm_match_fields.append(match_dl_type)

            match_dl_src = OxmTLV()
            match_dl_src.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_SRC
            match_dl_src.oxm_value = packet.source.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_src)

            match_dl_dst = OxmTLV()
            match_dl_dst.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_DST
            match_dl_dst.oxm_value = packet.destination.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_dst)

            action = Output13(port=port)

            instruction = InstructionApplyAction()
            instruction.actions.append(action)

            flow_mod.instructions.append(instruction)

        flow_mod.command = FlowModCommand.OFPFC_ADD
        flow_mod.priority = settings.flow_priority

        return flow_mod
Пример #13
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.lldp_macs
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        # Learn the port where the sender is connected
        in_port = packet_in.in_port

        switch = event.source.switch
        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = FlowMod()
            flow_mod.command = FlowModCommand.OFPFC_ADD
            flow_mod.priority = settings.flow_priority

            match_dl_type = OxmTLV()
            match_dl_type.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE
            match_dl_type.oxm_value = ethernet.ether_type.value.to_bytes(
                2, 'big')
            flow_mod.match.oxm_match_fields.append(match_dl_type)

            match_dl_src = OxmTLV()
            match_dl_src.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_SRC
            match_dl_src.oxm_value = ethernet.source.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_src)

            match_dl_dst = OxmTLV()
            match_dl_dst.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_DST
            match_dl_dst.oxm_value = ethernet.destination.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_dst)

            action = ActionOutput(port=ports[0])

            instruction = InstructionApplyAction()
            instruction.actions.append(action)

            flow_mod.instructions.append(instruction)

            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = PacketOut()
        packet_out.buffer_id = packet_in.buffer_id
        packet_out.in_port = in_port
        packet_out.data = packet_in.data

        port = ports[0] if ports else PortNo.OFPP_FLOOD

        out_action = ActionOutput(port=port)

        packet_out.actions.append(out_action)
        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)