From 2a810b8e6fe88ceef3ef781bfddef79829834b45 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Mon, 16 May 2016 14:51:53 +0200 Subject: Fix interface dump caching Change-Id: I18d29bebf754c34bbc05e5c9cfb78d8aba87c205 Signed-off-by: Marek Gradzki --- .../v3po/interfacesstate/EthernetCustomizer.java | 4 +- .../v3po/interfacesstate/InterfaceCustomizer.java | 7 ++- .../v3po/interfacesstate/InterfaceUtils.java | 63 +++++++++++++--------- .../v3po/interfacesstate/InterfaceUtilsTest.java | 12 +++++ 4 files changed, 54 insertions(+), 32 deletions(-) (limited to 'v3po') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java index eca13c1c9..74ea45c11 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java @@ -16,8 +16,6 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump; - import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; @@ -70,7 +68,7 @@ public class EthernetCustomizer extends FutureJVppCustomizer final InterfaceKey key = id.firstKeyOf(Interface.class); final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName()), getCachedInterfaceDump(ctx)); + interfaceContext.getIndex(key.getName()), ctx); builder.setMtu((int) iface.linkMtu); switch (iface.linkDuplex) { diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java index 82e114603..51d4022d7 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java @@ -23,6 +23,7 @@ import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -72,11 +73,9 @@ public class InterfaceCustomizer extends FutureJVppCustomizer LOG.debug("Reading attributes for interface: {}", id); final InterfaceKey key = id.firstKeyOf(id.getTargetType()); - final Map cachedDump = getCachedInterfaceDump(ctx); - // Pass cached details from getAllIds to getDetails to avoid additional dumps final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName()), cachedDump); + interfaceContext.getIndex(key.getName()), ctx); LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); builder.setName(key.getName()); @@ -97,7 +96,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @SuppressWarnings("unchecked") public static Map getCachedInterfaceDump(final @Nonnull Context ctx) { return ctx.get(DUMPED_IFCS_CONTEXT_KEY) == null - ? Collections.emptyMap() + ? new HashMap<>() // allow customizers to update the cache : (Map) ctx.get(DUMPED_IFCS_CONTEXT_KEY); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java index 036018e88..1ee472745 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkNotNull; +import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump; import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; @@ -26,6 +27,7 @@ import java.math.BigInteger; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; @@ -92,15 +94,15 @@ public final class InterfaceUtils { } // TODO rename and move to V3poUtils + /** - * Reads first 6 bytes of supplied byte array and converts to string as Yang dictates - *

Replace later with + * Reads first 6 bytes of supplied byte array and converts to string as Yang dictates

Replace later with * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- util/src/main/ * java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java * * @param vppPhysAddress byte array of bytes in big endian order, constructing the network IF physical address. * @return String like "aa:bb:cc:dd:ee:ff" - * @throws NullPointerException if vppPhysAddress is null + * @throws NullPointerException if vppPhysAddress is null * @throws IllegalArgumentException if vppPhysAddress.length < 6 */ public static String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) { @@ -110,7 +112,7 @@ public final class InterfaceUtils { StringBuilder physAddr = new StringBuilder(); appendHexByte(physAddr, vppPhysAddress[0]); - for (int i=1; i < PHYSICAL_ADDRESS_LENGTH; i++) { + for (int i = 1; i < PHYSICAL_ADDRESS_LENGTH; i++) { physAddr.append(":"); appendHexByte(physAddr, vppPhysAddress[i]); } @@ -144,34 +146,34 @@ public final class InterfaceUtils { /** * Queries VPP for interface description given interface key. * - * @param futureJvpp VPP Java Future API - * @param key interface key - * @param index VPP index of the interface - * @param allInterfaces cached interfaces dump with all the interfaces. If interface not present, another dump all - * will be performed - * + * @param futureJvpp VPP Java Future API + * @param key interface key + * @param index VPP index of the interface + * @param ctx per-tx scope context containing cached dump with all the interfaces. If the cache is not + * available or outdated, another dump will be performed. * @return SwInterfaceDetails DTO or null if interface was not found - * * @throws IllegalArgumentException If interface cannot be found */ @Nonnull public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp, @Nonnull InterfaceKey key, final int index, - @Nonnull final Map allInterfaces) { + @Nonnull final Context ctx) { final SwInterfaceDump request = new SwInterfaceDump(); request.nameFilter = key.getName().getBytes(); request.nameFilterValid = 1; + final Map allInterfaces = getCachedInterfaceDump(ctx); + + // Returned cached if available + if (allInterfaces.containsKey(index)) { + return allInterfaces.get(index); + } + CompletionStage requestFuture = futureJvpp.swInterfaceDump(request); SwInterfaceDetailsReplyDump ifaces = V3poUtils.getReply(requestFuture.toCompletableFuture()); if (null == ifaces || null == ifaces.swInterfaceDetails || ifaces.swInterfaceDetails.isEmpty()) { request.nameFilterValid = 0; - // Returned cached if available - if(allInterfaces.containsKey(index)) { - return allInterfaces.get(index); - } - LOG.warn("VPP returned null instead of interface by key {} and its not cached", key.getName()); LOG.warn("Iterating through all the interfaces to find interface: {}", key.getName()); @@ -179,10 +181,20 @@ public final class InterfaceUtils { requestFuture = futureJvpp.swInterfaceDump(request); ifaces = V3poUtils.getReply(requestFuture.toCompletableFuture()); - return ifaces.swInterfaceDetails.stream().filter((swIfc) -> swIfc.swIfIndex == index) - .findFirst().orElseThrow(() -> new IllegalArgumentException("Unable to find interface " + key.getName())); + // Update the cache + allInterfaces.clear(); + allInterfaces + .putAll(ifaces.swInterfaceDetails.stream().collect(Collectors.toMap(d -> d.swIfIndex, d -> d))); + + if (allInterfaces.containsKey(index)) { + return allInterfaces.get(index); + } + throw new IllegalArgumentException("Unable to find interface " + key.getName()); } - return Iterables.getOnlyElement(ifaces.swInterfaceDetails); + + final SwInterfaceDetails iface = Iterables.getOnlyElement(ifaces.swInterfaceDetails); + allInterfaces.put(index, iface); // update the cache + return iface; } /** @@ -193,15 +205,15 @@ public final class InterfaceUtils { */ @Nonnull public static Class getInterfaceType(@Nonnull final String interfaceName) { - if(interfaceName.startsWith("tap")) { + if (interfaceName.startsWith("tap")) { return Tap.class; } - if(interfaceName.startsWith("vxlan")) { + if (interfaceName.startsWith("vxlan")) { return VxlanTunnel.class; } - if(interfaceName.startsWith("VirtualEthernet")) { + if (interfaceName.startsWith("VirtualEthernet")) { return VhostUser.class; } @@ -210,8 +222,9 @@ public final class InterfaceUtils { static boolean isInterfaceOfType(final Context ctx, final int index, final Class ifcType) { - final SwInterfaceDetails cachedDetails = checkNotNull(InterfaceCustomizer.getCachedInterfaceDump(ctx).get(index), - "Interface {} cannot be found in context", index); + final SwInterfaceDetails cachedDetails = + checkNotNull(getCachedInterfaceDump(ctx).get(index), + "Interface {} cannot be found in context", index); return ifcType.equals(getInterfaceType(V3poUtils.toString(cachedDetails.interfaceName))); } } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtilsTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtilsTest.java index ff6ed3dde..0a0eff03b 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtilsTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtilsTest.java @@ -19,6 +19,10 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static org.junit.Assert.assertEquals; import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; public class InterfaceUtilsTest { @@ -37,4 +41,12 @@ public class InterfaceUtilsTest { public void testVppPhysAddrToYangInvalidByteArrayLength() throws Exception { InterfaceUtils.vppPhysAddrToYang(new byte[]{1, 2, 3, 4, 5}); } + + @Test + public void testGetInterfaceType() { + assertEquals(Tap.class, InterfaceUtils.getInterfaceType("tap0")); + assertEquals(VxlanTunnel.class, InterfaceUtils.getInterfaceType("vxlan0")); + assertEquals(VhostUser.class, InterfaceUtils.getInterfaceType("VirtualEthernet0/0/0")); + assertEquals(EthernetCsmacd.class, InterfaceUtils.getInterfaceType("local0")); + } } \ No newline at end of file -- cgit 1.2.3-korg