From db99c43fcbb03f6a2d0736a0b3518da27bc7f9e3 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Fri, 20 May 2016 09:51:30 +0200 Subject: HONEYCOMB-61: Extend VPP initializers to initialize everything readers provide Change-Id: Ic7c82f4abfb3bd1bb5065fdfc9c080ed3ba6c94c Signed-off-by: Maros Marsalek --- v3po/features/src/main/features/features.xml | 1 + .../v3po/initializers/InterfacesInitializer.java | 196 ++++++++++++++++++--- .../v3po/interfaces/EthernetCustomizer.java | 1 + .../v3po/interfaces/VlanTagRewriteCustomizer.java | 17 +- .../v3po/interfacesstate/EthernetCustomizer.java | 16 +- .../v3po/interfacesstate/InterfaceUtils.java | 5 + .../v3po/interfacesstate/L2Customizer.java | 44 +++-- .../interfacesstate/VlanTagRewriteCustomizer.java | 8 + .../interfaces/VlanTagRewriteCustomizerTest.java | 9 + .../v3po/interfacesstate/L2CustomizerTest.java | 45 +++-- .../VlanTagRewriteCustomizerTest.java | 1 + 11 files changed, 286 insertions(+), 57 deletions(-) diff --git a/v3po/features/src/main/features/features.xml b/v3po/features/src/main/features/features.xml index 1e5f28f8c..98fc17aff 100644 --- a/v3po/features/src/main/features/features.xml +++ b/v3po/features/src/main/features/features.xml @@ -32,6 +32,7 @@ odl-mdsal-broker odl-v3po-api + odl-netconf-connector-ssh odl-netconf-mdsal mvn:io.fd.honeycomb.v3po/v3po-impl/${project.version} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java index 0b5cef4d8..faaf06306 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java @@ -16,11 +16,9 @@ package io.fd.honeycomb.v3po.translate.v3po.initializers; -import com.google.common.base.Function; import com.google.common.collect.Lists; import io.fd.honeycomb.v3po.vpp.data.init.AbstractDataTreeConverter; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.opendaylight.controller.md.sal.binding.api.DataBroker; 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.InterfacesBuilder; @@ -29,6 +27,29 @@ 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.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus; +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.VppInterfaceAugmentationBuilder; +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.VxlanVni; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.EthernetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.TapBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBasedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.XconnectBasedBuilder; +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.L2; +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.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.Interconnection; +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.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.interconnection.XconnectBased; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,26 +69,159 @@ public class InterfacesInitializer extends AbstractDataTreeConverter - CONVERT_INTERFACE = - new Function() { - @Nullable - @Override - public Interface apply( - @Nullable final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface input) { - - InterfaceBuilder builder = new InterfaceBuilder(); - builder.setKey(new InterfaceKey(input.getKey().getName())); - builder.setName(input.getName()); - // builder.setDescription(); not present in interfaces-state - builder.setType(input.getType()); - builder.setEnabled(AdminStatus.Up.equals(input.getAdminStatus())); - // builder.setLinkUpDownTrapEnable(); not present in interfaces-state - return builder.build(); - } - }; + // FIXME this kind of initialization/transformation is bad + // There is no relation to readers, it cannot be extended (readers can) and its hard to keep in sync with readers + + // TODO add IP v4/ v6 initializer + + private static Interface initialize( + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface input) { + InterfaceBuilder builder = new InterfaceBuilder(); + builder.setKey(new InterfaceKey(input.getKey().getName())); + builder.setName(input.getName()); + builder.setType(input.getType()); + builder.setEnabled(AdminStatus.Up.equals(input.getAdminStatus())); + // builder.setLinkUpDownTrapEnable(); not present in interfaces-state + + final VppInterfaceStateAugmentation vppIfcAugmentation = + input.getAugmentation(VppInterfaceStateAugmentation.class); + if(vppIfcAugmentation != null) { + final VppInterfaceAugmentationBuilder augmentBuilder = new VppInterfaceAugmentationBuilder(); + builder.setDescription(vppIfcAugmentation.getDescription()); + + final Vxlan vxlan = vppIfcAugmentation.getVxlan(); + if(vxlan != null) { + setVxlan(augmentBuilder, vxlan); + } + + final Tap tap = vppIfcAugmentation.getTap(); + if(tap != null) { + setTap(input, augmentBuilder, tap); + } + + final VhostUser vhostUser = vppIfcAugmentation.getVhostUser(); + if(vhostUser != null) { + setVhostUser(augmentBuilder, vhostUser); + } + + final L2 l2 = vppIfcAugmentation.getL2(); + if(l2 != null) { + setL2(augmentBuilder, l2); + } + + final SubInterface subInterface = vppIfcAugmentation.getSubInterface(); + if(subInterface != null) { + setSubinterface(augmentBuilder, subInterface); + } + + final Ethernet ethernet = vppIfcAugmentation.getEthernet(); + if(ethernet != null) { + setEthernet(augmentBuilder, ethernet); + } + + // TODO set routing, not present in interface-state + + builder.addAugmentation(VppInterfaceAugmentation.class, augmentBuilder.build()); + } + + return builder.build(); + } + + private static void setSubinterface(final VppInterfaceAugmentationBuilder augmentBuilder, + final SubInterface subInterface) { + final SubInterfaceBuilder subIfcBuilder = new SubInterfaceBuilder(); + + if(subInterface.isDefaultSubif() != null) { + subIfcBuilder.setDefaultSubif(subInterface.isDefaultSubif()); + } + if(subInterface.isExactMatch() != null) { + subIfcBuilder.setExactMatch(subInterface.isExactMatch()); + } + if(subInterface.isMatchAnyInnerId() != null) { + subIfcBuilder.setMatchAnyInnerId(subInterface.isMatchAnyInnerId()); + } + if(subInterface.isMatchAnyOuterId() != null) { + subIfcBuilder.setMatchAnyOuterId(subInterface.isMatchAnyOuterId()); + } + + subIfcBuilder.setIdentifier(subInterface.getIdentifier()); + subIfcBuilder.setInnerId(subInterface.getInnerId()); + subIfcBuilder.setNumberOfTags(subInterface.getNumberOfTags()); + subIfcBuilder.setOuterId(subInterface.getOuterId()); + subIfcBuilder.setSuperInterface(subInterface.getSuperInterface()); + subIfcBuilder.setVlanType(subInterface.getVlanType()); + + augmentBuilder.setSubInterface(subIfcBuilder.build()); + } + + private static void setEthernet(final VppInterfaceAugmentationBuilder augmentBuilder, final Ethernet ethernet) { + final EthernetBuilder ethernetBuilder = new EthernetBuilder(); + ethernetBuilder.setMtu(ethernet.getMtu()); + augmentBuilder.setEthernet(ethernetBuilder.build()); + } + + private static void setL2(final VppInterfaceAugmentationBuilder augmentBuilder, final L2 l2) { + final L2Builder l2Builder = new L2Builder(); + + final Interconnection interconnection = l2.getInterconnection(); + if(interconnection != null) { + if (interconnection instanceof XconnectBased) { + final XconnectBasedBuilder xconnectBasedBuilder = new XconnectBasedBuilder(); + xconnectBasedBuilder.setXconnectOutgoingInterface( + ((XconnectBased) interconnection).getXconnectOutgoingInterface()); + l2Builder.setInterconnection(xconnectBasedBuilder.build()); + } else if (interconnection instanceof BridgeBased) { + final BridgeBasedBuilder bridgeBasedBuilder = new BridgeBasedBuilder(); + bridgeBasedBuilder.setBridgeDomain(((BridgeBased) interconnection).getBridgeDomain()); + bridgeBasedBuilder + .setBridgedVirtualInterface(((BridgeBased) interconnection).isBridgedVirtualInterface()); + bridgeBasedBuilder.setSplitHorizonGroup(((BridgeBased) interconnection).getSplitHorizonGroup()); + l2Builder.setInterconnection(bridgeBasedBuilder.build()); + } + } + + final VlanTagRewrite vlanTagRewrite = l2.getVlanTagRewrite(); + if(vlanTagRewrite != null) { + final VlanTagRewriteBuilder vlanTagRewriteBuilder = new VlanTagRewriteBuilder(); + vlanTagRewriteBuilder.setFirstPushed(vlanTagRewrite.getFirstPushed()); + vlanTagRewriteBuilder.setRewriteOperation(vlanTagRewrite.getRewriteOperation()); + vlanTagRewriteBuilder.setTag1(vlanTagRewrite.getTag1()); + vlanTagRewriteBuilder.setTag2(vlanTagRewrite.getTag2()); + l2Builder.setVlanTagRewrite(vlanTagRewriteBuilder.build()); + } + + augmentBuilder.setL2(l2Builder.build()); + } + + private static void setVhostUser(final VppInterfaceAugmentationBuilder augmentBuilder, final VhostUser vhostUser) { + final VhostUserBuilder vhostUserBuilder = new VhostUserBuilder(); + vhostUserBuilder.setRole(vhostUser.getRole()); + vhostUserBuilder.setSocket(vhostUser.getSocket()); + augmentBuilder.setVhostUser(vhostUserBuilder.build()); + } + + private static void setTap( + final @Nonnull org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface input, + final VppInterfaceAugmentationBuilder augmentBuilder, + final Tap tap) { + final TapBuilder tapBuilder = new TapBuilder(); + tapBuilder.setMac(input.getPhysAddress()); + tapBuilder.setTapName(tap.getTapName()); +// tapBuilder.setDeviceInstance(); + augmentBuilder.setTap(tapBuilder.build()); + } + + private static void setVxlan(final VppInterfaceAugmentationBuilder augmentBuilder, final Vxlan vxlan) { + final VxlanBuilder vxlanBuilder = new VxlanBuilder(); + vxlanBuilder.setDst(vxlan.getDst()); + vxlanBuilder.setSrc(vxlan.getSrc()); + vxlanBuilder.setEncapVrfId(vxlan.getEncapVrfId()); + vxlanBuilder.setVni(new VxlanVni(vxlan.getVni())); + augmentBuilder.setVxlan(vxlanBuilder.build()); + } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java index e8d6e39c7..dd3a85628 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java @@ -55,6 +55,7 @@ public class EthernetCustomizer extends AbstractInterfaceTypeCustomizer * Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command. */ -public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer { +public class VlanTagRewriteCustomizer extends AbstractInterfaceTypeCustomizer { private static final Logger LOG = LoggerFactory.getLogger(VlanTagRewriteCustomizer.class); private final NamingContext interfaceContext; @@ -66,9 +67,13 @@ public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements Ch } @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final VlanTagRewrite dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException.CreateFailedException { + protected Class getExpectedInterfaceType() { + return SubInterface.class; + } + + @Override + protected void writeInterface(final InstanceIdentifier id, final VlanTagRewrite dataAfter, + final WriteContext writeContext) throws WriteFailedException.CreateFailedException { try { setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException e) { diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java index 8173b67ba..49a6fd630 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java @@ -16,8 +16,6 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump; - import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; @@ -45,21 +43,20 @@ public class EthernetCustomizer extends FutureJVppCustomizer private NamingContext interfaceContext; public EthernetCustomizer(@Nonnull final FutureJVpp jvpp, - final NamingContext interfaceContext) { + @Nonnull final NamingContext interfaceContext) { super(jvpp); this.interfaceContext = interfaceContext; } @Override - public void merge(@Nonnull Builder parentBuilder, - @Nonnull Ethernet readValue) { + public void merge(@Nonnull final Builder parentBuilder, + @Nonnull final Ethernet readValue) { ((VppInterfaceStateAugmentationBuilder) parentBuilder).setEthernet(readValue); } @Nonnull @Override - public EthernetBuilder getBuilder( - @Nonnull InstanceIdentifier id) { + public EthernetBuilder getBuilder(@Nonnull InstanceIdentifier id) { return new EthernetBuilder(); } @@ -72,7 +69,10 @@ public class EthernetCustomizer extends FutureJVppCustomizer final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); - builder.setMtu((int) iface.linkMtu); + if(iface.linkMtu != 0) { + builder.setMtu((int) iface.linkMtu); + } + switch (iface.linkDuplex) { case 1: builder.setDuplex(Ethernet.Duplex.Half); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java index ee66aef1f..bbcb4fdb9 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java @@ -230,6 +230,11 @@ public final class InterfaceUtils { final SwInterfaceDetails cachedDetails = checkNotNull(getCachedInterfaceDump(ctx).get(index), "Interface {} cannot be found in context", index); + return isInterfaceOfType(ifcType, cachedDetails); + } + + static boolean isInterfaceOfType(final Class ifcType, + final SwInterfaceDetails cachedDetails) { return ifcType.equals(getInterfaceType(V3poUtils.toString(cachedDetails.interfaceName))); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java index 1bc9c2b3a..f0d260de2 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java @@ -16,6 +16,8 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static com.google.common.base.Preconditions.checkState; + import com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; @@ -35,6 +37,7 @@ 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.openvpp.jvpp.dto.BridgeDomainDetails; import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; import org.openvpp.jvpp.dto.BridgeDomainDump; import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; @@ -83,12 +86,22 @@ public class L2Customizer extends FutureJVppCustomizer ifaceId, ctx.getModificationCache()); LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); - final Optional bdForInterface = getBridgeDomainForInterface(ifaceId); + final BridgeDomainDetailsReplyDump dumpReply = getDumpReply(); + final Optional bdForInterface = getBridgeDomainForInterface(ifaceId, dumpReply); if (bdForInterface.isPresent()) { final BridgeDomainSwIfDetails bdSwIfDetails = bdForInterface.get(); final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId, ctx.getMappingContext())); - // bbBuilder.setBridgedVirtualInterface // TODO where to find that value? + + // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index + final Optional bridgeDomainForInterface = + getBridgeDomainForInterface(ifaceId, dumpReply, bdForInterface.get().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) { + bbBuilder.setBridgedVirtualInterface(true); + } + if (bdSwIfDetails.shg != 0) { bbBuilder.setSplitHorizonGroup((short)bdSwIfDetails.shg); } @@ -98,7 +111,23 @@ public class L2Customizer extends FutureJVppCustomizer // TODO is there a way to check if interconnection is XconnectBased? } - private Optional getBridgeDomainForInterface(final int ifaceId) { + private Optional getBridgeDomainForInterface(final int ifaceId, + final BridgeDomainDetailsReplyDump reply) { + if (null == reply || null == reply.bridgeDomainSwIfDetails || reply.bridgeDomainSwIfDetails.isEmpty()) { + return Optional.empty(); + } + // interface can be added to only one BD only + return reply.bridgeDomainSwIfDetails.stream().filter(a -> a.swIfIndex == ifaceId).findFirst(); + } + + + private Optional getBridgeDomainForInterface(final int ifaceId, + final BridgeDomainDetailsReplyDump reply, + int bdId) { + return reply.bridgeDomainDetails.stream().filter(a -> a.bdId == bdId).findFirst(); + } + + private BridgeDomainDetailsReplyDump getDumpReply() { // We need to perform full bd dump, because there is no way // to ask VPP for BD details given interface id/name (TODO add it to vpp.api?) // TODO cache dump result @@ -107,13 +136,6 @@ public class L2Customizer extends FutureJVppCustomizer final CompletableFuture bdCompletableFuture = getFutureJVpp().bridgeDomainSwIfDump(request).toCompletableFuture(); - final BridgeDomainDetailsReplyDump reply = V3poUtils.getReply(bdCompletableFuture); - - if (null == reply || null == reply.bridgeDomainSwIfDetails || reply.bridgeDomainSwIfDetails.isEmpty()) { - return Optional.empty(); - } - - // interface can be added to only one BD only - return reply.bridgeDomainSwIfDetails.stream().filter(a -> a.swIfIndex == ifaceId).findFirst(); + return V3poUtils.getReply(bdCompletableFuture); } } 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 index d05e089a2..64abf6dc8 100644 --- 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 @@ -16,6 +16,8 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; + import com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; @@ -25,6 +27,7 @@ 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.SubInterface; 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; @@ -76,6 +79,11 @@ public class VlanTagRewriteCustomizer extends FutureJVppCustomizer final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); + // Tag rewrite is only possible for subinterfaces + if (!isInterfaceOfType(SubInterface.class, iface)) { + return; + } + builder.setFirstPushed(iface.subDot1Ad == 1 ? VlanType._802dot1q : VlanType._802dot1ad); builder.setRewriteOperation(TagRewriteOperation.forValue(iface.vtrOp)); if (iface.vtrTag1 != 0) { 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 index 39a9823b5..639257914 100644 --- 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 @@ -26,6 +26,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; +import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.MappingContext; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; @@ -39,7 +40,9 @@ 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.InterfaceBuilder; 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.SubInterface; 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; @@ -140,6 +143,9 @@ public class VlanTagRewriteCustomizerTest { final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); whenL2InterfaceVlanTagRewriteThenSuccess(); + // Vlan Tag rewrite is checking ifc type by reading its configuration from write context + doReturn(Optional.of(new InterfaceBuilder().setType(SubInterface.class).build())) + .when(writeContext).readAfter(any(InstanceIdentifier.class)); customizer.writeCurrentAttributes(id, vlanTagRewrite, writeContext); @@ -153,6 +159,9 @@ public class VlanTagRewriteCustomizerTest { final InstanceIdentifier id = getVlanTagRewriteId(VLAN_IF_NAME); whenL2InterfaceVlanTagRewriteThenFailure(); + // Vlan Tag rewrite is checking ifc type by reading its configuration from write context + doReturn(Optional.of(new InterfaceBuilder().setType(SubInterface.class).build())) + .when(writeContext).readAfter(any(InstanceIdentifier.class)); try { customizer.writeCurrentAttributes(id, vlanTagRewrite, writeContext); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java index b09381584..b4bf1e115 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java @@ -34,7 +34,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import org.junit.Test; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; @@ -52,6 +51,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.rev150105.interfaces.state._interface.l2.interconnection.BridgeBasedBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.openvpp.jvpp.dto.BridgeDomainDetails; import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; import org.openvpp.jvpp.dto.BridgeDomainDump; import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; @@ -91,15 +91,16 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest { VppInterfaceStateAugmentation.class).child(L2.class); } - private void whenBridgeDomainSwIfDumpThenReturn(final List bdSwIfList) + private void whenBridgeDomainSwIfDumpThenReturn(final List bdSwIfList, + final List bridgeDomainDetailses) throws ExecutionException, InterruptedException { - final CompletionStage replyCS = mock(CompletionStage.class); - final CompletableFuture replyFuture = mock(CompletableFuture.class); - when(replyCS.toCompletableFuture()).thenReturn(replyFuture); final BridgeDomainDetailsReplyDump reply = new BridgeDomainDetailsReplyDump(); reply.bridgeDomainSwIfDetails = bdSwIfList; - when(replyFuture.get()).thenReturn(reply); - when(api.bridgeDomainSwIfDump(any(BridgeDomainDump.class))).thenReturn(replyCS); + reply.bridgeDomainDetails = bridgeDomainDetailses; + + final CompletableFuture replyFuture = new CompletableFuture<>(); + replyFuture.complete(reply); + when(api.bridgeDomainSwIfDump(any(BridgeDomainDump.class))).thenReturn(replyFuture); } @@ -111,10 +112,14 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest { return bdSwIfDetails; } - private Interconnection generateInterconnection(final int ifId, final String bdName) { + private Interconnection generateInterconnection(final int ifId, final String bdName, final Boolean bvi) { final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); bbBuilder.setBridgeDomain(bdName); bbBuilder.setSplitHorizonGroup((short) 1); + // Empty type + if(bvi != null) { + bbBuilder.setBridgedVirtualInterface(bvi); + } return bbBuilder.build(); } @@ -143,11 +148,29 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest { cachedInterfaceDump.put(ifId, ifaceDetails); cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); - whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId))); + // BVI + whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId)), + Collections.singletonList(generateBdDetails(ifId, bdId))); - final L2Builder builder = mock(L2Builder.class); + L2Builder builder = mock(L2Builder.class); getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx); - verify(builder).setInterconnection(generateInterconnection(ifId, bdName)); + verify(builder).setInterconnection(generateInterconnection(ifId, bdName, true)); + + // Not BVI + whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId)), + Collections.singletonList(generateBdDetails(99 /* Different ifc is marked as BVI in bd details */, bdId))); + + builder = mock(L2Builder.class); + getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx); + + verify(builder).setInterconnection(generateInterconnection(ifId, bdName, null)); + } + + private BridgeDomainDetails generateBdDetails(final int ifId, final int bdId) { + final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails(); + bridgeDomainDetails.bviSwIfIndex = ifId; + bridgeDomainDetails.bdId = bdId; + return bridgeDomainDetails; } } \ 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 index d00745ec1..bd1e09c11 100644 --- 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 @@ -85,6 +85,7 @@ public class VlanTagRewriteCustomizerTest extends ChildReaderCustomizerTest