HONEYCOMB-46: Add NSH_SFC Feature in Honeycomb
authorHongjun Ni <[email protected]>
Fri, 2 Sep 2016 14:18:43 +0000 (22:18 +0800)
committerHongjun Ni <[email protected]>
Wed, 14 Sep 2016 02:35:12 +0000 (02:35 +0000)
Cherry pick to master

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 <[email protected]>
18 files changed:
nsh/api/pom.xml
nsh/api/src/main/yang/vpp-nsh.yang
nsh/impl/pom.xml
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/VppNshModule.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/VppNshConfiguration.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/cfgattrs/vppnsh.json [new file with mode: 0644]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshEntryWriterCustomizer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/NshMapWriterCustomizer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/config/VppNshWriterFactory.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/init/VppNshInitializer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshEntryReaderCustomizer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/NshMapReaderCustomizer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/oper/VppNshReaderFactory.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/FutureJVppNshCustomizer.java [new file with mode: 0755]
nsh/impl/src/main/java/io/fd/honeycomb/vppnsh/impl/util/JVppNshProvider.java [new file with mode: 0755]
nsh/pom.xml
vpp-integration/minimal-distribution/pom.xml
vpp-integration/minimal-distribution/src/main/java/io/fd/honeycomb/vpp/integration/distro/Main.java

index 94c6e77..07684b1 100644 (file)
@@ -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:
@@ -23,8 +23,8 @@
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
-  <groupId>io.fd.honeycomb.v3po</groupId>
-  <artifactId>nsh-api</artifactId>
+  <groupId>io.fd.honeycomb.vppnsh</groupId>
+  <artifactId>vppnsh-api</artifactId>
   <version>1.16.12-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
@@ -50,7 +50,7 @@
       <artifactId>yang-ext</artifactId>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
+      <groupId>io.fd.honeycomb.v3po</groupId>
       <artifactId>v3po-api</artifactId>
       <version>${project.version}</version>
     </dependency>
index 50dfe8e..47565ce 100644 (file)
@@ -66,12 +66,12 @@ module vpp-nsh {
     description "encap type";
   }
 
-  identity vxlan-gpe-encap-type {
+  identity vxlan-gpe {
     base "encap-type";
     description "vxlan-gpe encap type";
   }
 
-  identity vxlan-encap-type {
+  identity vxlan {
     base "encap-type";
     description "vxlan encap type";
   }
@@ -121,7 +121,9 @@ module vpp-nsh {
   }
 
   grouping nsh-md-type2-attributes {
-
+      leaf type {
+      type uint32;
+    }
   }
 
   grouping nsh-entry-base-attributes {
@@ -181,9 +183,13 @@ module vpp-nsh {
     leaf encap-type {
       type nsh-encap-type;
     }
+    leaf encap-if-name {
+      type string;
+      description "Interface Name";
+    }
   }
 
-  container nsh {
+  container vpp-nsh {
     description
     "NSH config data";
 
@@ -210,31 +216,19 @@ module vpp-nsh {
     }
   }
 
-  augment /nsh/nsh-entries/nsh-entry {
-    ext:augment-identifier nsh-entry-md-type-augment;
+  augment /vpp-nsh/nsh-entries/nsh-entry {
+    ext:augment-identifier nsh-md-type-1-augment;
     when "/md-type = 'vpp-nsh:md-type1' ";
     uses nsh-md-type1-attributes;
   }
 
-  augment /nsh/nsh-entries/nsh-entry {
-    ext:augment-identifier nsh-entry-md-type-augment;
+  augment /vpp-nsh/nsh-entries/nsh-entry {
+    ext:augment-identifier nsh-md-type-2-augment;
     when "/md-type = 'vpp-nsh:md-type2' ";
     uses nsh-md-type2-attributes;
   }
 
-  augment /nsh/nsh-maps/nsh-map {
-    ext:augment-identifier nsh-vxlan-gpe-encap-augment;
-    when "/encap-type = 'vpp-nsh:vxlan-gpe-encap-type' ";
-    uses v3po:vxlan-gpe-base-attributes;
-  }
-
-  augment /nsh/nsh-maps/nsh-map {
-    ext:augment-identifier vxlan-encap-augment;
-    when "/encap-type = 'vpp-nsh:vxlan-encap-type' ";
-    uses v3po:vxlan-base-attributes;
-  }
-
-  container nsh-state {
+  container vpp-nsh-state {
     config false;
 
     description
@@ -262,4 +256,16 @@ module vpp-nsh {
       }
     }
   }
+
+  augment /vpp-nsh-state/nsh-entries/nsh-entry {
+    ext:augment-identifier nsh-md-type-1-state-augment;
+    when "/md-type = 'vpp-nsh:md-type1' ";
+    uses nsh-md-type1-attributes;
+  }
+
+  augment /vpp-nsh-state/nsh-entries/nsh-entry {
+    ext:augment-identifier nsh-md-type-2-state-augment;
+    when "/md-type = 'vpp-nsh:md-type2' ";
+    uses nsh-md-type2-attributes;
+  }
 }
\ No newline at end of file
index 276f4f8..dbe3ae6 100644 (file)
@@ -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:
  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.vpp</groupId>
-        <artifactId>vpp-impl-parent</artifactId>
-        <version>1.16.12-SNAPSHOT</version>
-        <relativePath>../../vpp-common/vpp-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.12-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.12-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>nsh-api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vppnsh-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.12-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+        <groupId>io.fd.nsh_sfc</groupId>
+        <artifactId>nsh-sfc</artifactId>
+        <version>16.12-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 (executable)
index 0000000..48f3233
--- /dev/null
@@ -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 (executable)
index 0000000..e649150
--- /dev/null
@@ -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 (file)
index 0000000..f2fe985
--- /dev/null
@@ -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 (executable)
index 0000000..d3c15ae
--- /dev/null
@@ -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 (executable)
index 0000000..f2757bd
--- /dev/null
@@ -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 (executable)
index 0000000..fbf37c3
--- /dev/null
@@ -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 (executable)
index 0000000..ca13d8a
--- /dev/null
@@ -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 (executable)
index 0000000..53dff0b
--- /dev/null
@@ -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 (executable)
index 0000000..7d6c64b
--- /dev/null
@@ -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 (executable)
index 0000000..a7467c8
--- /dev/null
@@ -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 (executable)
index 0000000..f25e33c
--- /dev/null
@@ -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 (executable)
index 0000000..130b499
--- /dev/null
@@ -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);
+        }
+    }
+}
+
index a7368e1..0bebc44 100644 (file)
@@ -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:
     <relativePath/>
   </parent>
 
-  <groupId>io.fd.honeycomb.v3po</groupId>
-  <artifactId>nsh-aggregator</artifactId>
+  <groupId>io.fd.honeycomb.nsh</groupId>
+  <artifactId>vppnsh-aggregator</artifactId>
   <version>1.16.12-SNAPSHOT</version>
-  <name>nsh</name>
+  <name>vppnsh</name>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
   <prerequisites>
index 390db81..732ae4a 100644 (file)
@@ -32,6 +32,7 @@
     <v3po.version>1.16.12-SNAPSHOT</v3po.version>
     <lisp.version>1.16.12-SNAPSHOT</lisp.version>
     <vpp.common.min.distro.version>1.16.12-SNAPSHOT</vpp.common.min.distro.version>
+    <vppnsh.version>1.16.12-SNAPSHOT</vppnsh.version>
   </properties>
 
   <build>
       <artifactId>lisp2vpp</artifactId>
       <version>${lisp.version}</version>
     </dependency>
+    <dependency>
+      <groupId>io.fd.honeycomb.vppnsh</groupId>
+      <artifactId>vppnsh-impl</artifactId>
+      <version>${vppnsh.version}</version>
+    </dependency>
   </dependencies>
 </project>
index 7c1d07d..04377c3 100644 (file)
@@ -21,6 +21,7 @@ import com.google.inject.Module;
 import io.fd.honeycomb.lisp.LispModule;
 import io.fd.honeycomb.translate.v3po.V3poModule;
 import io.fd.honeycomb.vpp.distro.VppCommonModule;
+import io.fd.honeycomb.vppnsh.impl.VppNshModule;
 import java.util.List;
 
 public class Main {
@@ -32,6 +33,7 @@ public class Main {
         sampleModules.add(new VppCommonModule());
         sampleModules.add(new V3poModule());
         sampleModules.add(new LispModule());
+        sampleModules.add(new VppNshModule());
 
         io.fd.honeycomb.infra.distro.Main.init(sampleModules);
     }