diff options
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.java | 104 |
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) { |