From ad7888abe9853b4cdf324308486b9785c52f15e4 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 24 May 2016 16:52:31 +0200 Subject: Replace interface mapping context for reused vxlan tunnel This can occur when vxlan interface is deleted and then added, but read between those operations cached zombie vxlan interface in the interface mapping context Change-Id: I74fd5126bbcd0df5b5f78725c51030584effe9e4 Signed-off-by: Maros Marsalek --- .../translate/v3po/interfaces/VxlanCustomizer.java | 13 +++++++++++ .../v3po/interfaces/VxlanCustomizerTest.java | 26 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'v3po') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java index df9c25f6a..bec0e8366 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java @@ -118,6 +118,19 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { throw new VppApiInvocationException("vxlanAddDelTunnel", reply.context, reply.retval); } else { LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan); + if(interfaceContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) { + // VPP keeps vxlan tunnels present even after they are delete(reserving ID for next tunnel) + // This may cause inconsistencies in mapping context when configuring tunnels like this: + // 1. Add tunnel 2. Delete tunnel 3. Read interfaces (reserved mapping e.g. vxlan_tunnel0 -> 6 + // will get into mapping context) 4. Add tunnel (this will add another mapping with the same + // reserved ID and context is invalid) + // That's why a check has to be performed here removing mapping vxlan_tunnel0 -> 6 mapping and storing + // new name for that ID + final String formerName = interfaceContext.getName(reply.swIfIndex, writeContext.getMappingContext()); + LOG.debug("Removing updated mapping of a vxlan tunnel, id: {}, former name: {}, new name: {}", + reply.swIfIndex, formerName, swIfName); + interfaceContext.removeName(formerName, writeContext.getMappingContext()); + } // Add new interface to our interface context interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext()); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java index 1ddb48089..f44057f7e 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; +import static java.util.Collections.singletonList; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -30,6 +31,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; +import com.google.common.base.Optional; import com.google.common.net.InetAddresses; import io.fd.honeycomb.v3po.translate.MappingContext; import io.fd.honeycomb.v3po.translate.ModificationCache; @@ -44,6 +46,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; @@ -151,11 +156,32 @@ public class VxlanCustomizerTest { whenVxlanAddDelTunnelThenSuccess(); + doReturn(Optional.absent()) + .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class)); + customizer.writeCurrentAttributes(id, vxlan, writeContext); verifyVxlanAddWasInvoked(vxlan); verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get())); } + @Test + public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception { + final Vxlan vxlan = generateVxlan(); + + whenVxlanAddDelTunnelThenSuccess(); + final Optional ifcMapping = getMapping(ifaceName, 0); + + doReturn(Optional.of(new MappingsBuilder().setMapping(singletonList(ifcMapping.get())).build())) + .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class)); + + customizer.writeCurrentAttributes(id, vxlan, writeContext); + verifyVxlanAddWasInvoked(vxlan); + + // Remove the first mapping before putting in the new one + verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance"))); + verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(ifcMapping.get())); + } + @Test public void testWriteCurrentAttributesFailed() throws Exception { final Vxlan vxlan = generateVxlan(); -- cgit 1.2.3-korg