HONEYCOMB-61: Extend VPP initializers to initialize everything readers provide
authorMaros Marsalek <[email protected]>
Fri, 20 May 2016 07:51:30 +0000 (09:51 +0200)
committerMaros Marsalek <[email protected]>
Tue, 24 May 2016 08:36:45 +0000 (08:36 +0000)
Change-Id: Ic7c82f4abfb3bd1bb5065fdfc9c080ed3ba6c94c
Signed-off-by: Maros Marsalek <[email protected]>
v3po/features/src/main/features/features.xml
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java

index 1e5f28f..98fc17a 100644 (file)
@@ -32,6 +32,7 @@
   <feature name='odl-v3po' version='${project.version}' description='OpenDaylight :: v3po'>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${project.version}'>odl-v3po-api</feature>
+    <!-- FIXME remove netconf-connector-ssh from features, only netconf northbound is needed -->
     <feature version='${netconf.version}'>odl-netconf-connector-ssh</feature>
     <feature version='${mdsal.version}'>odl-netconf-mdsal</feature>
     <bundle>mvn:io.fd.honeycomb.v3po/v3po-impl/${project.version}</bundle>
index 0b5cef4..faaf063 100644 (file)
 
 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<InterfacesS
     protected Interfaces convert(final InterfacesState operationalData) {
         LOG.debug("InterfacesInitializer.convert()");
         InterfacesBuilder interfacesBuilder = new InterfacesBuilder();
-        interfacesBuilder.setInterface(Lists.transform(operationalData.getInterface(), CONVERT_INTERFACE));
+        interfacesBuilder
+            .setInterface(Lists.transform(operationalData.getInterface(), InterfacesInitializer::initialize));
         return interfacesBuilder.build();
     }
 
-    private static final Function<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface, Interface>
-            CONVERT_INTERFACE =
-            new Function<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface, Interface>() {
-                @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());
+    }
 }
index e8d6e39..dd3a856 100644 (file)
@@ -55,6 +55,7 @@ public class EthernetCustomizer extends AbstractInterfaceTypeCustomizer<Ethernet
                                        @Nonnull final Ethernet dataAfter, @Nonnull final WriteContext writeContext) {
         // TODO
         LOG.warn("Unsupported, ignoring configuration {}", dataAfter);
+        // VPP API does not support setting MTU
     }
 
     @Override
index d1e55a0..9292a2f 100644 (file)
@@ -18,8 +18,7 @@ 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.AbstractInterfaceTypeCustomizer;
 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;
@@ -27,7 +26,9 @@ 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.InterfaceType;
 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.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;
@@ -47,7 +48,7 @@ import org.slf4j.LoggerFactory;
  * Sends {@code l2_interface_vlan_tag_rewrite} message to VPP.<br>
  * Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command.
  */
-public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<VlanTagRewrite> {
+public class VlanTagRewriteCustomizer extends AbstractInterfaceTypeCustomizer<VlanTagRewrite> {
 
     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<VlanTagRewrite> id,
-                                       @Nonnull final VlanTagRewrite dataAfter, @Nonnull final WriteContext writeContext)
-            throws WriteFailedException.CreateFailedException {
+    protected Class<? extends InterfaceType> getExpectedInterfaceType() {
+        return SubInterface.class;
+    }
+
+    @Override
+    protected void writeInterface(final InstanceIdentifier<VlanTagRewrite> id, final VlanTagRewrite dataAfter,
+                                  final WriteContext writeContext) throws WriteFailedException.CreateFailedException {
         try {
             setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext);
         } catch (VppApiInvocationException e) {
index 8173b67..49a6fd6 100644 (file)
@@ -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<? extends DataObject> parentBuilder,
-                      @Nonnull Ethernet readValue) {
+    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder,
+                      @Nonnull final Ethernet readValue) {
         ((VppInterfaceStateAugmentationBuilder) parentBuilder).setEthernet(readValue);
     }
 
     @Nonnull
     @Override
-    public EthernetBuilder getBuilder(
-            @Nonnull InstanceIdentifier<Ethernet> id) {
+    public EthernetBuilder getBuilder(@Nonnull InstanceIdentifier<Ethernet> 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);
index ee66aef..bbcb4fd 100644 (file)
@@ -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<? extends InterfaceType> ifcType,
+                                     final SwInterfaceDetails cachedDetails) {
         return ifcType.equals(getInterfaceType(V3poUtils.toString(cachedDetails.interfaceName)));
     }
 }
index 1bc9c2b..f0d260d 100644 (file)
@@ -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<BridgeDomainSwIfDetails> bdForInterface = getBridgeDomainForInterface(ifaceId);
+        final BridgeDomainDetailsReplyDump dumpReply = getDumpReply();
+        final Optional<BridgeDomainSwIfDetails> 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<BridgeDomainDetails> 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<BridgeDomainSwIfDetails> getBridgeDomainForInterface(final int ifaceId) {
+    private Optional<BridgeDomainSwIfDetails> 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<BridgeDomainDetails> 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<BridgeDomainDetailsReplyDump> 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);
     }
 }
index d05e089..64abf6d 100644 (file)
@@ -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) {
index 39a9823..6392579 100644 (file)
@@ -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<VlanTagRewrite> 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<VlanTagRewrite> 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);
index b093815..b4bf1e1 100644 (file)
@@ -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<L2, L2Builder> {
                         VppInterfaceStateAugmentation.class).child(L2.class);
     }
 
-    private void whenBridgeDomainSwIfDumpThenReturn(final List<BridgeDomainSwIfDetails> bdSwIfList)
+    private void whenBridgeDomainSwIfDumpThenReturn(final List<BridgeDomainSwIfDetails> bdSwIfList,
+                                                    final List<BridgeDomainDetails> bridgeDomainDetailses)
             throws ExecutionException, InterruptedException {
-        final CompletionStage<BridgeDomainDetailsReplyDump> replyCS = mock(CompletionStage.class);
-        final CompletableFuture<BridgeDomainDetailsReplyDump> 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<BridgeDomainDetailsReplyDump> replyFuture = new CompletableFuture<>();
+        replyFuture.complete(reply);
+        when(api.bridgeDomainSwIfDump(any(BridgeDomainDump.class))).thenReturn(replyFuture);
     }
 
 
@@ -111,10 +112,14 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest<L2, L2Builder> {
         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<L2, L2Builder> {
         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
index d00745e..bd1e09c 100644 (file)
@@ -85,6 +85,7 @@ public class VlanTagRewriteCustomizerTest extends ChildReaderCustomizerTest<Vlan
 
         final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
         ifaceDetails.subId = ifId;
+        ifaceDetails.interfaceName = ifName.getBytes();
         cachedInterfaceDump.put(ifId, ifaceDetails);
         cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);