From 8b95b03db7970d4381cba38c1ee9b416521fd5a8 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Mon, 16 May 2016 15:04:18 +0200 Subject: HONEYCOMB-48: vlan tag rewrite support Change-Id: Id20aa699db1fd48b253b3abb1b4341e779a9b98f Signed-off-by: Marek Gradzki --- .../v3po/interfaces/VlanTagRewriteCustomizer.java | 143 +++++++++++++ .../interfacesstate/VlanTagRewriteCustomizer.java | 88 ++++++++ .../rev160406/InterfacesHoneycombWriterModule.java | 20 +- .../InterfacesStateHoneycombReaderModule.java | 36 +++- .../interfaces/VlanTagRewriteCustomizerTest.java | 232 +++++++++++++++++++++ .../VlanTagRewriteCustomizerTest.java | 97 +++++++++ 6 files changed, 612 insertions(+), 4 deletions(-) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java (limited to 'v3po') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java new file mode 100644 index 000000000..7e7e319eb --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java @@ -0,0 +1,143 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.util.concurrent.CompletionStage; +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.rev150105.TagRewriteOperation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewrite; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewriteReply; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Writer Customizer responsible for vlan tag rewrite.
+ * Sends {@code l2_interface_vlan_tag_rewrite} message to VPP.
+ * Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command. + */ +public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(VlanTagRewriteCustomizer.class); + private final NamingContext interfaceContext; + + public VlanTagRewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext) { + super(futureJvpp); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((L2) parentData).getVlanTagRewrite()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VlanTagRewrite dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException.CreateFailedException { + try { + setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + private void setTagRewrite(final String ifname, final VlanTagRewrite cfg) throws VppApiInvocationException { + final int swIfIndex = interfaceContext.getIndex(ifname); + LOG.debug("Setting tag rewrite for interface {}(id=): {}", ifname, swIfIndex, cfg); + + final CompletionStage replyCompletionStage = + getFutureJVpp().l2InterfaceVlanTagRewrite(getTagRewriteRequest(swIfIndex, cfg)); + + final L2InterfaceVlanTagRewriteReply reply = V3poUtils.getReply(replyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { + LOG.debug("Failed to set tag rewrite for interface {}(id=): {}", ifname, swIfIndex, cfg); + throw new VppApiInvocationException("l2InterfaceVlanTagRewrite", reply.context, reply.retval); + } else { + LOG.debug("Tag rewrite for interface {}(id=) set successfully: {}", ifname, swIfIndex, cfg); + } + } + + private L2InterfaceVlanTagRewrite getTagRewriteRequest(final int swIfIndex, final VlanTagRewrite cfg) { + final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite(); + request.swIfIndex = swIfIndex; + + request.vtrOp = cfg.getRewriteOperation().getIntValue(); // TODO make mandatory + request.pushDot1Q = (byte) (VlanType._802dot1q.equals(cfg.getFirstPushed()) + ? 1 + : 0); + final VlanTag tag1 = cfg.getTag1(); + if (tag1 != null) { + request.tag1 = tag1.getValue(); + } + final VlanTag tag2 = cfg.getTag2(); + if (tag2 != null) { + request.tag2 = tag2.getValue(); + } + return request; + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VlanTagRewrite dataBefore, + @Nonnull final VlanTagRewrite dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (dataBefore.equals(dataAfter)) { + LOG.debug("dataBefore equals dataAfter, update will not be performed"); + return; + } + try { + setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VlanTagRewrite dataBefore, @Nonnull final WriteContext writeContext) + throws WriteFailedException.DeleteFailedException { + try { + // disable tag rewrite + final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); + builder.setRewriteOperation(TagRewriteOperation.Disabled); + setTagRewrite(id.firstKeyOf(Interface.class).getName(), builder.build()); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java new file mode 100644 index 000000000..d7404e6d5 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java @@ -0,0 +1,88 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfacesstate; + +import com.google.common.base.Preconditions; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +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.rev150105.TagRewriteOperation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewriteBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading vlan tag-rewrite configuration state form the VPP. + */ +public class VlanTagRewriteCustomizer extends FutureJVppCustomizer + implements ChildReaderCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); + private final NamingContext interfaceContext; + + public VlanTagRewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext) { + super(futureJvpp); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Override + public void merge(@Nonnull final Builder parentBuilder, + @Nonnull final VlanTagRewrite readValue) { + ((L2Builder) parentBuilder).setVlanTagRewrite(readValue); + } + + @Nonnull + @Override + public VlanTagRewriteBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new VlanTagRewriteBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VlanTagRewriteBuilder builder, @Nonnull final Context ctx) + throws ReadFailedException { + LOG.debug("Reading attributes for sub interface: {}", id); + final InterfaceKey key = id.firstKeyOf(Interface.class); + + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, + interfaceContext.getIndex(key.getName()), ctx); + + builder.setFirstPushed(iface.subDot1Ad == 1 ? VlanType._802dot1q : VlanType._802dot1ad); + builder.setRewriteOperation(TagRewriteOperation.forValue(iface.vtrOp)); + if (iface.vtrTag1 != 0) { + builder.setTag1(new VlanTag(iface.vtrTag1)); + } + if (iface.vtrTag2 != 0) { + builder.setTag2(new VlanTag(iface.vtrTag2)); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java index fb60635bf..9443dc2a7 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java @@ -13,13 +13,16 @@ import io.fd.honeycomb.v3po.translate.v3po.interfaces.EthernetCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.InterfaceCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.L2Customizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.RoutingCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.SubInterfaceCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.TapCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.VhostUserCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.VlanTagRewriteCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.VxlanCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.ip.Ipv4Customizer; import io.fd.honeycomb.v3po.translate.v3po.interfaces.ip.Ipv6Customizer; import io.fd.honeycomb.v3po.translate.write.ChildWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; 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; @@ -30,9 +33,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.rev150105.interfaces._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Tap; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewrite; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.ChildOf; @@ -104,16 +109,27 @@ public class InterfacesHoneycombWriterModule extends org.opendaylight.yang.gen.v new VhostUserCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); final ChildWriter tapWriter = new CompositeChildWriter<>(Tap.class, - new TapCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); + new TapCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); + final ChildWriter subIfWriter = new CompositeChildWriter<>(SubInterface.class, + new SubInterfaceCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); + + final ChildWriter vlanTagWriter = new CompositeChildWriter<>(VlanTagRewrite.class, + new VlanTagRewriteCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); + + final List>> l2ChildWriters = Collections.singletonList(vlanTagWriter); final ChildWriter l2Writer = new CompositeChildWriter<>(L2.class, - new L2Customizer(getVppJvppIfcDependency(), getInterfaceContextDependency(), getBridgeDomainContextDependency())); + l2ChildWriters, + RWUtils.emptyAugWriterList(), + new L2Customizer(getVppJvppIfcDependency(), getInterfaceContextDependency(), getBridgeDomainContextDependency()) + ); final List>> vppIfcChildWriters = Lists.newArrayList(); vppIfcChildWriters.add(vhostUserWriter); vppIfcChildWriters.add(vxlanWriter); vppIfcChildWriters.add(tapWriter); vppIfcChildWriters.add(ethernetWriter); + vppIfcChildWriters.add(subIfWriter); vppIfcChildWriters.add(l2Writer); vppIfcChildWriters.add(routingWriter); diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java index 920a5e783..3bc7ad883 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java @@ -11,14 +11,21 @@ import io.fd.honeycomb.v3po.translate.impl.read.CompositeChildReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeListReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeRootReader; import io.fd.honeycomb.v3po.translate.read.ChildReader; +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.util.read.CloseableReader; import io.fd.honeycomb.v3po.translate.util.read.ReflexiveAugmentReaderCustomizer; import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.L2Customizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.EthernetCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.SubInterfaceCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.TapCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.VhostUserCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.VlanTagRewriteCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.VxlanCustomizer; +import io.fd.honeycomb.v3po.translate.write.ChildWriter; +import java.util.Collections; import java.util.List; 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.InterfacesStateBuilder; @@ -27,11 +34,18 @@ 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.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Tap; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.ChildOf; +import org.opendaylight.yangtools.yang.binding.DataObject; public class InterfacesStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesStateHoneycombReaderModule { @@ -68,14 +82,32 @@ public class InterfacesStateHoneycombReaderModule extends new VhostUserCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); final ChildReader> vxlanReader = - new CompositeChildReader<>(Vxlan.class, - new VxlanCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); + new CompositeChildReader<>(Vxlan.class, + new VxlanCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); + + final ChildReader> subInterfaceReader = + new CompositeChildReader<>(SubInterface.class, + new SubInterfaceCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); + + final ChildReader vlanTagReader = + new CompositeChildReader<>(VlanTagRewrite.class, + new VlanTagRewriteCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); + + + final List>> l2ChildReaders = Collections.singletonList(vlanTagReader); + final ChildReader> l2Reader = + new CompositeChildReader<>(L2.class, + l2ChildReaders, + RWUtils.emptyAugReaderList(), + new L2Customizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency(), getBridgeDomainContextIfcStateDependency())); final List>> childReaders = Lists.newArrayList(); childReaders.add(ethernetReader); childReaders.add(tapReader); childReaders.add(vhostUserReader); childReaders.add(vxlanReader); + childReaders.add(subInterfaceReader); + childReaders.add(l2Reader); final ChildReader vppInterfaceStateAugmentationChildReader = new CompositeChildReader<>(VppInterfaceStateAugmentation.class, diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java new file mode 100644 index 000000000..ae768145a --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java @@ -0,0 +1,232 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +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.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.rev150105.TagRewriteOperation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewrite; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewriteReply; +import org.openvpp.jvpp.future.FutureJVpp; + +public class VlanTagRewriteCustomizerTest { + + @Mock + private FutureJVpp api; + @Mock + private WriteContext writeContext; + + private NamingContext namingContext; + private VlanTagRewriteCustomizer customizer; + + public static final String VLAN_IF_NAME = "local0.0"; + public static final int VLAN_IF_ID = 1; + + @Before + public void setUp() throws Exception { + initMocks(this); + namingContext = new NamingContext("generatedSubInterfaceName"); + customizer = new VlanTagRewriteCustomizer(api, namingContext); + namingContext.addName(VLAN_IF_ID, VLAN_IF_NAME); + } + + private InstanceIdentifier getVlanTagRewriteId(final String name) { + return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation( + VppInterfaceAugmentation.class).child(L2.class).child(VlanTagRewrite.class); + } + + private VlanTagRewrite generateVlanTagRewrite(final int vtrOp) { + final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); + builder.setRewriteOperation(TagRewriteOperation.forValue(vtrOp)); + builder.setTag1(new VlanTag(100)); + builder.setTag2(new VlanTag(200)); + builder.setFirstPushed(VlanType._802dot1ad); + return builder.build(); + } + + private L2InterfaceVlanTagRewrite generateL2InterfaceVlanTagRewrite(final int superIfId, final int vtrOp) { + final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite(); + request.swIfIndex = superIfId; + request.vtrOp = vtrOp; + request.pushDot1Q = 0; + request.tag1 = 100; + request.tag2 = 200; + return request; + } + + private void whenL2InterfaceVlanTagRewriteThen(final int retval) throws ExecutionException, InterruptedException { + final CompletableFuture replyFuture = new CompletableFuture<>(); + final L2InterfaceVlanTagRewriteReply reply = new L2InterfaceVlanTagRewriteReply(); + reply.retval = retval; + replyFuture.complete(reply); + doReturn(replyFuture).when(api).l2InterfaceVlanTagRewrite(any(L2InterfaceVlanTagRewrite.class)); + } + + private void whenL2InterfaceVlanTagRewriteThenSuccess() throws ExecutionException, InterruptedException { + whenL2InterfaceVlanTagRewriteThen(0); + } + + private void whenL2InterfaceVlanTagRewriteThenFailure() throws ExecutionException, InterruptedException { + whenL2InterfaceVlanTagRewriteThen(-1); + } + + private void verifyL2InterfaceVlanTagRewriteWasInvoked(final L2InterfaceVlanTagRewrite expected) { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(L2InterfaceVlanTagRewrite.class); + verify(api).l2InterfaceVlanTagRewrite(argumentCaptor.capture()); + final L2InterfaceVlanTagRewrite actual = argumentCaptor.getValue(); + assertEquals(expected.swIfIndex, actual.swIfIndex); + assertEquals(expected.vtrOp, actual.vtrOp); + assertEquals(expected.pushDot1Q, actual.pushDot1Q); + assertEquals(expected.tag1, actual.tag1); + assertEquals(expected.tag2, actual.tag2); + } + + private void verifyL2InterfaceVlanTagRewriteDeleteWasInvoked() { + final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite(); + request.swIfIndex = VLAN_IF_ID; + verifyL2InterfaceVlanTagRewriteWasInvoked(request); + } + + @Test + public void testCreate() throws Exception { + final int vtrOp = 6; + final VlanTagRewrite vlanTagRewrite = generateVlanTagRewrite(vtrOp); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenSuccess(); + + customizer.writeCurrentAttributes(id, vlanTagRewrite, writeContext); + + verifyL2InterfaceVlanTagRewriteWasInvoked(generateL2InterfaceVlanTagRewrite(VLAN_IF_ID, vtrOp)); + } + + @Test + public void testCreateFailed() throws Exception { + final int vtrOp = 6; + final VlanTagRewrite vlanTagRewrite = generateVlanTagRewrite(vtrOp); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenFailure(); + + try { + customizer.writeCurrentAttributes(id, vlanTagRewrite, writeContext); + } catch (WriteFailedException.CreateFailedException e) { + assertEquals(VppApiInvocationException.class, e.getCause().getClass()); + verifyL2InterfaceVlanTagRewriteWasInvoked(generateL2InterfaceVlanTagRewrite(VLAN_IF_ID, vtrOp)); + return; + } + fail("WriteFailedException.CreateFailedException was expected"); + } + + @Test + public void testUpdateNoChange() throws Exception { + final VlanTagRewrite before = generateVlanTagRewrite(6); + final VlanTagRewrite after = generateVlanTagRewrite(6); + customizer.updateCurrentAttributes(null, before, after, writeContext); + verify(api, never()).l2InterfaceVlanTagRewrite(any()); + } + + @Test + public void testUpdate() throws Exception { + final int vtrOpAfter = 5; + final VlanTagRewrite before = generateVlanTagRewrite(6); + final VlanTagRewrite after = generateVlanTagRewrite(vtrOpAfter); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenSuccess(); + + customizer.updateCurrentAttributes(id, before, after, writeContext); + + verifyL2InterfaceVlanTagRewriteWasInvoked(generateL2InterfaceVlanTagRewrite(VLAN_IF_ID, vtrOpAfter)); + } + + @Test + public void testUpdateFailed() throws Exception { + final int vtrOpAfter = 5; + final VlanTagRewrite before = generateVlanTagRewrite(6); + final VlanTagRewrite after = generateVlanTagRewrite(vtrOpAfter); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenFailure(); + + try { + customizer.updateCurrentAttributes(id, before, after, writeContext); + } catch (WriteFailedException.UpdateFailedException e) { + assertEquals(VppApiInvocationException.class, e.getCause().getClass()); + verifyL2InterfaceVlanTagRewriteWasInvoked(generateL2InterfaceVlanTagRewrite(VLAN_IF_ID, vtrOpAfter)); + return; + } + fail("WriteFailedException.UpdateFailedException was expected"); + } + + @Test + public void testDelete() throws Exception { + final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); + builder.setRewriteOperation(TagRewriteOperation.Disabled); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenSuccess(); + + customizer.deleteCurrentAttributes(id, builder.build(), writeContext); + + verifyL2InterfaceVlanTagRewriteDeleteWasInvoked(); + } + + @Test + public void testDeleteFailed() throws Exception { + final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); + builder.setRewriteOperation(TagRewriteOperation.Disabled); + final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); + + whenL2InterfaceVlanTagRewriteThenFailure(); + + try { + customizer.deleteCurrentAttributes(id, builder.build(), writeContext); + } catch (WriteFailedException.DeleteFailedException e) { + assertEquals(VppApiInvocationException.class, e.getCause().getClass()); + verifyL2InterfaceVlanTagRewriteDeleteWasInvoked(); + return; + } + fail("WriteFailedException.DeleteFailedException was expected"); + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java new file mode 100644 index 000000000..2263160e3 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java @@ -0,0 +1,97 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfacesstate; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import java.util.HashMap; +import java.util.Map; +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.rev150105.TagRewriteOperation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewriteBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceDetails; + +public class VlanTagRewriteCustomizerTest extends ChildReaderCustomizerTest { + + private NamingContext interfacesContext; + + public VlanTagRewriteCustomizerTest() { + super(VlanTagRewrite.class); + } + + @Override + public void setUpBefore() { + interfacesContext = new NamingContext("generatedIfaceName"); + } + + + @Override + protected RootReaderCustomizer initCustomizer() { + return new VlanTagRewriteCustomizer(api, interfacesContext); + } + + @Test + public void testMerge() { + final L2Builder builder = mock(L2Builder.class); + final VlanTagRewrite value = mock(VlanTagRewrite.class); + getCustomizer().merge(builder, value); + verify(builder).setVlanTagRewrite(value); + } + + private InstanceIdentifier getVlanTagRewriteId(final String name) { + return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation( + VppInterfaceStateAugmentation.class).child(L2.class).child(VlanTagRewrite.class); + } + + @Test + public void testRead() throws ReadFailedException { + final Context ctx = new Context(); + final Map cachedInterfaceDump = new HashMap<>(); + final int ifId = 1; + final String ifName = "eth0.sub0"; + interfacesContext.addName(ifId, ifName); + final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); + ifaceDetails.subId = ifId; + cachedInterfaceDump.put(ifId, ifaceDetails); + ctx.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); + + final VlanTagRewriteBuilder builder = mock(VlanTagRewriteBuilder.class); + getCustomizer().readCurrentAttributes(getVlanTagRewriteId(ifName), builder, ctx); + + verify(builder).setFirstPushed(VlanType._802dot1ad); + verify(builder).setRewriteOperation(TagRewriteOperation.Disabled); + verify(builder, never()).setTag1(any()); + verify(builder, never()).setTag2(any()); + } +} \ No newline at end of file -- cgit 1.2.3-korg