summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java')
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java104
1 files changed, 50 insertions, 54 deletions
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) {