summaryrefslogtreecommitdiffstats
path: root/ipsec/ipsec-impl
diff options
context:
space:
mode:
authorTibor Král <tibor.kral@pantheon.tech>2018-11-14 18:20:02 +0100
committerTibor Král <tibor.kral@pantheon.tech>2019-01-16 10:07:28 +0100
commit26589d440f332fe52238fa258d7d7b58df43eee5 (patch)
treedd3eaa8cf5cc3bd9fcfbff1239227c784ce935e7 /ipsec/ipsec-impl
parent8ad4f38beb1350d1cd62d11a9a15ac78ee0623f9 (diff)
HC2VPP-87: Expose IPSEC management
Change-Id: Ib13a2cdba5a0902581c455de67cc0ee64d20598d Signed-off-by: Tibor Král <tibor.kral@pantheon.tech>
Diffstat (limited to 'ipsec/ipsec-impl')
-rw-r--r--ipsec/ipsec-impl/pom.xml114
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java53
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java63
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java127
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java249
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java68
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java156
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java104
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java233
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java148
-rw-r--r--ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java119
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java83
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java35
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java113
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java116
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java60
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java167
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java119
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java287
-rw-r--r--ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java175
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json25
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json25
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json25
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json8
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json8
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json8
-rw-r--r--ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json8
-rw-r--r--ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json32
-rw-r--r--ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json25
-rw-r--r--ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json32
-rw-r--r--ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json11
-rw-r--r--ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json31
-rw-r--r--ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json21
-rw-r--r--ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json21
34 files changed, 2869 insertions, 0 deletions
diff --git a/ipsec/ipsec-impl/pom.xml b/ipsec/ipsec-impl/pom.xml
new file mode 100644
index 000000000..9cf3dd97a
--- /dev/null
+++ b/ipsec/ipsec-impl/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019 PANTHEON.tech.
+
+ 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.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.hc2vpp.common</groupId>
+ <artifactId>vpp-impl-parent</artifactId>
+ <relativePath>../../vpp-common/vpp-impl-parent</relativePath>
+ <version>1.19.01-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.fd.hc2vpp.ipsec</groupId>
+ <artifactId>ipsec-impl</artifactId>
+ <name>${project.artifactId}</name>
+ <version>1.19.01-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ipsec-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!--VPP common-->
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>cfg-init</artifactId>
+ </dependency>
+
+ <!-- Translation -->
+ <dependency>
+ <groupId>io.fd.hc2vpp.common</groupId>
+ <artifactId>vpp-translate-utils</artifactId>
+ </dependency>
+
+ <!-- DI -->
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.jmob</groupId>
+ <artifactId>guice.conf</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ </dependency>
+ <!-- Testing dependencies-->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-testlib</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.hc2vpp.common</groupId>
+ <artifactId>vpp-translate-test</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb.infra</groupId>
+ <artifactId>test-tools</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java
new file mode 100644
index 000000000..36dd8ae85
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory;
+import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Module class instantiating IpSec plugin components.
+ */
+public class IpsecModule extends AbstractModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IpsecModule.class);
+ private static final String SAD_ENTRIES_MAPPING = "sad-entries-mapping";
+
+ @Override
+ protected void configure() {
+ LOG.info("Installing IPSec module");
+
+ bind(MultiNamingContext.class).toInstance(new MultiNamingContext(SAD_ENTRIES_MAPPING, 1));
+ LOG.info("Injecting writers factories");
+ final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+ writerFactoryBinder.addBinding().to(IpsecWriterFactory.class).in(Singleton.class);
+
+ LOG.info("Injecting readers factories");
+ final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ readerFactoryBinder.addBinding().to(IpsecReaderFactory.class).in(Singleton.class);
+
+ LOG.info("Module IPSec successfully configured");
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java
new file mode 100644
index 000000000..e148022e8
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.read;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import io.fd.honeycomb.translate.impl.read.GenericInitListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing readers for IpSec plugin's data.
+ */
+public final class IpsecReaderFactory implements ReaderFactory {
+
+ private static final InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class);
+ private FutureJVppCore vppApi;
+
+ @Inject
+ public IpsecReaderFactory(final FutureJVppCore vppApi) {
+ this.vppApi = vppApi;
+ }
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ registry.subtreeAdd(Sets
+ .newHashSet(InstanceIdentifier.create(IpsecState.class).child(Sa.class),
+ InstanceIdentifier.create(IpsecState.class).augmentation(IpsecStateSpdAugmentation.class)
+ .child(Spd.class)), new GenericReader<>(IPSEC_STATE_ID,
+ new IpsecStateCustomizer(vppApi)));
+ registry.addStructuralReader(IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class),
+ IpsecStateSpdAugmentationBuilder.class);
+ registry.subtreeAdd(Sets
+ .newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class)),
+ new GenericInitListReader<>(
+ IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class).child(Spd.class),
+ new IpsecStateSpdCustomizer(vppApi)));
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java
new file mode 100644
index 000000000..4755c7a82
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.read;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.LinkedList;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.SaBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateCustomizer extends FutureJVppCustomizer
+ implements JvppReplyConsumer, InitializingReaderCustomizer<IpsecState, IpsecStateBuilder>, Ipv4Translator,
+ Ipv6Translator {
+
+ private final DumpCacheManager<IpsecSaDetailsReplyDump, Void> ipsecSaDetailsReplyDumpManager;
+
+ public IpsecStateCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ this.ipsecSaDetailsReplyDumpManager =
+ new DumpCacheManager.DumpCacheManagerBuilder<IpsecSaDetailsReplyDump, Void>()
+ .withExecutor(new IpsecStateCustomizer.IpsecStateSaDetailsDumpExecutor(vppApi))
+ .acceptOnly(IpsecSaDetailsReplyDump.class)
+ .build();
+ }
+
+ @Nonnull
+ @Override
+ public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<IpsecState> id,
+ @Nonnull final IpsecState readValue, @Nonnull final ReadContext ctx) {
+ return Initialized.create(id, readValue);
+ }
+
+ @Nonnull
+ @Override
+ public IpsecStateBuilder getBuilder(@Nonnull final InstanceIdentifier<IpsecState> id) {
+ return new IpsecStateBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<IpsecState> id,
+ @Nonnull final IpsecStateBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ final Optional<IpsecSaDetailsReplyDump> dumpSa =
+ ipsecSaDetailsReplyDumpManager.getDump(id, ctx.getModificationCache());
+
+ if (dumpSa.isPresent()) {
+ LinkedList<Sa> listSa = new LinkedList<>();
+ IpsecSaDetailsReplyDump reply = dumpSa.get();
+ for (IpsecSaDetails details : reply.ipsecSaDetails) {
+ SaBuilder saBuilder = new SaBuilder();
+ saBuilder.setSpi(Integer.toUnsignedLong(details.spi))
+ .setAntiReplayWindow(Long.valueOf(details.replayWindow).intValue())
+ .setAuthenticationAlgorithm(IkeIntegrityAlgorithmT.forValue(details.integAlg))
+ .setEncryptionAlgorithm(IkeEncryptionAlgorithmT.forValue(details.cryptoAlg));
+ listSa.add(saBuilder.build());
+ }
+ builder.setSa(listSa);
+ }
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final IpsecState readValue) {
+ IpsecStateBuilder ipsecParentBuilder = (IpsecStateBuilder) parentBuilder;
+ ipsecParentBuilder.setHoldDown(readValue.getHoldDown())
+ .setPolicy(readValue.getPolicy())
+ .setProposal(readValue.getProposal())
+ .setRedundancy(readValue.getRedundancy())
+ .setSa(readValue.getSa())
+ .addAugmentation(IpsecStateSpdAugmentation.class,
+ readValue.augmentation(IpsecStateSpdAugmentation.class));
+ }
+
+ static final class IpsecStateSaDetailsDumpExecutor
+ implements EntityDumpExecutor<IpsecSaDetailsReplyDump, Void>, JvppReplyConsumer {
+
+ private final FutureJVppCore jvpp;
+
+ IpsecStateSaDetailsDumpExecutor(final FutureJVppCore jvpp) {
+ this.jvpp = jvpp;
+ }
+
+ @Nonnull
+ @Override
+ public IpsecSaDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+ throws ReadFailedException {
+ IpsecSaDump dump = new IpsecSaDump();
+ dump.saId = -1;
+ return getReplyForRead(jvpp.ipsecSaDump(dump).toCompletableFuture(), identifier);
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java
new file mode 100644
index 000000000..45f54cdb8
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.read;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecSpdOperation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IpsecStateSpdCustomizer extends FutureJVppCustomizer
+ implements JvppReplyConsumer, InitializingListReaderCustomizer<Spd, SpdKey, SpdBuilder>, Ipv4Translator,
+ Ipv6Translator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IpsecStateSpdCustomizer.class);
+ private final DumpCacheManager<IpsecSpdDetailsReplyDump, Void> ipsecSpdDetailsReplyDumpManager;
+ private final DumpCacheManager<IpsecSpdsDetailsReplyDump, Void> ipsecSpdsReplyDumpManager;
+
+ public IpsecStateSpdCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ IpsecStateSpdsReplyDumpExecutor spdsExecutor =
+ new IpsecStateSpdCustomizer.IpsecStateSpdsReplyDumpExecutor(vppApi);
+ this.ipsecSpdsReplyDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdsDetailsReplyDump, Void>()
+ .withExecutor(spdsExecutor)
+ .acceptOnly(IpsecSpdsDetailsReplyDump.class)
+ .build();
+
+ this.ipsecSpdDetailsReplyDumpManager =
+ new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdDetailsReplyDump, Void>()
+ .withExecutor(
+ new IpsecStateSpdCustomizer.IpsecStateSpdDetailsDumpExecutor(vppApi, spdsExecutor))
+ .acceptOnly(IpsecSpdDetailsReplyDump.class)
+ .build();
+ }
+
+ @Nonnull
+ @Override
+ public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Spd> id,
+ @Nonnull final Spd readValue,
+ @Nonnull final ReadContext ctx) {
+ return Initialized.create(id, readValue);
+ }
+
+ @Nonnull
+ @Override
+ public SpdBuilder getBuilder(@Nonnull final InstanceIdentifier<Spd> id) {
+ return new SpdBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final SpdBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ SpdKey key = id.firstKeyOf(Spd.class);
+ builder.withKey(key);
+ builder.setSpdId(key.getSpdId());
+ Optional<IpsecSpdDetailsReplyDump> spdDump =
+ ipsecSpdDetailsReplyDumpManager.getDump(id, ctx.getModificationCache());
+ if (spdDump.isPresent()) {
+ List<SpdEntries> spdEntries =
+ spdDump.get().ipsecSpdDetails.stream().map(details -> translateDetailToEntry(details))
+ .collect(Collectors.toList());
+ builder.setSpdEntries(spdEntries);
+ }
+ }
+
+ @Nonnull
+ @Override
+ public List<SpdKey> getAllIds(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final ReadContext context)
+ throws ReadFailedException {
+ List<SpdKey> spdKeys = new LinkedList<>();
+ Optional<IpsecSpdsDetailsReplyDump> spdsDump =
+ ipsecSpdsReplyDumpManager.getDump(id, context.getModificationCache());
+ if (spdsDump.isPresent()) {
+ spdKeys = spdsDump.get().ipsecSpdsDetails.stream().map(details -> new SpdKey(details.spdId))
+ .collect(Collectors.toList());
+ }
+
+ LOG.debug("SPDs found in VPP: {}", spdKeys);
+ return spdKeys;
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Spd> readData) {
+ ((IpsecStateSpdAugmentationBuilder) builder).setSpd(readData);
+ }
+
+ private SpdEntries translateDetailToEntry(final IpsecSpdDetails details) {
+
+ SpdEntriesBuilder builder = new SpdEntriesBuilder();
+ builder.setDirection(IpsecTrafficDirection.forValue(details.isOutbound))
+ .setIsIpv6(ByteDataTranslator.INSTANCE.byteToBoolean(details.isIpv6))
+ .setPriority(details.priority);
+ switch (details.policy) {
+ case 0:
+ builder.setOperation(IpsecSpdOperation.Bypass);
+ break;
+ case 1:
+ builder.setOperation(IpsecSpdOperation.Discard);
+ break;
+ case 3:
+ builder.setOperation(IpsecSpdOperation.Protect);
+ builder.setProtectSaId(details.saId);
+ break;
+ }
+
+ if (builder.isIsIpv6()) {
+ processIpv6AddressRanges(builder, details);
+ } else {
+ processIpv4AddressRanges(builder, details);
+ }
+
+ return builder.build();
+ }
+
+ private void processIpv4AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) {
+ if (details.localStartAddr != null && details.localStartAddr.length > 0) {
+ builder.setLaddrStart(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStartAddr)).stringValue()));
+ }
+ if (details.localStopAddr != null && details.localStopAddr.length > 0) {
+ builder.setLaddrStop(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStopAddr)).stringValue()));
+ }
+ if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) {
+ builder.setRaddrStart(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStartAddr)).stringValue()));
+ }
+ if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) {
+ builder.setRaddrStop(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStopAddr)).stringValue()));
+ }
+ }
+
+ private void processIpv6AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) {
+ if (details.localStartAddr != null && details.localStartAddr.length > 0) {
+ builder.setLaddrStart(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStartAddr)).stringValue()));
+ }
+ if (details.localStopAddr != null && details.localStopAddr.length > 0) {
+ builder.setLaddrStop(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStopAddr)).stringValue()));
+ }
+ if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) {
+ builder.setRaddrStart(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStartAddr)).stringValue()));
+ }
+ if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) {
+ builder.setRaddrStop(IpAddressBuilder.getDefaultInstance(
+ new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStopAddr)).stringValue()));
+ }
+ }
+
+ public static class IpsecStateSpdDetailsDumpExecutor
+ implements EntityDumpExecutor<IpsecSpdDetailsReplyDump, Void>, JvppReplyConsumer {
+ private FutureJVppCore jvpp;
+ private IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor;
+
+ public IpsecStateSpdDetailsDumpExecutor(
+ final FutureJVppCore vppApi, final IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor) {
+ this.jvpp = vppApi;
+ this.spdsDumpExecutor = spdsDumpExecutor;
+ }
+
+ @Nonnull
+ @Override
+ public IpsecSpdDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+ throws ReadFailedException {
+ IpsecSpdDetailsReplyDump fullReplyDump = new IpsecSpdDetailsReplyDump();
+ fullReplyDump.ipsecSpdDetails = new LinkedList<>();
+
+ Optional<IpsecSpdsDetailsReplyDump> spdsReply =
+ Optional.of(spdsDumpExecutor.executeDump(identifier, params));
+ IpsecSpdsDetailsReplyDump spdDump = spdsReply.get();
+ for (IpsecSpdsDetails spdsDetail : spdDump.ipsecSpdsDetails) {
+ IpsecSpdDump dump = new IpsecSpdDump();
+ dump.spdId = spdsDetail.spdId;
+ dump.saId = -1;
+ IpsecSpdDetailsReplyDump reply =
+ getReplyForRead(jvpp.ipsecSpdDump(dump).toCompletableFuture(), identifier);
+ fullReplyDump.ipsecSpdDetails.addAll(reply.ipsecSpdDetails);
+ }
+
+ return fullReplyDump;
+ }
+ }
+
+ private class IpsecStateSpdsReplyDumpExecutor implements EntityDumpExecutor<IpsecSpdsDetailsReplyDump, Void> {
+ private final FutureJVppCore jvpp;
+
+ public IpsecStateSpdsReplyDumpExecutor(
+ final FutureJVppCore vppApi) {
+ this.jvpp = vppApi;
+ }
+
+ @Nonnull
+ @Override
+ public IpsecSpdsDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
+ throws ReadFailedException {
+ return getReplyForRead(jvpp.ipsecSpdsDump(new IpsecSpdsDump()).toCompletableFuture(), identifier);
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java
new file mode 100644
index 000000000..6886b9b5d
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2GlobalConfigurationCustomizer extends FutureJVppCustomizer
+ implements WriterCustomizer<IkeGlobalConfiguration>, JvppReplyConsumer {
+ public Ikev2GlobalConfigurationCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+ @Nonnull final IkeGlobalConfiguration dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ IpsecIkeGlobalConfAugmentation fileAUg = dataAfter.augmentation(IpsecIkeGlobalConfAugmentation.class);
+ if (fileAUg != null) {
+ if (fileAUg.getLocalKeyFile() != null) {
+ Ikev2SetLocalKey request = new Ikev2SetLocalKey();
+ request.keyFile = fileAUg.getLocalKeyFile().getBytes();
+ getReplyForWrite(getFutureJVpp().ikev2SetLocalKey(request).toCompletableFuture(), id);
+ }
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+ @Nonnull final IkeGlobalConfiguration dataBefore,
+ @Nonnull final IkeGlobalConfiguration dataAfter,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ writeCurrentAttributes(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id,
+ @Nonnull final IkeGlobalConfiguration dataBefore,
+ @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ // VPP doesn't support deletion of local key file
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java
new file mode 100644
index 000000000..300ea6b8e
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDel;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.nio.ByteBuffer;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeGeneralPolicyProfileGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2PolicyCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<Policy, PolicyKey>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator {
+
+ public Ikev2PolicyCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+ request.isAdd = BYTE_TRUE;
+ request.name = dataAfter.getName().getBytes();
+ getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id);
+ addAuthorization(dataAfter, id);
+ addTrafficSelectors(dataAfter, id);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+ request.isAdd = BYTE_FALSE;
+ request.name = dataBefore.getName().getBytes();
+ getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore,
+ @Nonnull final Policy dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ addAuthorization(dataAfter, id);
+ addTrafficSelectors(dataAfter, id);
+ }
+
+ private void addTrafficSelectors(final Policy dataAfter, final InstanceIdentifier<Policy> id)
+ throws WriteFailedException {
+ IpsecIkev2PolicyAugmentation aug = dataAfter.augmentation(IpsecIkev2PolicyAugmentation.class);
+ if (aug == null) {
+ return;
+ }
+ if (aug.getTrafficSelectors() != null) {
+ for (TrafficSelectors selector : aug.getTrafficSelectors()) {
+ Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs();
+ if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) {
+ addTsRequest.isLocal = BYTE_TRUE;
+ addTsRequest.startAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue()))
+ .getInt();
+ addTsRequest.endAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue()))
+ .getInt();
+ if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) {
+ addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue();
+ addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue();
+ }
+ } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) {
+ addTsRequest.isLocal = BYTE_FALSE;
+ addTsRequest.startAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue()))
+ .getInt();
+ addTsRequest.endAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue()))
+ .getInt();
+ if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) {
+ addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue();
+ addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue();
+ }
+ }
+ if (selector.getProtocol() != null) {
+ addTsRequest.proto = selector.getProtocol().byteValue();
+ }
+ if (dataAfter.getName() != null) {
+ addTsRequest.name = dataAfter.getName().getBytes();
+ }
+ getReplyForWrite(getFutureJVpp().ikev2ProfileSetTs(addTsRequest).toCompletableFuture(), id);
+ }
+ }
+ }
+
+ private void addAuthorization(final Policy data, final InstanceIdentifier<Policy> id)
+ throws WriteFailedException {
+ Authentication auth = data.getAuthentication();
+ if (auth != null) {
+ if (auth.isPresharedKey() != null && data.getPreSharedKey() != null) {
+ setProfilePreSharedKeyAuth(data.key().getName(), data.getPreSharedKey(), id);
+ } else if (auth.isRsaSignature() != null) {
+ IpsecIkev2PolicyAugmentation aug = data.augmentation(IpsecIkev2PolicyAugmentation.class);
+ if (aug != null && aug.getCertificate() != null) {
+ setProfileRSAAuth(data.key().getName(), aug.getCertificate(), id);
+ }
+ }
+ }
+ }
+
+ private void setProfileRSAAuth(final String name, final String fileName, final InstanceIdentifier<Policy> id)
+ throws WriteFailedException {
+ Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+ request.name = name.getBytes();
+ request.data = fileName.getBytes();
+ request.authMethod = BYTE_TRUE;
+ getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id);
+ }
+
+ private void setProfilePreSharedKeyAuth(final String name,
+ final IkeGeneralPolicyProfileGrouping.PreSharedKey preSharedKey,
+ final InstanceIdentifier<Policy> id) throws WriteFailedException {
+ final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+ request.authMethod = BYTE_FALSE;
+ if (preSharedKey.getHexString() != null) {
+ request.isHex = BYTE_TRUE;
+ }
+ request.data = preSharedKey.stringValue().getBytes();
+ request.name = name.getBytes();
+ getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java
new file mode 100644
index 000000000..4c11f1633
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.FqdnString;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Rfc822AddressString;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2PolicyIdentityCustomizer extends FutureJVppCustomizer
+ implements WriterCustomizer<Identity>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ public Ikev2PolicyIdentityCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+ @Nonnull final Identity dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ String name = id.firstKeyOf(Policy.class).getName();
+ if (dataAfter.getLocal() != null) {
+ setProfileId(id, name, dataAfter.getLocal().getIdentity(), true);
+ }
+
+ if (dataAfter.getRemote() != null) {
+ setProfileId(id, name, dataAfter.getRemote().getIdentity(), false);
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+ @Nonnull final Identity dataBefore,
+ @Nonnull final Identity dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ writeCurrentAttributes(id, dataAfter, writeContext);
+ }
+
+ private void setProfileId(final InstanceIdentifier<Identity> id,
+ final String profileName,
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity data,
+ final boolean isLocalId) throws WriteFailedException {
+ final Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+ request.name = profileName.getBytes();
+ transformIdentityToRequest(data, request);
+ request.isLocal = isLocalId
+ ? BYTE_TRUE
+ : BYTE_FALSE;
+ getReplyForWrite(getFutureJVpp().ikev2ProfileSetId(request).toCompletableFuture(), id);
+ }
+
+ private void transformIdentityToRequest(
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity
+ identityData, final Ikev2ProfileSetId request) {
+ if (identityData instanceof Ipv4Address) {
+ request.idType = 1;
+ request.data = ipv4AddressNoZoneToArray(((Ipv4Address) identityData).getIpv4Address().getValue());
+ } else if (identityData instanceof FqdnString) {
+ request.idType = 2;
+ request.data = ((FqdnString) identityData).getFqdnString().getValue().getBytes();
+ } else if (identityData instanceof Rfc822AddressString) {
+ request.idType = 3;
+ request.data = ((Rfc822AddressString) identityData).getRfc822AddressString().getBytes();
+ } else if (identityData instanceof Ipv6Address) {
+ request.idType = 5;
+ request.data = ipv6AddressNoZoneToArray(((Ipv6Address) identityData).getIpv6Address());
+ }
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id,
+ @Nonnull final Identity dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ // VPP doesn't support deletion of Ikev2 Profile ID
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java
new file mode 100644
index 000000000..d7bbee32d
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.EncryptionAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IpsecSadEntryCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<SadEntries, SadEntriesKey>,
+ JvppReplyConsumer, ByteDataTranslator, Ipv6Translator, Ipv4Translator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IpsecSadEntryCustomizer.class);
+ private MultiNamingContext sadEntryMapping;
+
+ IpsecSadEntryCustomizer(final FutureJVppCore vppApi, final MultiNamingContext sadEntryMapping) {
+ super(vppApi);
+ this.sadEntryMapping = sadEntryMapping;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+ @Nonnull final SadEntries dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ addDelEntry(id, dataAfter, writeContext, true);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+ @Nonnull final SadEntries dataBefore,
+ @Nonnull final SadEntries dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ writeCurrentAttributes(id, dataAfter, writeContext);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id,
+ @Nonnull final SadEntries dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ addDelEntry(id, dataBefore, writeContext, false);
+ }
+
+ private void addDelEntry(final InstanceIdentifier<SadEntries> id,
+ final SadEntries dataAfter,
+ final WriteContext writeContext, boolean adding) throws WriteFailedException {
+ final IpsecSadAddDelEntry entry = new IpsecSadAddDelEntry();
+ IpsecSadEntriesAugmentation augment = dataAfter.augmentation(IpsecSadEntriesAugmentation.class);
+ if (augment != null && augment.getSaId() != null) {
+ entry.sadId = augment.getSaId();
+ }
+ if (dataAfter.getSpi() != null) {
+ entry.spi = dataAfter.getSpi().intValue();
+ }
+ if (dataAfter.getAntiReplayWindow() != null) {
+ entry.useAntiReplay = dataAfter.getAntiReplayWindow() > 0
+ ? BYTE_TRUE
+ : BYTE_FALSE;
+ }
+
+ if (dataAfter.getSaMode() != null) {
+ entry.isTunnel = Integer.valueOf(dataAfter.getSaMode().getIntValue()).byteValue();
+ }
+ entry.isAdd = adding
+ ? ByteDataTranslator.BYTE_TRUE
+ : ByteDataTranslator.BYTE_FALSE;
+ if (dataAfter.getEsp() != null) {
+ entry.protocol = 1;
+ fillEspAuthentication(entry, dataAfter.getEsp());
+ fillEspEncryption(entry, dataAfter.getEsp());
+
+ } else if (dataAfter.getAh() != null) {
+ entry.protocol = 0;
+ fillAhAuthentication(entry, dataAfter.getAh());
+ }
+
+ fillAddresses(entry, dataAfter);
+
+ LOG.debug("IPSec config change id={} request={}", id, entry);
+ final CompletionStage<IpsecSadAddDelEntryReply> ipsecSadEntryAddDellReplyFuture =
+ getFutureJVpp().ipsecSadAddDelEntry(entry);
+ getReplyForWrite(ipsecSadEntryAddDellReplyFuture.toCompletableFuture(), id);
+ if (adding) {
+ sadEntryMapping.addChild(dataAfter.key().getDirection().getName(), entry.sadId,
+ String.valueOf(dataAfter.key().getSpi()), writeContext.getMappingContext());
+ } else {
+ sadEntryMapping
+ .removeChild(dataAfter.key().getDirection().getName(), String.valueOf(dataAfter.key().getSpi()),
+ writeContext.getMappingContext());
+ }
+ }
+
+ private void fillAhAuthentication(IpsecSadAddDelEntry targetEntry, Ah data) {
+ //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512
+ AuthenticationAlgorithm authAlg = data.getAuthenticationAlgorithm();
+ if (authAlg != null) {
+ String integKey;
+ if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) {
+ integKey =
+ ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) authAlg)
+ .getHmacMd596().getKeyStr().stringValue();
+ targetEntry.integrityAlgorithm = 1;
+ } else if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) {
+ integKey =
+ ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) authAlg)
+ .getHmacSha196().getKeyStr().stringValue();
+ targetEntry.integrityAlgorithm = 2;
+ } else {
+ targetEntry.integrityAlgorithm = 0;
+ return;
+ }
+ targetEntry.integrityKey = integKey.getBytes();
+ }
+ }
+
+ private void fillEspAuthentication(IpsecSadAddDelEntry targetEntry, Esp data) {
+ //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication
+ authAlg = data.getAuthentication();
+ if (authAlg != null) {
+ String integKey;
+ if (authAlg.getAuthenticationAlgorithm() instanceof HmacMd596) {
+ integKey = ((HmacMd596) authAlg.getAuthenticationAlgorithm()).getHmacMd596().getKeyStr().stringValue();
+ targetEntry.integrityAlgorithm = 1;
+ } else if (authAlg.getAuthenticationAlgorithm() instanceof HmacSha196) {
+ integKey =
+ ((HmacSha196) authAlg.getAuthenticationAlgorithm()).getHmacSha196().getKeyStr().stringValue();
+ targetEntry.integrityAlgorithm = 2;
+ } else {
+ targetEntry.integrityAlgorithm = 0;
+ return;
+ }
+ targetEntry.integrityKey = integKey.getBytes();
+ }
+ }
+
+ private void fillEspEncryption(IpsecSadAddDelEntry targetEntry, Esp data) {
+ //0 = Null, 1 = AES-CBC-128, 2 = AES-CBC-192, 3 = AES-CBC-256, 4 = 3DES-CBC
+ if (data.getEncryption() != null && data.getEncryption().getEncryptionAlgorithm() != null) {
+ String cryptoKey = "";
+ EncryptionAlgorithm encrAlg = data.getEncryption().getEncryptionAlgorithm();
+ if (encrAlg instanceof Aes128Cbc) {
+ cryptoKey = ((Aes128Cbc) encrAlg).getAes128Cbc().getKeyStr().stringValue();
+ targetEntry.cryptoAlgorithm = 1;
+ } else if (encrAlg instanceof Aes192Cbc) {
+ cryptoKey = ((Aes192Cbc) encrAlg).getAes192Cbc().getKeyStr().stringValue();
+ targetEntry.cryptoAlgorithm = 2;
+ } else if (encrAlg instanceof Aes256Cbc) {
+ cryptoKey = ((Aes256Cbc) encrAlg).getAes256Cbc().getKeyStr().stringValue();
+ targetEntry.cryptoAlgorithm = 3;
+ } else if (encrAlg instanceof DesCbc) {
+ cryptoKey = ((DesCbc) encrAlg).getDesCbc().getKeyStr().stringValue();
+ targetEntry.cryptoAlgorithm = 4;
+ } else {
+ targetEntry.cryptoAlgorithm = 0;
+ return;
+ }
+ targetEntry.cryptoKey = cryptoKey.getBytes();
+ }
+ }
+
+ private void fillAddresses(IpsecSadAddDelEntry targetEntry, SadEntries data) {
+ if (data.getSourceAddress() != null && data.getSourceAddress().getIpAddress() != null) {
+ IpAddress sourceAddr = data.getSourceAddress().getIpAddress();
+ if (sourceAddr instanceof Ipv4Address) {
+ Ipv4Address ipv4 = (Ipv4Address) sourceAddr;
+ targetEntry.isTunnelIpv6 = 0;
+ targetEntry.tunnelSrcAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue());
+ } else if (sourceAddr instanceof Ipv6Address) {
+ Ipv6Address ipv6 = (Ipv6Address) sourceAddr;
+ targetEntry.isTunnelIpv6 = 1;
+ targetEntry.tunnelSrcAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address());
+ }
+ }
+
+ if (data.getDestinationAddress() != null && data.getDestinationAddress().getIpAddress() != null) {
+ IpAddress destAddr = data.getDestinationAddress().getIpAddress();
+
+ if (destAddr instanceof Ipv4Address) {
+ Ipv4Address ipv4 = (Ipv4Address) destAddr;
+ targetEntry.isTunnelIpv6 = 0;
+ targetEntry.tunnelDstAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue());
+ } else if (destAddr instanceof Ipv6Address) {
+ Ipv6Address ipv6 = (Ipv6Address) destAddr;
+ targetEntry.isTunnelIpv6 = 1;
+ targetEntry.tunnelDstAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address());
+ }
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java
new file mode 100644
index 000000000..771cf676a
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDel;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecSpdCustomizer extends FutureJVppCustomizer
+ implements ListWriterCustomizer<Spd, SpdKey>, JvppReplyConsumer, ByteDataTranslator,
+ Ipv6Translator, Ipv4Translator {
+
+ public IpsecSpdCustomizer(final FutureJVppCore vppApi) {
+ super(vppApi);
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ IpsecSpdAddDel spdCreate = new IpsecSpdAddDel();
+ spdCreate.isAdd = ByteDataTranslator.BYTE_TRUE;
+ spdCreate.spdId = dataAfter.getSpdId();
+ getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdCreate).toCompletableFuture(), id);
+ if (dataAfter.getSpdEntries() != null) {
+ for (SpdEntries entry : dataAfter.getSpdEntries()) {
+ addSpdEntry(id, dataAfter.getSpdId(), entry);
+ }
+ }
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ IpsecSpdAddDel spdDelete = new IpsecSpdAddDel();
+ spdDelete.isAdd = ByteDataTranslator.BYTE_FALSE;
+ spdDelete.spdId = dataBefore.getSpdId();
+ getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdDelete).toCompletableFuture(), id);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore,
+ @Nonnull final Spd dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ if (dataAfter.getSpdEntries() != null) {
+ for (SpdEntries entry : dataAfter.getSpdEntries()) {
+ addSpdEntry(id, dataAfter.getSpdId(), entry);
+ }
+ }
+ }
+
+ private void addSpdEntry(final InstanceIdentifier<Spd> id, int spdId, final SpdEntries entry)
+ throws WriteFailedException {
+ IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry();
+ request.spdId = spdId;
+ request.isAdd = ByteDataTranslator.BYTE_TRUE;
+ IpsecSpdEntriesAugmentation entryAug = entry.augmentation(IpsecSpdEntriesAugmentation.class);
+ if (entryAug == null) {
+ return;
+ }
+
+ if (entryAug.isIsIpv6() != null) {
+ request.isIpv6 = (byte) (entryAug.isIsIpv6()
+ ? 1
+ : 0);
+ }
+ if (entryAug.getDirection() != null) {
+ request.isOutbound = (byte) entryAug.getDirection().getIntValue();
+ }
+
+ if (entryAug.getPriority() != null) {
+ request.priority = entryAug.getPriority();
+ }
+
+ if (entryAug.getOperation() != null) {
+ final String operation = entryAug.getOperation().getName();
+ if (operation.equalsIgnoreCase("bypass")) {
+ request.policy = (byte) 0;
+ } else if (operation.equalsIgnoreCase("discard")) {
+ request.policy = (byte) 1;
+ } else if (operation.equalsIgnoreCase("protect")) {
+ request.policy = (byte) 3;
+ }
+ }
+
+ if (entryAug.getLaddrStart() != null) {
+ if (entryAug.getLaddrStart().getIpv4Address() != null) {
+ request.localAddressStart =
+ ipv4AddressNoZoneToArray(entryAug.getLaddrStart().getIpv4Address().getValue());
+ } else if (entryAug.getLaddrStart().getIpv6Address() != null) {
+ request.localAddressStart = ipv6AddressNoZoneToArray(entryAug.getLaddrStart().getIpv6Address());
+ }
+ }
+ if (entryAug.getLaddrStop() != null) {
+ if (entryAug.getLaddrStop().getIpv4Address() != null) {
+ request.localAddressStop =
+ ipv4AddressNoZoneToArray(entryAug.getLaddrStop().getIpv4Address().getValue());
+ } else if (entryAug.getLaddrStop().getIpv6Address() != null) {
+ request.localAddressStop = ipv6AddressNoZoneToArray(entryAug.getLaddrStop().getIpv6Address());
+ }
+ }
+ if (entryAug.getRaddrStop() != null) {
+ if (entryAug.getRaddrStop().getIpv4Address() != null) {
+ request.remoteAddressStop =
+ ipv4AddressNoZoneToArray(entryAug.getRaddrStop().getIpv4Address().getValue());
+ } else if (entryAug.getRaddrStop().getIpv6Address() != null) {
+ request.remoteAddressStop = ipv6AddressNoZoneToArray(entryAug.getRaddrStop().getIpv6Address());
+ }
+ }
+
+ if (entryAug.getRaddrStart() != null) {
+ if (entryAug.getRaddrStart().getIpv4Address() != null) {
+ request.remoteAddressStart =
+ ipv4AddressNoZoneToArray(entryAug.getRaddrStart().getIpv4Address().getValue());
+ } else if (entryAug.getRaddrStart().getIpv6Address() != null) {
+ request.remoteAddressStart = ipv6AddressNoZoneToArray(entryAug.getRaddrStart().getIpv6Address());
+ }
+ }
+ getReplyForWrite(getFutureJVpp().ipsecSpdAddDelEntry(request).toCompletableFuture(), id);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java
new file mode 100644
index 000000000..8b164ac74
--- /dev/null
+++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Local;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Remote;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256Cbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbc;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.DestinationAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.SourceAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing writers for IpSec plugin's data.
+ */
+public final class IpsecWriterFactory implements WriterFactory {
+
+ private static final InstanceIdentifier<Ikev2> IKE2_ID = InstanceIdentifier.create(Ikev2.class);
+ private static final InstanceIdentifier<Ipsec> IPSEC_ID = InstanceIdentifier.create(Ipsec.class);
+ private static final InstanceIdentifier<Sad> SAD_ID = IPSEC_ID.child(Sad.class);
+ private static final InstanceIdentifier<SadEntries> SAD_ENTRIES_ID = SAD_ID.child(SadEntries.class);
+ private static final InstanceIdentifier<Spd> SPD_ID = IPSEC_ID.child(Spd.class);
+
+ private final FutureJVppCore vppApi;
+ private MultiNamingContext sadEntriesMapping;
+
+ @Inject
+ public IpsecWriterFactory(final FutureJVppCore vppApi, final MultiNamingContext sadEntriesMappingContext) {
+ this.vppApi = vppApi;
+ this.sadEntriesMapping = sadEntriesMappingContext;
+ }
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(SadEntries.class).child(SourceAddress.class),
+ InstanceIdentifier.create(SadEntries.class).child(DestinationAddress.class),
+ InstanceIdentifier.create(SadEntries.class).child(Ah.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196.class),
+ InstanceIdentifier.create(SadEntries.class).child(Ah.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class)
+ .child(HmacSha196.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class)
+ .child(HmacMd596.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+ .child(Aes128Cbc.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+ .child(Aes192Cbc.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+ .child(Aes256Cbc.class),
+ InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class)
+ .child(DesCbc.class),
+ InstanceIdentifier.create(SadEntries.class).augmentation(IpsecSadEntriesAugmentation.class)),
+ new GenericListWriter<>(SAD_ENTRIES_ID, new IpsecSadEntryCustomizer(vppApi, sadEntriesMapping)));
+ registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class),
+ InstanceIdentifier.create(Spd.class).child(SpdEntries.class)
+ .augmentation(IpsecSpdEntriesAugmentation.class)),
+ new GenericListWriter<>(SPD_ID, new IpsecSpdCustomizer(vppApi)));
+ registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(IkeGlobalConfiguration.class)
+ .augmentation(IpsecIkeGlobalConfAugmentation.class)),
+ new GenericWriter<>(IKE2_ID.child(IkeGlobalConfiguration.class),
+ new Ikev2GlobalConfigurationCustomizer(vppApi)));
+ registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Policy.class).child(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication.class),
+ InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class),
+ InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class)
+ .child(TrafficSelectors.class)),
+ new GenericListWriter<>(IKE2_ID.child(Policy.class), new Ikev2PolicyCustomizer(vppApi)));
+ registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Identity.class).child(Local.class),
+ InstanceIdentifier.create(Identity.class).child(Remote.class)),
+ new GenericWriter<>(IKE2_ID.child(Policy.class).child(Identity.class),
+ new Ikev2PolicyIdentityCustomizer(vppApi)));
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java
new file mode 100644
index 000000000..42817d42a
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.testing.fieldbinder.Bind;
+import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory;
+import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.util.YangDAG;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class IpsecModuleTest {
+
+ @Bind
+ @Mock
+ private FutureJVppCore futureJVppCore;
+
+ @Inject
+ private Set<WriterFactory> writerFactories = new HashSet<>();
+
+ @Inject
+ private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ Guice.createInjector(new IpsecModule(), BoundFieldModule.of(this)).injectMembers(this);
+ }
+
+ @Test
+ public void testWriterFactories() throws Exception {
+ assertThat(writerFactories, is(not(empty())));
+ final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(new YangDAG());
+ writerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ assertEquals(1, writerFactories.size());
+ assertTrue(writerFactories.iterator().next() instanceof IpsecWriterFactory);
+ }
+
+ @Test
+ public void testReaderFactories() throws Exception {
+ assertThat(readerFactories, is(not(empty())));
+ final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(new YangDAG());
+ readerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ assertEquals(1, readerFactories.size());
+ assertTrue(readerFactories.iterator().next() instanceof IpsecReaderFactory);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java
new file mode 100644
index 000000000..bce8a982a
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.helpers;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor;
+import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+
+public interface SchemaContextTestHelper extends InjectablesProcessor {
+
+ @SchemaContextProvider
+ default ModuleInfoBackedContext getSchemaContext() {
+ return provideSchemaContextFor(ImmutableSet.of(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.$YangModuleInfoImpl
+ .getInstance()
+ ));
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java
new file mode 100644
index 000000000..9b8f9157f
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSaDump;
+import java.util.LinkedList;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateCustomizerTest extends ReaderCustomizerTest<IpsecState, IpsecStateBuilder>
+ implements ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class);
+ private static final String LOCAL_ADDR_START = "192.168.11.1";
+ private static final String REMOTE_ADDR_START = "192.168.22.1";
+ private static final String TUNNEL_SRC_ADDR = LOCAL_ADDR_START;
+ private static final String TUNNEL_DST_ADDR = REMOTE_ADDR_START;
+ private static final int REPLY_WINDOW = 88;
+ private static final int SA_ID = 10;
+ private static final int SPI = 1001;
+ private static final int CRYPTO_ALG = 1;
+ private static final String CRYPTO_KEY = "123456789";
+ private static final int INTEG_ALG = 2;
+ private static final String INTEG_KEY = "987654321";
+ private static final int PROTOCOL = 1;
+ private static final int LAST_SEQ_INB = 8;
+ private static final int HOLD_DOWN = 88;
+
+ public IpsecStateCustomizerTest() {
+ super(IpsecState.class, IpsecStateBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<IpsecState, IpsecStateBuilder> initCustomizer() {
+ return new IpsecStateCustomizer(api);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ final IpsecSaDetailsReplyDump saDetailsReply = new IpsecSaDetailsReplyDump();
+ LinkedList<IpsecSaDetails> saDetails = new LinkedList<>();
+ IpsecSaDetails saDetail = new IpsecSaDetails();
+ saDetail.spi = SPI;
+ saDetail.saId = SA_ID;
+ saDetail.cryptoAlg = CRYPTO_ALG;
+ saDetail.cryptoKey = CRYPTO_KEY.getBytes();
+ saDetail.integAlg = INTEG_ALG;
+ saDetail.integKey = INTEG_KEY.getBytes();
+ saDetail.isTunnel = BYTE_TRUE;
+ saDetail.isTunnelIp6 = BYTE_FALSE;
+ saDetail.protocol = PROTOCOL;
+ saDetail.lastSeqInbound = LAST_SEQ_INB;
+ saDetail.replayWindow = REPLY_WINDOW;
+ saDetail.useAntiReplay = BYTE_TRUE;
+ saDetail.tunnelSrcAddr = ipv4AddressNoZoneToArray(TUNNEL_SRC_ADDR);
+ saDetail.tunnelDstAddr = ipv4AddressNoZoneToArray(TUNNEL_DST_ADDR);
+ saDetails.add(saDetail);
+ saDetailsReply.ipsecSaDetails = saDetails;
+ IpsecSaDump saDump = new IpsecSaDump();
+ saDump.saId = SA_ID;
+ when(api.ipsecSaDump(any())).thenReturn(future(saDetailsReply));
+ }
+
+ @Test
+ public void testReadSa() throws ReadFailedException {
+ final IpsecStateBuilder builder = new IpsecStateBuilder();
+ getCustomizer().readCurrentAttributes(IPSEC_STATE_ID, builder, ctx);
+ assertEquals(builder.getSa().size(), 1);
+ Sa sa = builder.getSa().get(0);
+ assertEquals(sa.getAntiReplayWindow().intValue(), REPLY_WINDOW);
+ assertEquals(sa.getAuthenticationAlgorithm().getIntValue(), INTEG_ALG);
+ assertEquals(sa.getEncryptionAlgorithm().getIntValue(), CRYPTO_ALG);
+ assertEquals(sa.getSpi().intValue(), SPI);
+ }
+
+ @Test
+ public void testMerge() throws Exception {
+ final IpsecStateBuilder parentBuilder = new IpsecStateBuilder();
+ final IpsecStateBuilder builderForNewdata = new IpsecStateBuilder();
+ builderForNewdata.setHoldDown(new Long(HOLD_DOWN));
+ getCustomizer().merge(parentBuilder, builderForNewdata.build());
+ assertEquals(parentBuilder.getHoldDown().intValue(), HOLD_DOWN);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java
new file mode 100644
index 000000000..bf08fa8c3
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump;
+import java.util.LinkedList;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IpsecStateSpdCustomizerTest extends ReaderCustomizerTest<Spd, SpdBuilder>
+ implements ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static InstanceIdentifier<Spd> SPD_IID = InstanceIdentifier.create(IpsecState.class)
+ .augmentation(IpsecStateSpdAugmentation.class).child(Spd.class, new SpdKey(10));
+
+ private static final String LOCAL_ADDR_START = "192.168.11.1";
+ private static final String LOCAL_ADDR_END = "192.168.11.255";
+ private static final short PORT_START = 0;
+ private static final short PORT_END = Short.MAX_VALUE;
+ private static final int POLICY_PROTECT = 3;
+ private static final int SPD_ID = 10;
+ private static final int SA_ID = 10;
+ private static final int PROTOCOL = 1;
+ private static final int PRIORITY = 100;
+
+ public IpsecStateSpdCustomizerTest() {
+ super(Spd.class, SpdBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<Spd, SpdBuilder> initCustomizer() {
+ return new IpsecStateSpdCustomizer(api);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ final IpsecSpdDetailsReplyDump spdDetailsReply = new IpsecSpdDetailsReplyDump();
+ LinkedList<IpsecSpdDetails> spdDetails = new LinkedList<>();
+ IpsecSpdDetails spdDetail = new IpsecSpdDetails();
+ spdDetail.isIpv6 = BYTE_FALSE;
+ spdDetail.isOutbound = BYTE_TRUE;
+ spdDetail.spdId = SPD_ID;
+ spdDetail.protocol = PROTOCOL;
+ spdDetail.localStartAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_START);
+ spdDetail.localStopAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_END);
+ spdDetail.localStartPort = PORT_START;
+ spdDetail.localStopPort = PORT_END;
+ spdDetail.policy = POLICY_PROTECT;
+ spdDetail.saId = SA_ID;
+ spdDetail.priority = PRIORITY;
+ spdDetails.add(spdDetail);
+ spdDetailsReply.ipsecSpdDetails = spdDetails;
+ when(api.ipsecSpdDump(any())).thenReturn(future(spdDetailsReply));
+
+ IpsecSpdsDetailsReplyDump spdsReply = new IpsecSpdsDetailsReplyDump();
+ IpsecSpdsDetails spdsDetail = new IpsecSpdsDetails();
+ spdsDetail.spdId = SPD_ID;
+ spdsReply.ipsecSpdsDetails.add(spdsDetail);
+ when(api.ipsecSpdsDump(any())).thenReturn(future(spdsReply));
+ }
+
+ @Test
+ public void testReadSpd() throws ReadFailedException {
+ final SpdBuilder builder = new SpdBuilder();
+ getCustomizer().readCurrentAttributes(SPD_IID, builder, ctx);
+ assertEquals(builder.getSpdEntries().size(), 1);
+ SpdEntries spdEntries = builder.getSpdEntries().get(0);
+ assertEquals(spdEntries.getDirection().getName(), "outbound");
+ assertEquals(spdEntries.getPriority().intValue(), PRIORITY);
+ }
+
+ @Test
+ public void testMerge() throws Exception {
+ final IpsecStateSpdAugmentationBuilder parentBuilder = new IpsecStateSpdAugmentationBuilder();
+ final IpsecStateSpdAugmentationBuilder builderForNewData = new IpsecStateSpdAugmentationBuilder();
+ SpdBuilder spdBuilder = new SpdBuilder();
+ spdBuilder.setSpdId(SPD_ID);
+ getCustomizer().merge(parentBuilder, spdBuilder.build());
+ assertEquals(parentBuilder.getSpd().size(), 1);
+ assertEquals(parentBuilder.getSpd().get(0).getSpdId().intValue(), SPD_ID);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java
new file mode 100644
index 000000000..cf9e8b102
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey;
+import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKeyReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfigurationBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ikev2GlobalConfigurationCustomizerTest extends WriterCustomizerTest
+ implements SchemaContextTestHelper {
+ InstanceIdentifier<IkeGlobalConfiguration> IID = InstanceIdentifier.create(Ikev2.class)
+ .child(IkeGlobalConfiguration.class);
+ private Ikev2GlobalConfigurationCustomizer customizer;
+ private static final String LOCAL_KEY_FILE = "/home/localadmin/certs/client-key.pem";
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new Ikev2GlobalConfigurationCustomizer(api);
+ when(api.ikev2SetLocalKey(any())).thenReturn(future(new Ikev2SetLocalKeyReply()));
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ IkeGlobalConfigurationBuilder dataAfterBuilder = new IkeGlobalConfigurationBuilder();
+ IpsecIkeGlobalConfAugmentationBuilder augBuilder = new IpsecIkeGlobalConfAugmentationBuilder();
+ augBuilder.setLocalKeyFile(LOCAL_KEY_FILE);
+ dataAfterBuilder.addAugmentation(IpsecIkeGlobalConfAugmentation.class, augBuilder.build());
+ customizer.writeCurrentAttributes(IID, dataAfterBuilder.build(), writeContext);
+ Ikev2SetLocalKey request = new Ikev2SetLocalKey();
+ request.keyFile = LOCAL_KEY_FILE.getBytes();
+ verify(api).ikev2SetLocalKey(request);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java
new file mode 100644
index 000000000..0c7b65f1b
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDel;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDelReply;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuthReply;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTsReply;
+import java.nio.ByteBuffer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class Ikev2PolicyCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+ ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static final String IKEV2_PATH = "/hc2vpp-ietf-ipsec:ikev2";
+ private Ikev2PolicyCustomizer customizer;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new Ikev2PolicyCustomizer(api);
+ when(api.ikev2ProfileAddDel(any())).thenReturn(future(new Ikev2ProfileAddDelReply()));
+ when(api.ikev2ProfileSetTs(any())).thenReturn(future(new Ikev2ProfileSetTsReply()));
+ when(api.ikev2ProfileSetAuth(any())).thenReturn(future(new Ikev2ProfileSetAuthReply()));
+ }
+
+ @Test
+ public void testWrite(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2)
+ throws WriteFailedException {
+ Policy policy = ikev2.getPolicy().get(0);
+ customizer.writeCurrentAttributes(getId(policy.getName()), policy, writeContext);
+ Ikev2ProfileAddDel profileAddrequest = new Ikev2ProfileAddDel();
+ profileAddrequest.isAdd = BYTE_TRUE;
+ profileAddrequest.name = policy.getName().getBytes();
+
+ verify(api).ikev2ProfileAddDel(profileAddrequest);
+ verify(api).ikev2ProfileSetTs(translateTStoRequest(policy.augmentation(IpsecIkev2PolicyAugmentation.class)
+ .getTrafficSelectors().get(0), policy.getName()));
+ verify(api).ikev2ProfileSetAuth(translateAuthToRequest(policy));
+ }
+
+ @Test
+ public void testUpdate(
+ @InjectTestData(resourcePath = "/ikev2/addDelProfile_before.json", id = IKEV2_PATH) Ikev2 ikev2Before,
+ @InjectTestData(resourcePath = "/ikev2/addDelProfile_after.json", id = IKEV2_PATH) Ikev2 ikev2After)
+ throws WriteFailedException {
+ final Policy before = ikev2Before.getPolicy().get(0);
+ final Policy after = ikev2After.getPolicy().get(0);
+ customizer.updateCurrentAttributes(getId(before.getName()), before, after, writeContext);
+
+ verify(api, times(0)).ikev2ProfileAddDel(any());
+ verify(api).ikev2ProfileSetTs(translateTStoRequest(after.augmentation(IpsecIkev2PolicyAugmentation.class)
+ .getTrafficSelectors().get(0), after.getName()));
+ verify(api).ikev2ProfileSetAuth(translateAuthToRequest(after));
+ }
+
+ @Test
+ public void testDelete(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2)
+ throws WriteFailedException {
+ Policy policy = ikev2.getPolicy().get(0);
+ customizer.deleteCurrentAttributes(getId(policy.getName()), policy, writeContext);
+ final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel();
+ request.name = policy.getName().getBytes();
+ request.isAdd = BYTE_FALSE;
+ verify(api).ikev2ProfileAddDel(request);
+ verify(api, times(0)).ikev2ProfileSetTs(any());
+ verify(api, times(0)).ikev2ProfileSetAuth(any());
+ }
+
+ private InstanceIdentifier<Policy> getId(final String name) {
+ return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(name));
+ }
+
+ private Ikev2ProfileSetTs translateTStoRequest(final TrafficSelectors selector, final String policyName) {
+ Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs();
+ if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) {
+ addTsRequest.isLocal = ByteDataTranslator.BYTE_TRUE;
+ addTsRequest.startAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue())).getInt();
+ addTsRequest.endAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue()))
+ .getInt();
+ if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) {
+ addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue();
+ addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue();
+ }
+ } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) {
+ addTsRequest.isLocal = ByteDataTranslator.BYTE_FALSE;
+ addTsRequest.startAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue()))
+ .getInt();
+ addTsRequest.endAddr = ByteBuffer
+ .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue()))
+ .getInt();
+ if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) {
+ addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue();
+ addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue();
+ }
+ }
+ if (selector.getProtocol() != null) {
+ addTsRequest.proto = selector.getProtocol().byteValue();
+ }
+ if (policyName != null) {
+ addTsRequest.name = policyName.getBytes();
+ }
+ return addTsRequest;
+ }
+
+ private Ikev2ProfileSetAuth translateAuthToRequest(Policy policy) {
+ final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth();
+ Authentication auth = policy.getAuthentication();
+ if (auth != null) {
+ request.name = policy.getName().getBytes();
+ if (auth.isPresharedKey() != null && policy.getPreSharedKey() != null) {
+ request.authMethod = ByteDataTranslator.BYTE_FALSE;
+ if (policy.getPreSharedKey().getHexString() != null) {
+ request.isHex = ByteDataTranslator.BYTE_TRUE;
+ }
+ request.data = policy.getPreSharedKey().stringValue().getBytes();
+ } else if (auth.isRsaSignature() != null) {
+ IpsecIkev2PolicyAugmentation aug = policy.augmentation(IpsecIkev2PolicyAugmentation.class);
+ if (aug != null && aug.getCertificate() != null) {
+ request.data = aug.getCertificate().getBytes();
+ request.authMethod = ByteDataTranslator.BYTE_TRUE;
+ }
+ }
+ }
+ return request;
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java
new file mode 100644
index 000000000..bb8f0d762
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId;
+import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetIdReply;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class Ikev2PolicyIdentityCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+ ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static final String POLICY_NAME = "testPolicy";
+ private static final String IPV4_TYPE_DATA = "192.168.123.22";
+ private static final String IPV6_TYPE_DATA = "2001:DB8:0:0:8:800:200C:417A";
+ private static final String FQDN_TYPE_DATA = "vpp.home";
+ private static final String RFC822_TYPE_DATA = "rfc822@example.com";
+ private static final String IDENTITY_PATH =
+ "/hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:policy[hc2vpp-ietf-ipsec:name='" + POLICY_NAME +
+ "']/hc2vpp-ietf-ipsec:identity";
+ private Ikev2PolicyIdentityCustomizer customizer;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new Ikev2PolicyIdentityCustomizer(api);
+ when(api.ikev2ProfileSetId(any())).thenReturn(future(new Ikev2ProfileSetIdReply()));
+ }
+
+ @Test
+ public void testWriteLocalIpv4(
+ @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity identity)
+ throws WriteFailedException {
+ customizer.writeCurrentAttributes(getId(), identity, writeContext);
+ Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+ request.name = POLICY_NAME.getBytes();
+ request.idType = (byte) 1;
+ request.isLocal = BYTE_TRUE;
+ request.data = ipv4AddressNoZoneToArray(IPV4_TYPE_DATA);
+ verify(api).ikev2ProfileSetId(request);
+ }
+
+ @Test
+ public void testWriteRemoteFqdn(
+ @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_fqdn.json", id = IDENTITY_PATH) Identity identity)
+ throws WriteFailedException {
+ customizer.writeCurrentAttributes(getId(), identity, writeContext);
+ Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+ request.name = POLICY_NAME.getBytes();
+ request.idType = (byte) 2;
+ request.isLocal = BYTE_FALSE;
+ request.data = FQDN_TYPE_DATA.getBytes();
+ verify(api).ikev2ProfileSetId(request);
+ }
+
+ @Test
+ public void testWriteLocalIpv6(
+ @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_ipv6.json", id = IDENTITY_PATH) Identity identity)
+ throws WriteFailedException {
+ customizer.writeCurrentAttributes(getId(), identity, writeContext);
+ Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+ request.name = POLICY_NAME.getBytes();
+ request.idType = (byte) 5;
+ request.isLocal = BYTE_FALSE;
+ request.data = ipv6AddressNoZoneToArray(new Ipv6Address(IPV6_TYPE_DATA));
+ verify(api).ikev2ProfileSetId(request);
+ }
+
+ @Test
+ public void testUpdate(
+ @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity before,
+ @InjectTestData(resourcePath = "/ikev2/identity/identity_local_rfc822.json", id = IDENTITY_PATH) Identity after)
+ throws WriteFailedException {
+ customizer.updateCurrentAttributes(getId(), before, after, writeContext);
+ Ikev2ProfileSetId request = new Ikev2ProfileSetId();
+ request.name = POLICY_NAME.getBytes();
+ request.idType = (byte) 3;
+ request.isLocal = BYTE_TRUE;
+ request.data = RFC822_TYPE_DATA.getBytes();
+ verify(api).ikev2ProfileSetId(request);
+ }
+
+ private InstanceIdentifier<Identity> getId() {
+ return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(POLICY_NAME))
+ .child(Identity.class);
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java
new file mode 100644
index 000000000..912f50f27
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.MultiNamingContext;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.KeyStringGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.AhBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.EspBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.AuthenticationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.EncryptionBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256CbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbcBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class IpsecSadEntryCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+ ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static final String SAD_PATH = "/hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:sad";
+ private static final InstanceIdentifier<Sad> SAD_IID =
+ InstanceIdentifier.create(Ipsec.class).child(Sad.class);
+ private static final String INTEG_KEY = "0123456789012346";
+ private static final String CRYPTO_KEY = "9876543210987654";
+ private static final String TNL_SRC_ADDR = "192.168.1.1";
+ private static final String TNL_DST_ADDR = "192.168.1.2";
+ private static final int SPI_1002 = 1002;
+ private static final int SAD_ID = 10;
+
+ private IpsecSadEntryCustomizer customizer;
+ @Mock
+ private MultiNamingContext namingCntext;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new IpsecSadEntryCustomizer(api, namingCntext);
+ when(api.ipsecSadAddDelEntry(any())).thenReturn(future(new IpsecSadAddDelEntryReply()));
+ }
+
+ @Test
+ public void testWrite(@InjectTestData(resourcePath = "/sadEntries/addDelSadEntry.json", id = SAD_PATH) Sad sad)
+ throws WriteFailedException {
+ final SadEntries data = sad.getSadEntries().get(0);
+ final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+ request.isAdd = BYTE_TRUE;
+ request.spi = SPI_1002;
+ request.sadId = SAD_ID;
+ request.isTunnel = BYTE_TRUE;
+ request.isTunnelIpv6 = BYTE_FALSE;
+ request.integrityKey = INTEG_KEY.getBytes();
+ request.cryptoKey = CRYPTO_KEY.getBytes();
+ request.useAntiReplay = 0;
+ request.tunnelSrcAddress = ipv4AddressNoZoneToArray(TNL_SRC_ADDR);
+ request.tunnelDstAddress = ipv4AddressNoZoneToArray(TNL_DST_ADDR);
+
+ // ESP
+ request.protocol = BYTE_TRUE; //0 = AH, 1 = ESP
+ // - auth MD5-96
+ // - crypto Aes-Cbc-128
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+ IkeEncryptionAlgorithmT.EncrAesCbc128, request);
+ // - crypto Aes-Cbc-192
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+ IkeEncryptionAlgorithmT.EncrAesCbc192, request);
+ // - crypto Aes-Cbc-256
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+ IkeEncryptionAlgorithmT.EncrAesCbc256, request);
+ // - crypto DesCbc
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596,
+ IkeEncryptionAlgorithmT.EncrDes, request);
+
+ // - auth SHA1-96
+ // - crypto Aes-Cbc-128
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+ IkeEncryptionAlgorithmT.EncrAesCbc128, request);
+ // - crypto Aes-Cbc-192
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+ IkeEncryptionAlgorithmT.EncrAesCbc192, request);
+ // - crypto Aes-Cbc-256
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+ IkeEncryptionAlgorithmT.EncrAesCbc256, request);
+ // - crypto DesCbc
+ testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196,
+ IkeEncryptionAlgorithmT.EncrDes, request);
+
+ // AH
+ request.protocol = BYTE_FALSE;
+ request.cryptoAlgorithm = 0;
+ request.cryptoKey = null;
+ request.cryptoKeyLength = 0;
+ // - auth SHA1-96
+ testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacSha196, request);
+ // - auth MD5-96
+ testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacMd596, request);
+ }
+
+ @Test
+ public void testUpdate(
+ @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_before.json", id = SAD_PATH) Sad relaysBefore,
+ @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_after.json", id = SAD_PATH) Sad relayAfter)
+ throws WriteFailedException {
+ final SadEntries before = relaysBefore.getSadEntries().get(0);
+ final SadEntries after = relayAfter.getSadEntries().get(0);
+ final Long spi = after.getSpi();
+ customizer.updateCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), before, after, writeContext);
+ final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+ request.isAdd = BYTE_TRUE;
+ request.spi = SPI_1002;
+ request.sadId = SAD_ID;
+ request.protocol = BYTE_FALSE;
+ request.isTunnel = BYTE_FALSE;
+ request.isTunnelIpv6 = BYTE_TRUE;
+ request.integrityAlgorithm = 1;
+ request.integrityKey = INTEG_KEY.getBytes();
+ request.useAntiReplay = BYTE_TRUE;
+ request.tunnelSrcAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::11"));
+ request.tunnelDstAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::12"));
+ verify(api).ipsecSadAddDelEntry(request);
+ }
+
+ @Test
+ public void testDelete(@InjectTestData(resourcePath = "/sadEntries/delSadEntry.json", id = SAD_PATH) Sad sad)
+ throws WriteFailedException {
+ final SadEntries data = sad.getSadEntries().get(0);
+ final Long spi = data.getSpi();
+ customizer.deleteCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), data, writeContext);
+ final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry();
+ request.isAdd = BYTE_FALSE;
+ request.spi = SPI_1002;
+ request.sadId = SAD_ID;
+ verify(api).ipsecSadAddDelEntry(request);
+ }
+
+ private InstanceIdentifier<SadEntries> getId(final IpsecTrafficDirection direction, final Long spi) {
+ return SAD_IID.child(SadEntries.class, new SadEntriesKey(direction, spi));
+ }
+
+ private void testAhAuthorization(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg,
+ final IpsecSadAddDelEntry request) throws WriteFailedException {
+ SadEntriesBuilder builder = new SadEntriesBuilder(otherData);
+ builder.setEsp(null);
+ AhBuilder ahBuilder = new AhBuilder();
+ ahBuilder.setAuthenticationAlgorithm(getAhAuthentication(authAlg));
+ builder.setAh(ahBuilder.build());
+ customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)),
+ builder.build(), writeContext);
+ verify(api).ipsecSadAddDelEntry(request);
+ }
+
+ private void testEspAuthEncrCombination(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg,
+ final IkeEncryptionAlgorithmT encrAlg, final IpsecSadAddDelEntry request)
+ throws WriteFailedException {
+ SadEntriesBuilder builder = new SadEntriesBuilder(otherData);
+ builder.setAh(null);
+ EspBuilder espBuilder = new EspBuilder();
+ espBuilder.setAuthentication(getEspAuthentication(authAlg))
+ .setEncryption(getEspEncryption(encrAlg));
+ builder.setEsp(espBuilder.build());
+ customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)),
+ builder.build(), writeContext);
+
+ if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc128) {
+ request.cryptoAlgorithm = 1;
+ } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc192) {
+ request.cryptoAlgorithm = 2;
+ } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc256) {
+ request.cryptoAlgorithm = 3;
+ } else if (encrAlg == IkeEncryptionAlgorithmT.EncrDes) {
+ request.cryptoAlgorithm = 4;
+ } else {
+ request.cryptoAlgorithm = 0;
+ }
+
+ if (authAlg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+ request.integrityAlgorithm = 1;
+ } else if (authAlg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+ request.integrityAlgorithm = 2;
+ } else {
+ request.integrityAlgorithm = 0;
+ }
+
+ verify(api).ipsecSadAddDelEntry(request);
+ }
+
+ private Encryption getEspEncryption(IkeEncryptionAlgorithmT alg) {
+ if (alg == IkeEncryptionAlgorithmT.EncrAesCbc128) {
+ return new EncryptionBuilder().setEncryptionAlgorithm(new Aes128CbcBuilder().
+ setAes128Cbc(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128CbcBuilder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+ .build()).build()).build();
+ } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc192) {
+ return new EncryptionBuilder().setEncryptionAlgorithm(new Aes192CbcBuilder().
+ setAes192Cbc(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192CbcBuilder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+ .build()).build()).build();
+ } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc256) {
+ return new EncryptionBuilder().setEncryptionAlgorithm(new Aes256CbcBuilder().
+ setAes256Cbc(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256CbcBuilder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+ .build()).build()).build();
+ } else if (alg == IkeEncryptionAlgorithmT.EncrDes) {
+ return new EncryptionBuilder().setEncryptionAlgorithm(new DesCbcBuilder().setDesCbc(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbcBuilder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY))
+ .build()).build()).build();
+ }
+
+ return null;
+ }
+
+ private Authentication getEspAuthentication(IkeIntegrityAlgorithmT alg) {
+ if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+ return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacSha196Builder().setHmacSha196(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196Builder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build();
+ } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+ return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacMd596Builder().setHmacMd596(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596Builder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build();
+ }
+ return null;
+ }
+
+ private AuthenticationAlgorithm getAhAuthentication(IkeIntegrityAlgorithmT alg) {
+ if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196Builder()
+ .setHmacSha196(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196Builder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build();
+ } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596Builder()
+ .setHmacMd596(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596Builder()
+ .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build();
+ }
+ return null;
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java
new file mode 100644
index 000000000..a4b294002
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.ipsec.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDel;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntryReply;
+import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelReply;
+import java.util.Collections;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntriesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class IpsecSpdCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper,
+ ByteDataTranslator, Ipv4Translator, Ipv6Translator {
+
+ private static final int SPD_ID = 10;
+ private static final String IPSEC_PATH = "/hc2vpp-ietf-ipsec:ipsec";
+ private IpsecSpdCustomizer customizer;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new IpsecSpdCustomizer(api);
+ when(api.ipsecSpdAddDel(any())).thenReturn(future(new IpsecSpdAddDelReply()));
+ when(api.ipsecSpdAddDelEntry(any())).thenReturn(future(new IpsecSpdAddDelEntryReply()));
+ }
+
+ @Test
+ public void testWrite(@InjectTestData(resourcePath = "/spdEntries/addDelSpd.json", id = IPSEC_PATH) Ipsec ipsec)
+ throws WriteFailedException {
+ Spd spd = ipsec.getSpd().get(0);
+ customizer.writeCurrentAttributes(getSpdId(SPD_ID), spd, writeContext);
+ final IpsecSpdAddDel createSpdRequest = new IpsecSpdAddDel();
+ createSpdRequest.isAdd = BYTE_TRUE;
+ createSpdRequest.spdId = SPD_ID;
+
+ verify(api).ipsecSpdAddDel(createSpdRequest);
+ verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(0), SPD_ID, true));
+ verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(1), SPD_ID, true));
+ }
+
+ @Test
+ public void testUpdate(
+ @InjectTestData(resourcePath = "/spdEntries/addDelSpd_before.json", id = IPSEC_PATH) Ipsec ipsecBefore,
+ @InjectTestData(resourcePath = "/spdEntries/addDelSpd_after.json", id = IPSEC_PATH) Ipsec ipsecAfter)
+ throws WriteFailedException {
+ Spd before = ipsecBefore.getSpd().get(0);
+ Spd after = ipsecAfter.getSpd().get(0);
+ customizer.updateCurrentAttributes(getSpdId(SPD_ID), before, after, writeContext);
+ verify(api).ipsecSpdAddDelEntry(translateSpdEntry(after.getSpdEntries().get(0), SPD_ID, true));
+ }
+
+ @Test
+ public void testDelete()
+ throws WriteFailedException {
+ SpdBuilder spdBuilder = new SpdBuilder();
+ spdBuilder.setSpdId(SPD_ID)
+ .withKey(new SpdKey(SPD_ID))
+ .setSpdEntries(Collections.singletonList(new SpdEntriesBuilder().build()));
+ customizer.deleteCurrentAttributes(getSpdId(SPD_ID), spdBuilder.build(), writeContext);
+ IpsecSpdAddDel request = new IpsecSpdAddDel();
+ request.spdId = SPD_ID;
+ request.isAdd = BYTE_FALSE;
+ verify(api).ipsecSpdAddDel(request);
+ }
+
+ private InstanceIdentifier<Spd> getSpdId(final int spdId) {
+ return InstanceIdentifier.create(Ipsec.class).child(Spd.class, new SpdKey(spdId));
+ }
+
+ private IpsecSpdAddDelEntry translateSpdEntry(final SpdEntries entry, int spdId, boolean isAdd) {
+ IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry();
+ request.spdId = spdId;
+ request.isAdd = isAdd
+ ? BYTE_TRUE
+ : BYTE_FALSE;
+ IpsecSpdEntriesAugmentation aug = entry.augmentation(IpsecSpdEntriesAugmentation.class);
+ if (aug != null) {
+ if (aug.isIsIpv6() != null) {
+ request.isIpv6 = (byte) (aug.isIsIpv6()
+ ? 1
+ : 0);
+ }
+
+ if (aug.getDirection() != null) {
+ request.isOutbound = (byte) aug.getDirection().getIntValue();
+ }
+
+ if (aug.getPriority() != null) {
+ request.priority = aug.getPriority();
+ }
+
+ if (aug.getOperation() != null) {
+ final String operation = aug.getOperation().getName();
+ if (operation.equalsIgnoreCase("bypass")) {
+ request.policy = (byte) 0;
+ } else if (operation.equalsIgnoreCase("discard")) {
+ request.policy = (byte) 1;
+ } else if (operation.equalsIgnoreCase("protect")) {
+ request.policy = (byte) 3;
+ }
+ }
+
+ if (aug.getLaddrStart() != null) {
+ if (aug.getLaddrStart().getIpv4Address() != null) {
+ request.localAddressStart =
+ ipv4AddressNoZoneToArray(aug.getLaddrStart().getIpv4Address().getValue());
+ } else if (aug.getLaddrStart().getIpv6Address() != null) {
+ request.localAddressStart = ipv6AddressNoZoneToArray(aug.getLaddrStart().getIpv6Address());
+ }
+ }
+
+ if (aug.getLaddrStop() != null) {
+ if (aug.getLaddrStop().getIpv4Address() != null) {
+ request.localAddressStop = ipv4AddressNoZoneToArray(aug.getLaddrStop().getIpv4Address().getValue());
+ } else if (aug.getLaddrStop().getIpv6Address() != null) {
+ request.localAddressStop = ipv6AddressNoZoneToArray(aug.getLaddrStop().getIpv6Address());
+ }
+ }
+
+ if (aug.getRaddrStop() != null) {
+ if (aug.getRaddrStop().getIpv4Address() != null) {
+ request.remoteAddressStop =
+ ipv4AddressNoZoneToArray(aug.getRaddrStop().getIpv4Address().getValue());
+ } else if (aug.getRaddrStop().getIpv6Address() != null) {
+ request.remoteAddressStop = ipv6AddressNoZoneToArray(aug.getRaddrStop().getIpv6Address());
+ }
+ }
+
+ if (aug.getRaddrStart() != null) {
+ if (aug.getRaddrStart().getIpv4Address() != null) {
+ request.remoteAddressStart =
+ ipv4AddressNoZoneToArray(aug.getRaddrStart().getIpv4Address().getValue());
+ } else if (aug.getRaddrStart().getIpv6Address() != null) {
+ request.remoteAddressStart = ipv6AddressNoZoneToArray(aug.getRaddrStart().getIpv6Address());
+ }
+ }
+ }
+ return request;
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json
new file mode 100644
index 000000000..ac5f8c797
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json
@@ -0,0 +1,25 @@
+{
+ "ikev2": {
+ "policy": [
+ {
+ "name": "testPolicy",
+ "lifetime": 0,
+ "connection-type": "both",
+ "authentication" : {
+ "rsa-signature" : "true"
+ },
+ "certificate": "/home/localadmin/certs/server-cert.pem",
+ "traffic-selectors": [
+ {
+ "ts-name":"TS1",
+ "protocol":0,
+ "remote-address-low":"192.168.124.0",
+ "remote-address-high":"192.168.124.255",
+ "remote-port-low":0,
+ "remote-port-high":65535
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json
new file mode 100644
index 000000000..3dfa39345
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json
@@ -0,0 +1,25 @@
+{
+ "ikev2": {
+ "policy": [
+ {
+ "name": "testPolicy",
+ "lifetime": 0,
+ "connection-type": "both",
+ "authentication" : {
+ "preshared-key" : "true"
+ },
+ "pre-shared-key": "0123456789012345",
+ "traffic-selectors": [
+ {
+ "ts-name":"TS1",
+ "protocol":0,
+ "local-address-low":"192.168.124.0",
+ "local-address-high":"192.168.124.255",
+ "local-port-low":0,
+ "local-port-high":65535
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json
new file mode 100644
index 000000000..3dfa39345
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json
@@ -0,0 +1,25 @@
+{
+ "ikev2": {
+ "policy": [
+ {
+ "name": "testPolicy",
+ "lifetime": 0,
+ "connection-type": "both",
+ "authentication" : {
+ "preshared-key" : "true"
+ },
+ "pre-shared-key": "0123456789012345",
+ "traffic-selectors": [
+ {
+ "ts-name":"TS1",
+ "protocol":0,
+ "local-address-low":"192.168.124.0",
+ "local-address-high":"192.168.124.255",
+ "local-port-low":0,
+ "local-port-high":65535
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json
new file mode 100644
index 000000000..f068bd78b
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json
@@ -0,0 +1,8 @@
+{
+ "identity" : {
+ "local":
+ {
+ "ipv4-address": "192.168.123.22"
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json
new file mode 100644
index 000000000..6e152d9c4
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json
@@ -0,0 +1,8 @@
+{
+ "identity" : {
+ "local":
+ {
+ "rfc822-address-string": "rfc822@example.com"
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json
new file mode 100644
index 000000000..514f84116
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json
@@ -0,0 +1,8 @@
+{
+ "identity" : {
+ "remote":
+ {
+ "fqdn-string": "vpp.home"
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json
new file mode 100644
index 000000000..0674d357f
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json
@@ -0,0 +1,8 @@
+{
+ "identity" : {
+ "remote":
+ {
+ "ipv6-address": "2001:DB8:0:0:8:800:200C:417A"
+ }
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json
new file mode 100644
index 000000000..c522ba2de
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json
@@ -0,0 +1,32 @@
+{
+ "sad": {
+ "sad-entries": [
+ {
+ "spi": 1002,
+ "direction": "outbound",
+ "sa-id": 10,
+ "security-protocol": "esp",
+ "sa-mode": "tunnel",
+ "esp": {
+ "authentication": {
+ "hmac-sha1-96": {
+ "key-str": "0123456789012346"
+ }
+ },
+ "encryption": {
+ "aes-128-cbc": {
+ "key-str": "9876543210987654"
+ }
+ }
+ },
+ "source-address": {
+ "ipv4-address": "192.168.1.1"
+ },
+ "destination-address": {
+ "ipv4-address": "192.168.1.2"
+ },
+ "anti-replay-window": 0
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json
new file mode 100644
index 000000000..fa618a391
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json
@@ -0,0 +1,25 @@
+{
+ "sad": {
+ "sad-entries": [
+ {
+ "spi": 1002,
+ "direction": "inbound",
+ "sa-id": 10,
+ "security-protocol": "ah",
+ "sa-mode": "transport",
+ "ah": {
+ "hmac-md5-96": {
+ "key-str": "0123456789012346"
+ }
+ },
+ "source-address": {
+ "ipv6-address": "2001::11"
+ },
+ "destination-address": {
+ "ipv6-address": "2001::12"
+ },
+ "anti-replay-window": 32
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json
new file mode 100644
index 000000000..a88a14600
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json
@@ -0,0 +1,32 @@
+{
+ "sad": {
+ "sad-entries": [
+ {
+ "spi": 1002,
+ "direction": "outbound",
+ "sa-id": 10,
+ "security-protocol": "esp",
+ "sa-mode": "tunnel",
+ "esp": {
+ "authentication": {
+ "hmac-sha1-96": {
+ "key-str": "0123456789012346"
+ }
+ },
+ "encryption": {
+ "aes-128-cbc": {
+ "key-str": "9876543210987654"
+ }
+ }
+ },
+ "source-address": {
+ "ipv6-address": "2001::1"
+ },
+ "destination-address": {
+ "ipv6-address": "2001::10"
+ },
+ "anti-replay-window": 32
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json
new file mode 100644
index 000000000..23998d60f
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json
@@ -0,0 +1,11 @@
+{
+ "sad": {
+ "sad-entries": [
+ {
+ "spi": 1002,
+ "direction": "outbound",
+ "sa-id": 10
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json
new file mode 100644
index 000000000..85fe81d0d
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json
@@ -0,0 +1,31 @@
+{
+ "ipsec" : {
+ "spd": [
+ {
+ "spd-id": 10,
+ "spd-entries": [
+ {
+ "name": "test",
+ "priority":100,
+ "direction":"outbound",
+ "operation":"bypass",
+ "laddr-start":"192.168.124.0",
+ "laddr-stop":"192.168.124.255",
+ "raddr-start":"192.168.125.0",
+ "raddr-stop":"192.168.125.255"
+ },
+ {
+ "name": "TestSPDEntryIpv6",
+ "priority":100,
+ "direction":"inbound",
+ "operation":"bypass",
+ "laddr-start":"2001::1",
+ "laddr-stop":"2001::100",
+ "raddr-start":"2001::101",
+ "raddr-stop":"2001::200"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json
new file mode 100644
index 000000000..600dde46a
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json
@@ -0,0 +1,21 @@
+{
+ "ipsec" : {
+ "spd": [
+ {
+ "spd-entries": [
+ {
+ "name": "TestSPDEntryUpdate",
+ "priority":80,
+ "direction":"inbound",
+ "operation":"bypass",
+ "laddr-start":"2001::1",
+ "laddr-stop":"2001::100",
+ "raddr-start":"2001::101",
+ "raddr-stop":"2001::200"
+ }
+ ],
+ "spd-id": 10
+ }
+ ]
+ }
+}
diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json
new file mode 100644
index 000000000..be14bd6f9
--- /dev/null
+++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json
@@ -0,0 +1,21 @@
+{
+ "ipsec" : {
+ "spd": [
+ {
+ "spd-entries": [
+ {
+ "name": "TestSPDEntryUpdate",
+ "priority":100,
+ "direction":"outbound",
+ "operation":"discard",
+ "laddr-start":"192.168.124.0",
+ "laddr-stop":"192.168.124.255",
+ "raddr-start":"192.168.125.0",
+ "raddr-stop":"192.168.125.255"
+ }
+ ],
+ "spd-id": 10
+ }
+ ]
+ }
+}