HONEYCOMG-37 Enable ipv6 addresses for vxlan-tunnels 62/1062/4
authorMaros Marsalek <mmarsale@cisco.com>
Wed, 11 May 2016 09:01:08 +0000 (11:01 +0200)
committerMaros Marsalek <mmarsale@cisco.com>
Fri, 13 May 2016 06:59:33 +0000 (06:59 +0000)
+ Add logging to other interface type customizers

Change-Id: I177c0af26991c5f421b513f5fd9964ca1c23027e
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
v3po/api/src/main/yang/v3po.yang
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.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/TapCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java
vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java

index e346ae1..ca335aa 100644 (file)
@@ -191,15 +191,15 @@ module v3po {
       when "../if:type = 'v3po:vxlan-tunnel'";
 
       leaf src {
-        /* mandatory true; */
-        type inet:ipv4-address;
+        /*mandatory true;*/
+        type inet:ip-address;
       }
       leaf dst {
-        /* mandatory true; */
-        type inet:ipv4-address;
+        /*mandatory true;*/
+        type inet:ip-address;
       }
       leaf vni {
-        /* mandatory true; */
+        /*mandatory true;*/
         type vxlan-vni;
       }
       leaf encap-vrf-id {
@@ -338,11 +338,13 @@ module v3po {
       when "../if:type = 'v3po:vxlan-tunnel'";
 
       leaf src {
-        type inet:ipv4-address;
+        type inet:ip-address;
       }
       leaf dst {
-        type inet:ipv4-address;
+        type inet:ip-address;
       }
+
+
       leaf vni {
         type uint32;
       }
index b5ef6e0..2034a03 100644 (file)
@@ -16,6 +16,8 @@
 
 package io.fd.honeycomb.v3po.translate.v3po.interfaces;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.base.Optional;
 import com.google.common.net.InetAddresses;
 import io.fd.honeycomb.v3po.translate.Context;
@@ -28,6 +30,7 @@ import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
 import java.net.InetAddress;
 import java.util.concurrent.CompletionStage;
 import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 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.Vxlan;
@@ -94,15 +97,17 @@ public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriter
     }
 
     private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException {
-        final InetAddress srcAddress = InetAddresses.forString(vxlan.getSrc().getValue());
-        final InetAddress dstAddress = InetAddresses.forString(vxlan.getDst().getValue());
+        final byte isIpv6 = (byte) (isIpv6(vxlan) ? 1 : 0);
+        final InetAddress srcAddress = InetAddresses.forString(getAddressString(vxlan.getSrc()));
+        final InetAddress dstAddress = InetAddresses.forString(getAddressString(vxlan.getDst()));
+
         int encapVrfId = vxlan.getEncapVrfId().intValue();
         int vni = vxlan.getVni().getValue().intValue();
 
         LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
         final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
                 getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, srcAddress.getAddress(),
-                        dstAddress.getAddress(), encapVrfId, -1, vni, (byte) 0 /* is IPV6 */));
+                        dstAddress.getAddress(), encapVrfId, -1, vni, isIpv6));
 
         final VxlanAddDelTunnelReply reply =
                 V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture());
@@ -116,16 +121,36 @@ public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriter
         }
     }
 
+    private boolean isIpv6(final Vxlan vxlan) {
+        if (vxlan.getSrc().getIpv4Address() == null) {
+            checkArgument(vxlan.getDst().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s", vxlan.getSrc(),
+                vxlan.getDst());
+            return true;
+        } else {
+            checkArgument(vxlan.getDst().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s", vxlan.getSrc(),
+                vxlan.getDst());
+            return false;
+        }
+    }
+
+    private String getAddressString(final IpAddress addr) {
+        return addr.getIpv4Address() == null
+                ? addr.getIpv6Address().getValue()
+                : addr.getIpv4Address().getValue();
+    }
+
     private void deleteVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException {
-        final InetAddress srcAddress = InetAddresses.forString(vxlan.getSrc().getValue());
-        final InetAddress dstAddress = InetAddresses.forString(vxlan.getDst().getValue());
+        final byte isIpv6 = (byte) (isIpv6(vxlan) ? 1 : 0);
+        final InetAddress srcAddress = InetAddresses.forString(getAddressString(vxlan.getSrc()));
+        final InetAddress dstAddress = InetAddresses.forString(getAddressString(vxlan.getDst()));
+
         int encapVrfId = vxlan.getEncapVrfId().intValue();
         int vni = vxlan.getVni().getValue().intValue();
 
         LOG.debug("Deleting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
         final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
                 getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 0 /* is add */, srcAddress.getAddress(),
-                        dstAddress.getAddress(), encapVrfId, -1, vni, (byte) 0 /* is IPV6 */));
+                        dstAddress.getAddress(), encapVrfId, -1, vni, isIpv6));
 
         final VxlanAddDelTunnelReply reply =
                 V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture());
@@ -139,8 +164,7 @@ public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriter
         }
     }
 
-
-    private VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final byte[] srcAddr, final byte[] dstAddr,
+    private static VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final byte[] srcAddr, final byte[] dstAddr,
                                                     final int encapVrfId,
                                                     final int decapNextIndex, final int vni, final byte isIpv6) {
         final VxlanAddDelTunnel vxlanAddDelTunnel = new VxlanAddDelTunnel();
index 3db497a..036018e 100644 (file)
 
 package io.fd.honeycomb.v3po.translate.v3po.interfacesstate;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
+import io.fd.honeycomb.v3po.translate.Context;
 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
 import java.math.BigInteger;
 import java.util.Map;
@@ -204,4 +207,11 @@ public final class InterfaceUtils {
 
         return EthernetCsmacd.class;
     }
+
+    static boolean isInterfaceOfType(final Context ctx, final int index,
+                                     final Class<? extends InterfaceType> ifcType) {
+        final SwInterfaceDetails cachedDetails = checkNotNull(InterfaceCustomizer.getCachedInterfaceDump(ctx).get(index),
+            "Interface {} cannot be found in context", index);
+        return ifcType.equals(getInterfaceType(V3poUtils.toString(cachedDetails.interfaceName)));
+    }
 }
index 1245f6a..e7cd560 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 io.fd.honeycomb.v3po.translate.Context;
 import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
 import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
@@ -51,22 +53,19 @@ public class TapCustomizer extends FutureJVppCustomizer
     public static final String DUMPED_TAPS_CONTEXT_KEY = TapCustomizer.class.getName() + "dumpedTapsDuringGetAllIds";
     private NamingContext interfaceContext;
 
-    public TapCustomizer(@Nonnull final FutureJVpp jvpp,
-                         final NamingContext interfaceContext) {
+    public TapCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
     }
 
     @Override
-    public void merge(@Nonnull Builder<? extends DataObject> parentBuilder,
-                      @Nonnull Tap readValue) {
+    public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull Tap readValue) {
         ((VppInterfaceStateAugmentationBuilder) parentBuilder).setTap(readValue);
     }
 
     @Nonnull
     @Override
-    public TapBuilder getBuilder(
-            @Nonnull InstanceIdentifier<Tap> id) {
+    public TapBuilder getBuilder(@Nonnull InstanceIdentifier<Tap> id) {
         return new TapBuilder();
     }
 
@@ -75,8 +74,14 @@ public class TapCustomizer extends FutureJVppCustomizer
                                       @Nonnull final TapBuilder builder,
                                       @Nonnull final Context ctx) throws ReadFailedException {
         final InterfaceKey key = id.firstKeyOf(Interface.class);
+        // Relying here that parent InterfaceCustomizer was invoked first (PREORDER)
+        // to fill in the context with initial ifc mapping
+        final int index = interfaceContext.getIndex(key.getName());
+        if (!isInterfaceOfType(ctx, index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap.class)) {
+            return;
+        }
 
-        // TODO add logging
+        LOG.debug("Reading attributes for tap interface: {}", key.getName());
 
         @SuppressWarnings("unchecked")
         Map<Integer, SwInterfaceTapDetails> mappedTaps =
@@ -102,14 +107,10 @@ public class TapCustomizer extends FutureJVppCustomizer
             ctx.put(DUMPED_TAPS_CONTEXT_KEY, mappedTaps);
         }
 
-        // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping
-        final int index = interfaceContext.getIndex(key.getName());
         final SwInterfaceTapDetails swInterfaceTapDetails = mappedTaps.get(index);
-        if(swInterfaceTapDetails == null) {
-            // Not a Tap interface type
-            return;
-        }
+        LOG.trace("Tap interface: {} attributes returned from VPP: {}", key.getName(), swInterfaceTapDetails);
 
         builder.setTapName(V3poUtils.toString(swInterfaceTapDetails.devName));
+        LOG.debug("Tap interface: {}, id: {} attributes read as: {}", key.getName(), index, builder);
     }
 }
index 4b9c7c8..70a6da1 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 io.fd.honeycomb.v3po.translate.Context;
 import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
 import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
@@ -53,22 +55,19 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
     public static final String DUMPED_VHOST_USERS_CONTEXT_KEY = VhostUserCustomizer.class.getName() + "dumpedVhostUsersDuringGetAllIds";
     private NamingContext interfaceContext;
 
-    public VhostUserCustomizer(@Nonnull final FutureJVpp jvpp,
-                               final NamingContext interfaceContext) {
+    public VhostUserCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
     }
 
     @Override
-    public void merge(@Nonnull Builder<? extends DataObject> parentBuilder,
-                      @Nonnull VhostUser readValue) {
+    public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull VhostUser readValue) {
         ((VppInterfaceStateAugmentationBuilder) parentBuilder).setVhostUser(readValue);
     }
 
     @Nonnull
     @Override
-    public VhostUserBuilder getBuilder(
-            @Nonnull InstanceIdentifier<VhostUser> id) {
+    public VhostUserBuilder getBuilder(@Nonnull InstanceIdentifier<VhostUser> id) {
         return new VhostUserBuilder();
     }
 
@@ -77,6 +76,14 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
                                       @Nonnull final VhostUserBuilder builder,
                                       @Nonnull final Context ctx) throws ReadFailedException {
         final InterfaceKey key = id.firstKeyOf(Interface.class);
+        // Relying here that parent InterfaceCustomizer was invoked first (PREORDER)
+        // to fill in the context with initial ifc mapping
+        final int index = interfaceContext.getIndex(key.getName());
+        if (!isInterfaceOfType(ctx, index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)) {
+            return;
+        }
+
+        LOG.debug("Reading attributes for vhpost user interface: {}", key.getName());
 
         @SuppressWarnings("unchecked")
         Map<Integer, SwInterfaceVhostUserDetails> mappedVhostUsers =
@@ -103,12 +110,8 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
         }
 
         // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping
-        final int index = interfaceContext.getIndex(key.getName());
         final SwInterfaceVhostUserDetails swInterfaceVhostUserDetails = mappedVhostUsers.get(index);
-        if(swInterfaceVhostUserDetails == null) {
-            // Not a VhostUser interface type
-            return;
-        }
+        LOG.trace("Vhost user interface: {} attributes returned from VPP: {}", key.getName(), swInterfaceVhostUserDetails);
 
         builder.setRole(swInterfaceVhostUserDetails.isServer == 1 ? VhostUserRole.Server : VhostUserRole.Client);
         builder.setFeatures(BigInteger.valueOf(swInterfaceVhostUserDetails.features));
@@ -116,6 +119,7 @@ public class VhostUserCustomizer extends FutureJVppCustomizer
         builder.setSocket(V3poUtils.toString(swInterfaceVhostUserDetails.sockFilename));
         builder.setVirtioNetHdrSize((long) swInterfaceVhostUserDetails.virtioNetHdrSz);
         builder.setConnectError(Integer.toString(swInterfaceVhostUserDetails.sockErrno));
-        // TODO add logging
+
+        LOG.debug("Vhost user interface: {}, id: {} attributes read as: {}", key.getName(), index, builder);
     }
 }
index 18bf01d..8294160 100644 (file)
@@ -16,6 +16,8 @@
 
 package io.fd.honeycomb.v3po.translate.v3po.interfacesstate;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import io.fd.honeycomb.v3po.translate.Context;
 import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
 import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
@@ -25,16 +27,15 @@ import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
 import java.util.concurrent.CompletionStage;
-import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
 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.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
 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.VxlanBuilder;
 import org.opendaylight.yangtools.concepts.Builder;
@@ -47,16 +48,13 @@ import org.openvpp.jvpp.future.FutureJVpp;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 public class VxlanCustomizer extends FutureJVppCustomizer
         implements ChildReaderCustomizer<Vxlan, VxlanBuilder> {
 
     private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class);
-    public static final String DUMPED_VXLANS_CONTEXT_KEY = VxlanCustomizer.class.getName() + "dumpedVxlansDuringGetAllIds";
     private NamingContext interfaceContext;
 
-    public VxlanCustomizer(@Nonnull final FutureJVpp jvpp,
-                           final NamingContext interfaceContext) {
+    public VxlanCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext) {
         super(jvpp);
         this.interfaceContext = interfaceContext;
     }
@@ -69,8 +67,7 @@ public class VxlanCustomizer extends FutureJVppCustomizer
 
     @Nonnull
     @Override
-    public VxlanBuilder getBuilder(
-            @Nonnull InstanceIdentifier<Vxlan> id) {
+    public VxlanBuilder getBuilder(@Nonnull InstanceIdentifier<Vxlan> id) {
         return new VxlanBuilder();
     }
 
@@ -79,61 +76,60 @@ public class VxlanCustomizer extends FutureJVppCustomizer
                                       @Nonnull final VxlanBuilder builder,
                                       @Nonnull final Context ctx) throws ReadFailedException {
         final InterfaceKey key = id.firstKeyOf(Interface.class);
-
-        // TODO add logging
-
-        // FIXME this should take different approach than Tap or Vhost customizers since vxlan dump allows
-        // to specify interface index, making it possible to dump just a single interface
-        // However we need to determine the type of current interface somehow to know it is vxlan type and we can perform
-        // the dump (InterfaceCustomizer can store the type in ctx)
-
-        @SuppressWarnings("unchecked")
-        Map<Integer, VxlanTunnelDetails> mappedVxlans =
-            (Map<Integer, VxlanTunnelDetails>) ctx.get(DUMPED_VXLANS_CONTEXT_KEY);
-
-        if(mappedVxlans == null) {
-            // Full Vxlan dump has to be performed here, no filter or anything is here to help so at least we cache it
-            final VxlanTunnelDump request = new VxlanTunnelDump();
-            request.swIfIndex = -1;
-
-            final CompletionStage<VxlanTunnelDetailsReplyDump> swInterfaceVxlanDetailsReplyDumpCompletionStage =
-                getFutureJVpp().vxlanTunnelDump(request);
-            final VxlanTunnelDetailsReplyDump reply =
-                V3poUtils.getReply(swInterfaceVxlanDetailsReplyDumpCompletionStage.toCompletableFuture());
-
-            if(null == reply || null == reply.vxlanTunnelDetails) {
-                mappedVxlans = Collections.emptyMap();
-            } else {
-                final List<VxlanTunnelDetails> swInterfaceVxlanDetails = reply.vxlanTunnelDetails;
-                // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes
-                mappedVxlans = swInterfaceVxlanDetails.stream()
-                    .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails));
-            }
-
-            ctx.put(DUMPED_VXLANS_CONTEXT_KEY, mappedVxlans);
+        // Relying here that parent InterfaceCustomizer was invoked first (PREORDER)
+        // to fill in the context with initial ifc mapping
+        final int index = interfaceContext.getIndex(key.getName());
+        if (!InterfaceUtils.isInterfaceOfType(ctx, index, VxlanTunnel.class)) {
+            return;
         }
 
-        // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping
-        final int index = interfaceContext.getIndex(key.getName());
-        final VxlanTunnelDetails swInterfaceVxlanDetails = mappedVxlans.get(index);
-        if(swInterfaceVxlanDetails == null) {
-            // Not a Vxlan interface type
+        LOG.debug("Reading attributes for vxlan tunnel: {}", key.getName());
+        // Dump just a single
+        final VxlanTunnelDump request = new VxlanTunnelDump();
+        request.swIfIndex = index;
+
+        final CompletionStage<VxlanTunnelDetailsReplyDump> swInterfaceVxlanDetailsReplyDumpCompletionStage =
+            getFutureJVpp().vxlanTunnelDump(request);
+        final VxlanTunnelDetailsReplyDump reply =
+            V3poUtils.getReply(swInterfaceVxlanDetailsReplyDumpCompletionStage.toCompletableFuture());
+
+        // VPP keeps vxlan tunnel interfaces even after they were deleted (optimization)
+        // However there ar no longer any vxlan tunnel specific fields assigned to it and this call
+        // returns nothing
+        if (reply == null || reply.vxlanTunnelDetails == null || reply.vxlanTunnelDetails.isEmpty()) {
+            LOG.debug(
+                "Vxlan tunnel {}, id {} has no attributes assigned in VPP. Probably is a leftover interface placeholder" +
+                    "after delete", key.getName(), index);
             return;
         }
 
-        if(swInterfaceVxlanDetails.isIpv6 == 1) {
-            // FIXME enable ipv6 in the vxlan model
-//            builder.setDst(new Ipv6Address(parseAddress(swInterfaceVxlanDetails.dstAddress).getHostAddress()));
-//            builder.setSrc(new Ipv6Address(parseAddress(swInterfaceVxlanDetails.srcAddress).getHostAddress()));
+        checkState(reply.vxlanTunnelDetails.size() == 1,
+            "Unexpected number of returned vxlan tunnels: {} for tunnel: {}", reply.vxlanTunnelDetails, key.getName());
+        LOG.trace("Vxlan tunnel: {} attributes returned from VPP: {}", key.getName(), reply);
+
+        final VxlanTunnelDetails swInterfaceVxlanDetails = reply.vxlanTunnelDetails.get(0);
+        if (swInterfaceVxlanDetails.isIpv6 == 1) {
+            final Ipv6Address dstIpv6 =
+                new Ipv6Address(parseAddress(swInterfaceVxlanDetails.dstAddress).getHostAddress());
+            builder.setDst(new IpAddress(dstIpv6));
+            final Ipv6Address srcIpv6 =
+                new Ipv6Address(parseAddress(swInterfaceVxlanDetails.srcAddress).getHostAddress());
+            builder.setSrc(new IpAddress(srcIpv6));
         } else {
-            builder.setDst(new Ipv4Address(parseAddress(Arrays.copyOfRange(swInterfaceVxlanDetails.dstAddress, 0, 4)).getHostAddress()));
-            builder.setSrc(new Ipv4Address(parseAddress(Arrays.copyOfRange(swInterfaceVxlanDetails.srcAddress, 0, 4)).getHostAddress()));
+            final byte[] dstBytes = Arrays.copyOfRange(swInterfaceVxlanDetails.dstAddress, 0, 4);
+            final Ipv4Address dstIpv4 = new Ipv4Address(parseAddress(dstBytes).getHostAddress());
+            builder.setDst(new IpAddress(dstIpv4));
+            final byte[] srcBytes = Arrays.copyOfRange(swInterfaceVxlanDetails.srcAddress, 0, 4);
+            final Ipv4Address srcIpv4 = new Ipv4Address(parseAddress(srcBytes).getHostAddress());
+            builder.setSrc(new IpAddress(srcIpv4));
         }
         builder.setEncapVrfId((long) swInterfaceVxlanDetails.encapVrfId);
         builder.setVni((long) swInterfaceVxlanDetails.vni);
+        LOG.debug("Vxlan tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder);
     }
 
-    private InetAddress parseAddress(final byte[] addr) {
+    @Nonnull
+    private static InetAddress parseAddress(@Nonnull final byte[] addr) {
         try {
             return InetAddress.getByAddress(addr);
         } catch (UnknownHostException e) {
index 2f1a9e6..a599d75 100644 (file)
@@ -40,6 +40,7 @@ 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.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -104,8 +105,8 @@ public class VxlanCustomizerTest {
         final VxlanAddDelTunnel actual = argumentCaptor.getValue();
         assertEquals(0, actual.isIpv6);
         assertEquals(-1, actual.decapNextIndex);
-        assertArrayEquals(InetAddresses.forString(vxlan.getSrc().getValue()).getAddress(), actual.srcAddress);
-        assertArrayEquals(InetAddresses.forString(vxlan.getDst().getValue()).getAddress(), actual.dstAddress);
+        assertArrayEquals(InetAddresses.forString(vxlan.getSrc().getIpv4Address().getValue()).getAddress(), actual.srcAddress);
+        assertArrayEquals(InetAddresses.forString(vxlan.getDst().getIpv4Address().getValue()).getAddress(), actual.dstAddress);
         assertEquals(vxlan.getEncapVrfId().intValue(), actual.encapVrfId);
         assertEquals(vxlan.getVni().getValue().intValue(), actual.vni);
         return actual;
@@ -122,8 +123,8 @@ public class VxlanCustomizerTest {
 
     private static Vxlan generateVxlan(long vni) {
         final VxlanBuilder builder = new VxlanBuilder();
-        builder.setSrc(new Ipv4Address("192.168.20.10"));
-        builder.setDst(new Ipv4Address("192.168.20.11"));
+        builder.setSrc(new IpAddress(new Ipv4Address("192.168.20.10")));
+        builder.setDst(new IpAddress(new Ipv4Address("192.168.20.11")));
         builder.setEncapVrfId(Long.valueOf(123));
         builder.setVni(new VxlanVni(Long.valueOf(vni)));
         return builder.build();
index c23f0f6..3e5a840 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
 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;
@@ -189,8 +190,8 @@ final class VppModifier {
 
     private Vxlan prepareVxlan(final Ipv4AddressNoZone ipSrc, final Ipv4AddressNoZone ipDst) {
         final VxlanBuilder vxlanBuilder = new VxlanBuilder();
-        vxlanBuilder.setSrc(ipSrc);
-        vxlanBuilder.setDst(ipDst);
+        vxlanBuilder.setSrc(new IpAddress(ipSrc));
+        vxlanBuilder.setDst(new IpAddress(ipDst));
         final TunnelParameters tunnelParameters = config.getTunnelParameters();
         if (tunnelParameters instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.tunnel.parameters.Vxlan) {
             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.tunnel.parameters.Vxlan vxlan =