diff options
Diffstat (limited to 'samples/samples-impl/src/main/java/io/fd/hc2vpp/samples/read/VxlanReadCustomizer.java')
-rw-r--r-- | samples/samples-impl/src/main/java/io/fd/hc2vpp/samples/read/VxlanReadCustomizer.java | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/samples/samples-impl/src/main/java/io/fd/hc2vpp/samples/read/VxlanReadCustomizer.java b/samples/samples-impl/src/main/java/io/fd/hc2vpp/samples/read/VxlanReadCustomizer.java new file mode 100644 index 000000000..133155b6f --- /dev/null +++ b/samples/samples-impl/src/main/java/io/fd/hc2vpp/samples/read/VxlanReadCustomizer.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.hc2vpp.samples.read; + + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.fd.hc2vpp.common.translate.util.AddressTranslator; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev161214.sample.plugin.params.VxlansBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev161214.sample.plugin.params.vxlans.VxlanTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev161214.sample.plugin.params.vxlans.VxlanTunnelBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.sample.plugin.rev161214.sample.plugin.params.vxlans.VxlanTunnelKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + + +/** + * Reader for {@link VxlanTunnel} list node from our YANG model. + */ +public final class VxlanReadCustomizer implements + ListReaderCustomizer<VxlanTunnel, VxlanTunnelKey, VxlanTunnelBuilder>, + // provides utility methods to translate binary data + ByteDataTranslator, + // provides utility methods to translate Ipv4,Ipv6,Mac addresses. + // in case that just one address family processing is needed,use *address-family-name*Translator, + // for ex Ipv4Translator + AddressTranslator, + // provides utility methods to consume results of jvpp api calls + JvppReplyConsumer { + + // JVpp core. This is the Java API for VPP's core API. + private final FutureJVppCore jVppCore; + // Naming context for interfaces + // Honeycomb provides a "context" storage for plugins. This storage is used for storing metadata required during + // data translation (just like in this plugin). An example of such metadata would be interface identifier. In Honeycomb + // we use string names for interfaces, however VPP uses only indices (that are created automatically). + // This means that translation layer has to store the mapping between HC interface name <-> VPP' interface index. + // And since vxlan tunnel is a type of interface in VPP, the same applies here + // + // Honeycomb provides a couple utilities on top of context storage such as NamingContext. It is just a map + // backed by context storage that makes the lookup and storing easier. + private final NamingContext vxlanNamingContext; + + // Dump manager that provides intelligent caching based on provided contextual key + private DumpCacheManager<VxlanTunnelDetailsReplyDump, Integer> dumpManager; + + public VxlanReadCustomizer(final FutureJVppCore jVppCore, final NamingContext vxlanNamingContext) { + this.jVppCore = jVppCore; + this.vxlanNamingContext = vxlanNamingContext; + + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<VxlanTunnelDetailsReplyDump, Integer>() + // executor handles dumping of data itself, based on provided lambda + // instanceIdentifier - identifier of entity that we are caching, should be the one passed as parameter + // to getAllIds or readCurrentAttributes. Caching is by default performed based on this key + // param - can be anything that needs to be bind to request + .withExecutor((instanceIdentifier, param) -> { + // creates dump request + final VxlanTunnelDump vxlanTunnelDump = new VxlanTunnelDump(); + // binds parameters, in this case index of interface + vxlanTunnelDump.swIfIndex = param; + // perform dump action with default timeout and either return result or throw ReadFailedException + // identified by provided instanceIdentifier + return getReplyForRead(jVppCore.vxlanTunnelDump(vxlanTunnelDump).toCompletableFuture(), instanceIdentifier); + }) + // this provides type-awareness for caching, so multiple DumpManagers can be used withing the same + // customizer, using same instance identifiers, as long as they handle different data types + .acceptOnly(VxlanTunnelDetailsReplyDump.class) + + // either acceptOnly is required or custom cache key factory must be provided to tell manager, + // how to produce keys. can be used to change caching scope of data + //.withCacheKeyFactory() + + // serves as post-dump processing of any kind, triggered only once after calling executor + //.withPostProcessingFunction() + .build(); + } + + /** + * Provide a list of IDs for all VXLANs in VPP + */ + @Nonnull + @Override + public List<VxlanTunnelKey> getAllIds(@Nonnull final InstanceIdentifier<VxlanTunnel> id, + @Nonnull final ReadContext context) + throws ReadFailedException { + + final Optional<VxlanTunnelDetailsReplyDump> dump = dumpManager.getDump(id, context.getModificationCache(), 0); + + if (!dump.isPresent()) { + return Collections.emptyList(); + } + + return dump.get().vxlanTunnelDetails.stream() + // Need a name of an interface here. Use context to look it up from index + // In case the naming context does not contain such mapping, it creates an artificial one + .map(a -> new VxlanTunnelKey(vxlanNamingContext.getName(a.swIfIndex, context.getMappingContext()))) + .collect(Collectors.toList()); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<VxlanTunnel> readData) { + // Just set the readValue into parent builder + // The cast has to be performed here + ((VxlansBuilder) builder).setVxlanTunnel(readData); + } + + @Nonnull + @Override + public VxlanTunnelBuilder getBuilder(@Nonnull final InstanceIdentifier<VxlanTunnel> id) { + // Setting key from id is not necessary, builder will take care of that + return new VxlanTunnelBuilder(); + } + + /** + * Read all the attributes of a single VXLAN tunnel + */ + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanTunnel> id, + @Nonnull final VxlanTunnelBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + // The ID received here contains the name of a particular interface that should be read + // It was either requested directly by HC users or is one of the IDs from getAllIds that could have been invoked + // just before this method invocation + final String vxlanName = id.firstKeyOf(VxlanTunnel.class).getId(); + + // Naming context must contain the mapping because: + // 1. The vxlan tunnel was created in VPP using HC + this plugin meaning we stored the mapping in write customizer + // 2. The vxlan tunnel was already present in VPP, but HC reconciliation mechanism took care of that (as long as proper Initializer is provided by this plugin) + + final Optional<VxlanTunnelDetailsReplyDump> dump = dumpManager.getDump(id, ctx.getModificationCache(), + vxlanNamingContext.getIndex(vxlanName, ctx.getMappingContext())); + + + Preconditions.checkState(dump.isPresent() && dump.get().vxlanTunnelDetails != null); + final VxlanTunnelDetails singleVxlanDetail = dump.get().vxlanTunnelDetails.stream().findFirst().get(); + + // Now translate all attributes into provided builder + final Boolean isIpv6 = byteToBoolean(singleVxlanDetail.isIpv6); + builder.setSrc(arrayToIpAddress(isIpv6, singleVxlanDetail.srcAddress)); + builder.setDst(arrayToIpAddress(isIpv6, singleVxlanDetail.dstAddress)); + // There are additional attributes of a vxlan tunnel that wont be used here + } +}
\ No newline at end of file |