summaryrefslogtreecommitdiffstats
path: root/nsh/impl
diff options
context:
space:
mode:
authorHongjun Ni <hongjun.ni@intel.com>2016-09-02 22:18:43 +0800
committerMaros Marsalek <mmarsale@cisco.com>2016-09-12 07:39:41 +0000
commitf1a1a73f83f0652a3038de96cb8121f7ddc80e87 (patch)
treef5891e616d6518f9ffbfb5d46fdea0ebacb1e0bc /nsh/impl
parent4c80caaa0a39b52b693fda5165ca4ac3d96e2b2a (diff)
HONEYCOMB-46: Add NSH_SFC Feature in Honeycomb
PatchSet 9: Remove unused imports PatchSet 8: Fix interface DI broken PatchSet 7: Move VppNshModule to distribution PatchSet 2: Augment with encap-if-name for nsh-map Change-Id: Ia12afb72edfe804f26b84021b997d55db3129933 Signed-off-by: Hongjun Ni <hongjun.ni@intel.com>
Diffstat (limited to 'nsh/impl')
-rw-r--r--nsh/impl/pom.xml117
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/VppNshModule.java67
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/VppNshConfiguration.java41
-rw-r--r--nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/vppnsh.json3
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshEntryWriterCustomizer.java168
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshMapWriterCustomizer.java141
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/VppNshWriterFactory.java82
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/init/VppNshInitializer.java87
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshEntryReaderCustomizer.java215
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshMapReaderCustomizer.java185
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/VppNshReaderFactory.java85
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/FutureJVppNshCustomizer.java44
-rwxr-xr-xnsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/JVppNshProvider.java61
13 files changed, 1265 insertions, 31 deletions
diff --git a/nsh/impl/pom.xml b/nsh/impl/pom.xml
index 4fa591f1d..58730cf90 100644
--- a/nsh/impl/pom.xml
+++ b/nsh/impl/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015 Cisco and/or its affiliates.
+ Copyright (c) 2015 Intel 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:
@@ -13,37 +13,92 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <groupId>io.fd.honeycomb.common</groupId>
- <artifactId>impl-parent</artifactId>
- <version>1.16.9-SNAPSHOT</version>
- <relativePath>../../common/impl-parent</relativePath>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <groupId>io.fd.honeycomb.v3po</groupId>
- <artifactId>nsh-impl</artifactId>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>impl-parent</artifactId>
<version>1.16.9-SNAPSHOT</version>
- <packaging>bundle</packaging>
+ <relativePath>../../common/impl-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.fd.honeycomb.vppnsh</groupId>
+ <artifactId>vppnsh-impl</artifactId>
+ <version>1.16.9-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <guice.version>4.1.0</guice.version>
+ <guice.config.version>1.2.0</guice.config.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vppnsh-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>nsh-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <version>${guice.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.jmob</groupId>
+ <artifactId>guice.conf</artifactId>
+ <version>${guice.config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ <version>${guice.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>notification-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>cfg-init</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.vpp</groupId>
+ <artifactId>jvpp-registry</artifactId>
+ <version>16.09-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.nsh_sfc</groupId>
+ <artifactId>nsh-sfc</artifactId>
+ <version>16.09-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb.vpp</groupId>
+ <artifactId>vpp-translate-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>minimal-distribution</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb.v3po</groupId>
+ <artifactId>v3po2vpp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
</project>
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/VppNshModule.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/VppNshModule.java
new file mode 100755
index 000000000..48f323394
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/VppNshModule.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.notification.ManagedNotificationProducer;
+import io.fd.honeycomb.vppnsh.impl.cfgattrs.VppNshConfiguration;
+import io.fd.honeycomb.vppnsh.impl.config.VppNshWriterFactory;
+import io.fd.honeycomb.vppnsh.impl.oper.VppNshReaderFactory;
+import io.fd.honeycomb.vppnsh.impl.init.VppNshInitializer;
+import io.fd.honeycomb.vppnsh.impl.util.JVppNshProvider;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import net.jmob.guice.conf.core.ConfigurationModule;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+
+/**
+ * This is some glue code necessary for Honeycomb distribution to pick up the plugin classes
+ */
+public final class VppNshModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ // These are plugin specific config attributes
+ install(ConfigurationModule.create());
+ requestInjection(VppNshConfiguration.class);
+
+ // Naming contexts
+ bind(NamingContext.class)
+ .annotatedWith(Names.named("nsh-entry-context"))
+ .toInstance(new NamingContext("nsh-entry-", "nsh-entry-context"));
+
+ bind(NamingContext.class)
+ .annotatedWith(Names.named("nsh-map-context"))
+ .toInstance(new NamingContext("nsh-map-", "nsh-map-context"));
+
+ // Bind to Plugin's JVPP.
+ bind(FutureJVppNsh.class).toProvider(JVppNshProvider.class).in(Singleton.class);
+
+ // Below are classes picked up by HC framework
+ Multibinder.newSetBinder(binder(), WriterFactory.class).addBinding().to(VppNshWriterFactory.class);
+ Multibinder.newSetBinder(binder(), ReaderFactory.class).addBinding().to(VppNshReaderFactory.class);
+ Multibinder.newSetBinder(binder(), DataTreeInitializer.class).addBinding().to(VppNshInitializer.class);
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/VppNshConfiguration.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/VppNshConfiguration.java
new file mode 100755
index 000000000..e6491509d
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/VppNshConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.cfgattrs;
+
+import com.google.common.base.MoreObjects;
+
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+@BindConfig(value = "vppnsh", syntax = Syntax.JSON)
+public class VppNshConfiguration {
+
+ public boolean isNshEnabled() {
+ return Boolean.valueOf(nshEnable);
+ }
+
+ @InjectConfig("nsh-enabled")
+ public String nshEnable;
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("nshEnable", nshEnable)
+ .toString();
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/vppnsh.json b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/vppnsh.json
new file mode 100644
index 000000000..f2fe985b9
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/vppnsh.json
@@ -0,0 +1,3 @@
+{
+ "nsh-enabled" : "false"
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshEntryWriterCustomizer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshEntryWriterCustomizer.java
new file mode 100755
index 000000000..d3c15ae88
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshEntryWriterCustomizer.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.config;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte;
+
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import javax.xml.bind.DatatypeConverter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NextProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1Augment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1AugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntryKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.nsh.dto.*;
+import org.openvpp.jvpp.nsh.callback.*;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import io.fd.honeycomb.vppnsh.impl.util.FutureJVppNshCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Writer customizer responsible for NshEntry create/delete.
+ */
+public class NshEntryWriterCustomizer extends FutureJVppNshCustomizer
+ implements ListWriterCustomizer<NshEntry, NshEntryKey> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NshEntryWriterCustomizer.class);
+ private final NamingContext nshEntryContext;
+
+ public NshEntryWriterCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh,
+ @Nonnull final NamingContext nshEntryContext) {
+ super(futureJVppNsh);
+ this.nshEntryContext = checkNotNull(nshEntryContext, "nshEntryContext should not be null");
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final NshEntry dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Creating nsh entry: iid={} dataAfter={}", id, dataAfter);
+ try {
+ final int newEntryIndex =
+ nshAddDelEntry(true, id, dataAfter, ~0 /* value not present */, writeContext.getMappingContext());
+
+ // Add nsh entry name <-> vpp index mapping to the naming context:
+ nshEntryContext.addName(newEntryIndex, dataAfter.getName(), writeContext.getMappingContext());
+ LOG.debug("Successfully created nsh entry(id={]): iid={} dataAfter={}", newEntryIndex, id, dataAfter);
+ } catch (VppBaseCallException e) {
+ throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final NshEntry dataBefore, @Nonnull final NshEntry dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ throw new UnsupportedOperationException("Nsh entry update is not supported");
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final NshEntry dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Removing nsh entry: iid={} dataBefore={}", id, dataBefore);
+ final String entryName = dataBefore.getName();
+ checkState(nshEntryContext.containsIndex(entryName, writeContext.getMappingContext()),
+ "Removing nsh entry {}, but index could not be found in the nsh entry context", entryName);
+
+ final int entryIndex = nshEntryContext.getIndex(entryName, writeContext.getMappingContext());
+ try {
+ nshAddDelEntry(false, id, dataBefore, entryIndex, writeContext.getMappingContext());
+
+ // Remove deleted interface from interface context:
+ nshEntryContext.removeName(dataBefore.getName(), writeContext.getMappingContext());
+ LOG.debug("Successfully removed nsh entry(id={]): iid={} dataAfter={}", entryIndex, id, dataBefore);
+ } catch (VppBaseCallException e) {
+ throw new WriteFailedException.DeleteFailedException(id, e);
+ }
+ }
+
+ private int nshAddDelEntry(final boolean isAdd, @Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final NshEntry entry, final int entryId, final MappingContext ctx)
+ throws VppBaseCallException, WriteTimeoutException {
+ final CompletionStage<NshAddDelEntryReply> createNshEntryReplyCompletionStage =
+ getFutureJVppNsh().nshAddDelEntry(getNshAddDelEntryRequest(isAdd, entryId, entry, ctx));
+
+ final NshAddDelEntryReply reply =
+ TranslateUtils.getReplyForWrite(createNshEntryReplyCompletionStage.toCompletableFuture(), id);
+ return reply.entryIndex;
+
+ }
+
+ private void getNshEntryMdType1Request(@Nonnull final NshEntry entry,
+ @Nonnull NshAddDelEntry request) {
+ final NshMdType1Augment nshMdType1Augment = entry.getAugmentation(NshMdType1Augment.class);
+ if (nshMdType1Augment != null) {
+ request.c1 = (int) nshMdType1Augment.getC1().longValue();
+ request.c2 = (int) nshMdType1Augment.getC2().longValue();
+ request.c3 = (int) nshMdType1Augment.getC3().longValue();
+ request.c4 = (int) nshMdType1Augment.getC4().longValue();
+ }
+ }
+
+ private NshAddDelEntry getNshAddDelEntryRequest(final boolean isAdd, final int entryIndex,
+ @Nonnull final NshEntry entry,
+ @Nonnull final MappingContext ctx) {
+ final NshAddDelEntry request = new NshAddDelEntry();
+ request.isAdd = booleanToByte(isAdd);
+
+ request.verOC = (byte) entry.getVersion().shortValue();
+ request.length = (byte) entry.getLength().intValue();
+ if (entry.getNextProtocol() == Ipv4.class)
+ request.nextProtocol = 1;
+ else if (entry.getNextProtocol() == Ipv6.class)
+ request.nextProtocol = 2;
+ else if (entry.getNextProtocol() == Ethernet.class)
+ request.nextProtocol = 3;
+ else
+ request.nextProtocol = 0;
+
+ if (entry.getMdType() == MdType1.class)
+ {
+ request.mdType = 1;
+ getNshEntryMdType1Request(entry, request);
+ }
+ else if (entry.getMdType() == MdType1.class)
+ request.mdType = 2;
+ else
+ request.mdType = 0;
+
+ request.nspNsi = (entry.getNsp().intValue()<<8) | entry.getNsi();
+
+ return request;
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshMapWriterCustomizer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshMapWriterCustomizer.java
new file mode 100755
index 000000000..f2757bd64
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshMapWriterCustomizer.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.config;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte;
+
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import javax.xml.bind.DatatypeConverter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.EncapType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.maps.NshMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.maps.NshMapKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.nsh.dto.*;
+import org.openvpp.jvpp.nsh.callback.*;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import io.fd.honeycomb.vppnsh.impl.util.FutureJVppNshCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Writer customizer responsible for NshMap create/delete.
+ */
+public class NshMapWriterCustomizer extends FutureJVppNshCustomizer
+ implements ListWriterCustomizer<NshMap, NshMapKey> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NshMapWriterCustomizer.class);
+ private final NamingContext nshMapContext;
+ private final NamingContext interfaceContext;
+
+ public NshMapWriterCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh,
+ @Nonnull final NamingContext nshMapContext,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppNsh);
+ this.nshMapContext = checkNotNull(nshMapContext, "nshMapContext should not be null");
+ this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final NshMap dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ LOG.debug("Creating nsh map: iid={} dataAfter={}", id, dataAfter);
+ try {
+ final int newMapIndex =
+ nshAddDelMap(true, id, dataAfter, ~0 /* value not present */, writeContext.getMappingContext());
+
+ // Add nsh map name <-> vpp index mapping to the naming context:
+ nshMapContext.addName(newMapIndex, dataAfter.getName(), writeContext.getMappingContext());
+ LOG.debug("Successfully created nsh map(id={]): iid={} dataAfter={}", newMapIndex, id, dataAfter);
+ } catch (VppBaseCallException e) {
+ throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final NshMap dataBefore, @Nonnull final NshMap dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ throw new UnsupportedOperationException("Nsh map update is not supported");
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final NshMap dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ LOG.debug("Removing nsh map: iid={} dataBefore={}", id, dataBefore);
+ final String mapName = dataBefore.getName();
+ checkState(nshMapContext.containsIndex(mapName, writeContext.getMappingContext()),
+ "Removing nsh map {}, but index could not be found in the nsh map context", mapName);
+
+ final int mapIndex = nshMapContext.getIndex(mapName, writeContext.getMappingContext());
+ try {
+ nshAddDelMap(false, id, dataBefore, mapIndex, writeContext.getMappingContext());
+
+ // Remove deleted interface from interface context:
+ nshMapContext.removeName(dataBefore.getName(), writeContext.getMappingContext());
+ LOG.debug("Successfully removed nsh map(id={]): iid={} dataAfter={}", mapIndex, id, dataBefore);
+ } catch (VppBaseCallException e) {
+ throw new WriteFailedException.DeleteFailedException(id, e);
+ }
+ }
+
+ private int nshAddDelMap(final boolean isAdd, @Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final NshMap map, final int mapId, final MappingContext ctx)
+ throws VppBaseCallException, WriteTimeoutException {
+ final CompletionStage<NshAddDelMapReply> createNshMapReplyCompletionStage =
+ getFutureJVppNsh().nshAddDelMap(getNshAddDelMapRequest(isAdd, mapId, map, ctx));
+
+ final NshAddDelMapReply reply =
+ TranslateUtils.getReplyForWrite(createNshMapReplyCompletionStage.toCompletableFuture(), id);
+ return reply.mapIndex;
+
+ }
+
+ private NshAddDelMap getNshAddDelMapRequest(final boolean isAdd, final int mapIndex,
+ @Nonnull final NshMap map,
+ @Nonnull final MappingContext ctx) {
+ final NshAddDelMap request = new NshAddDelMap();
+ request.isAdd = booleanToByte(isAdd);
+
+ request.nspNsi = (map.getNsp().intValue()<<8) | map.getNsi();
+ request.mappedNspNsi = (map.getMappedNsp().intValue()<<8) | map.getMappedNsi();
+
+ if (map.getEncapType() == VxlanGpe.class) {
+ request.nextNode = 2;
+ }
+
+ checkState(interfaceContext.containsIndex(map.getEncapIfName(), ctx),
+ "Mapping does not contains mapping for provider interface Name ".concat(map.getEncapIfName()));
+ request.swIfIndex = interfaceContext.getIndex(map.getEncapIfName(), ctx);
+
+ return request;
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/VppNshWriterFactory.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/VppNshWriterFactory.java
new file mode 100755
index 000000000..fbf37c368
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/VppNshWriterFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.config;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNsh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1Augment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType2Augment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.maps.NshMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+
+public class VppNshWriterFactory implements WriterFactory {
+
+ @Nonnull
+ private final FutureJVppNsh jvppNsh;
+ private final NamingContext nshEntryContext;
+ private final NamingContext nshMapContext;
+ private final NamingContext interfaceContext;
+
+ @Inject
+ public VppNshWriterFactory(@Nonnull final FutureJVppNsh jvppNsh,
+ @Named("nsh-entry-context") @Nonnull final NamingContext nshEntryContext,
+ @Named("nsh-map-context") @Nonnull final NamingContext nshMapContext,
+ @Named("interface-context") @Nonnull final NamingContext interfaceContext) {
+ this.jvppNsh = jvppNsh;
+ this.nshEntryContext = nshEntryContext;
+ this.nshMapContext = nshMapContext;
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ // WriterFactory is intended for registering Writers into HC framework
+ // Writers handle ONLY config (config "true") data coming from upper layers and propagate them into lower layer/device
+ // they are triggered when RESTCONF PUT/POST on config is invoked or when NETCONF edit-config + commit operation is executed
+
+ // VppNsh has no handlers
+ // NshEntries has no handlers
+ // NshEntry =
+ final InstanceIdentifier<NshEntries> nshEntriesId = InstanceIdentifier.create(VppNsh.class).child(NshEntries.class);
+ final InstanceIdentifier<NshEntry> nshEntryId = nshEntriesId.child(NshEntry.class);
+ registry.subtreeAdd(
+ Sets.newHashSet(
+ InstanceIdentifier.create(NshEntry.class).augmentation(NshMdType1Augment.class),
+ InstanceIdentifier.create(NshEntry.class).augmentation(NshMdType2Augment.class)),
+ new GenericListWriter<>(nshEntryId, new NshEntryWriterCustomizer(jvppNsh, nshEntryContext)));
+
+ // VppNsh has no handlers
+ // NshMaps has no handlers
+ // NshMap =
+ final InstanceIdentifier<NshMap> nshMapId =
+ InstanceIdentifier.create(VppNsh.class).child(NshMaps.class).child(NshMap.class);
+ registry.add(new GenericListWriter<>(nshMapId, new NshMapWriterCustomizer(jvppNsh, nshMapContext, interfaceContext)));
+
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/init/VppNshInitializer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/init/VppNshInitializer.java
new file mode 100755
index 000000000..ca13d8a19
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/init/VppNshInitializer.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.init;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.init.AbstractDataTreeConverter;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNsh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.NshMapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.maps.NshMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.maps.NshMapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is an initializer for VppNsh plugin. Its main goal is to revers-engineer configuration data (config "true")
+ * for Nsh model from operational data. In this case, we are trying to recreate Nsh container from NshsState
+ * container. Thanks to symmetrical nature of the model, it's pretty straightforward.
+ *
+ * This is very useful when the lower layer already contains some data that should be revers-engineer to config data
+ * in honeycomb in order to get HC and lower layer to sync... It makes life of upper layers much easier
+ *
+ * However it's not always possible to perform this task so the initializers are optional for plugins
+ */
+public class VppNshInitializer extends AbstractDataTreeConverter<VppNshState, VppNsh> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VppNshInitializer.class);
+ private static final InstanceIdentifier<VppNshState> OPER_ID = InstanceIdentifier.create(VppNshState.class);
+ private static final InstanceIdentifier<VppNsh> CFG_ID = InstanceIdentifier.create(VppNsh.class);
+
+ @Inject
+ public VppNshInitializer(@Named("honeycomb-initializer") final DataBroker bindingDataBroker) {
+ super(bindingDataBroker, OPER_ID, CFG_ID);
+ }
+
+ @Override
+ protected VppNsh convert(final VppNshState operationalData) {
+ // Just convert operational data into config data
+ // The operational data are queried from lower layer using readerCustomizers from this plugin
+
+ LOG.info("Initializing VppNsh config data from: {}", operationalData);
+
+ VppNshBuilder vppNshBuilder = new VppNshBuilder();
+
+ NshEntriesBuilder nshEntriesBuilder = new NshEntriesBuilder()
+ .setNshEntry(operationalData.getNshEntries().getNshEntry().stream()
+ .map(oper -> new NshEntryBuilder(oper).setName(oper.getName()).build())
+ .collect(Collectors.toList()));
+ vppNshBuilder.setNshEntries(nshEntriesBuilder.build());
+
+ NshMapsBuilder nshMapsBuilder = new NshMapsBuilder()
+ .setNshMap(operationalData.getNshMaps().getNshMap().stream()
+ .map(oper -> new NshMapBuilder(oper).setName(oper.getName()).build())
+ .collect(Collectors.toList()));
+ vppNshBuilder.setNshMaps(nshMapsBuilder.build());
+
+ return vppNshBuilder.build();
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshEntryReaderCustomizer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshEntryReaderCustomizer.java
new file mode 100755
index 000000000..53dff0b64
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshEntryReaderCustomizer.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.oper;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NextProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1StateAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1StateAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.entries.NshEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.entries.NshEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.entries.NshEntryKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.nsh.dto.NshEntryDump;
+import org.openvpp.jvpp.nsh.dto.NshAddDelEntry;
+import org.openvpp.jvpp.nsh.dto.NshEntryDetails;
+import org.openvpp.jvpp.nsh.dto.NshEntryDetailsReplyDump;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import io.fd.honeycomb.vppnsh.impl.util.FutureJVppNshCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Reader customizer responsible for nsh entry read.<br> to VPP.
+ */
+public class NshEntryReaderCustomizer extends FutureJVppNshCustomizer
+ implements ListReaderCustomizer<NshEntry, NshEntryKey, NshEntryBuilder> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NshEntryReaderCustomizer.class);
+ private final NamingContext nshEntryContext;
+
+ public NshEntryReaderCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh,
+ @Nonnull final NamingContext nshEntryContext) {
+ super(futureJVppNsh);
+ this.nshEntryContext = checkNotNull(nshEntryContext, "nshEntryContext should not be null");
+ }
+
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder,
+ @Nonnull final List<NshEntry> readData) {
+ ((NshEntriesBuilder) builder).setNshEntry(readData);
+ }
+
+ @Nonnull
+ @Override
+ public NshEntryBuilder getBuilder(@Nonnull final InstanceIdentifier<NshEntry> id) {
+ return new NshEntryBuilder();
+ }
+
+ private void setNshEntryMdType1Augment(@Nonnull final NshEntryBuilder builder,
+ @Nonnull NshEntryDetails nshEntryDetails) {
+ final NshMdType1StateAugmentBuilder augmentBuilder = new NshMdType1StateAugmentBuilder();
+ augmentBuilder.setC1((long)nshEntryDetails.c1);
+ augmentBuilder.setC2((long)nshEntryDetails.c2);
+ augmentBuilder.setC3((long)nshEntryDetails.c3);
+ augmentBuilder.setC4((long)nshEntryDetails.c4);
+
+ builder.addAugmentation(NshMdType1StateAugment.class, augmentBuilder.build());
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final NshEntryBuilder builder, @Nonnull final ReadContext ctx)
+ throws ReadFailedException {
+ LOG.debug("Reading attributes for nsh entry: {}", id);
+ try {
+ final NshEntryKey key = id.firstKeyOf(NshEntry.class);
+ checkArgument(key != null, "could not find NshEntry key in {}", id);
+ final NshEntryDump request = new NshEntryDump();
+
+ final String entryName = key.getName();
+ if (!nshEntryContext.containsIndex(entryName, ctx.getMappingContext())) {
+ LOG.debug("Could not find nsh entry {} in the naming context", entryName);
+ return;
+ }
+ request.entryIndex = nshEntryContext.getIndex(entryName, ctx.getMappingContext());
+
+ final CompletionStage<NshEntryDetailsReplyDump> nshEntryDetailsReplyDumpCompletionStage =
+ getFutureJVppNsh().nshEntryDump(request);
+ final NshEntryDetailsReplyDump reply =
+ TranslateUtils.getReplyForRead(nshEntryDetailsReplyDumpCompletionStage.toCompletableFuture(), id);
+
+ if (reply == null || reply.nshEntryDetails == null || reply.nshEntryDetails.isEmpty()) {
+ LOG.debug("Has no Nsh Entry {} in VPP. ", key.getName());
+ return;
+ }
+
+ LOG.trace("Nsh Entry : {} attributes returned from VPP: {}", key.getName(), reply);
+
+ final NshEntryDetails nshEntryDetails = reply.nshEntryDetails.get(0);
+ builder.setName(entryName);
+ builder.setKey(key);
+ builder.setVersion( (short) nshEntryDetails.verOC );
+ builder.setLength( (short) nshEntryDetails.length );
+
+ switch(nshEntryDetails.nextProtocol) {
+ case 1:
+ builder.setNextProtocol(Ipv4.class);
+ break;
+ case 2:
+ builder.setNextProtocol(Ipv6.class);
+ break;
+ case 3:
+ builder.setNextProtocol(Ethernet.class);
+ break;
+ default:
+ LOG.trace("Unsupported next protocol for nsh entry: {}", nshEntryDetails.nextProtocol);
+ return;
+ }
+
+ switch(nshEntryDetails.mdType) {
+ case 1:
+ {
+ builder.setMdType(MdType1.class);
+ setNshEntryMdType1Augment(builder, nshEntryDetails);
+ break;
+ }
+ case 2:
+ {
+ builder.setMdType(MdType1.class);
+ break;
+ }
+ default:
+ LOG.trace("Unsupported Mdtype for nsh entry: {}", nshEntryDetails.mdType);
+ return;
+ }
+
+ builder.setNsp( (long)((nshEntryDetails.nspNsi>>8) & 0xFFFFFF));
+ builder.setNsi( (short)(nshEntryDetails.nspNsi & 0xFF ));
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Attributes for nsh entry {} successfully read: {}", id, builder.build());
+ }
+ } catch (VppBaseCallException e) {
+ LOG.warn("Failed to readCurrentAttributes for: {}", id);
+ throw new ReadFailedException( id, e );
+ }
+ }
+
+ @Nonnull
+ @Override
+ public List<NshEntryKey> getAllIds(@Nonnull final InstanceIdentifier<NshEntry> id,
+ @Nonnull final ReadContext context) throws ReadFailedException {
+ LOG.debug("Reading list of keys for nsh entry: {}", id);
+
+ final NshEntryDump request = new NshEntryDump();
+ request.entryIndex = -1; // dump call
+
+ NshEntryDetailsReplyDump reply;
+ try {
+ reply = getFutureJVppNsh().nshEntryDump(request).toCompletableFuture().get();
+ } catch (Exception e) {
+ throw new IllegalStateException("Nsh Entry dump failed", e);
+ }
+
+ if (reply == null || reply.nshEntryDetails == null) {
+ return Collections.emptyList();
+ }
+
+ final int nIdsLength = reply.nshEntryDetails.size();
+ LOG.debug("vppstate.NshEntryCustomizer.getAllIds: nIds.length={}", nIdsLength);
+ if (nIdsLength == 0) {
+ return Collections.emptyList();
+ }
+
+ final List<NshEntryKey> allIds = new ArrayList<>(nIdsLength);
+ for (NshEntryDetails detail : reply.nshEntryDetails) {
+ final String nshName = nshEntryContext.getName(detail.entryIndex, context.getMappingContext());
+ LOG.debug("vppstate.NshEntryCustomizer.getAllIds: nName={}", nshName);
+ allIds.add(new NshEntryKey(nshName));
+ }
+
+ return allIds;
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshMapReaderCustomizer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshMapReaderCustomizer.java
new file mode 100755
index 000000000..7d6c64baf
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshMapReaderCustomizer.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.oper;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.EncapType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshMapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.maps.NshMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.maps.NshMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.maps.NshMapKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.nsh.dto.NshMapDump;
+import org.openvpp.jvpp.nsh.dto.NshMapDetails;
+import org.openvpp.jvpp.nsh.dto.NshMapDetailsReplyDump;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import io.fd.honeycomb.vppnsh.impl.util.FutureJVppNshCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Reader customizer responsible for nsh map read.<br> to VPP.
+ */
+public class NshMapReaderCustomizer extends FutureJVppNshCustomizer
+ implements ListReaderCustomizer<NshMap, NshMapKey, NshMapBuilder> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NshMapReaderCustomizer.class);
+ private final NamingContext nshMapContext;
+ private final NamingContext interfaceContext;
+
+ public NshMapReaderCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh,
+ @Nonnull final NamingContext nshMapContext,
+ @Nonnull final NamingContext interfaceContext) {
+ super(futureJVppNsh);
+ this.nshMapContext = checkNotNull(nshMapContext, "nshMapContext should not be null");
+ this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+ }
+
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder,
+ @Nonnull final List<NshMap> readData) {
+ ((NshMapsBuilder) builder).setNshMap(readData);
+ }
+
+ @Nonnull
+ @Override
+ public NshMapBuilder getBuilder(@Nonnull final InstanceIdentifier<NshMap> id) {
+ return new NshMapBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final NshMapBuilder builder, @Nonnull final ReadContext ctx)
+ throws ReadFailedException {
+ LOG.debug("Reading attributes for nsh map: {}", id);
+ try {
+ final NshMapKey key = id.firstKeyOf(NshMap.class);
+ checkArgument(key != null, "could not find NshMap key in {}", id);
+ final NshMapDump request = new NshMapDump();
+
+ final String mapName = key.getName();
+ if (!nshMapContext.containsIndex(mapName, ctx.getMappingContext())) {
+ LOG.debug("Could not find nsh map {} in the naming context", mapName);
+ return;
+ }
+ request.mapIndex = nshMapContext.getIndex(mapName, ctx.getMappingContext());
+
+ final CompletionStage<NshMapDetailsReplyDump> nshMapDetailsReplyDumpCompletionStage =
+ getFutureJVppNsh().nshMapDump(request);
+ final NshMapDetailsReplyDump reply =
+ TranslateUtils.getReplyForRead(nshMapDetailsReplyDumpCompletionStage.toCompletableFuture(), id);
+
+ if (reply == null || reply.nshMapDetails == null || reply.nshMapDetails.isEmpty()) {
+ LOG.debug("Has no Nsh Map {} in VPP. ", key.getName());
+ return;
+ }
+
+ LOG.trace("Nsh Map : {} attributes returned from VPP: {}", key.getName(), reply);
+
+ final NshMapDetails nshMapDetails = reply.nshMapDetails.get(0);
+ builder.setName(mapName);
+ builder.setKey(key);
+
+ builder.setNsp( (long)((nshMapDetails.nspNsi>>8) & 0xFFFFFF));
+ builder.setNsi( (short)(nshMapDetails.nspNsi & 0xFF ));
+
+ builder.setMappedNsp( (long)((nshMapDetails.mappedNspNsi>>8) & 0xFFFFFF));
+ builder.setMappedNsi( (short)(nshMapDetails.mappedNspNsi & 0xFF ));
+
+ switch(nshMapDetails.nextNode) {
+ case 2:
+ builder.setEncapType(VxlanGpe.class);
+ break;
+ default:
+ LOG.trace("Unsupported encap type for nsh map: {}", nshMapDetails.nextNode);
+ return;
+ }
+
+ checkState(interfaceContext.containsName(nshMapDetails.swIfIndex, ctx.getMappingContext()),
+ "Mapping does not contains mapping for provider interface Index ");
+ final String interfaceName = interfaceContext.getName(nshMapDetails.swIfIndex, ctx.getMappingContext());
+ builder.setEncapIfName(interfaceName);
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Attributes for nsh map {} successfully read: {}", id, builder.build());
+ }
+ } catch (VppBaseCallException e) {
+ LOG.warn("Failed to readCurrentAttributes for: {}", id);
+ throw new ReadFailedException( id, e );
+ }
+ }
+
+ @Nonnull
+ @Override
+ public List<NshMapKey> getAllIds(@Nonnull final InstanceIdentifier<NshMap> id,
+ @Nonnull final ReadContext context) throws ReadFailedException {
+ LOG.debug("Reading list of keys for nsh map: {}", id);
+
+ final NshMapDump request = new NshMapDump();
+ request.mapIndex = -1; // dump call
+
+ NshMapDetailsReplyDump reply;
+ try {
+ reply = getFutureJVppNsh().nshMapDump(request).toCompletableFuture().get();
+ } catch (Exception e) {
+ throw new IllegalStateException("Nsh Map dump failed", e);
+ }
+
+ if (reply == null || reply.nshMapDetails == null) {
+ return Collections.emptyList();
+ }
+
+ final int nIdsLength = reply.nshMapDetails.size();
+ LOG.debug("vppstate.NshMapCustomizer.getAllIds: nIds.length={}", nIdsLength);
+ if (nIdsLength == 0) {
+ return Collections.emptyList();
+ }
+
+ final List<NshMapKey> allIds = new ArrayList<>(nIdsLength);
+ for (NshMapDetails detail : reply.nshMapDetails) {
+ final String nshName = nshMapContext.getName(detail.mapIndex, context.getMappingContext());
+ LOG.debug("vppstate.NshMapCustomizer.getAllIds: nName={}", nshName);
+ allIds.add(new NshMapKey(nshName));
+ }
+
+ return allIds;
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/VppNshReaderFactory.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/VppNshReaderFactory.java
new file mode 100755
index 000000000..a7467c800
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/VppNshReaderFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.oper;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNsh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.VppNshStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.entries.NshEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.entries.NshEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.NshMapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.maps.NshMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.state.nsh.maps.NshMapBuilder;
+
+import io.fd.honeycomb.vppnsh.impl.oper.NshEntryReaderCustomizer;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppNshReaderFactory implements ReaderFactory {
+
+ private final FutureJVppNsh jvppNsh;
+ private final NamingContext nshEntryContext;
+ private final NamingContext nshMapContext;
+ private final NamingContext interfaceContext;
+
+ @Inject
+ public VppNshReaderFactory(final FutureJVppNsh jvppNsh,
+ @Named("nsh-entry-context") final NamingContext nshEntryContext,
+ @Named("nsh-map-context") final NamingContext nshMapContext,
+ @Named("interface-context") @Nonnull final NamingContext interfaceContext) {
+ this.jvppNsh = jvppNsh;
+ this.nshEntryContext = nshEntryContext;
+ this.nshMapContext = nshMapContext;
+ this.interfaceContext = interfaceContext;
+ }
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ // ReaderFactory is intended for registering Readers into HC framework
+ // Readers provide ONLY operational (config "false") data straight from underlying device/layer
+ // they are triggered when RESTCONF GET on operational is invoked or when NETCONF get operation is executed
+
+ // VppNshState(Structural)
+ final InstanceIdentifier<VppNshState> vppNshStateId = InstanceIdentifier.create(VppNshState.class);
+ registry.addStructuralReader(vppNshStateId, VppNshStateBuilder.class);
+
+ // NshENtries(Structural)
+ final InstanceIdentifier<NshEntries> nshEntriesId = vppNshStateId.child(NshEntries.class);
+ registry.addStructuralReader(nshEntriesId, NshEntriesBuilder.class);
+ // NshENtry
+ final InstanceIdentifier<NshEntry> nshEntryId = nshEntriesId.child(NshEntry.class);
+ registry.add(new GenericListReader<>(nshEntryId, new NshEntryReaderCustomizer(jvppNsh, nshEntryContext)));
+
+ // NshMaps(Structural)
+ final InstanceIdentifier<NshMaps> nshMapsId = vppNshStateId.child(NshMaps.class);
+ registry.addStructuralReader(nshMapsId, NshMapsBuilder.class);
+ // NshMap
+ final InstanceIdentifier<NshMap> nshMapId = nshMapsId.child(NshMap.class);
+ registry.add(new GenericListReader<>(nshMapId, new NshMapReaderCustomizer(jvppNsh, nshMapContext, interfaceContext)));
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/FutureJVppNshCustomizer.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/FutureJVppNshCustomizer.java
new file mode 100755
index 000000000..f25e33cc5
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/FutureJVppNshCustomizer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Intel 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.honeycomb.vppnsh.impl.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import javax.annotation.Nonnull;
+
+/**
+ * Abstract utility to hold the NshApi reference.
+ */
+@Beta
+public abstract class FutureJVppNshCustomizer {
+
+ private final FutureJVppNsh futureJVppNsh;
+
+ public FutureJVppNshCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh) {
+ this.futureJVppNsh = Preconditions.checkNotNull(futureJVppNsh, "futureJVppNsh should not be null");
+ }
+
+ /**
+ * Get NshApi reference
+ *
+ * @return NshApi reference
+ */
+ public FutureJVppNsh getFutureJVppNsh() {
+ return futureJVppNsh;
+ }
+}
diff --git a/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/JVppNshProvider.java b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/JVppNshProvider.java
new file mode 100755
index 000000000..130b499a6
--- /dev/null
+++ b/nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/JVppNshProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Intel and 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.honeycomb.vppnsh.impl.util;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import java.io.IOException;
+import org.openvpp.jvpp.JVppRegistry;
+import org.openvpp.jvpp.nsh.future.FutureJVppNsh;
+import org.openvpp.jvpp.nsh.future.FutureJVppNshFacade;
+import org.openvpp.jvpp.nsh.JVppNshImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides future API for jvpp-nsh plugin. Must be a singleton due to shutdown hook usage.
+ * Registers shutdown hook to free plugin's resources on shutdown.
+ */
+public final class JVppNshProvider extends ProviderTrait<FutureJVppNsh> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JVppNshProvider.class);
+
+ @Inject
+ private JVppRegistry registry;
+
+ @Override
+ protected FutureJVppNshFacade create() {
+ try {
+ final JVppNshImpl jVppNsh = new JVppNshImpl();
+ // Free jvpp-nsh plugin's resources on shutdown
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ LOG.info("Unloading jvpp-nsh plugin");
+ jVppNsh.close();
+ LOG.info("Successfully unloaded jvpp-nsh plugin");
+ }
+ });
+
+ LOG.info("Successfully loaded jvpp-nsh plugin");
+ return new FutureJVppNshFacade(registry, jVppNsh);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to open VPP management connection", e);
+ }
+ }
+}
+