From b1b07f942fd77b7d987cc44aabd492db5e8c29a0 Mon Sep 17 00:00:00 2001 From: Jan Srnicek Date: Tue, 15 Aug 2017 10:15:06 +0200 Subject: HC2VPP-205 / HC2VPP-25 - Sub interface caching improvement Improves dumping mechanism for sub interfaces in a way that if full dump was already performed, it will be used from cache instead of new dump call. Also prevents creating dump dto's if not necessary Change-Id: I46a305ec1b325c2d949bff9e2b151752ccd508b6 Signed-off-by: Jan Srnicek --- .../main/java/io/fd/hc2vpp/v3po/V3poModule.java | 5 + .../v3po/factory/InterfacesStateReaderFactory.java | 29 +-- ...SubinterfaceStateAugmentationReaderFactory.java | 45 +++-- .../v3po/interfacesstate/EthernetCustomizer.java | 20 +- .../hc2vpp/v3po/interfacesstate/GreCustomizer.java | 15 +- .../interfacesstate/InterconnectionReadUtils.java | 11 +- .../v3po/interfacesstate/InterfaceCustomizer.java | 77 ++------ .../interfacesstate/InterfaceDataTranslator.java | 118 ++---------- .../hc2vpp/v3po/interfacesstate/L2Customizer.java | 15 +- .../v3po/interfacesstate/RewriteCustomizer.java | 21 +-- .../interfacesstate/SubInterfaceCustomizer.java | 49 ++--- .../interfacesstate/SubInterfaceL2Customizer.java | 45 ++--- .../hc2vpp/v3po/interfacesstate/TapCustomizer.java | 34 +++- .../v3po/interfacesstate/VhostUserCustomizer.java | 42 +++-- .../v3po/interfacesstate/VxlanCustomizer.java | 76 ++++---- .../v3po/interfacesstate/VxlanGpeCustomizer.java | 20 +- .../cache/InterfaceCacheDumpManager.java | 59 ++++++ .../cache/InterfaceCacheDumpManagerImpl.java | 197 ++++++++++++++++++++ .../cache/InterfaceCacheDumpManagerProvider.java | 38 ++++ .../cache/StaticCacheKeyFactory.java | 45 +++++ .../interfacesstate/EthernetCustomizerTest.java | 32 ++-- .../v3po/interfacesstate/GreCustomizerTest.java | 49 +++-- .../interfacesstate/InterfaceCustomizerTest.java | 75 ++++---- .../v3po/interfacesstate/L2CustomizerTest.java | 18 +- .../interfacesstate/RewriteCustomizerTest.java | 30 +-- .../SubInterfaceCustomizerTest.java | 38 ++-- .../SubInterfaceL2CustomizerTest.java | 21 +-- .../v3po/interfacesstate/TapCustomizerTest.java | 25 ++- .../interfacesstate/VhostUserCustomizerTest.java | 27 +-- .../v3po/interfacesstate/VxlanCustomizerTest.java | 49 ++--- .../interfacesstate/VxlanGpeCustomizerTest.java | 47 ++--- .../cache/InterfaceCacheDumpManagerImplTest.java | 203 +++++++++++++++++++++ 32 files changed, 1016 insertions(+), 559 deletions(-) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/V3poModule.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/V3poModule.java index fb8911088..b12893955 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/V3poModule.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/V3poModule.java @@ -17,6 +17,7 @@ package io.fd.hc2vpp.v3po; import com.google.inject.AbstractModule; +import com.google.inject.Singleton; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; import io.fd.hc2vpp.common.translate.util.NamingContext; @@ -26,6 +27,8 @@ import io.fd.hc2vpp.v3po.factory.L2HoneycombWriterFactory; import io.fd.hc2vpp.v3po.factory.L2StateHoneycombReaderFactory; import io.fd.hc2vpp.v3po.factory.SubinterfaceAugmentationWriterFactory; import io.fd.hc2vpp.v3po.factory.SubinterfaceStateAugmentationReaderFactory; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManagerProvider; import io.fd.hc2vpp.v3po.notification.InterfaceChangeNotificationProducerProvider; import io.fd.honeycomb.notification.ManagedNotificationProducer; import io.fd.honeycomb.translate.read.ReaderFactory; @@ -50,6 +53,8 @@ public class V3poModule extends AbstractModule { .annotatedWith(Names.named("bridge-domain-context")) .toInstance(new NamingContext("bridge-domain-", "bridge-domain-context")); + bind(InterfaceCacheDumpManager.class).toProvider(InterfaceCacheDumpManagerProvider.class).in(Singleton.class); + // Context utility for deleted interfaces bind(DisabledInterfacesManager.class).toInstance(new DisabledInterfacesManager()); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java index 44390b41d..eaacb135a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesStateReaderFactory.java @@ -30,6 +30,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.TapCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.VhostUserCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.VxlanCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.VxlanGpeCustomizer; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.hc2vpp.v3po.interfacesstate.pbb.PbbRewriteStateCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.span.InterfaceMirroredInterfacesCustomizer; import io.fd.honeycomb.translate.impl.read.GenericInitListReader; @@ -65,6 +66,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { private final NamingContext ifcNamingCtx; private final NamingContext bdNamingCtx; private final DisabledInterfacesManager ifcDisableContext; + private final InterfaceCacheDumpManager ifaceDumpManager; private final FutureJVppCore jvpp; static final InstanceIdentifier IFC_STATE_ID = @@ -75,11 +77,13 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { public InterfacesStateReaderFactory(final FutureJVppCore jvpp, @Named("interface-context") final NamingContext ifcNamingCtx, @Named("bridge-domain-context") final NamingContext bdNamingCtx, - final DisabledInterfacesManager ifcDisableContext) { + final DisabledInterfacesManager ifcDisableContext, + final InterfaceCacheDumpManager ifaceDumpManager) { this.jvpp = jvpp; this.ifcNamingCtx = ifcNamingCtx; this.bdNamingCtx = bdNamingCtx; this.ifcDisableContext = ifcDisableContext; + this.ifaceDumpManager = ifaceDumpManager; } @Override @@ -87,7 +91,8 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { // InterfacesState(Structural) registry.addStructuralReader(IFC_STATE_ID, InterfacesStateBuilder.class); // Interface - registry.add(new GenericInitListReader<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingCtx, ifcDisableContext))); + registry.add(new GenericInitListReader<>(IFC_ID, + new InterfaceCustomizer(ifcNamingCtx, ifcDisableContext, ifaceDumpManager))); // v3po.yang initVppIfcAugmentationReaders(registry, IFC_ID); @@ -104,25 +109,28 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { registry.addStructuralReader(vppIfcAugId, VppInterfaceStateAugmentationBuilder.class); // Ethernet registry.add(new GenericInitReader<>(vppIfcAugId.child(Ethernet.class), - new EthernetCustomizer(jvpp, ifcNamingCtx))); + new EthernetCustomizer(ifaceDumpManager))); // Routing registry.add(new GenericInitReader<>(vppIfcAugId.child(Routing.class), - new InterfaceRoutingCustomizer(jvpp, ifcNamingCtx))); + new InterfaceRoutingCustomizer(jvpp, ifcNamingCtx))); // Tap - registry.add(new GenericInitReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcNamingCtx))); + registry.add(new GenericInitReader<>(vppIfcAugId.child(Tap.class), + new TapCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager))); // VhostUser registry.add(new GenericInitReader<>(vppIfcAugId.child(VhostUser.class), - new VhostUserCustomizer(jvpp, ifcNamingCtx))); + new VhostUserCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager))); // Vxlan - registry.add(new GenericInitReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcNamingCtx))); + registry.add(new GenericInitReader<>(vppIfcAugId.child(Vxlan.class), + new VxlanCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager))); // VxlanGpe registry.add(new GenericInitReader<>(vppIfcAugId.child(VxlanGpe.class), - new VxlanGpeCustomizer(jvpp, ifcNamingCtx))); + new VxlanGpeCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager))); // Gre - registry.add(new GenericInitReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcNamingCtx))); + registry.add(new GenericInitReader<>(vppIfcAugId.child(Gre.class), + new GreCustomizer(jvpp, ifcNamingCtx, ifaceDumpManager))); // L2 registry.add(new GenericInitReader<>(vppIfcAugId.child(L2.class), - new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx))); + new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx, ifaceDumpManager))); // Span final InstanceIdentifier spanId = vppIfcAugId.child(Span.class); registry.addStructuralReader(spanId, SpanBuilder.class); @@ -141,5 +149,4 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { registry.add(new GenericReader<>(ifcId.augmentation(PbbRewriteStateInterfaceAugmentation.class).child( PbbRewriteState.class), new PbbRewriteStateCustomizer(jvpp))); } - } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java index de91a067b..a041bc820 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceStateAugmentationReaderFactory.java @@ -24,6 +24,7 @@ import io.fd.hc2vpp.v3po.interfacesstate.RewriteCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceCustomizer; import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceL2Customizer; import io.fd.hc2vpp.v3po.interfacesstate.SubInterfaceRoutingCustomizer; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.hc2vpp.v3po.interfacesstate.span.SubInterfaceMirroredInterfacesCustomizer; import io.fd.honeycomb.translate.impl.read.GenericInitListReader; import io.fd.honeycomb.translate.impl.read.GenericInitReader; @@ -36,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinter import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.VppSubinterfaceSpanStateAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.interfaces.state._interface.sub.interfaces.sub._interface.SpanState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.subinterface.span.rev170607.interfaces.state._interface.sub.interfaces.sub._interface.SpanStateBuilder; - import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.span.state.attributes.MirroredInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.SubinterfaceStateAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.SubinterfaceStateAugmentationBuilder; @@ -45,12 +45,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.match.attributes.match.type.vlan.tagged.VlanTagged; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Tags; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.tags.Tag; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.routing.attributes.Routing; - import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -59,21 +58,24 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF private final FutureJVppCore jvpp; private final NamingContext ifcCtx; private final NamingContext bdCtx; + private final InterfaceCacheDumpManager ifaceDumpManager; @Inject public SubinterfaceStateAugmentationReaderFactory(final FutureJVppCore jvpp, @Named("interface-context") final NamingContext ifcCtx, - @Named("bridge-domain-context") final NamingContext bdCtx) { + @Named("bridge-domain-context") final NamingContext bdCtx, + final InterfaceCacheDumpManager ifaceDumpManager) { this.jvpp = jvpp; this.ifcCtx = ifcCtx; this.bdCtx = bdCtx; + this.ifaceDumpManager = ifaceDumpManager; } @Override public void init(final ModifiableReaderRegistryBuilder registry) { // SubinterfaceStateAugmentation(Structural) final InstanceIdentifier subIfcAugId = - InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class); + InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class); registry.addStructuralReader(subIfcAugId, SubinterfaceStateAugmentationBuilder.class); // SubInterfaces(Structural) final InstanceIdentifier subIfcsId = subIfcAugId.child(SubInterfaces.class); @@ -81,26 +83,30 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF // SubInterface(Subtree) final InstanceIdentifier subIfcId = subIfcsId.child(SubInterface.class); registry.subtreeAdd(Sets.newHashSet( - InstanceIdentifier.create(SubInterface.class).child(Tags.class), - InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class), - InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class), - InstanceIdentifier.create(SubInterface.class).child(Match.class), - InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)), - new GenericInitListReader<>(subIfcId, new SubInterfaceCustomizer(jvpp, ifcCtx))); + InstanceIdentifier.create(SubInterface.class).child(Tags.class), + InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class), + InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class), + InstanceIdentifier.create(SubInterface.class).child(Match.class), + InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)), + new GenericInitListReader<>(subIfcId, + new SubInterfaceCustomizer(jvpp, ifcCtx, ifaceDumpManager))); // L2 final InstanceIdentifier l2Id = subIfcId.child(L2.class); - registry.add(new GenericInitReader<>(l2Id, new SubInterfaceL2Customizer(jvpp, ifcCtx, bdCtx))); + registry.add(new GenericInitReader<>(l2Id, + new SubInterfaceL2Customizer(jvpp, ifcCtx, bdCtx, ifaceDumpManager))); // Rewrite(Subtree) registry.subtreeAdd(Sets.newHashSet( - InstanceIdentifier.create(Rewrite.class).child(PushTags.class), - InstanceIdentifier.create(Rewrite.class).child(PushTags.class) - .child( - org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)), - new GenericReader<>(l2Id.child(Rewrite.class), new RewriteCustomizer(jvpp, ifcCtx))); + InstanceIdentifier.create(Rewrite.class).child(PushTags.class), + InstanceIdentifier.create(Rewrite.class).child(PushTags.class) + .child( + org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)), + new GenericReader<>(l2Id.child(Rewrite.class), + new RewriteCustomizer(ifaceDumpManager))); final InstanceIdentifier routingId = subIfcId.child(Routing.class); registry.add(new GenericReader<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcCtx))); - final InstanceIdentifier spanStateAugId = subIfcId.augmentation(VppSubinterfaceSpanStateAugmentation.class); + final InstanceIdentifier spanStateAugId = + subIfcId.augmentation(VppSubinterfaceSpanStateAugmentation.class); registry.addStructuralReader(spanStateAugId, VppSubinterfaceSpanStateAugmentationBuilder.class); final InstanceIdentifier spanStateId = spanStateAugId @@ -108,6 +114,7 @@ public final class SubinterfaceStateAugmentationReaderFactory implements ReaderF registry.addStructuralReader(spanStateId, SpanStateBuilder.class); final InstanceIdentifier mirroredInterfacesId = spanStateId.child(MirroredInterfaces.class); - registry.add(new GenericInitReader<>(mirroredInterfacesId, new SubInterfaceMirroredInterfacesCustomizer(jvpp, ifcCtx))); + registry.add(new GenericInitReader<>(mirroredInterfacesId, + new SubInterfaceMirroredInterfacesCustomizer(jvpp, ifcCtx))); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizer.java index 1afdbcd37..8bb01a98b 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizer.java @@ -16,15 +16,13 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -35,20 +33,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class EthernetCustomizer extends FutureJVppCustomizer +public class EthernetCustomizer implements InitializingReaderCustomizer, InterfaceDataTranslator { - private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class); - private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public EthernetCustomizer(@Nonnull final FutureJVppCore jvpp, - @Nonnull final NamingContext interfaceContext) { - super(jvpp); - this.interfaceContext = interfaceContext; + public EthernetCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) { + this.dumpManager = dumpManager; } @Override @@ -69,8 +62,7 @@ public class EthernetCustomizer extends FutureJVppCustomizer @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); - final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(), - interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, key.getName()); if (iface.linkMtu != 0) { builder.setMtu((int) iface.linkMtu); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizer.java index 3d1782a1e..ee54a110f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizer.java @@ -18,13 +18,14 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkState; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.vpp.jvpp.core.dto.GreTunnelDetails; import io.fd.vpp.jvpp.core.dto.GreTunnelDetailsReplyDump; import io.fd.vpp.jvpp.core.dto.GreTunnelDump; @@ -54,11 +55,15 @@ public class GreCustomizer extends FutureJVppCustomizer implements InitializingReaderCustomizer, InterfaceDataTranslator { private static final Logger LOG = LoggerFactory.getLogger(GreCustomizer.class); - private NamingContext interfaceContext; + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public GreCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) { + public GreCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; } @Override @@ -79,7 +84,7 @@ public class GreCustomizer extends FutureJVppCustomizer @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, GreTunnel.class, LOG)) { + if (!isInterfaceOfType(dumpManager, id, ctx, GreTunnel.class)) { return; } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterconnectionReadUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterconnectionReadUtils.java index 5c3072e42..a25531303 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterconnectionReadUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterconnectionReadUtils.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails; @@ -49,13 +50,16 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator { private final FutureJVppCore futureJVppCore; private final NamingContext interfaceContext; private final NamingContext bridgeDomainContext; + private final InterfaceCacheDumpManager dumpManager; InterconnectionReadUtils(@Nonnull final FutureJVppCore futureJVppCore, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext bridgeDomainContext) { + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { this.futureJVppCore = requireNonNull(futureJVppCore, "futureJVppCore should not be null"); this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null"); this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null"); + this.dumpManager = requireNonNull(dumpManager, "dumpManager should not be null"); } @Nullable @@ -64,8 +68,7 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator { throws ReadFailedException { final int ifaceId = interfaceContext.getIndex(ifaceName, ctx.getMappingContext()); - final SwInterfaceDetails iface = getVppInterfaceDetails(futureJVppCore, id, ifaceName, - ifaceId, ctx.getModificationCache(), LOG); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName); LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); final BridgeDomainDetailsReplyDump dumpReply = getDumpReply(id); @@ -78,7 +81,7 @@ final class InterconnectionReadUtils implements InterfaceDataTranslator { // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index final Optional bridgeDomainForInterface = - getBridgeDomainForInterface(dumpReply, bd.bdId); + getBridgeDomainForInterface(dumpReply, bd.bdId); // Since we already found an interface assigned to a bridge domain, the details for BD must be present checkState(bridgeDomainForInterface.isPresent()); if (bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) { diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizer.java index fe04e5d80..5ec0082e4 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizer.java @@ -17,25 +17,17 @@ package io.fd.hc2vpp.v3po.interfacesstate; import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.v3po.DisabledInterfacesManager; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.ModificationCache; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; @@ -54,36 +46,21 @@ import org.slf4j.LoggerFactory; /** * Customizer for reading ietf-interfaces:interfaces-state/interface. */ -public class InterfaceCustomizer extends FutureJVppCustomizer +public class InterfaceCustomizer implements InitializingListReaderCustomizer, ByteDataTranslator, InterfaceDataTranslator { - public static final String DUMPED_IFCS_CONTEXT_KEY = - InterfaceCustomizer.class.getName() + "dumpedInterfacesDuringGetAllIds"; private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); private final NamingContext interfaceNamingContext; private final DisabledInterfacesManager interfaceDisableContext; + private final InterfaceCacheDumpManager dumpManager; - public InterfaceCustomizer(@Nonnull final FutureJVppCore jvpp, - @Nonnull final NamingContext interfaceNamingContext, - @Nonnull final DisabledInterfacesManager interfaceDisableContext) { - super(jvpp); + public InterfaceCustomizer(@Nonnull final NamingContext interfaceNamingContext, + @Nonnull final DisabledInterfacesManager interfaceDisableContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { this.interfaceNamingContext = interfaceNamingContext; this.interfaceDisableContext = interfaceDisableContext; - } - - public static void cacheInterfaceDump(final @Nonnull ReadContext context, final SwInterfaceDetailsReplyDump ifaces) { - context.getModificationCache().put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream() - .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails))); - } - - @Nonnull - @SuppressWarnings("unchecked") - public static Map getCachedInterfaceDump(@Nonnull final ModificationCache ctx) { - return ctx.get(DUMPED_IFCS_CONTEXT_KEY) == null - ? new HashMap<>() - // allow customizers to update the cache - : (Map) ctx.get(DUMPED_IFCS_CONTEXT_KEY); + this.dumpManager = dumpManager; } @Nonnull @@ -106,9 +83,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer return; } - // Pass cached details from getAllIds to getDetails to avoid additional dumps - final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, ifaceName, - index, ctx.getModificationCache(), LOG); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName); LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); if (!isRegularInterface(iface)) { @@ -140,44 +115,13 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @Nonnull final ReadContext context) throws ReadFailedException { final List interfacesKeys; LOG.trace("Dumping all interfaces to get all IDs"); - - final SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilter = "".getBytes(); - request.nameFilterValid = 0; - - final CompletableFuture swInterfaceDetailsReplyDumpCompletableFuture = - getFutureJVpp().swInterfaceDump(request).toCompletableFuture(); - final SwInterfaceDetailsReplyDump ifaces = - getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, id); - - if (null == ifaces || null == ifaces.swInterfaceDetails) { - LOG.debug("No interfaces for :{} found in VPP", id); - return Collections.emptyList(); - } - - // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes - cacheInterfaceDump(context, ifaces); - final MappingContext mappingCtx = context.getMappingContext(); - final Set interfacesIdxs = ifaces.swInterfaceDetails.stream() + final Set interfacesIdxs = dumpManager.getInterfaces(id, context) .filter(elt -> elt != null) // Filter out disabled interfaces, dont read them // This also prevents child readers in being invoked such as vxlan (which relies on disabling interfaces) .filter(elt -> !interfaceDisableContext .isInterfaceDisabled(elt.swIfIndex, mappingCtx)) - .map((elt) -> { - // Store interface name from VPP in context if not yet present - if (!interfaceNamingContext.containsName(elt.swIfIndex, mappingCtx)) { - interfaceNamingContext.addName(elt.swIfIndex, toString(elt.interfaceName), - mappingCtx); - } - LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP", - interfaceNamingContext.getName(elt.swIfIndex, mappingCtx), - elt.interfaceName, - elt.swIfIndex); - - return elt; - }) // filter out sub-interfaces .filter(InterfaceDataTranslator.INSTANCE::isRegularInterface) .map(elt -> elt.swIfIndex) @@ -207,7 +151,8 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @Override public Initialized init( - @Nonnull final InstanceIdentifier id, @Nonnull final Interface readValue, @Nonnull final ReadContext ctx) { + @Nonnull final InstanceIdentifier id, @Nonnull final Interface readValue, + @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder() .setName(readValue.getName()) diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java index b3c3679cd..ec47ee2f2 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslator.java @@ -17,23 +17,17 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Objects.requireNonNull; import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.ModificationCache; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.util.RWUtils; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.math.BigInteger; -import java.util.Map; import java.util.Objects; -import java.util.concurrent.CompletionStage; import java.util.stream.Collector; -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; @@ -46,7 +40,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanGpeTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanTunnel; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyConsumer { @@ -136,74 +129,6 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo return yangIfIndex - 1; } - - /** - * Queries VPP for interface description given interface key. - * - * @param futureJVppCore VPP Java Future API - * @param id InstanceIdentifier, which is passed in ReadFailedException - * @param name interface name - * @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 - * @throws ReadFailedException If read operation had failed - */ - @Nonnull - default SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final InstanceIdentifier id, - @Nonnull final String name, final int index, - @Nonnull final ModificationCache ctx, - @Nonnull final Logger callerLogger) - throws ReadFailedException { - requireNonNull(futureJVppCore, "futureJVppCore should not be null"); - requireNonNull(name, "name should not be null"); - requireNonNull(ctx, "ctx should not be null"); - - final SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilter = name.getBytes(); - request.nameFilterValid = 1; - - final Map allInterfaces = InterfaceCustomizer.getCachedInterfaceDump(ctx); - - // Returned cached if available - if (allInterfaces.containsKey(index)) { - return allInterfaces.get(index); - } - - SwInterfaceDetailsReplyDump ifaces; - - CompletionStage requestFuture = futureJVppCore.swInterfaceDump(request); - ifaces = getReplyForRead(requestFuture.toCompletableFuture(), id); - if (null == ifaces || null == ifaces.swInterfaceDetails || ifaces.swInterfaceDetails.isEmpty()) { - request.nameFilterValid = 0; - - callerLogger.warn("VPP returned null instead of interface by key {} and its not cached", name); - callerLogger.warn("Iterating through all the interfaces to find interface: {}", name); - - // Or else just perform full dump and do inefficient filtering - requestFuture = futureJVppCore.swInterfaceDump(request); - ifaces = getReplyForRead(requestFuture.toCompletableFuture(), id); - - // 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 " + name); - } - - // SwInterfaceDump's name filter does prefix match, so we need additional filtering: - final SwInterfaceDetails iface = - ifaces.swInterfaceDetails.stream().filter(d -> d.swIfIndex == index).collect(SINGLE_ITEM_COLLECTOR); - allInterfaces.put(index, iface); // update the cache - return iface; - } - /** * Determine interface type based on its VPP name (relying on VPP's interface naming conventions) * @@ -240,20 +165,15 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo } /** - * Check interface type. Uses interface details from VPP to determine. Uses {@link - * #getVppInterfaceDetails(FutureJVppCore, InstanceIdentifier, String, int, ModificationCache, Logger)} internally - * so tries to utilize cache before asking VPP. + * Check interface type. Uses interface details from VPP to determine. */ - default boolean isInterfaceOfType(@Nonnull final FutureJVppCore jvpp, - @Nonnull final ModificationCache cache, + default boolean isInterfaceOfType(@Nonnull final InterfaceCacheDumpManager dumpManager, @Nonnull final InstanceIdentifier id, - final int index, - @Nonnull final Class ifcType, - @Nonnull final Logger callerLogger) + @Nonnull final ReadContext ctx, + @Nonnull final Class ifcType) throws ReadFailedException { final String name = id.firstKeyOf(Interface.class).getName(); - final SwInterfaceDetails vppInterfaceDetails = - getVppInterfaceDetails(jvpp, id, name, index, cache, callerLogger); + final SwInterfaceDetails vppInterfaceDetails = dumpManager.getInterfaceDetail(id, ctx, name); return isInterfaceOfType(ifcType, vppInterfaceDetails); } @@ -264,13 +184,11 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo } /** - * Checks whether provided {@link SwInterfaceDetails} is detail of sub-interface
- *
  • subId == unique number of sub-interface within set of sub-interfaces of single interface - *
  • swIfIndex == unique index of interface/sub-interface within all interfaces - *
  • supSwIfIndex == unique index of parent interface - *
  • in case of interface , swIfIndex value equals supSwIfIndex - *
  • in case of subinterface, supSwIfIndex equals index of parent interface, - * swIfIndex is index of subinterface itselt + * Checks whether provided {@link SwInterfaceDetails} is detail of sub-interface
  • subId == unique number of + * sub-interface within set of sub-interfaces of single interface
  • swIfIndex == unique index of + * interface/sub-interface within all interfaces
  • supSwIfIndex == unique index of parent interface
  • in case of + * interface , swIfIndex value equals supSwIfIndex
  • in case of subinterface, supSwIfIndex equals index of parent + * interface, swIfIndex is index of subinterface itselt */ default boolean isSubInterface(@Nonnull final SwInterfaceDetails elt) { //cant check by subId != 0, because you can pick 0 as value @@ -278,13 +196,11 @@ public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyCo } /** - * Checks whether provided {@link SwInterfaceDetails} is detail of interface
    - *
  • subId == unique number of subinterface within set of subinterfaces of single interface - *
  • swIfIndex == unique index of interface/subinterface within all interfaces - *
  • supSwIfIndex == unique index of parent interface - *
  • in case of interface , swIfIndex value equals supSwIfIndex - *
  • in case of subinterface, supSwIfIndex equals index of parent interface, - * swIfIndex is index of subinterface itselt + * Checks whether provided {@link SwInterfaceDetails} is detail of interface
  • subId == unique number of + * subinterface within set of subinterfaces of single interface
  • swIfIndex == unique index of + * interface/subinterface within all interfaces
  • supSwIfIndex == unique index of parent interface
  • in case of + * interface , swIfIndex value equals supSwIfIndex
  • in case of subinterface, supSwIfIndex equals index of parent + * interface, swIfIndex is index of subinterface itselt */ default boolean isRegularInterface(@Nonnull final SwInterfaceDetails elt) { return !isSubInterface(elt); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/L2Customizer.java index c199dfd9e..1761b385f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/L2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/L2Customizer.java @@ -16,13 +16,14 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.vpp.jvpp.core.future.FutureJVppCore; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; @@ -31,11 +32,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceStateAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.Interconnection; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.BridgeBased; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.XconnectBased; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -52,9 +53,11 @@ public class L2Customizer extends FutureJVppCustomizer implements InitializingRe public L2Customizer(@Nonnull final FutureJVppCore futureJVppCore, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext bridgeDomainContext) { + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(futureJVppCore); - this.icReadUtils = new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext); + this.icReadUtils = + new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager); } @Override diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizer.java index 7dec4c265..46d85cfa1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizer.java @@ -16,18 +16,16 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Preconditions; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.translate.util.TagRewriteOperation; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.hc2vpp.v3po.util.SubInterfaceUtils; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; @@ -40,9 +38,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607._802dot1ad; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607._802dot1q; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.RewriteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTagsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTagsKey; @@ -55,19 +53,17 @@ import org.slf4j.LoggerFactory; /** * Customizer for reading vlan tag-rewrite configuration state form the VPP. */ -public class RewriteCustomizer extends FutureJVppCustomizer +public class RewriteCustomizer implements ReaderCustomizer, InterfaceDataTranslator { // No initialization necessary since its parent Subinterface L2 customzier sets the entire subtree during // initialization private static final Logger LOG = LoggerFactory.getLogger(RewriteCustomizer.class); - private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public RewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final NamingContext interfaceContext) { - super(futureJVppCore); - this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + public RewriteCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) { + this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null"); } @Override @@ -89,8 +85,7 @@ public class RewriteCustomizer extends FutureJVppCustomizer final String subInterfaceName = getSubInterfaceName(id); LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); - final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, subInterfaceName, - interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache(), LOG); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName); LOG.debug("VPP sub-interface details: {}", iface); checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizer.java index 2bf635fb9..9c39722ab 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizer.java @@ -16,12 +16,13 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Preconditions; import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.hc2vpp.v3po.util.SubInterfaceUtils; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; @@ -29,13 +30,10 @@ import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; +import java.util.Objects; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; @@ -74,17 +72,21 @@ import org.slf4j.LoggerFactory; * Customizer for reading sub interfaces form the VPP. */ public class SubInterfaceCustomizer extends FutureJVppCustomizer - implements InitializingListReaderCustomizer, ByteDataTranslator, + implements InitializingListReaderCustomizer, + ByteDataTranslator, InterfaceDataTranslator { private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); private static final Dot1qTag.VlanId ANY_VLAN_ID = new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any); - private NamingContext interfaceContext; + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; public SubInterfaceCustomizer(@Nonnull final FutureJVppCore jvpp, - @Nonnull final NamingContext interfaceContext) { + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); - this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null"); } private static String getSubInterfaceName(final InstanceIdentifier id) { @@ -119,30 +121,8 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer final String ifaceName = key.getName(); final int ifaceId = interfaceContext.getIndex(ifaceName, context.getMappingContext()); - // TODO HONEYCOMB-189 if we know that full dump was already performed we could use cache - // (checking if getCachedInterfaceDump() returns non empty map is not enough, because - // we could be part of particular iface state read - final SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilter = "".getBytes(); - request.nameFilterValid = 0; - - final CompletableFuture swInterfaceDetailsReplyDumpCompletableFuture = - getFutureJVpp().swInterfaceDump(request).toCompletableFuture(); - final SwInterfaceDetailsReplyDump ifaces = - getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, id); - - if (null == ifaces || null == ifaces.swInterfaceDetails) { - LOG.warn("Looking for sub-interfaces, but no interfaces found in VPP"); - return Collections.emptyList(); - } - - // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes - context.getModificationCache() - .put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream() - .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails))); - - final List interfacesKeys = ifaces.swInterfaceDetails.stream() - .filter(elt -> elt != null) + final List interfacesKeys = dumpManager.getInterfaces(id,context) + .filter(Objects::nonNull) // accept only sub-interfaces for current iface: .filter(elt -> isSubInterface(elt) && elt.supSwIfIndex == ifaceId) .map(details -> new SubInterfaceKey(new Long(details.subId))) @@ -171,8 +151,7 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer final String subInterfaceName = getSubInterfaceName(id); LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); - final SwInterfaceDetails iface = getVppInterfaceDetails(getFutureJVpp(), id, subInterfaceName, - interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache(), LOG); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName); LOG.debug("VPP sub-interface details: {}", iface); checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2Customizer.java index f068ac26f..4fd200bd4 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2Customizer.java @@ -18,20 +18,17 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getSubInterfaceName; -import com.google.common.collect.ImmutableMap; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.Interconnection; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.BridgeBased; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.state.attributes.interconnection.XconnectBased; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface; @@ -48,7 +45,7 @@ import org.slf4j.LoggerFactory; /** * Customizer for reading vlan sub interface L2 operational state */ -public class SubInterfaceL2Customizer extends FutureJVppCustomizer +public class SubInterfaceL2Customizer implements InitializingReaderCustomizer { private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class); @@ -56,9 +53,10 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer public SubInterfaceL2Customizer(@Nonnull final FutureJVppCore futureJVppCore, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext bridgeDomainContext) { - super(futureJVppCore); - this.icReadUtils = new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext); + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + this.icReadUtils = + new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager); } @Override @@ -78,7 +76,8 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer LOG.debug("Reading attributes for sub-interface L2: {}", id); final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); - final String subInterfaceName = getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + final String subInterfaceName = + getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); builder.setInterconnection(icReadUtils.readInterconnection(id, subInterfaceName, ctx)); } @@ -89,27 +88,31 @@ public class SubInterfaceL2Customizer extends FutureJVppCustomizer @Nonnull final L2 readValue, @Nonnull final ReadContext ctx) { - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder builder= + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder + builder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2Builder(); - if(readValue.getInterconnection() instanceof XconnectBased){ + if (readValue.getInterconnection() instanceof XconnectBased) { XconnectBased state = (XconnectBased) readValue.getInterconnection(); - builder.setInterconnection(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder() - .setXconnectOutgoingInterface(state.getXconnectOutgoingInterface()) - .build()); - }else { + builder.setInterconnection( + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.XconnectBasedBuilder() + .setXconnectOutgoingInterface(state.getXconnectOutgoingInterface()) + .build()); + } else { BridgeBased state = (BridgeBased) readValue.getInterconnection(); - builder.setInterconnection(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder() - .setBridgeDomain(state.getBridgeDomain()) - .setBridgedVirtualInterface(state.isBridgedVirtualInterface()) - .setSplitHorizonGroup(state.getSplitHorizonGroup()) - .build()); + builder.setInterconnection( + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBasedBuilder() + .setBridgeDomain(state.getBridgeDomain()) + .setBridgedVirtualInterface(state.isBridgedVirtualInterface()) + .setSplitHorizonGroup(state.getSplitHorizonGroup()) + .build()); } return Initialized.create(getCfgId(id), builder.setRewrite(readValue.getRewrite()).build()); } - static InstanceIdentifier getCfgId(final InstanceIdentifier id) { + static InstanceIdentifier getCfgId( + final InstanceIdentifier id) { return SubInterfaceCustomizer.getCfgId(RWUtils.cutId(id, SubInterface.class)) .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.config.attributes.L2.class); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizer.java index b3c7f788b..fb8e6b55c 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizer.java @@ -16,9 +16,12 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import static java.lang.String.format; + import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; @@ -53,12 +56,17 @@ public class TapCustomizer extends FutureJVppCustomizer implements InitializingReaderCustomizer, InterfaceDataTranslator, JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(TapCustomizer.class); + // TODO - HC2VPP-213 - used dump cache manager public static final String DUMPED_TAPS_CONTEXT_KEY = TapCustomizer.class.getName() + "dumpedTapsDuringGetAllIds"; private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public TapCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) { + public TapCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; } @Override @@ -79,8 +87,11 @@ public class TapCustomizer extends FutureJVppCustomizer final InterfaceKey key = id.firstKeyOf(Interface.class); final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap.class, LOG)) { + final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + if (!isInterfaceOfType( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.Tap.class, + ifcDetails)) { return; } @@ -115,9 +126,6 @@ public class TapCustomizer extends FutureJVppCustomizer builder.setTapName(toString(swInterfaceTapDetails.devName)); - final SwInterfaceDetails ifcDetails = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(), - interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG); - if (ifcDetails.tag[0] != 0) { // tag supplied builder.setTag(toString(ifcDetails.tag)); } @@ -129,15 +137,21 @@ public class TapCustomizer extends FutureJVppCustomizer @Nonnull final InstanceIdentifier id, @Nonnull final Tap readValue, @Nonnull final ReadContext ctx) { // The MAC address & tag is set from interface details, those details are retrieved from cache final InterfaceKey key = id.firstKeyOf(Interface.class); - final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - final SwInterfaceDetails ifcDetails = - InterfaceCustomizer.getCachedInterfaceDump(ctx.getModificationCache()).get(index); + + final SwInterfaceDetails ifcDetails; + try { + ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + } catch (ReadFailedException e) { + throw new IllegalStateException(format("Unable to read interface %s", key.getName()), e); + } return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.TapBuilder() .setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address))) .setTapName(readValue.getTapName()) - .setTag(ifcDetails.tag[0] == 0 ? null : toString(ifcDetails.tag)) + .setTag(ifcDetails.tag[0] == 0 + ? null + : toString(ifcDetails.tag)) // tapBuilder.setDeviceInstance(); .build()); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizer.java index 282e1a537..4ce646d98 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizer.java @@ -16,14 +16,17 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import static java.lang.String.format; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails; import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump; @@ -51,16 +54,22 @@ import org.slf4j.LoggerFactory; public class VhostUserCustomizer extends FutureJVppCustomizer - implements InitializingReaderCustomizer, InterfaceDataTranslator, JvppReplyConsumer { + implements InitializingReaderCustomizer, InterfaceDataTranslator, + JvppReplyConsumer { + //TODO - HC2VPP-212 - use dump cache manager public static final String DUMPED_VHOST_USERS_CONTEXT_KEY = VhostUserCustomizer.class.getName() + "dumpedVhostUsersDuringGetAllIds"; private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class); private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public VhostUserCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) { + public VhostUserCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; } @Override @@ -81,9 +90,12 @@ public class VhostUserCustomizer extends FutureJVppCustomizer final InterfaceKey key = id.firstKeyOf(Interface.class); final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, + final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + + if (!isInterfaceOfType( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VhostUser.class, - LOG)) { + ifcDetails)) { return; } @@ -121,9 +133,6 @@ public class VhostUserCustomizer extends FutureJVppCustomizer LOG.trace("Vhost user interface: {} attributes returned from VPP: {}", key.getName(), swInterfaceVhostUserDetails); - final SwInterfaceDetails ifcDetails = getVppInterfaceDetails(getFutureJVpp(), id, key.getName(), - interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache(), LOG); - builder.setRole(swInterfaceVhostUserDetails.isServer == 1 ? VhostUserRole.Server : VhostUserRole.Client); @@ -147,14 +156,19 @@ public class VhostUserCustomizer extends FutureJVppCustomizer @Nonnull final ReadContext ctx) { // The tag is set from interface details, those details are retrieved from cache final InterfaceKey key = id.firstKeyOf(Interface.class); - final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - final SwInterfaceDetails ifcDetails = - InterfaceCustomizer.getCachedInterfaceDump(ctx.getModificationCache()).get(index); + final SwInterfaceDetails ifcDetails; + try { + ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + } catch (ReadFailedException e) { + throw new IllegalStateException(format("Unable to find VHost interface %s", key.getName()), e); + } return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VhostUserBuilder() .setRole(readValue.getRole()) .setSocket(readValue.getSocket()) - .setTag(ifcDetails.tag[0] == 0 ? null : toString(ifcDetails.tag)) + .setTag(ifcDetails.tag[0] == 0 + ? null + : toString(ifcDetails.tag)) .build()); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizer.java index b2e352052..c11d2398c 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizer.java @@ -18,13 +18,24 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkState; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.concurrent.CompletionStage; - import javax.annotation.Nonnull; - 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.inet.types.rev130715.Ipv6Address; @@ -44,33 +55,23 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; -import io.fd.hc2vpp.common.translate.util.NamingContext; -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.Initialized; -import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; -import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; - public class VxlanCustomizer extends FutureJVppCustomizer -implements InitializingReaderCustomizer, InterfaceDataTranslator, JvppReplyConsumer { + implements InitializingReaderCustomizer, InterfaceDataTranslator, JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public VxlanCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) { + public VxlanCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; } @Override public void merge(@Nonnull Builder parentBuilder, - @Nonnull Vxlan readValue) { + @Nonnull Vxlan readValue) { ((VppInterfaceStateAugmentationBuilder) parentBuilder).setVxlan(readValue); } @@ -82,12 +83,12 @@ implements InitializingReaderCustomizer, InterfaceDataTrans @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final VxlanBuilder builder, - @Nonnull final ReadContext ctx) throws ReadFailedException { + @Nonnull final VxlanBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, VxlanTunnel.class, LOG)) { + if (!isInterfaceOfType(dumpManager, id, ctx, VxlanTunnel.class)) { return; } @@ -135,15 +136,15 @@ implements InitializingReaderCustomizer, InterfaceDataTrans builder.setEncapVrfId((long) swInterfaceVxlanDetails.encapVrfId); builder.setVni(new VxlanVni((long) swInterfaceVxlanDetails.vni)); switch (swInterfaceVxlanDetails.decapNextIndex) { - case 1: - builder.setDecapNext(L2Input.class); - break; - case 2: - builder.setDecapNext(NshProxy.class); - break; - default: - LOG.trace("Unsupported decap next index for vxlan: {}", swInterfaceVxlanDetails.decapNextIndex); - return; + case 1: + builder.setDecapNext(L2Input.class); + break; + case 2: + builder.setDecapNext(NshProxy.class); + break; + default: + LOG.trace("Unsupported decap next index for vxlan: {}", swInterfaceVxlanDetails.decapNextIndex); + return; } LOG.debug("Vxlan tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder); } @@ -159,15 +160,16 @@ implements InitializingReaderCustomizer, InterfaceDataTrans @Override public Initialized init( - @Nonnull final InstanceIdentifier id, @Nonnull final Vxlan readValue, @Nonnull final ReadContext ctx) { + @Nonnull final InstanceIdentifier id, @Nonnull final Vxlan readValue, + @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanBuilder() - .setDst(readValue.getDst()) - .setSrc(readValue.getSrc()) - .setEncapVrfId(readValue.getEncapVrfId()) - .setVni(new VxlanVni(readValue.getVni())) - .setDecapNext(readValue.getDecapNext()) - .build()); + .setDst(readValue.getDst()) + .setSrc(readValue.getSrc()) + .setEncapVrfId(readValue.getEncapVrfId()) + .setVni(new VxlanVni(readValue.getVni())) + .setDecapNext(readValue.getDecapNext()) + .build()); } private InstanceIdentifier getCfgId( diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizer.java index 9afbdc7d6..2e2f60c2e 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizer.java @@ -18,14 +18,15 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkState; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadContext; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.Initialized; import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; -import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails; import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump; import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump; @@ -57,11 +58,15 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer implements InitializingReaderCustomizer, InterfaceDataTranslator, JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class); - private NamingContext interfaceContext; + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; - public VxlanGpeCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext) { + public VxlanGpeCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { super(jvpp); this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; } @Override @@ -83,7 +88,7 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer final InterfaceKey key = id.firstKeyOf(Interface.class); final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, VxlanGpeTunnel.class, LOG)) { + if (!isInterfaceOfType(dumpManager, id, ctx, VxlanGpeTunnel.class)) { return; } @@ -147,7 +152,8 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer @Override public Initialized init( - @Nonnull final InstanceIdentifier id, @Nonnull final VxlanGpe readValue, @Nonnull final ReadContext ctx) { + @Nonnull final InstanceIdentifier id, @Nonnull final VxlanGpe readValue, + @Nonnull final ReadContext ctx) { return Initialized.create(getCfgId(id), new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.VxlanGpeBuilder() .setLocal(readValue.getLocal()) diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java new file mode 100644 index 000000000..589d59024 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManager.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.v3po.interfacesstate.cache; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Manager for dump data of interfaces. The main purpose of this manager is to cache common interface data between + * various classes that process this kind of data. If reader does not use this utility, it introduces a big overhead + * because of size/complexity of interfaces dump + */ +public interface InterfaceCacheDumpManager { + + /** + * Provides stream of all currently configured vpp interfaces + * + * @param identifier id of currently processed data + * @param ctx context of current transaction + * @return {@link Stream} of currently configured interfaces + * @throws ReadFailedException if dumping of data was unsuccessful + */ + @Nonnull + Stream getInterfaces(@Nonnull final InstanceIdentifier identifier, + @Nonnull final ReadContext ctx) throws ReadFailedException; + + /** + * Provides details of interface + * + * @param identifier id of currently processed data + * @param ctx context of current transaction + * @param interfaceName name of requested interface + * @return {@link SwInterfaceDetails} of requested interface + * @throws ReadFailedException if dumping of data was unsuccessful + */ + @Nullable + SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) throws ReadFailedException; +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java new file mode 100644 index 000000000..e9b114018 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImpl.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.v3po.interfacesstate.cache; + +import static io.fd.hc2vpp.common.translate.util.JvppReplyConsumer.INSTANCE; +import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS; +import static java.util.stream.Collectors.toMap; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.ModificationCache; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manager for dump data of interfaces/sub-interfaces + */ +final class InterfaceCacheDumpManagerImpl implements InterfaceCacheDumpManager { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceCacheDumpManagerImpl.class); + + // byNameIndex must be cached, not held as reference here, to have it destroyed with cache after transaction + static final String BY_NAME_INDEX_KEY = InterfaceCacheDumpManagerImpl.class.getName() + "_byNameIndex"; + private NamingContext namingContext; + private final DumpCacheManager specificDumpManager; + private final DumpCacheManager fullDumpManager; + + InterfaceCacheDumpManagerImpl(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext namingContext) { + this.namingContext = namingContext; + specificDumpManager = specificInterfaceDumpManager(jvpp); + fullDumpManager = fullInterfaceDumpManager(jvpp, + new StaticCacheKeyFactory(StaticCacheKeyFactory.class.getName() + "_dump")); + } + + @Override + @Nonnull + public synchronized Stream getInterfaces(@Nonnull final InstanceIdentifier identifier, + @Nonnull final ReadContext ctx) + throws ReadFailedException { + LOG.debug("Reading all interfaces[{}]", identifier); + return initMapAndGet(identifier, ctx).entrySet().stream().map(Map.Entry::getValue); + } + + @Override + @Nullable + public synchronized SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) + throws ReadFailedException { + final Map interfaceIndex = getMap(ctx); + + // does not attempt to cover cases with concurrent updates, as tx should be atomic + if (interfaceIndex != null) { + // tries to find interface in map + return interfaceIndex.get(interfaceName); + } else { + // if map is not present, use specific dump(it will be cached standard way, under key constructed from IID) + return dumpSpecificDetail(identifier, ctx, interfaceName); + } + } + + private SwInterfaceDetails dumpSpecificDetail(@Nonnull final InstanceIdentifier identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) + throws ReadFailedException { + LOG.debug("Interface {} not present in cached data, performing specific dump[{}]", interfaceName, + identifier); + final SwInterfaceDetailsReplyDump reply = + specificDumpManager.getDump(identifier, ctx.getModificationCache(), interfaceName) + .or(new SwInterfaceDetailsReplyDump()); + + if (reply.swInterfaceDetails.isEmpty()) { + return null; + } + + return reply.swInterfaceDetails.get(0); + } + + private Map initMapAndGet(final InstanceIdentifier identifier, final ReadContext ctx) + throws ReadFailedException { + + final ModificationCache cache = ctx.getModificationCache(); + if (!cache.containsKey(BY_NAME_INDEX_KEY)) { + LOG.debug("Performing dump[{}]", identifier); + final SwInterfaceDetailsReplyDump dump = + fullDumpManager.getDump(identifier, cache, NO_PARAMS) + .or(new SwInterfaceDetailsReplyDump()); + + // naming context initialization must be done here, as it is uses getName in next step, therefore it would + // create artificial mapping for every interface, because this happens before interface dump is processed + dump.swInterfaceDetails.forEach((elt) -> { + // Store interface name from VPP in context if not yet present + if (!namingContext.containsName(elt.swIfIndex, ctx.getMappingContext())) { + namingContext.addName(elt.swIfIndex, ByteDataTranslator.INSTANCE.toString(elt.interfaceName), + ctx.getMappingContext()); + } + LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP", + getInterfaceName(ctx, elt), + elt.interfaceName, + elt.swIfIndex); + }); + + final Map freshIndex = dump.swInterfaceDetails.stream() + .collect(toMap(detail -> getInterfaceName(ctx, detail), + detail -> detail)); + putMap(freshIndex, ctx); + } + + return getMap(ctx); + } + + private String getInterfaceName(final ReadContext ctx, final SwInterfaceDetails elt) { + return namingContext.getName(elt.swIfIndex, ctx.getMappingContext()); + } + + private static Map getMap(final ReadContext ctx) { + return (Map) ctx.getModificationCache().get(BY_NAME_INDEX_KEY); + } + + private static void putMap(final Map map, final ReadContext ctx) { + ctx.getModificationCache().put(BY_NAME_INDEX_KEY, map); + } + + + private static DumpCacheManager fullInterfaceDumpManager( + final FutureJVppCore jvpp, + final StaticCacheKeyFactory cacheKeyFactory) { + return new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(fullInterfaceDumpExecutor(jvpp)) + .withCacheKeyFactory(cacheKeyFactory) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static DumpCacheManager specificInterfaceDumpManager( + final FutureJVppCore jvpp) { + return new DumpCacheManager.DumpCacheManagerBuilder() + .withExecutor(specificInterfaceDumpExecutor(jvpp)) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static EntityDumpExecutor fullInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, params) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } + + private static EntityDumpExecutor specificInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, ifaceName) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = ifaceName.getBytes(); + request.nameFilterValid = 1; + + final CompletableFuture + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java new file mode 100644 index 000000000..7a6119bf1 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerProvider.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.v3po.interfacesstate.cache; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.inject.Named; + +public class InterfaceCacheDumpManagerProvider implements Provider { + + @Inject + private FutureJVppCore jvpp; + + @Inject + @Named("interface-context") + private NamingContext namingContext; + + @Override + public InterfaceCacheDumpManager get() { + return new InterfaceCacheDumpManagerImpl(jvpp, namingContext); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java new file mode 100644 index 000000000..e34e915e2 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/cache/StaticCacheKeyFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.v3po.interfacesstate.cache; + +import io.fd.honeycomb.translate.util.read.cache.CacheKeyFactory; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class StaticCacheKeyFactory implements CacheKeyFactory { + + private final String key; + + public StaticCacheKeyFactory(@Nonnull final String key) { + this.key = key; + } + + @Nonnull + @Override + public String createKey(@Nonnull final InstanceIdentifier actualContextIdentifier, + @Nullable final Void dumpParams) { + return key; + } + + @Nonnull + @Override + public Class getCachedDataType() { + return SwInterfaceDetailsReplyDump.class; + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java index a681706f7..e53fccdab 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java @@ -16,15 +16,20 @@ package io.fd.hc2vpp.v3po.interfacesstate; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -34,18 +39,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.EthernetBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; public class EthernetCustomizerTest extends ReaderCustomizerTest implements - InterfaceDumpHelper { + InterfaceDumpHelper { private static final String IFC_CTX_NAME = "ifc-test-instance"; private static final String IF_NAME = "local0"; private static final int IF_INDEX = 1; private static final InstanceIdentifier IID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(Ethernet.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(Ethernet.class); private NamingContext interfaceContext; + @Mock + private InterfaceCacheDumpManager dumpCacheManager; + public EthernetCustomizerTest() { super(Ethernet.class, VppInterfaceStateAugmentationBuilder.class); } @@ -58,15 +65,16 @@ public class EthernetCustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new EthernetCustomizer(api, interfaceContext); + return new EthernetCustomizer(dumpCacheManager); } - private void testRead(final int linkDuplex, final EthernetStateAttributes.Duplex duplex) throws ReadFailedException { + private void testRead(final int linkDuplex, final EthernetStateAttributes.Duplex duplex) + throws ReadFailedException { final EthernetBuilder builder = mock(EthernetBuilder.class); final short mtu = 123; - whenSwInterfaceDumpThenReturn(api, ifaceDetails(mtu, linkDuplex)); + when(dumpCacheManager.getInterfaceDetail(any(), any(), any())).thenReturn(ifaceDetails(mtu, linkDuplex)); getCustomizer().readCurrentAttributes(IID, builder, ctx); - verify(builder).setMtu((int)mtu); + verify(builder).setMtu((int) mtu); verify(builder).setDuplex(duplex); } @@ -74,7 +82,7 @@ public class EthernetCustomizerTest extends ReaderCustomizerTest { @@ -55,23 +57,25 @@ public class GreCustomizerTest extends ReaderCustomizerTest { private NamingContext interfacesContext; static final InstanceIdentifier IID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(Gre.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(Gre.class); + + @Mock + private InterfaceCacheDumpManager dumpCacheManager; public GreCustomizerTest() { super(Gre.class, VppInterfaceStateAugmentationBuilder.class); } @Override - public void setUp() throws UnknownHostException, VppInvocationException { + public void setUp() throws UnknownHostException, VppInvocationException, ReadFailedException { interfacesContext = new NamingContext("gre-tunnel", IFC_CTX_NAME); defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME); final SwInterfaceDetails v = new SwInterfaceDetails(); v.interfaceName = "gre-tunnel4".getBytes(); - final Map map = new HashMap<>(); - map.put(0, v); - cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map); + + when(dumpCacheManager.getInterfaceDetail(IID, ctx, IFACE_NAME)).thenReturn(v); final GreTunnelDetailsReplyDump value = new GreTunnelDetailsReplyDump(); final GreTunnelDetails greTunnelDetails = new GreTunnelDetails(); @@ -103,29 +107,20 @@ public class GreCustomizerTest extends ReaderCustomizerTest { verify(api).greTunnelDump(any(GreTunnelDump.class)); } - @Test(expected = NullPointerException.class) - public void testReadCurrentAttributesVppNameNotCached() throws Exception { - InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0); - - final GreBuilder builder = getCustomizer().getBuilder(IID); - getCustomizer().readCurrentAttributes(IID, builder, ctx); - } - @Test public void testReadCurrentAttributesWrongType() throws Exception { final SwInterfaceDetails v = new SwInterfaceDetails(); v.interfaceName = "tap-2".getBytes(); - InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v); + + when(dumpCacheManager.getInterfaceDetail(IID, ctx, IFACE_NAME)).thenReturn(v); final GreBuilder builder = getCustomizer().getBuilder(IID); getCustomizer().readCurrentAttributes(IID, builder, ctx); - - // Should be ignored verifyZeroInteractions(api); } @Override protected ReaderCustomizer initCustomizer() { - return new GreCustomizer(api, interfacesContext); + return new GreCustomizer(api, interfacesContext, dumpCacheManager); } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java index 2f8a30b84..d8fa719ff 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java @@ -17,20 +17,24 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.hc2vpp.v3po.DisabledInterfacesManager; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest; import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.DisabledInterfacesManager; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; import org.junit.Test; import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; @@ -39,12 +43,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppInvocationException; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; public class InterfaceCustomizerTest extends ListReaderCustomizerTest - implements InterfaceDataTranslator, InterfaceDumpHelper { + implements InterfaceDataTranslator, InterfaceDumpHelper { private static final String IFC_CTX_NAME = "ifc-test-instance"; private static final String IFACE0_NAME = "eth0"; @@ -57,6 +58,8 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest initCustomizer() { - return new InterfaceCustomizer(api, interfacesContext, interfaceDisableContext); - } - - private void verifySwInterfaceDumpWasInvoked(final int nameFilterValid, final String ifaceName, - final int dumpIfcsInvocationCount) - throws VppInvocationException { - final SwInterfaceDump expected = new SwInterfaceDump(); - expected.nameFilterValid = (byte) nameFilterValid; - expected.nameFilter = ifaceName.getBytes(); - verify(api, times(dumpIfcsInvocationCount)).swInterfaceDump(expected); + return new InterfaceCustomizer(interfacesContext, interfaceDisableContext, dumpCacheManager); } private void assertIfacesAreEqual(final Interface iface, final SwInterfaceDetails details) { @@ -102,31 +96,16 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest id = InstanceIdentifier.create(InterfacesState.class) - .child(Interface.class, new InterfaceKey(ifaceName)); - final InterfaceBuilder builder = getCustomizer().getBuilder(id); - - whenSwInterfaceDumpThenReturn(api); - - try { - getCustomizer().readCurrentAttributes(id, builder, ctx); - } catch (IllegalArgumentException e) { - verifySwInterfaceDumpWasInvoked(0, ifaceName, 2); - return; - } - - fail("ReadFailedException was expected"); + assertIfacesAreEqual(builder.build(), iface); + verify(dumpCacheManager, times(1)).getInterfaceDetail(id, ctx, IFACE0_NAME); } @Test @@ -140,12 +119,16 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME), new InterfaceKey( IFACE1_NAME)); final List actualIds = getCustomizer().getAllIds(id, ctx); - verifySwInterfaceDumpWasInvoked(0, "", 1); + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; // sub-interface should not be on the list assertEquals(expectedIds, actualIds); + verify(dumpCacheManager, times(1)).getInterfaces(id, ctx); } @Test @@ -191,12 +177,13 @@ public class InterfaceCustomizerTest extends ListReaderCustomizerTest expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME)); final List actualIds = getCustomizer().getAllIds(id, ctx); // disabled interface should not be on the list assertEquals(expectedIds, actualIds); + verify(dumpCacheManager, times(1)).getInterfaces(id, ctx); } } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java index 63cb3d972..53934ff80 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails; import io.fd.vpp.jvpp.core.dto.BridgeDomainDetailsReplyDump; @@ -34,6 +35,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -52,6 +54,9 @@ public class L2CustomizerTest extends ReaderCustomizerTest { private NamingContext interfaceContext; private NamingContext bridgeDomainContext; + @Mock + private InterfaceCacheDumpManager dumpCacheManager; + public L2CustomizerTest() { super(L2.class, VppInterfaceStateAugmentationBuilder.class); } @@ -64,13 +69,13 @@ public class L2CustomizerTest extends ReaderCustomizerTest { @Override protected ReaderCustomizer initCustomizer() { - return new L2Customizer(api, interfaceContext, bridgeDomainContext); + return new L2Customizer(api, interfaceContext, bridgeDomainContext, dumpCacheManager); } private InstanceIdentifier getL2Id(final String name) { return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)) - .augmentation( - VppInterfaceStateAugmentation.class).child(L2.class); + .augmentation( + VppInterfaceStateAugmentation.class).child(L2.class); } private void whenBridgeDomainDumpThenReturn(final List bridgeDomainDetails) { @@ -101,7 +106,6 @@ public class L2CustomizerTest extends ReaderCustomizerTest { @Test public void testRead() throws Exception { - final Map cachedInterfaceDump = new HashMap<>(); final int ifId = 1; final int bdId = 1; final String bdName = "bd001"; @@ -111,8 +115,6 @@ public class L2CustomizerTest extends ReaderCustomizerTest { final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = ifId; - cachedInterfaceDump.put(ifId, ifaceDetails); - cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); // BVIinterfaceContext whenBridgeDomainDumpThenReturn(Collections.singletonList(generateBdDetails(ifId, ifId, bdId))); @@ -124,7 +126,7 @@ public class L2CustomizerTest extends ReaderCustomizerTest { // Not BVI whenBridgeDomainDumpThenReturn(Collections - .singletonList(generateBdDetails(ifId, 99 /* Different ifc is marked as BVI in bd details */, bdId))); + .singletonList(generateBdDetails(ifId, 99 /* Different ifc is marked as BVI in bd details */, bdId))); builder = mock(L2Builder.class); getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx); @@ -136,7 +138,7 @@ public class L2CustomizerTest extends ReaderCustomizerTest { final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails(); bridgeDomainDetails.bviSwIfIndex = bviSwIfIndex; bridgeDomainDetails.bdId = bdId; - bridgeDomainDetails.swIfDetails = new BridgeDomainSwIf[] {generateBdSwIfDetails(ifId)}; + bridgeDomainDetails.swIfDetails = new BridgeDomainSwIf[]{generateBdSwIfDetails(ifId)}; return bridgeDomainDetails; } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java index dc748fe45..887b3e3e6 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java @@ -19,19 +19,20 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.translate.util.TagRewriteOperation; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -40,9 +41,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.SubInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.interfaces.state._interface.sub.interfaces.SubInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.Rewrite; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.rewrite.attributes.RewriteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.l2.state.attributes.L2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.tag.rewrite.PushTags; import org.opendaylight.yangtools.yang.binding.ChildOf; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -60,6 +61,9 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest> captor; + @Mock + private InterfaceCacheDumpManager dumpCacheManager; + public RewriteCustomizerTest() { super(Rewrite.class, L2Builder.class); } @@ -72,14 +76,15 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new RewriteCustomizer(api, interfacesContext); + return new RewriteCustomizer(dumpCacheManager); } private InstanceIdentifier getVlanTagRewriteId(final String name, final long index) { - final Class> child = (Class)Rewrite.class; + final Class> child = (Class) Rewrite.class; final InstanceIdentifier id = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation( - SubinterfaceStateAugmentation.class).child(SubInterfaces.class) + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)) + .augmentation( + SubinterfaceStateAugmentation.class).child(SubInterfaces.class) .child(SubInterface.class, new SubInterfaceKey(index)) .child(child); return id; @@ -87,8 +92,6 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest cachedInterfaceDump = new HashMap<>(); - final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = VLAN_ID; ifaceDetails.interfaceName = VLAN_IF_NAME.getBytes(); @@ -97,14 +100,13 @@ public class RewriteCustomizerTest extends ReaderCustomizerTest vlanTagRewriteId = getVlanTagRewriteId(IF_NAME, VLAN_ID); + when(dumpCacheManager.getInterfaceDetail(vlanTagRewriteId, ctx, VLAN_IF_NAME)).thenReturn(ifaceDetails); + getCustomizer().readCurrentAttributes(vlanTagRewriteId, builder, ctx); verify(builder).setVlanType(_802dot1q.class); verify(builder).setPopTags((short) 2); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java index 32e351e66..c20e21892 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java @@ -20,18 +20,20 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest; import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.stream.Stream; import org.junit.Test; import org.mockito.ArgumentCaptor; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -46,8 +48,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev170607.sub._interface.base.attributes.Tags; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest implements - InterfaceDumpHelper { +public class SubInterfaceCustomizerTest + extends ListReaderCustomizerTest implements + InterfaceDumpHelper { private static final String IFC_CTX_NAME = "ifc-test-instance"; private static final String SUPER_IF_NAME = "local0"; @@ -58,6 +61,9 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest initCustomizer() { - return new SubInterfaceCustomizer(api, interfacesContext); + return new SubInterfaceCustomizer(api, interfacesContext, dumpCacheManager); } private InstanceIdentifier getSubInterfaceId(final String name, final long id) { - return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation( - SubinterfaceStateAugmentation.class).child( - SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(id)); + return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)) + .augmentation( + SubinterfaceStateAugmentation.class).child( + SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(id)); } @Test public void testRead() throws ReadFailedException { - final Map cachedInterfaceDump = new HashMap<>(); final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = VLAN_IF_ID; @@ -95,11 +101,12 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest subInterfaceId = getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID); + + when(dumpCacheManager.getInterfaceDetail(subInterfaceId, ctx, VLAN_IF_NAME)).thenReturn(ifaceDetails); + getCustomizer().readCurrentAttributes(subInterfaceId, builder, ctx); verify(builder).setIdentifier((long) VLAN_IF_ID); @@ -109,7 +116,7 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest matchCaptor = ArgumentCaptor.forClass(Match.class); verify(builder).setMatch(matchCaptor.capture()); - final VlanTagged matchType = (VlanTagged)matchCaptor.getValue().getMatchType(); + final VlanTagged matchType = (VlanTagged) matchCaptor.getValue().getMatchType(); assertTrue(matchType.getVlanTagged().isMatchExactTags()); } @@ -120,10 +127,11 @@ public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest subInterfaceId = getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID); + when(dumpCacheManager.getInterfaces(subInterfaceId, ctx)).thenReturn(Stream.of(iface)); final List allIds = - getCustomizer().getAllIds(getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID), ctx); + getCustomizer().getAllIds(subInterfaceId, ctx); assertEquals(1, allIds.size()); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java index 39aefb3b3..ebdf30170 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java @@ -22,9 +22,11 @@ import static org.mockito.Mockito.when; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -50,9 +52,13 @@ public class SubInterfaceL2CustomizerTest extends ReaderCustomizerTest IID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(SubinterfaceStateAugmentation.class) - .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)).child(L2.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(SubinterfaceStateAugmentation.class) + .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)) + .child(L2.class); + + @Mock + private InterfaceCacheDumpManager dumpCacheManager; public SubInterfaceL2CustomizerTest() { super(L2.class, SubInterfaceBuilder.class); @@ -68,13 +74,6 @@ public class SubInterfaceL2CustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new SubInterfaceL2Customizer(api, interfaceContext, bridgeDomainContext); - } - - @Test(expected = ReadFailedException.class) - public void testReadFailed() throws ReadFailedException { - final L2Builder builder = mock(L2Builder.class); - when(api.swInterfaceDump(any())).thenReturn(failedFuture()); - getCustomizer().readCurrentAttributes(IID, builder, ctx); + return new SubInterfaceL2Customizer(api, interfaceContext, bridgeDomainContext, dumpCacheManager); } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java index e268f7b15..1fbefd696 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java @@ -21,12 +21,17 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetailsReplyDump; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -35,9 +40,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.Tap; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.TapBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetailsReplyDump; public class TapCustomizerTest extends ReaderCustomizerTest implements InterfaceDumpHelper { @@ -46,10 +48,13 @@ public class TapCustomizerTest extends ReaderCustomizerTest imp private static final String TAP_NAME = "testTapName"; private static final int IF_INDEX = 1; private static final InstanceIdentifier IID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(Tap.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(Tap.class); private NamingContext interfaceContext; + @Mock + private InterfaceCacheDumpManager dumpCacheManager; + public TapCustomizerTest() { super(Tap.class, VppInterfaceStateAugmentationBuilder.class); } @@ -58,7 +63,7 @@ public class TapCustomizerTest extends ReaderCustomizerTest imp protected void setUp() throws Exception { interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME); defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME); - whenSwInterfaceDumpThenReturn(api, ifaceDetails()); + when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(ifaceDetails()); } private SwInterfaceDetails ifaceDetails() { @@ -71,7 +76,7 @@ public class TapCustomizerTest extends ReaderCustomizerTest imp @Override protected ReaderCustomizer initCustomizer() { - return new TapCustomizer(api, interfaceContext); + return new TapCustomizer(api, interfaceContext, dumpCacheManager); } @Test diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java index b83b74e2d..e58877eb1 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java @@ -21,13 +21,18 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump; import java.math.BigInteger; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -37,21 +42,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VhostUserBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails; -import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump; public class VhostUserCustomizerTest extends ReaderCustomizerTest implements - InterfaceDumpHelper { + InterfaceDumpHelper { private static final String IFC_CTX_NAME = "ifc-test-instance"; private static final String IF_NAME = "VirtualEthernet1"; private static final int IF_INDEX = 1; private static final InstanceIdentifier IID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(VhostUser.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(VhostUser.class); private NamingContext interfaceContext; + @Mock + private InterfaceCacheDumpManager dumpCacheManager; + public VhostUserCustomizerTest() { super(VhostUser.class, VppInterfaceStateAugmentationBuilder.class); } @@ -60,7 +65,7 @@ public class VhostUserCustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new VhostUserCustomizer(api, interfaceContext); + return new VhostUserCustomizer(api, interfaceContext, dumpCacheManager); } @Test diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java index f5e659f50..ba0cf2d2d 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java @@ -23,13 +23,23 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import com.google.common.collect.Lists; +import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.VppInvocationException; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.Map; - import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -40,17 +50,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import com.google.common.collect.Lists; - -import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; -import io.fd.hc2vpp.common.translate.util.NamingContext; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.vpp.jvpp.VppInvocationException; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump; - public class VxlanCustomizerTest extends ReaderCustomizerTest { private static final String IFC_CTX_NAME = "ifc-test-instance"; @@ -60,22 +59,24 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest IID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class); + .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class); + + @Mock + private InterfaceCacheDumpManager dumpCacheManager; public VxlanCustomizerTest() { super(Vxlan.class, VppInterfaceStateAugmentationBuilder.class); } @Override - public void setUp() throws UnknownHostException, VppInvocationException { + public void setUp() throws UnknownHostException, VppInvocationException, ReadFailedException { interfacesContext = new NamingContext("vxlan-tunnel", IFC_CTX_NAME); defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME); final SwInterfaceDetails v = new SwInterfaceDetails(); v.interfaceName = "vxlan-tunnel4".getBytes(); - final Map map = new HashMap<>(); - map.put(0, v); - cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map); + + when(dumpCacheManager.getInterfaceDetail(IID, ctx, IF_NAME)).thenReturn(v); final VxlanTunnelDetailsReplyDump value = new VxlanTunnelDetailsReplyDump(); final VxlanTunnelDetails vxlanTunnelDetails = new VxlanTunnelDetails(); @@ -110,9 +111,10 @@ public class VxlanCustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new VxlanCustomizer(api, interfacesContext); + return new VxlanCustomizer(api, interfacesContext, dumpCacheManager); } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java index f8f1e14b6..ce794302b 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java @@ -19,20 +19,28 @@ package io.fd.hc2vpp.v3po.interfacesstate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; import com.google.common.collect.Lists; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.hc2vpp.common.translate.util.NamingContext; import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails; +import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.Map; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -41,11 +49,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanGpe; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces.state._interface.VxlanGpeBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; -import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails; -import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump; -import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump; public class VxlanGpeCustomizerTest extends ReaderCustomizerTest { @@ -55,23 +58,25 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest VXLAN_GPE_ID = - InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) - .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class); + InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class); + + @Mock + private InterfaceCacheDumpManager dumpCacheManager; public VxlanGpeCustomizerTest() { super(VxlanGpe.class, VppInterfaceStateAugmentationBuilder.class); } @Override - public void setUp() throws UnknownHostException, VppBaseCallException { + public void setUp() throws UnknownHostException, VppBaseCallException, ReadFailedException { interfacesContext = new NamingContext("vxlan_gpe_inf", IFC_CTX_NAME); defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME); final SwInterfaceDetails v = new SwInterfaceDetails(); v.interfaceName = "vxlan_gpe_inf2".getBytes(); - final Map map = new HashMap<>(); - map.put(0, v); - cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map); + + when(dumpCacheManager.getInterfaceDetail(any(), any(), matches(IF_NAME))).thenReturn(v); final VxlanGpeTunnelDetailsReplyDump value = new VxlanGpeTunnelDetailsReplyDump(); final VxlanGpeTunnelDetails vxlanGpeTunnelDetails = new VxlanGpeTunnelDetails(); @@ -108,9 +113,10 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest initCustomizer() { - return new VxlanGpeCustomizer(api, interfacesContext); + return new VxlanGpeCustomizer(api, interfacesContext, dumpCacheManager); } } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java new file mode 100644 index 000000000..6f47f162d --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/cache/InterfaceCacheDumpManagerImplTest.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.v3po.interfacesstate.cache; + +import static io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheDumpManagerImpl.BY_NAME_INDEX_KEY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import io.fd.hc2vpp.common.test.util.FutureProducer; +import io.fd.hc2vpp.common.test.util.NamingContextHelper; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.ModificationCache; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfaceCacheDumpManagerImplTest implements NamingContextHelper, FutureProducer { + + private static final String IFACE_0 = "iface-0"; + private static final String IFACE_1 = "iface-1"; + private static final String IFACE_2 = "iface-2"; + private static final String IFACE_3 = "iface-3"; + + @Mock + private FutureJVppCore jvpp; + @Mock + private ReadContext ctx; + @Mock + private MappingContext mappingContext; + + private InstanceIdentifier identifier; + private InstanceIdentifier identifierThree; + private NamingContext namingContext; + private ModificationCache cache; + private InterfaceCacheDumpManagerImpl manager; + + @Before + public void setUp() throws Exception { + initMocks(this); + namingContext = new NamingContext("interface-", "interface-context"); + cache = new ModificationCache(); + manager = new InterfaceCacheDumpManagerImpl(jvpp, namingContext); + when(ctx.getModificationCache()).thenReturn(cache); + when(ctx.getMappingContext()).thenReturn(mappingContext); + identifier = InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class, new InterfaceKey(IFACE_0)); + + identifierThree = InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class, new InterfaceKey(IFACE_3)); + + when(jvpp.swInterfaceDump(fullRequest())).thenReturn(future(fullReply())); + + // this one is not in full dump + when(jvpp.swInterfaceDump(specificRequest(IFACE_3))).thenReturn(future(specificReplyThree())); + defineMapping(mappingContext, IFACE_0, 0, "interface-context"); + defineMapping(mappingContext, IFACE_1, 1, "interface-context"); + defineMapping(mappingContext, IFACE_2, 2, "interface-context"); + defineMapping(mappingContext, IFACE_3, 3, "interface-context"); + } + + @Test + public void getInterfaces() throws Exception { + assertFalse(cache.containsKey(BY_NAME_INDEX_KEY)); + final List interfaces = manager.getInterfaces(identifier, ctx).collect(Collectors.toList()); + assertEquals(3, interfaces.size()); + assertTrue(interfaces.contains(detailZero())); + assertTrue(interfaces.contains(detailOne())); + assertTrue(interfaces.contains(detailTwo())); + + // first request must call jvpp + verify(jvpp, times(1)).swInterfaceDump(fullRequest()); + assertTrue(cache.containsKey(BY_NAME_INDEX_KEY)); + + // then cached value should be returned + final List cachedInterfaces = + manager.getInterfaces(identifier, ctx).collect(Collectors.toList()); + assertEquals(3, cachedInterfaces.size()); + assertTrue(cachedInterfaces.contains(detailZero())); + assertTrue(cachedInterfaces.contains(detailOne())); + assertTrue(cachedInterfaces.contains(detailTwo())); + + //verify that dump wasn't invoked again + verifyNoMoreInteractions(jvpp); + } + + @Test + public void getInterfaceDetailFromCache() throws Exception { + final HashMap cachedMap = new HashMap<>(); + final SwInterfaceDetails detailZero = detailZero(); + cachedMap.put(IFACE_0, detailZero); + cache.put(BY_NAME_INDEX_KEY, cachedMap); + when(jvpp.swInterfaceDump(specificRequest(IFACE_0))).thenReturn(future(specificReplyZero())); + final SwInterfaceDetails interfaceDetail = manager.getInterfaceDetail(identifier, ctx, IFACE_0); + assertEquals(detailZero, interfaceDetail); + + // must not call jvpp, just get it from cache + verifyZeroInteractions(jvpp); + } + + @Test + public void getInterfaceDetailNotInFullDump() throws Exception { + assertFalse(cache.containsKey(BY_NAME_INDEX_KEY)); + final SwInterfaceDetails specificDetail = manager.getInterfaceDetail(identifierThree, ctx, IFACE_3); + assertEquals(detailThree(), specificDetail); + + verify(jvpp, times(1)).swInterfaceDump(specificRequest(IFACE_3)); + } + + private SwInterfaceDetailsReplyDump fullReply() { + final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump(); + reply.swInterfaceDetails = Arrays.asList(detailZero(), detailOne(), detailTwo()); + return reply; + } + + private static SwInterfaceDetails detailTwo() { + SwInterfaceDetails detail3 = new SwInterfaceDetails(); + detail3.swIfIndex = 2; + detail3.interfaceName = IFACE_2.getBytes(); + return detail3; + } + + private static SwInterfaceDetails detailOne() { + SwInterfaceDetails detail2 = new SwInterfaceDetails(); + detail2.swIfIndex = 1; + detail2.interfaceName = IFACE_1.getBytes(); + return detail2; + } + + private static SwInterfaceDetails detailThree() { + SwInterfaceDetails detail2 = new SwInterfaceDetails(); + detail2.swIfIndex = 3; + detail2.interfaceName = IFACE_3.getBytes(); + return detail2; + } + + private static SwInterfaceDetails detailZero() { + SwInterfaceDetails detail1 = new SwInterfaceDetails(); + detail1.swIfIndex = 0; + detail1.interfaceName = IFACE_0.getBytes(); + return detail1; + } + + private SwInterfaceDetailsReplyDump specificReplyThree() { + final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump(); + reply.swInterfaceDetails = Arrays.asList(detailThree()); + return reply; + } + + private SwInterfaceDetailsReplyDump specificReplyZero() { + final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump(); + reply.swInterfaceDetails = Arrays.asList(detailZero()); + return reply; + } + + private static SwInterfaceDump specificRequest(final String ifaceName) { + final SwInterfaceDump specificRequest = new SwInterfaceDump(); + specificRequest.nameFilterValid = 1; + specificRequest.nameFilter = ifaceName.getBytes(); + return specificRequest; + } + + private static SwInterfaceDump fullRequest() { + final SwInterfaceDump fullRequest = new SwInterfaceDump(); + fullRequest.nameFilterValid = 0; + fullRequest.nameFilter = "".getBytes(); + return fullRequest; + } +} \ No newline at end of file -- cgit 1.2.3-korg