diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7a863ab7..c2b6474c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,11 @@ All notable changes to the of_core NApp will be documented in this file. [UNRELEASED] - Under development ******************************** +Changed +======= +- ``MatchDLVLAN`` can handle values such as ``"4096/4096"`` and 0 + + [2022.3.1] - 2023-02-23 *********************** diff --git a/tests/integration/v0x04/test_match.py b/tests/integration/v0x04/test_match.py index ab723fe8..1ba767f5 100644 --- a/tests/integration/v0x04/test_match.py +++ b/tests/integration/v0x04/test_match.py @@ -20,3 +20,17 @@ def test_dl_vlan_pyof(self): of_tlv = expected.as_of_tlv() actual = MatchDLVLAN.from_of_tlv(of_tlv) self.assertEqual(expected, actual) + + def test_dl_vlan_mask_pyof(self): + """Convert to and from pyog OxmTLV with mask""" + expected = MatchDLVLAN("4096/4096") + of_tlv = expected.as_of_tlv() + actual = MatchDLVLAN.from_of_tlv(of_tlv) + self.assertEqual(expected, actual) + + def test_dl_vlan_zero_pyof(self): + """Convert to and from pyog OxmTLV with 0""" + expected = MatchDLVLAN(0) + of_tlv = expected.as_of_tlv() + actual = MatchDLVLAN.from_of_tlv(of_tlv) + self.assertEqual(expected, actual) diff --git a/v0x04/match_fields.py b/v0x04/match_fields.py index 39e5be1e..a61ec883 100644 --- a/v0x04/match_fields.py +++ b/v0x04/match_fields.py @@ -42,7 +42,10 @@ def as_of_tlv(self): except ValueError: value, mask = map(int, self.value.split('/')) oxm_hasmask = True - value = value | VlanId.OFPVID_PRESENT + if value == 0: + value = VlanId.OFPVID_NONE + else: + value = value | VlanId.OFPVID_PRESENT value_bytes = value.to_bytes(2, 'big') if mask: mask = mask | VlanId.OFPVID_PRESENT @@ -53,11 +56,20 @@ def as_of_tlv(self): @classmethod def from_of_tlv(cls, tlv): - """Return an instance from a pyof OXM TLV.""" - vlan_id = int.from_bytes(tlv.oxm_value[:2], 'big') & 4095 + """Return an instance from a pyof OXM TLV. + *oxm_value=0x1000/0x1000 is a valid case. It's necessary to + deserialize 0x1000 as 4096 thus it is ignore to not obtain 0 + """ + vlan_id = int.from_bytes(tlv.oxm_value[:2], 'big') + if vlan_id != 4096: + # Ignore 4096 + vlan_id &= 4095 value = vlan_id if tlv.oxm_hasmask: - vlan_mask = int.from_bytes(tlv.oxm_value[2:], 'big') & 4095 + vlan_mask = int.from_bytes(tlv.oxm_value[2:], 'big') + if vlan_mask != 4096: + # Ignore 4096 + vlan_mask &= 4095 value = f'{vlan_id}/{vlan_mask}' return cls(value)