diff options
author | Maros Marsalek <mmarsale@cisco.com> | 2016-05-11 11:01:08 +0200 |
---|---|---|
committer | Maros Marsalek <mmarsale@cisco.com> | 2016-05-13 06:59:33 +0000 |
commit | 11395c60f5c204a6c050c5d90c902c4fc5940537 (patch) | |
tree | a5d7261a1f187fd9d5b4c87ca06aeaf2bf734795 | |
parent | 65e93b3426fcc61ee821c3674b51f8365721abeb (diff) |
HONEYCOMG-37 Enable ipv6 addresses for vxlan-tunnels
+ Add logging to other interface type customizers
Change-Id: I177c0af26991c5f421b513f5fd9964ca1c23027e
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
8 files changed, 139 insertions, 100 deletions
diff --git a/v3po/api/src/main/yang/v3po.yang b/v3po/api/src/main/yang/v3po.yang index e346ae144..ca335aa1c 100644 --- a/v3po/api/src/main/yang/v3po.yang +++ b/v3po/api/src/main/yang/v3po.yang @@ -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; } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java index b5ef6e010..2034a0301 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java @@ -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(); 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 3db497a5c..036018e88 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 @@ -16,8 +16,11 @@ 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))); + } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java index 1245f6a53..e7cd560bb 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.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 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); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java index 4b9c7c8bc..70a6da1cc 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.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 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); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java index 18bf01d6c..829416034 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java @@ -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) { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java index 2f1a9e606..a599d7565 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java @@ -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(); diff --git a/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java b/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java index c23f0f6ef..3e5a84068 100644 --- a/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java +++ b/vbd/impl/src/main/java/io/fd/honeycomb/vbd/impl/VppModifier.java @@ -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 = |