Example #1
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 __repr__(self):
        return (f"{type(self).__name__}({self.field.oxm_field!s}, "
                f"{self.field.oxm_value})")

    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
Example #2
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
Example #3
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)
Example #4
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)