From a5defc544b5664b138ecb51340c375bb664d6b52 Mon Sep 17 00:00:00 2001 From: Jan Srnicek Date: Wed, 14 Dec 2016 09:54:19 +0100 Subject: Span model update reflecting api changes Allows use of Rx/Tx/Both Span states Allows setting state per src-interface Change-Id: I07346bf3976be34aa85336bdeedff94f83a3173c Signed-off-by: Jan Srnicek --- .../v3po/factory/InterfacesStateReaderFactory.java | 8 +- .../v3po/factory/InterfacesWriterFactory.java | 10 +- .../span/MirroredInterfaceCustomizer.java | 119 +++++++++++++++++++ .../span/MirroredInterfacesCustomizer.java | 126 -------------------- .../span/MirroredInterfacesCustomizer.java | 18 ++- .../span/MirroredInterfaceCustomizerTest.java | 115 ++++++++++++++++++ .../span/MirroredInterfacesCustomizerTest.java | 129 +++++++++++++++++++++ 7 files changed, 391 insertions(+), 134 deletions(-) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizer.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java (limited to 'v3po/v3po2vpp/src') 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 830147cc2..494a17375 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 @@ -16,6 +16,7 @@ package io.fd.hc2vpp.v3po.factory; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.inject.Inject; import com.google.inject.name.Named; @@ -72,6 +73,7 @@ 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.rev161214.interfaces.state._interface.VxlanGpe; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.acl.Ingress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.Ip4Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.Ip6Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.L2Acl; @@ -186,8 +188,10 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { final InstanceIdentifier spanId = vppIfcAugId.child(Span.class); registry.addStructuralReader(spanId, SpanBuilder.class); // MirroredInterfaces - registry.add(new GenericInitReader<>(spanId.child(MirroredInterfaces.class), - new MirroredInterfacesCustomizer(jvpp, ifcNamingCtx))); + registry.subtreeAdd( + ImmutableSet.of(InstanceIdentifier.create(MirroredInterfaces.class).child(MirroredInterface.class)), + new GenericInitReader<>(spanId.child(MirroredInterfaces.class), + new MirroredInterfacesCustomizer(jvpp, ifcNamingCtx))); } private void initPbbRewriteAugmentation(final ModifiableReaderRegistryBuilder registry, diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java index 94b7f02d7..27a2dd95a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java @@ -41,7 +41,7 @@ import io.fd.hc2vpp.v3po.interfaces.ip.Ipv4Customizer; import io.fd.hc2vpp.v3po.interfaces.ip.Ipv4NeighbourCustomizer; import io.fd.hc2vpp.v3po.interfaces.ip.Ipv6Customizer; import io.fd.hc2vpp.v3po.interfaces.pbb.PbbRewriteCustomizer; -import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfacesCustomizer; +import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfaceCustomizer; import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.impl.write.GenericListWriter; import io.fd.honeycomb.translate.impl.write.GenericWriter; @@ -71,6 +71,7 @@ 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.rev161214.interfaces._interface.VxlanGpe; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.acl.Ingress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.Ip4Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.Ip6Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classfier.acl.rev161214.acl.base.attributes.L2Acl; @@ -198,10 +199,11 @@ public final class InterfacesWriterFactory implements WriterFactory { // Span writers // Mirrored interfaces - final InstanceIdentifier mirroredIfcsId = VPP_IFC_AUG_ID + final InstanceIdentifier mirroredIfcId = VPP_IFC_AUG_ID .child(Span.class) - .child(MirroredInterfaces.class); - registry.addAfter(new GenericWriter<>(mirroredIfcsId, new MirroredInterfacesCustomizer(jvpp, ifcNamingContext)), + .child(MirroredInterfaces.class) + .child(MirroredInterface.class); + registry.addAfter(new GenericWriter<>(mirroredIfcId, new MirroredInterfaceCustomizer(jvpp, ifcNamingContext)), ifcId); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizer.java new file mode 100644 index 000000000..1d6c5ec92 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizer.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 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.interfaces.span; + +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.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisable; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.SpanState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class MirroredInterfaceCustomizer + extends FutureJVppCustomizer + implements ListWriterCustomizer, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(MirroredInterfaceCustomizer.class); + + private final NamingContext ifcContext; + + public MirroredInterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore, final NamingContext ifcContext) { + super(futureJVppCore); + this.ifcContext = ifcContext; + } + + private SwInterfaceSpanEnableDisable getSpanAddDelRequest(final int dstId, final Integer srcId, final boolean isAdd, + @Nullable final SpanState state) { + final SwInterfaceSpanEnableDisable spanAddDel = new SwInterfaceSpanEnableDisable(); + spanAddDel.state = (byte) (isAdd + ? state != null + ? state.getIntValue() + : 0 + : 0);// either one of 1(rx),2(tx),3(both) or 0 for disable/delete + spanAddDel.swIfIndexFrom = srcId; + spanAddDel.swIfIndexTo = dstId; + return spanAddDel; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final MirroredInterface mirroredInterface, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + final String destinationInterfaceName = instanceIdentifier.firstKeyOf(Interface.class).getName(); + final String sourceInterfaceName = mirroredInterface.getIfaceRef(); + final SpanState spanState = mirroredInterface.getState(); + + LOG.debug("Enabling span for source interface {} | destination interface {} | state {}", sourceInterfaceName, + destinationInterfaceName, spanState); + + getReplyForWrite(getFutureJVpp().swInterfaceSpanEnableDisable( + getSpanAddDelRequest( + interfaceId(writeContext, ifcContext, destinationInterfaceName), + interfaceId(writeContext, ifcContext, sourceInterfaceName), + true, + spanState)) + .toCompletableFuture(), instanceIdentifier); + LOG.debug("Span for source interface {} | destination interface {} | state {} successfully enabled", + sourceInterfaceName, destinationInterfaceName, spanState); + } + + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final MirroredInterface mirroredInterfaceBefore, + @Nonnull final MirroredInterface mirroredInterfaceAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + deleteCurrentAttributes(instanceIdentifier, mirroredInterfaceBefore, writeContext); + writeCurrentAttributes(instanceIdentifier, mirroredInterfaceAfter, writeContext); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final MirroredInterface mirroredInterface, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final String destinationInterfaceName = instanceIdentifier.firstKeyOf(Interface.class).getName(); + final String sourceInterfaceName = mirroredInterface.getIfaceRef(); + LOG.debug("Disabling span for source interface {} | destination interface {} ", sourceInterfaceName, + destinationInterfaceName); + + getReplyForWrite(getFutureJVpp().swInterfaceSpanEnableDisable( + getSpanAddDelRequest( + interfaceId(writeContext, ifcContext, destinationInterfaceName), + interfaceId(writeContext, ifcContext, sourceInterfaceName), + false, + null)) + .toCompletableFuture(), instanceIdentifier); + LOG.debug("Span for source interface {} | destination interface {} successfully disabled", + sourceInterfaceName, destinationInterfaceName); + } + + private static int interfaceId(final WriteContext writeContext, final NamingContext ifcContext, final String name) { + return ifcContext.getIndex(name, writeContext.getMappingContext()); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizer.java deleted file mode 100644 index b7376332d..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizer.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2016 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.interfaces.span; - -import com.google.common.base.Preconditions; -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.spi.write.WriterCustomizer; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisable; -import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisableReply; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import java.util.List; -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.Interface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class MirroredInterfacesCustomizer - extends FutureJVppCustomizer - implements WriterCustomizer, JvppReplyConsumer { - - private static final Logger LOG = LoggerFactory.getLogger(MirroredInterfacesCustomizer.class); - - private final NamingContext ifcContext; - - public MirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore, final NamingContext ifcContext) { - super(futureJVppCore); - this.ifcContext = ifcContext; - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MirroredInterfaces dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.trace("Writing mirrored interfaces for: {} as: {}", id, dataAfter); - - final int dstId = - ifcContext.getIndex(id.firstKeyOf(Interface.class).getName(), writeContext.getMappingContext()); - - // Collect source IDs - final List srcIds = dataAfter.getMirroredInterface().stream() - .map(ifcName -> ifcContext.getIndex(ifcName, writeContext.getMappingContext())) - // Collecting before executing to verify we have all the IDs first, failing fast... - .collect(Collectors.toList()); - - Preconditions.checkArgument(!srcIds.contains(dstId), - "Source and Destination interface for port mirroring detected: %s at %s", dstId, id); - - // Invoke addition for each source ID - final List> futures = srcIds.stream() - .map(srcId -> getSpanAddDelRequest(dstId, srcId, true)) - .map(request -> getFutureJVpp().swInterfaceSpanEnableDisable(request).toCompletableFuture()) - .collect(Collectors.toList()); - - // Wait for success/exception - for (final CompletableFuture future : futures) { - getReplyForWrite(future, id); - } - - LOG.trace("Mirrored interfaces for: {} written successfully", id); - } - - private SwInterfaceSpanEnableDisable getSpanAddDelRequest(final int dstId, final Integer srcId, final boolean isAdd) { - final SwInterfaceSpanEnableDisable spanAddDel = new SwInterfaceSpanEnableDisable(); - spanAddDel.state = (byte) (isAdd ? 3 : 0); // 3 - enable rx & tx : 0 - disabled - spanAddDel.swIfIndexFrom = srcId; - spanAddDel.swIfIndexTo = dstId; - return spanAddDel; - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MirroredInterfaces dataBefore, - @Nonnull final MirroredInterfaces dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - deleteCurrentAttributes(id, dataBefore, writeContext); - writeCurrentAttributes(id, dataAfter, writeContext); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final MirroredInterfaces dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.trace("Removing mirrored interfaces for: {} as: {}", id, dataBefore); - - final int dstId = - ifcContext.getIndex(id.firstKeyOf(Interface.class).getName(), writeContext.getMappingContext()); - - final List srcIds = dataBefore.getMirroredInterface().stream() - .map(ifcName -> ifcContext.getIndex(ifcName, writeContext.getMappingContext())) - // Collecting before executing to verify we have all the IDs first, failing fast... - .collect(Collectors.toList()); - - final List> futures = srcIds.stream() - .map(srcId -> getSpanAddDelRequest(dstId, srcId, false)) - .map(request -> getFutureJVpp().swInterfaceSpanEnableDisable(request).toCompletableFuture()) - .collect(Collectors.toList()); - - for (final CompletableFuture future : futures) { - getReplyForWrite(future, id); - } - - LOG.trace("Mirrored interfaces for: {} removed successfully", id); - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizer.java index 2396bcfb7..f6aa4982c 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizer.java @@ -32,11 +32,15 @@ import java.util.List; 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.state.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.SpanState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Span; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.SpanBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceKey; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -79,10 +83,20 @@ public final class MirroredInterfacesCustomizer ctx.getModificationCache().put(getCacheKey(), replyForRead); } - final List mirroredInterfaces = + final List mirroredInterfaces = replyForRead.swInterfaceSpanDetails.stream() .filter(detail -> detail.swIfIndexTo == dstId) - .map(detail -> ifcContext.getName(detail.swIfIndexFrom, ctx.getMappingContext())) + .filter(detail -> detail.state != 0) // filters disabled(we use disabled as delete) + .map(detail -> { + final String interfaceName = + ifcContext.getName(detail.swIfIndexFrom, ctx.getMappingContext()); + return new MirroredInterfaceBuilder() + .setIfaceRef(interfaceName) + .setKey(new MirroredInterfaceKey(interfaceName)) + .setState(SpanState.forValue(detail.state)) + .build(); + } + ) .collect(Collectors.toList()); LOG.debug("Mirrored interfaces for: {} read as: {}", id, mirroredInterfaces); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizerTest.java new file mode 100644 index 000000000..c7d04f16d --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceCustomizerTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 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.interfaces.span; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisable; +import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanEnableDisableReply; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.SpanState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Span; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class MirroredInterfaceCustomizerTest extends WriterCustomizerTest { + + private static final String IFACE_NAME = "iface"; + private static final int IFACE_INDEX = 3; + private static final String SRC_IFACE_NAME = "src-iface"; + private static final int SRC_IFACE_INDEX = 5; + + private NamingContext interfaceContext; + private MirroredInterfaceCustomizer customizer; + + private InstanceIdentifier validId; + private MirroredInterface validData; + + @Captor + private ArgumentCaptor requestCaptor; + + public void setUpTest() { + interfaceContext = new NamingContext("iface", "iface-context"); + customizer = new MirroredInterfaceCustomizer(api, interfaceContext); + defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, "iface-context"); + defineMapping(mappingContext, SRC_IFACE_NAME, SRC_IFACE_INDEX, "iface-context"); + + validId = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) + .augmentation(VppInterfaceAugmentation.class).child(Span.class) + .child(MirroredInterfaces.class) + .child(MirroredInterface.class); + + validData = new MirroredInterfaceBuilder() + .setIfaceRef(SRC_IFACE_NAME) + .setState(SpanState.Receive) + .build(); + + when(api.swInterfaceSpanEnableDisable(any())).thenReturn(future(new SwInterfaceSpanEnableDisableReply())); + } + + @Test + public void writeCurrentAttributes() throws Exception { + customizer.writeCurrentAttributes(validId, validData, writeContext); + verify(api, times(1)).swInterfaceSpanEnableDisable(requestCaptor.capture()); + assertCreateRequest(requestCaptor.getValue()); + } + + @Test + public void updateCurrentAttributes() throws Exception { + customizer.updateCurrentAttributes(validId, validData, validData, writeContext); + verify(api, times(2)).swInterfaceSpanEnableDisable(requestCaptor.capture()); + assertDeleteRequest(requestCaptor.getAllValues().get(0)); + assertCreateRequest(requestCaptor.getAllValues().get(1)); + } + + @Test + public void deleteCurrentAttributes() throws Exception { + customizer.deleteCurrentAttributes(validId, validData, writeContext); + verify(api, times(1)).swInterfaceSpanEnableDisable(requestCaptor.capture()); + assertDeleteRequest(requestCaptor.getValue()); + } + + private static void assertCreateRequest(final SwInterfaceSpanEnableDisable createRequest) { + assertNotNull(createRequest); + assertEquals(1, createRequest.state); + assertEquals(IFACE_INDEX, createRequest.swIfIndexTo); + assertEquals(SRC_IFACE_INDEX, createRequest.swIfIndexFrom); + } + + private static void assertDeleteRequest(final SwInterfaceSpanEnableDisable deleteRequest) { + assertNotNull(deleteRequest); + assertEquals(0, deleteRequest.state); + assertEquals(IFACE_INDEX, deleteRequest.swIfIndexTo); + assertEquals(SRC_IFACE_INDEX, deleteRequest.swIfIndexFrom); + } + +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java new file mode 100644 index 000000000..296bfc45d --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016 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.span; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; +import static org.mockito.ArgumentMatchers.any; +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.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanDetails; +import io.fd.vpp.jvpp.core.dto.SwInterfaceSpanDetailsReplyDump; +import java.util.Arrays; +import org.junit.Test; +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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.SpanState; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Span; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.SpanBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.MirroredInterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.span.attributes.mirrored.interfaces.MirroredInterfaceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +public class MirroredInterfacesCustomizerTest + extends ReaderCustomizerTest { + + private static final String IFACE_NAME = "iface"; + + private static final String SRC_IFACE_NAME_1 = "src-one"; + private static final String SRC_IFACE_NAME_2 = "src-two"; + private static final String SRC_IFACE_NAME_3 = "src-three"; + + private static final int IFACE_INDEX = 3; + + private NamingContext interfaceContext; + private InstanceIdentifier validId; + private MirroredInterface validData; + + public MirroredInterfacesCustomizerTest() { + super(MirroredInterfaces.class, SpanBuilder.class); + } + + @Override + protected void setUp() throws Exception { + interfaceContext = new NamingContext("iface", "iface-context"); + defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, "iface-context"); + defineMapping(mappingContext, SRC_IFACE_NAME_1, 1, "iface-context"); + defineMapping(mappingContext, SRC_IFACE_NAME_2, 2, "iface-context"); + defineMapping(mappingContext, SRC_IFACE_NAME_3, 3, "iface-context"); + + validId = InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) + .augmentation(VppInterfaceStateAugmentation.class).child(Span.class) + .child(MirroredInterfaces.class); + + SwInterfaceSpanDetailsReplyDump dump = new SwInterfaceSpanDetailsReplyDump(); + SwInterfaceSpanDetails detail1 = new SwInterfaceSpanDetails(); + + detail1.swIfIndexTo = IFACE_INDEX; + detail1.swIfIndexFrom = 1; + detail1.state = 1; + + SwInterfaceSpanDetails detail2 = new SwInterfaceSpanDetails(); + + detail2.swIfIndexTo = IFACE_INDEX; + detail2.swIfIndexFrom = 2; + detail2.state = 3; + + SwInterfaceSpanDetails detail3 = new SwInterfaceSpanDetails(); + + detail3.swIfIndexTo = IFACE_INDEX; + detail3.swIfIndexFrom = 3; + detail3.state = 0; + + dump.swInterfaceSpanDetails = Arrays.asList(detail1, detail2, detail3); + + when(api.swInterfaceSpanDump(any())).thenReturn(future(dump)); + } + + @Test + public void readCurrentAttributes() throws Exception { + MirroredInterfacesBuilder builder = new MirroredInterfacesBuilder(); + getCustomizer().readCurrentAttributes(validId, builder, ctx); + + + final MirroredInterfaces data = builder.build(); + // 1,2 should be returned,0 should be filtered out because of disabled state + + assertThat(data.getMirroredInterface(), hasSize(2)); + assertThat(data.getMirroredInterface(), containsInAnyOrder( + mirroredInterface(SRC_IFACE_NAME_1, SpanState.Receive), + mirroredInterface(SRC_IFACE_NAME_2, SpanState.Both))); + } + + private MirroredInterface mirroredInterface(final String ifaceName, final SpanState state) { + return new MirroredInterfaceBuilder() + .setIfaceRef(ifaceName) + .setKey(new MirroredInterfaceKey(ifaceName)) + .setState(state) + .build(); + } + + @Override + protected ReaderCustomizer initCustomizer() { + return new MirroredInterfacesCustomizer(api, interfaceContext); + } +} \ No newline at end of file -- cgit 1.2.3-korg