summaryrefslogtreecommitdiffstats
path: root/acl/acl-impl
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2016-12-16 13:07:56 +0100
committerMarek Gradzki <mgradzki@cisco.com>2016-12-20 13:59:56 +0100
commitf8273e10b19ecc82bdda81feef9982ce28d5de21 (patch)
tree98d2d9686bcf24f64c0c18c633554e8629f2e22e /acl/acl-impl
parente3b9212110528217c2477f588ebccc0d76ee31e1 (diff)
HONEYCOMB-310: translation layer for acl plugin
Not covered by this patch (moved to subsequent commits): - postman collection - distinguish ingress/egress ACLs while reading assigned acls - proper support for acl tag - unit tests improvements - read for acls (not necessarily assigned) - initializers Change-Id: I5a198ce1a6e20d0b1d95b4d2d83d0464fb86580c Signed-off-by: Jan Srnicek <jsrnicek@cisco.com> Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'acl/acl-impl')
-rw-r--r--acl/acl-impl/asciidoc/Readme.adoc3
-rw-r--r--acl/acl-impl/pom.xml115
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/AclModule.java82
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/JVppAclProvider.java73
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppAclCustomizer.java194
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppMacIpAclCustomizer.java143
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/factory/InterfaceAclReaderFactory.java85
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/FutureJVppAclCustomizer.java38
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/AceConverter.java94
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/MacIpAceDataExtractor.java83
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/StandardAceDataExtractor.java98
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclDataExtractor.java68
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclValidator.java84
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclWriter.java125
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequest.java162
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequest.java111
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducer.java203
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizer.java98
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclMacIpCustomizer.java78
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/VppAclCustomizer.java110
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/AbstractAclWriterFactory.java44
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/InterfaceAclWriterFactory.java59
-rw-r--r--acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/VppAclWriterFactory.java82
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclModuleTest.java122
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclTestSchemaContext.java46
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequestTest.java188
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequestTest.java149
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducerTest.java102
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizerTest.java50
-rw-r--r--acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/VppAclCustomizerTest.java340
-rw-r--r--acl/acl-impl/src/test/resources/acl/macip/macip-acl.json27
-rw-r--r--acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp-v6.json36
-rw-r--r--acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp.json36
-rw-r--r--acl/acl-impl/src/test/resources/acl/standard/standard-acl-tcp.json38
-rw-r--r--acl/acl-impl/src/test/resources/acl/standard/standard-acl-udp.json36
-rw-r--r--acl/acl-impl/src/test/resources/rules/icmp-rule.json33
-rw-r--r--acl/acl-impl/src/test/resources/rules/icmp-v6-rule.json33
-rw-r--r--acl/acl-impl/src/test/resources/rules/other-rule.json26
-rw-r--r--acl/acl-impl/src/test/resources/rules/tcp-rule.json35
-rw-r--r--acl/acl-impl/src/test/resources/rules/udp-rule.json33
40 files changed, 3562 insertions, 0 deletions
diff --git a/acl/acl-impl/asciidoc/Readme.adoc b/acl/acl-impl/asciidoc/Readme.adoc
new file mode 100644
index 000000000..e990bc255
--- /dev/null
+++ b/acl/acl-impl/asciidoc/Readme.adoc
@@ -0,0 +1,3 @@
+= acl-impl
+
+Overview of acl-impl \ No newline at end of file
diff --git a/acl/acl-impl/pom.xml b/acl/acl-impl/pom.xml
new file mode 100644
index 000000000..7f08ca762
--- /dev/null
+++ b/acl/acl-impl/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2015 Cisco and/or its affiliates.
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at:
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>impl-parent</artifactId>
+ <version>1.17.01-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.fd.hc2vpp.acl</groupId>
+ <artifactId>acl-impl</artifactId>
+ <version>1.17.01-SNAPSHOT</version>
+
+ <properties>
+ <jvpp.acl.version>1.0-SNAPSHOT</jvpp.acl.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.fd.hc2vpp.acl</groupId>
+ <artifactId>acl-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.fd.vpp</groupId>
+ <artifactId>jvpp-acl</artifactId>
+ <version>${jvpp.acl.version}</version>
+ </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>
+
+ <!-- Infra dependencies -->
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>minimal-distribution</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- HC2VPP Dependencies -->
+ <dependency>
+ <groupId>io.fd.hc2vpp.common</groupId>
+ <artifactId>vpp-translate-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Test -->
+ <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>com.google.inject.extensions</groupId>
+ <artifactId>guice-testlib</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</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>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/AclModule.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/AclModule.java
new file mode 100644
index 000000000..f15119be6
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/AclModule.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+import io.fd.hc2vpp.acl.read.factory.InterfaceAclReaderFactory;
+import io.fd.hc2vpp.acl.write.factory.InterfaceAclWriterFactory;
+import io.fd.hc2vpp.acl.write.factory.VppAclWriterFactory;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import net.jmob.guice.conf.core.ConfigurationModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AclModule extends AbstractModule {
+
+ public static final String STANDARD_ACL_CONTEXT_NAME = "standard-acl-context";
+ public static final String STANDARD_LEARNED_ACL_NAME_PREFIX = "standard-learned-acl-";
+ public static final String MAC_IP_ACL_CONTEXT_NAME = "mac-ip-acl-context";
+ public static final String MAC_IP_LEARNED_ACL_NAME_PREFIX = "mac-ip-acl-context";
+
+ private static final Logger LOG = LoggerFactory.getLogger(AclModule.class);
+
+ private final Class<? extends Provider<FutureJVppAclFacade>> jvppAclProviderClass;
+
+ public AclModule() {
+ this(JVppAclProvider.class);
+ }
+
+ @VisibleForTesting
+ AclModule(@Nonnull final Class<? extends Provider<FutureJVppAclFacade>> jvppAclProviderClass) {
+ this.jvppAclProviderClass = jvppAclProviderClass;
+ }
+
+ @Override
+ protected void configure() {
+ LOG.info("Configuring module Acl");
+ install(ConfigurationModule.create());
+
+ // binds JVpp Acl future facade
+ bind(FutureJVppAclFacade.class).toProvider(jvppAclProviderClass).in(Singleton.class);
+
+ bind(NamingContext.class).annotatedWith(Names.named(STANDARD_ACL_CONTEXT_NAME))
+ .toInstance(new NamingContext(STANDARD_LEARNED_ACL_NAME_PREFIX, STANDARD_ACL_CONTEXT_NAME));
+
+ bind(NamingContext.class).annotatedWith(Names.named(MAC_IP_ACL_CONTEXT_NAME))
+ .toInstance(new NamingContext(MAC_IP_LEARNED_ACL_NAME_PREFIX, MAC_IP_ACL_CONTEXT_NAME));
+
+ final Multibinder<WriterFactory> writerFactoryMultibinder =
+ Multibinder.newSetBinder(binder(), WriterFactory.class);
+ writerFactoryMultibinder.addBinding().to(VppAclWriterFactory.class);
+ writerFactoryMultibinder.addBinding().to(InterfaceAclWriterFactory.class);
+
+ final Multibinder<ReaderFactory> readerFactoryMultibinder =
+ Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ readerFactoryMultibinder.addBinding().to(InterfaceAclReaderFactory.class);
+
+ LOG.info("Module Acl successfully configured");
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/JVppAclProvider.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/JVppAclProvider.java
new file mode 100644
index 000000000..b3caa0e9c
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/JVppAclProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl;
+
+import com.google.inject.Inject;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.vpp.jvpp.JVppRegistry;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.acl.JVppAclImpl;
+import io.fd.vpp.jvpp.acl.dto.AclPluginGetVersion;
+import io.fd.vpp.jvpp.acl.dto.AclPluginGetVersionReply;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class JVppAclProvider extends ProviderTrait<FutureJVppAclFacade> implements JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JVppAclProvider.class);
+
+ @Inject
+ private JVppRegistry registry;
+
+ private static JVppAclImpl initAclApi() {
+ final JVppAclImpl jvppAcl = new JVppAclImpl();
+ // Free jvpp-acl plugin's resources on shutdown
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ LOG.info("Unloading jvpp-acl plugin");
+ jvppAcl.close();
+ LOG.info("Successfully unloaded jvpp-acl plugin");
+ }
+ });
+ return jvppAcl;
+ }
+
+ @Override
+ protected FutureJVppAclFacade create() {
+ try {
+ return reportVersionAndGet(initAclApi());
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to open VPP management connection", e);
+ } catch (TimeoutException | VppBaseCallException e) {
+ throw new IllegalStateException("Unable to load ACL plugin version", e);
+ }
+ }
+
+ private FutureJVppAclFacade reportVersionAndGet(final JVppAclImpl jvppAcl)
+ throws IOException, TimeoutException, VppBaseCallException {
+ final FutureJVppAclFacade futureFacade = new FutureJVppAclFacade(registry, jvppAcl);
+ final AclPluginGetVersionReply pluginVersion =
+ getReply(futureFacade.aclPluginGetVersion(new AclPluginGetVersion()).toCompletableFuture());
+ LOG.info("Acl plugin successfully loaded[version {}.{}]", pluginVersion.major, pluginVersion.minor);
+ return futureFacade;
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppAclCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppAclCustomizer.java
new file mode 100644
index 000000000..90f2b2fe2
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppAclCustomizer.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.read;
+
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.acl.util.FutureJVppAclCustomizer;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager.DumpCacheManagerBuilder;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpPostProcessingFunction;
+import io.fd.vpp.jvpp.acl.dto.AclDetailsReplyDump;
+import io.fd.vpp.jvpp.acl.dto.AclDump;
+import io.fd.vpp.jvpp.acl.dto.AclInterfaceListDetailsReplyDump;
+import io.fd.vpp.jvpp.acl.dto.AclInterfaceListDump;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.EgressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.IngressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAcls;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAclsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAclsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppAcl;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppAclCustomizer extends FutureJVppAclCustomizer
+ implements ListReaderCustomizer<VppAcls, VppAclsKey, VppAclsBuilder>, JvppReplyConsumer, ByteDataTranslator {
+
+ private final NamingContext interfaceContext;
+ private final NamingContext standardAclContext;
+ /**
+ * true == ingress
+ * false == egress
+ */
+ private final boolean input;
+ private final DumpCacheManager<AclInterfaceListDetailsReplyDump, Integer> aclReferenceDumpManager;
+ private final DumpCacheManager<AclDetailsReplyDump, Integer> aclDumpManager;
+
+ public VppAclCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext standardAclContext,
+ final boolean input) {
+ super(jVppAclFacade);
+ this.interfaceContext = interfaceContext;
+ this.standardAclContext = standardAclContext;
+ this.input = input;
+
+ aclReferenceDumpManager =
+ new DumpCacheManagerBuilder<AclInterfaceListDetailsReplyDump, Integer>()
+ .withExecutor(createAclReferenceDumpExecutor())
+ .withPostProcessingFunction(input
+ ? createInputAclFilter()
+ : createOutputAclFilter())
+ .acceptOnly(AclInterfaceListDetailsReplyDump.class)
+ .build();
+
+ aclDumpManager = new DumpCacheManagerBuilder<AclDetailsReplyDump, Integer>()
+ .withExecutor(createAclExecutor())
+ .acceptOnly(AclDetailsReplyDump.class)
+ .build();
+ }
+
+ private EntityDumpExecutor<AclDetailsReplyDump, Integer> createAclExecutor() {
+ return (identifier, params) -> {
+ AclDump request = new AclDump();
+ request.aclIndex = params;
+ return getReplyForRead(getjVppAclFacade().aclDump(request).toCompletableFuture(), identifier);
+ };
+ }
+
+ private EntityDumpPostProcessingFunction<AclInterfaceListDetailsReplyDump> createInputAclFilter() {
+ return dump -> {
+ // filters acl's to first N(those are input ones)
+ dump.aclInterfaceListDetails = dump.aclInterfaceListDetails
+ .stream()
+ .map(iface -> {
+ iface.acls = Arrays.copyOfRange(iface.acls, 0, iface.nInput - 1);
+ return iface;
+ })
+ .collect(Collectors.toList());
+ return dump;
+ };
+ }
+
+ private EntityDumpPostProcessingFunction<AclInterfaceListDetailsReplyDump> createOutputAclFilter() {
+ return dump -> {
+ // filters acl's to last N(those are output ones)
+ dump.aclInterfaceListDetails = dump.aclInterfaceListDetails
+ .stream()
+ .map(iface -> {
+ iface.acls = Arrays.copyOfRange(iface.acls, iface.nInput, iface.acls.length);
+ return iface;
+ })
+ .collect(Collectors.toList());
+ return dump;
+ };
+ }
+
+ private EntityDumpExecutor<AclInterfaceListDetailsReplyDump, Integer> createAclReferenceDumpExecutor() {
+ return (identifier, params) -> {
+ AclInterfaceListDump dumpRequest = new AclInterfaceListDump();
+ dumpRequest.swIfIndex = params;
+ return getReplyForRead(getjVppAclFacade().aclInterfaceListDump(dumpRequest).toCompletableFuture(),
+ identifier);
+ };
+ }
+
+ @Nonnull
+ @Override
+ public List<VppAclsKey> getAllIds(@Nonnull final InstanceIdentifier<VppAcls> id, @Nonnull final ReadContext context)
+ throws ReadFailedException {
+
+ final String parentInterfaceName = id.firstKeyOf(Interface.class).getName();
+ final int parentInterfaceIndex = interfaceContext.getIndex(parentInterfaceName, context.getMappingContext());
+
+ final Optional<AclInterfaceListDetailsReplyDump> dumpReply =
+ aclReferenceDumpManager.getDump(id, context.getModificationCache(), parentInterfaceIndex);
+
+ if (dumpReply.isPresent() && !dumpReply.get().aclInterfaceListDetails.isEmpty()) {
+ return Arrays.stream(dumpReply.get().aclInterfaceListDetails.get(0).acls)
+ .mapToObj(aclIndex -> standardAclContext.getName(aclIndex, context.getMappingContext()))
+ .map(aclName -> new VppAclsKey(aclName, VppAcl.class))
+ .collect(Collectors.toList());
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<VppAcls> readData) {
+ if (input) {
+ IngressBuilder.class.cast(builder).setVppAcls(readData);
+ } else {
+ EgressBuilder.class.cast(builder).setVppAcls(readData);
+ }
+ }
+
+ @Nonnull
+ @Override
+ public VppAclsBuilder getBuilder(@Nonnull final InstanceIdentifier<VppAcls> id) {
+ return new VppAclsBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VppAcls> id,
+ @Nonnull final VppAclsBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ final VppAclsKey vppAclsKey = id.firstKeyOf(VppAcls.class);
+ final String aclName = vppAclsKey.getName();
+ final int aclIndex = standardAclContext.getIndex(aclName, ctx.getMappingContext());
+
+ final Optional<AclDetailsReplyDump> dumpReply =
+ aclDumpManager.getDump(id, ctx.getModificationCache(), aclIndex);
+
+ if (dumpReply.isPresent() && !dumpReply.get().aclDetails.isEmpty()) {
+ // FIXME (model expects hex string, but tag is written and read as ascii string)
+ // decide how tag should be handled (model change might be needed).
+ builder.setName(aclName);
+ builder.setType(vppAclsKey.getType());
+ builder.setTag(new HexString(printHexBinary(dumpReply.get().aclDetails.get(0).tag)));
+ } else {
+ throw new ReadFailedException(id,
+ new IllegalArgumentException(String.format("Acl with name %s not found", aclName)));
+ }
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppMacIpAclCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppMacIpAclCustomizer.java
new file mode 100644
index 000000000..982d89b9a
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/VppMacIpAclCustomizer.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.read;
+
+import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.acl.util.FutureJVppAclCustomizer;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
+import io.fd.vpp.jvpp.acl.dto.MacipAclDetails;
+import io.fd.vpp.jvpp.acl.dto.MacipAclDetailsReplyDump;
+import io.fd.vpp.jvpp.acl.dto.MacipAclDump;
+import io.fd.vpp.jvpp.acl.dto.MacipAclInterfaceGet;
+import io.fd.vpp.jvpp.acl.dto.MacipAclInterfaceGetReply;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.IngressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAclBuilder;
+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 VppMacIpAclCustomizer extends FutureJVppAclCustomizer
+ implements ReaderCustomizer<VppMacipAcl, VppMacipAclBuilder>, JvppReplyConsumer, ByteDataTranslator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VppMacIpAclCustomizer.class);
+
+ private final DumpCacheManager<MacipAclDetailsReplyDump, Integer> macIpAclDumpManager;
+ private final DumpCacheManager<MacipAclInterfaceGetReply, Void> interfaceMacIpAclDumpManager;
+ private final NamingContext interfaceContext;
+ private final NamingContext macIpAclContext;
+
+ public VppMacIpAclCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext macIpAclContext) {
+ super(jVppAclFacade);
+
+ // for dumping of Mac-ip details
+ macIpAclDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<MacipAclDetailsReplyDump, Integer>()
+ .withExecutor(createMacIpDumpExecutor())
+ .acceptOnly(MacipAclDetailsReplyDump.class)
+ .build();
+
+ // for dumping of reference on interface
+ interfaceMacIpAclDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<MacipAclInterfaceGetReply, Void>()
+ .withExecutor(createInterfaceMacIpDumpExecutor())
+ .acceptOnly(MacipAclInterfaceGetReply.class)
+ .build();
+ this.interfaceContext = interfaceContext;
+ this.macIpAclContext = macIpAclContext;
+ }
+
+ private EntityDumpExecutor<MacipAclDetailsReplyDump, Integer> createMacIpDumpExecutor() {
+ return (identifier, params) -> {
+ MacipAclDump request = new MacipAclDump();
+ request.aclIndex = params;
+
+ return getReplyForRead(getjVppAclFacade().macipAclDump(request).toCompletableFuture(), identifier);
+ };
+ }
+
+ private EntityDumpExecutor<MacipAclInterfaceGetReply, Void> createInterfaceMacIpDumpExecutor() {
+ return (identifier, params) -> getReplyForRead(
+ getjVppAclFacade().macipAclInterfaceGet(new MacipAclInterfaceGet()).toCompletableFuture(),
+ identifier);
+ }
+
+ @Nonnull
+ @Override
+ public VppMacipAclBuilder getBuilder(@Nonnull final InstanceIdentifier<VppMacipAcl> id) {
+ return new VppMacipAclBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VppMacipAcl> id,
+ @Nonnull final VppMacipAclBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ final String interfaceName = id.firstKeyOf(Interface.class).getName();
+ final MappingContext mappingContext = ctx.getMappingContext();
+ final int interfaceIndex = interfaceContext.getIndex(interfaceName, mappingContext);
+ final ModificationCache modificationCache = ctx.getModificationCache();
+ final Optional<MacipAclInterfaceGetReply> interfacesMacIpDumpReply =
+ interfaceMacIpAclDumpManager.getDump(id, modificationCache, NO_PARAMS);
+
+ if (interfacesMacIpDumpReply.isPresent() && interfaceIndex < interfacesMacIpDumpReply.get().count) {
+ final int aclIndex = interfacesMacIpDumpReply.get().acls[interfaceIndex];
+
+ final Optional<MacipAclDetailsReplyDump> macIpDumpReply =
+ macIpAclDumpManager.getDump(id, modificationCache, aclIndex);
+
+ if (macIpDumpReply.isPresent() && !macIpDumpReply.get().macipAclDetails.isEmpty()) {
+ final MacipAclDetails details = macIpDumpReply.get().macipAclDetails.get(0);
+
+ builder.setName(macIpAclContext.getName(aclIndex, mappingContext))
+ .setType(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppMacipAcl.class)
+ .setTag(new HexString(printHexBinary(details.tag)));
+ } else {
+ // this is invalid state(Interface in VPP will act as "deny-all" for security reasons), but generally
+ // it should not happen
+ throw new ReadFailedException(id,
+ new IllegalStateException(String.format("ACC with index %s not found in VPP", aclIndex)));
+ }
+ } else {
+ // this is valid state, so just logging
+ LOG.info("No Mac-ip ACL specified for Interface name={},index={}", interfaceName, interfaceIndex);
+ }
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder,
+ @Nonnull final VppMacipAcl readValue) {
+ IngressBuilder.class.cast(parentBuilder).setVppMacipAcl(readValue);
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/factory/InterfaceAclReaderFactory.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/factory/InterfaceAclReaderFactory.java
new file mode 100644
index 000000000..89520620d
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/read/factory/InterfaceAclReaderFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.read.factory;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.acl.AclModule;
+import io.fd.hc2vpp.acl.read.VppAclCustomizer;
+import io.fd.hc2vpp.acl.read.VppMacIpAclCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+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.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.EgressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.IngressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAcls;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceAclReaderFactory implements ReaderFactory {
+
+ @Inject
+ private FutureJVppAclFacade futureAclFacade;
+
+ @Inject
+ @Named(AclModule.STANDARD_ACL_CONTEXT_NAME)
+ private NamingContext standardAclContext;
+
+ @Inject
+ @Named(AclModule.MAC_IP_ACL_CONTEXT_NAME)
+ private NamingContext macIpAClContext;
+
+ @Inject
+ @Named("interface-context")
+ private NamingContext interfaceContext;
+
+ private static final InstanceIdentifier<Interface>
+ IFC_ID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ private static final InstanceIdentifier<VppAclInterfaceStateAugmentation> VPP_ACL_AUG_IID =
+ IFC_ID.augmentation(VppAclInterfaceStateAugmentation.class);
+ private static final InstanceIdentifier<Acl> ACL_IID = VPP_ACL_AUG_IID.child(Acl.class);
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ registry.addStructuralReader(VPP_ACL_AUG_IID, VppAclInterfaceStateAugmentationBuilder.class);
+ registry.addStructuralReader(ACL_IID, AclBuilder.class);
+
+ final InstanceIdentifier<Ingress> ingressInstanceIdentifier = ACL_IID.child(Ingress.class);
+ registry.addStructuralReader(ingressInstanceIdentifier, IngressBuilder.class);
+ registry.addAfter(new GenericListReader<>(ingressInstanceIdentifier.child(VppAcls.class),
+ new VppAclCustomizer(futureAclFacade, interfaceContext, standardAclContext, true)), IFC_ID);
+ registry.addAfter(new GenericReader<>(ingressInstanceIdentifier.child(VppMacipAcl.class),
+ new VppMacIpAclCustomizer(futureAclFacade, interfaceContext, macIpAClContext)), IFC_ID);
+
+ final InstanceIdentifier<Egress> egressInstanceIdentifier = ACL_IID.child(Egress.class);
+ registry.addStructuralReader(egressInstanceIdentifier, EgressBuilder.class);
+ registry.addAfter(new GenericListReader<>(egressInstanceIdentifier.child(VppAcls.class),
+ new VppAclCustomizer(futureAclFacade, interfaceContext, standardAclContext, false)), IFC_ID);
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/FutureJVppAclCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/FutureJVppAclCustomizer.java
new file mode 100644
index 000000000..e2d6bee58
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/FutureJVppAclCustomizer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+
+/**
+ * Holds reference to jvpp acl implementation
+ */
+public abstract class FutureJVppAclCustomizer {
+
+ private final FutureJVppAclFacade jVppAclFacade;
+
+ public FutureJVppAclCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade) {
+ this.jVppAclFacade = checkNotNull(jVppAclFacade, "JVpp Acl Future api is null");
+ }
+
+ public FutureJVppAclFacade getjVppAclFacade() {
+ return jVppAclFacade;
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/AceConverter.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/AceConverter.java
new file mode 100644
index 000000000..325787821
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/AceConverter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.ace;
+
+import io.fd.hc2vpp.acl.util.ace.extractor.MacIpAceDataExtractor;
+import io.fd.hc2vpp.acl.util.ace.extractor.StandardAceDataExtractor;
+import io.fd.hc2vpp.acl.util.protocol.ProtoPreBindRuleProducer;
+import io.fd.vpp.jvpp.acl.types.AclRule;
+import io.fd.vpp.jvpp.acl.types.MacipAclRule;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppMacipAce;
+
+/**
+ * Convert Ace's to vpp rules
+ */
+public interface AceConverter extends MacIpAceDataExtractor, StandardAceDataExtractor, ProtoPreBindRuleProducer {
+
+
+ default MacipAclRule[] convertToMacIpAclRules(@Nonnull final List<Ace> aces) {
+ return aces.stream()
+ .map(ace -> {
+ final VppMacipAce macIpAce = fromMacIpAce(ace);
+
+ MacipAclRule rule = new MacipAclRule();
+
+ rule.srcMac = sourceMacAsBytes(macIpAce);
+ rule.srcMacMask = sourceMacMaskAsBytes(macIpAce);
+ rule.isPermit = macIpAction(ace);
+
+ if (macIpIsIpv6(macIpAce)) {
+ rule.isIpv6 = 1;
+ rule.srcIpAddr = ipv6Address(macIpAce);
+ rule.srcIpPrefixLen = ipv6AddressPrefix(macIpAce);
+ } else {
+ rule.isIpv6 = 0;
+ rule.srcIpAddr = ipv4Address(macIpAce);
+ rule.srcIpPrefixLen = ipv4AddressPrefix(macIpAce);
+ }
+
+ return rule;
+ })
+ .collect(Collectors.toList())
+ .toArray(new MacipAclRule[aces.size()]);
+ }
+
+ default AclRule[] convertToStandardAclRules(@Nonnull final List<Ace> aces) {
+ return aces.stream()
+ .map(ace -> {
+ final VppAce standardAce = fromStandardAce(ace);
+
+ // pre-bind rule with protocol based attributes
+ AclRule rule = createPreBindRule(standardAce);
+
+ rule.isPermit = standardAction(ace);
+
+ if (standardIsIpv6(ace)) {
+ rule.isIpv6 = 1;
+ rule.srcIpAddr = ipv6SourceAddress(standardAce);
+ rule.srcIpPrefixLen = ipv6SourceAddressPrefix(standardAce);
+ rule.dstIpAddr = ipv6DestinationAddress(standardAce);
+ rule.dstIpPrefixLen = ipv6DestinationAddressPrefix(standardAce);
+ } else {
+ rule.isIpv6 = 0;
+ rule.srcIpAddr = ipv4SourceAddress(standardAce);
+ rule.srcIpPrefixLen = ipv4SourceAddressPrefix(standardAce);
+ rule.dstIpAddr = ipv4DestinationAddress(standardAce);
+ rule.dstIpPrefixLen = ipv4DestinationAddressPrefix(standardAce);
+ }
+
+
+ return rule;
+ })
+ .collect(Collectors.toList())
+ .toArray(new AclRule[aces.size()]);
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/MacIpAceDataExtractor.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/MacIpAceDataExtractor.java
new file mode 100644
index 000000000..a0d19902a
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/MacIpAceDataExtractor.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.ace.extractor;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Deny;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppMacipAceIpv4HeaderFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppMacipAceIpv6HeaderFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppMacipAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv6;
+
+public interface MacIpAceDataExtractor extends AddressTranslator {
+
+ default VppMacipAce fromMacIpAce(@Nonnull final Ace ace) {
+ return VppMacipAce.class.cast(ace.getMatches().getAceType());
+ }
+
+ default boolean macIpIsIpv6(@Nonnull final VppMacipAce ace) {
+ return ace.getVppMacipAceNodes().getAceIpVersion() instanceof AceIpv6;
+ }
+
+ default byte[] sourceMacAsBytes(@Nonnull final VppMacipAce ace) {
+ return macToByteArray(ace.getVppMacipAceNodes().getSourceMacAddress().getValue());
+ }
+
+ default byte[] sourceMacMaskAsBytes(@Nonnull final VppMacipAce ace) {
+ return macToByteArray(ace.getVppMacipAceNodes().getSourceMacAddressMask().getValue());
+ }
+
+ default byte[] ipv4Address(@Nonnull final VppMacipAce ace) {
+ return ipv4AddressPrefixToArray(
+ VppMacipAceIpv4HeaderFields.class.cast(ace.getVppMacipAceNodes().getAceIpVersion()).getSourceIpv4Network());
+ }
+
+ default byte ipv4AddressPrefix(@Nonnull final VppMacipAce ace) {
+ return extractPrefix(
+ VppMacipAceIpv4HeaderFields.class.cast(ace.getVppMacipAceNodes().getAceIpVersion()).getSourceIpv4Network());
+ }
+
+ default byte[] ipv6Address(@Nonnull final VppMacipAce ace) {
+ return ipv6AddressPrefixToArray(
+ VppMacipAceIpv6HeaderFields.class.cast(ace.getVppMacipAceNodes().getAceIpVersion()).getSourceIpv6Network());
+ }
+
+ default byte ipv6AddressPrefix(@Nonnull final VppMacipAce ace) {
+ return extractPrefix(
+ VppMacipAceIpv6HeaderFields.class.cast(ace.getVppMacipAceNodes().getAceIpVersion()).getSourceIpv6Network());
+ }
+
+ /**
+ * Only 0 and 1 are allowed for mac-ip
+ */
+ default byte macIpAction(@Nonnull final Ace ace) {
+ final PacketHandling action = ace.getActions().getPacketHandling();
+ if (action instanceof Permit) {
+ return 1;
+ } else if (action instanceof Deny) {
+ return 0;
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Unsupported packet-handling action %s for ACE %s", action, ace));
+ }
+ }
+
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/StandardAceDataExtractor.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/StandardAceDataExtractor.java
new file mode 100644
index 000000000..2e7ccbdc7
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/ace/extractor/StandardAceDataExtractor.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.ace.extractor;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.fd.hc2vpp.acl.util.protocol.ProtoPreBindRuleProducer;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Deny;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.AclIpv4HeaderFields;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.AclIpv6HeaderFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.actions.packet.handling.Stateful;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv6;
+
+
+public interface StandardAceDataExtractor extends AddressTranslator, ProtoPreBindRuleProducer {
+
+ /**
+ * Allowed packet-processing actions for Acl's
+ */
+ Map<Class<? extends PacketHandling>, Integer> ACTION_VALUE_PAIRS = ImmutableMap.of(Deny.class, 0, Permit.class, 1,
+ Stateful.class, 2);
+
+ default VppAce fromStandardAce(@Nonnull final Ace ace) {
+ return VppAce.class.cast(ace.getMatches().getAceType());
+ }
+
+ default boolean standardIsIpv6(@Nonnull final Ace ace) {
+ return VppAce.class.cast(ace.getMatches().getAceType()).getVppAceNodes().getAceIpVersion() instanceof AceIpv6;
+ }
+
+ default byte[] ipv4SourceAddress(@Nonnull final VppAce ace) {
+ return ipv4AddressPrefixToArray(
+ AclIpv4HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getSourceIpv4Network());
+ }
+
+ default byte ipv4SourceAddressPrefix(@Nonnull final VppAce ace) {
+ return extractPrefix(AclIpv4HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getSourceIpv4Network());
+ }
+
+ default byte[] ipv4DestinationAddress(@Nonnull final VppAce ace) {
+ return ipv4AddressPrefixToArray(
+ AclIpv4HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getDestinationIpv4Network());
+ }
+
+ default byte ipv4DestinationAddressPrefix(@Nonnull final VppAce ace) {
+ return extractPrefix(AceIpv4.class.cast(ace.getVppAceNodes().getAceIpVersion()).getDestinationIpv4Network());
+ }
+
+ default byte[] ipv6SourceAddress(@Nonnull final VppAce ace) {
+ return ipv6AddressPrefixToArray(
+ AclIpv6HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getSourceIpv6Network());
+ }
+
+ default byte ipv6SourceAddressPrefix(@Nonnull final VppAce ace) {
+ return extractPrefix(AclIpv6HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getSourceIpv6Network());
+ }
+
+ default byte[] ipv6DestinationAddress(@Nonnull final VppAce ace) {
+ return ipv6AddressPrefixToArray(
+ AclIpv6HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getDestinationIpv6Network());
+ }
+
+ default byte ipv6DestinationAddressPrefix(@Nonnull final VppAce ace) {
+ return extractPrefix(AclIpv6HeaderFields.class.cast(ace.getVppAceNodes().getAceIpVersion()).getDestinationIpv6Network());
+ }
+
+ default byte standardAction(@Nonnull final Ace ace) {
+ final PacketHandling action = ace.getActions().getPacketHandling();
+ return ACTION_VALUE_PAIRS.get(ACTION_VALUE_PAIRS.keySet().stream()
+ .filter(aClass -> aClass.isInstance(action))
+ .findAny()
+ .orElseThrow(() -> new IllegalArgumentException(
+ String.format("Unsupported packet-handling action %s for ACE %s", action,
+ ace.getRuleName())))).byteValue();
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclDataExtractor.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclDataExtractor.java
new file mode 100644
index 000000000..77e58fe0c
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclDataExtractor.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.acl;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppMacipAce;
+
+/**
+ * Extracts data from Acls.
+ * Expects data validated by {@link AclValidator}
+ */
+public interface AclDataExtractor {
+
+ /**
+ * Checks if provided {@link Acl} has aces of type {@link VppAce}
+ */
+ default boolean isStandardAcl(@Nonnull final Acl acl) {
+ return acl.getAccessListEntries().getAce().stream()
+ .map(Ace::getMatches)
+ .map(Matches::getAceType)
+ .filter(aceType -> aceType instanceof VppAce)
+ .findAny()
+ .isPresent();
+ }
+
+ /**
+ * Checks if provided {@link Acl} has aces of type {@link VppMacipAce}
+ */
+ default boolean isMacIpAcl(@Nonnull final Acl acl) {
+ return acl.getAccessListEntries().getAce().stream()
+ .map(Ace::getMatches)
+ .map(Matches::getAceType)
+ .filter(aceType -> aceType instanceof VppMacipAce)
+ .findAny()
+ .isPresent();
+ }
+
+ default List<Ace> getAces(@Nonnull final Acl acl) {
+ return acl.getAccessListEntries().getAce();
+ }
+
+ /**
+ * Convert {@link Acl} name to byte array as UTF_8
+ */
+ default byte[] getAclNameAsBytes(@Nonnull final Acl acl) {
+ return acl.getAclName().getBytes(StandardCharsets.UTF_8);
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclValidator.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclValidator.java
new file mode 100644
index 000000000..3779b82bf
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclValidator.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.acl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.AceType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppMacipAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppMacipAce;
+
+/**
+ * Validate Acl data if processable by vpp
+ */
+public interface AclValidator {
+
+ Set<Class<? extends AclBase>> SUPPORTED_ACL_TYPES = ImmutableSet.of(VppAcl.class, VppMacipAcl.class);
+
+ Map<Class<? extends AclBase>, Class<? extends AceType>> ACL_ACE_PAIRS = ImmutableMap.of(
+ VppAcl.class, VppAce.class,
+ VppMacipAcl.class, VppMacipAce.class);
+
+ static void isSupportedAclType(final Acl acl) {
+ checkArgument(SUPPORTED_ACL_TYPES.contains(acl.getAclType()),
+ "Unsupported Acl type %s detected for acl %s, allowed types are %s", acl.getAclType(),
+ acl.getAclName(), SUPPORTED_ACL_TYPES);
+ }
+
+ static void hasConsistentAceTypeForAclType(final Acl acl) {
+ checkTypesSame(acl.getAccessListEntries().getAce(), acl.getAclName(),
+ checkNotNull(ACL_ACE_PAIRS.get(acl.getAclType()), "Unsupported ACL type %s for ACL %s",
+ acl.getAclType(), acl.getAclName()));
+ }
+
+ static void checkTypesSame(final List<Ace> aces, final String aclName, final Class<? extends AceType> aceType) {
+ final Set<AceType> unsupportedAceTypes = aces.stream()
+ .map(Ace::getMatches)
+ .map(Matches::getAceType)
+ .filter(aceType::equals)
+ .collect(Collectors.toSet());
+ checkArgument(unsupportedAceTypes.isEmpty(), "Detected unsupported ace types [%s] for ACL %s, expected %s",
+ unsupportedAceTypes, aclName, aceType);
+ }
+
+ static void hasAceList(final Acl acl) {
+ //checks if aces are defined
+ checkArgument(!checkNotNull(checkNotNull(acl.getAccessListEntries(), "No access list entries defined")
+ .getAce(), "No aces defined")
+ .isEmpty(), "Empty ace list defined");
+ }
+
+ default void validateAcl(@Nonnull final Acl acl) {
+ hasAceList(acl);
+ isSupportedAclType(acl);
+ hasConsistentAceTypeForAclType(acl);
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclWriter.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclWriter.java
new file mode 100644
index 000000000..1fecc6c5b
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/acl/AclWriter.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.acl;
+
+import io.fd.hc2vpp.acl.util.ace.AceConverter;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.acl.dto.AclAddReplace;
+import io.fd.vpp.jvpp.acl.dto.AclAddReplaceReply;
+import io.fd.vpp.jvpp.acl.dto.AclDel;
+import io.fd.vpp.jvpp.acl.dto.MacipAclAdd;
+import io.fd.vpp.jvpp.acl.dto.MacipAclAddReply;
+import io.fd.vpp.jvpp.acl.dto.MacipAclDel;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Write standard and mac-ip acls
+ */
+public interface AclWriter extends AclDataExtractor, AceConverter, JvppReplyConsumer {
+
+ int ACL_INDEX_CREATE_NEW = -1;
+
+ default void addStandardAcl(@Nonnull final FutureJVppAclFacade futureFacade,
+ @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+ @Nonnull final NamingContext standardAclContext,
+ @Nonnull final MappingContext mappingContext) throws WriteFailedException {
+
+ final AclAddReplace request = new AclAddReplace();
+
+ request.tag = getAclNameAsBytes(acl);
+ request.aclIndex = ACL_INDEX_CREATE_NEW;
+ request.r = convertToStandardAclRules(getAces(acl));
+ request.count = request.r.length;
+
+ final AclAddReplaceReply reply =
+ getReplyForWrite(futureFacade.aclAddReplace(request).toCompletableFuture(), id);
+
+ // maps new acl to returned index
+ standardAclContext.addName(reply.aclIndex, acl.getAclName(), mappingContext);
+ }
+
+ // according to vpp team, this was tested extensively, and should work
+ default void updateStandardAcl(@Nonnull final FutureJVppAclFacade futureFacade,
+ @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+ @Nonnull final NamingContext standardAclContext,
+ @Nonnull final MappingContext mappingContext) throws WriteFailedException {
+
+ final AclAddReplace request = new AclAddReplace();
+
+ request.tag = getAclNameAsBytes(acl);
+ // by setting existing index, request is resolved as update
+ request.aclIndex = standardAclContext.getIndex(acl.getAclName(), mappingContext);
+ request.r = convertToStandardAclRules(getAces(acl));
+ request.count = request.r.length;
+
+ getReplyForWrite(futureFacade.aclAddReplace(request).toCompletableFuture(), id);
+
+ }
+
+
+ default void deleteStandardAcl(@Nonnull final FutureJVppAclFacade futureFacade,
+ @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+ @Nonnull final NamingContext standardAclContext,
+ @Nonnull final MappingContext mappingContext) throws WriteFailedException {
+
+ final AclDel request = new AclDel();
+ final String aclName = acl.getAclName();
+ request.aclIndex = standardAclContext.getIndex(aclName, mappingContext);
+
+ getReplyForDelete(futureFacade.aclDel(request).toCompletableFuture(), id);
+
+ // removes mapping after successful delete
+ standardAclContext.removeName(aclName, mappingContext);
+ }
+
+ default void addMacIpAcl(@Nonnull final FutureJVppAclFacade futureFacade,
+ @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+ @Nonnull final NamingContext macIpAclContext,
+ @Nonnull final MappingContext mappingContext) throws WriteFailedException {
+ final MacipAclAdd request = new MacipAclAdd();
+
+ request.tag = getAclNameAsBytes(acl);
+ request.r = convertToMacIpAclRules(getAces(acl));
+ request.count = request.r.length;
+
+ final MacipAclAddReply reply = getReplyForWrite(futureFacade.macipAclAdd(request).toCompletableFuture(), id);
+
+ // map mac-ip acl to returned index
+ macIpAclContext.addName(reply.aclIndex, acl.getAclName(), mappingContext);
+ }
+
+ default void deleteMacIpAcl(@Nonnull final FutureJVppAclFacade futureFacade,
+ @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+ @Nonnull final NamingContext macIpAclContext,
+ @Nonnull final MappingContext mappingContext) throws WriteFailedException {
+ final MacipAclDel request = new MacipAclDel();
+ final String aclName = acl.getAclName();
+ request.aclIndex = macIpAclContext.getIndex(aclName, mappingContext);
+
+ getReplyForDelete(futureFacade.macipAclDel(request).toCompletableFuture(), id);
+
+ macIpAclContext.removeName(aclName, mappingContext);
+ }
+
+
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequest.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequest.java
new file mode 100644
index 000000000..e3c5b727e
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.acl.util.iface.acl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.acl.dto.AclInterfaceSetAclList;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Multi-assignment single-request taking advantage from acl_interface_set_acl_list api
+ */
+public class AclInterfaceAssignmentRequest implements JvppReplyConsumer, ByteDataTranslator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AclInterfaceAssignmentRequest.class);
+
+ private final MappingContext mappingContext;
+ private InstanceIdentifier<Acl> identifier;
+ private List<String> inputAclNames;
+ private List<String> outputAclNames;
+ private NamingContext standardAclContext;
+ private NamingContext interfaceContext;
+
+
+ private AclInterfaceAssignmentRequest(final MappingContext mappingContext) {
+ this.mappingContext = checkNotNull(mappingContext, "Mapping context cannot be null");
+ }
+
+ public static AclInterfaceAssignmentRequest create(@Nonnull final MappingContext mappingContext) {
+ return new AclInterfaceAssignmentRequest(mappingContext);
+ }
+
+ public AclInterfaceAssignmentRequest identifier(
+ @Nonnull final InstanceIdentifier<Acl> identifier) {
+ this.identifier = identifier;
+ return this;
+ }
+
+ public AclInterfaceAssignmentRequest inputAclNames(@Nonnull final List<String> inputAclNames) {
+ this.inputAclNames = inputAclNames;
+ return this;
+ }
+
+ public AclInterfaceAssignmentRequest outputAclNames(@Nonnull final List<String> outputAclNames) {
+ this.outputAclNames = outputAclNames;
+ return this;
+ }
+
+ public AclInterfaceAssignmentRequest standardAclContext(@Nonnull final NamingContext standardAclContext) {
+ this.standardAclContext = standardAclContext;
+ return this;
+ }
+
+ public AclInterfaceAssignmentRequest interfaceContext(@Nonnull final NamingContext interfaceContext) {
+ this.interfaceContext = interfaceContext;
+ return this;
+ }
+
+ private void checkValidRequest() {
+ checkNotNull(identifier, "Identifier cannot be null");
+ checkNotNull(inputAclNames, "Input ACL names cannot be null");
+ checkNotNull(outputAclNames, "Output ACL names cannot be null");
+ checkNotNull(standardAclContext, "ACL context cannot be null");
+ checkNotNull(interfaceContext, "Interface context cannot be null");
+ }
+
+ public void executeAsCreate(@Nonnull final FutureJVppAclFacade api) throws WriteFailedException {
+ checkValidRequest();
+ final String interfaceName = identifier.firstKeyOf(Interface.class).getName();
+
+ // locking on mapping context, to prevent modifying of mappings (for both contexts) during binding/execution of request
+ synchronized (mappingContext) {
+ LOG.debug(
+ "Executing acl interface assignment write request for interface={}, input ACL's={},output ACL's={}",
+ interfaceName, inputAclNames, outputAclNames);
+
+ getReplyForWrite(api.aclInterfaceSetAclList(createRequest(interfaceName)).toCompletableFuture(),
+ identifier);
+ LOG.debug(
+ "Acl interface assignment write request for interface={}, input ACL's={},output ACL's={} successfully passed",
+ interfaceName, inputAclNames, outputAclNames);
+ }
+ }
+
+ public void executeAsUpdate(@Nonnull final FutureJVppAclFacade api, final Acl before, final Acl after)
+ throws WriteFailedException {
+ checkValidRequest();
+ final String interfaceName = identifier.firstKeyOf(Interface.class).getName();
+
+ // locking on mapping context, to prevent modifying of mappings (for both contexts) during binding/execution of request
+ synchronized (mappingContext) {
+ LOG.debug(
+ "Executing acl interface assignment update request for interface={}, input ACL's={},output ACL's={}",
+ interfaceName, inputAclNames, outputAclNames);
+
+ getReplyForUpdate(api.aclInterfaceSetAclList(createRequest(interfaceName)).toCompletableFuture(),
+ identifier, before, after);
+ LOG.debug(
+ "Acl interface assignment update request for interface={}, input ACL's={},output ACL's={} successfully passed",
+ interfaceName, inputAclNames, outputAclNames);
+ }
+ }
+
+ public void executeAsDelete(@Nonnull final FutureJVppAclFacade api) throws WriteFailedException {
+ checkValidRequest();
+ final String interfaceName = identifier.firstKeyOf(Interface.class).getName();
+
+ // locking on mapping context, to prevent modifying of mappings (for both contexts) during binding/execution of request
+ synchronized (mappingContext) {
+ LOG.debug(
+ "Executing acl interface assignment delete request for interface={}, input ACL's={},output ACL's={}",
+ interfaceName, inputAclNames, outputAclNames);
+
+ getReplyForDelete(api.aclInterfaceSetAclList(createRequest(interfaceName)).toCompletableFuture(),
+ identifier);
+ LOG.debug(
+ "Acl interface assignment delete request for interface={}, input ACL's={},output ACL's={} successfully passed",
+ interfaceName, inputAclNames, outputAclNames);
+ }
+ }
+
+ // synchronized on higher layer
+ private AclInterfaceSetAclList createRequest(final String interfaceName) {
+
+ AclInterfaceSetAclList request = new AclInterfaceSetAclList();
+ request.swIfIndex = interfaceContext.getIndex(interfaceName, mappingContext);
+ request.nInput = (byte) inputAclNames.size();
+ request.count = (byte) (inputAclNames.size() + outputAclNames.size());
+ request.acls = Stream.concat(inputAclNames.stream(), outputAclNames.stream())
+ .mapToInt(aclName -> standardAclContext.getIndex(aclName, mappingContext))
+ .toArray();
+ return request;
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequest.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequest.java
new file mode 100644
index 000000000..f8d726397
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.acl.util.iface.macip;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.acl.dto.MacipAclInterfaceAddDel;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MacIpInterfaceAssignmentRequest implements ByteDataTranslator, JvppReplyConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MacIpInterfaceAssignmentRequest.class);
+
+ private final boolean isNew;
+ private final MappingContext mappingContext;
+ private InstanceIdentifier<VppMacipAcl> identifier;
+ private String aclName;
+ private NamingContext macIpAclContext;
+ private NamingContext interfaceContext;
+
+
+ private MacIpInterfaceAssignmentRequest(final boolean isNew, final MappingContext mappingContext) {
+ this.isNew = isNew;
+ this.mappingContext = checkNotNull(mappingContext, "Mapping context cannot be null");
+ }
+
+ public static MacIpInterfaceAssignmentRequest addNew(@Nonnull final MappingContext mappingContext) {
+ return new MacIpInterfaceAssignmentRequest(true, mappingContext);
+ }
+
+ public static MacIpInterfaceAssignmentRequest deleteExisting(@Nonnull final MappingContext mappingContext) {
+ return new MacIpInterfaceAssignmentRequest(false, mappingContext);
+ }
+
+ public MacIpInterfaceAssignmentRequest identifier(@Nonnull final InstanceIdentifier<VppMacipAcl> identifier) {
+ this.identifier = identifier;
+ return this;
+ }
+
+ public MacIpInterfaceAssignmentRequest aclName(@Nonnull final String aclName) {
+ this.aclName = aclName;
+ return this;
+ }
+
+ public MacIpInterfaceAssignmentRequest macIpAclContext(@Nonnull final NamingContext macIpAclContext) {
+ this.macIpAclContext = macIpAclContext;
+ return this;
+ }
+
+ public MacIpInterfaceAssignmentRequest interfaceContext(@Nonnull final NamingContext interfaceContext) {
+ this.interfaceContext = interfaceContext;
+ return this;
+ }
+
+ private void checkValidRequest() {
+ checkNotNull(identifier, "Identifier cannot be null");
+ checkNotNull(aclName, "ACL name cannot be null");
+ checkNotNull(macIpAclContext, "ACL context cannot be null");
+ checkNotNull(interfaceContext, "Interface context cannot be null");
+ }
+
+ public void execute(@Nonnull final FutureJVppAclFacade api)
+ throws WriteFailedException {
+
+ // locking on mapping context, to prevent modifying of mappings (for both contexts) during execution of request
+ synchronized (mappingContext) {
+ checkValidRequest();
+
+ final String interfaceName = identifier.firstKeyOf(Interface.class).getName();
+
+ MacipAclInterfaceAddDel request = new MacipAclInterfaceAddDel();
+ request.isAdd = booleanToByte(isNew);
+ request.aclIndex = macIpAclContext.getIndex(aclName, mappingContext);
+ request.swIfIndex =
+ interfaceContext.getIndex(interfaceName, mappingContext);
+
+ LOG.debug("Executing mac-ip interface assignment request for isNew={},aclName={},interfaceName={}", isNew,
+ aclName, interfaceName);
+ getReplyForWrite(api.macipAclInterfaceAddDel(request).toCompletableFuture(), identifier);
+ LOG.debug(
+ "Mac-ip interface assignment request for isNew={},aclName={},interfaceName={} successfully passed",
+ isNew, aclName, interfaceName);
+ }
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducer.java
new file mode 100644
index 000000000..c1f9a40ff
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducer.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.protocol;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static io.fd.hc2vpp.acl.util.protocol.ProtoPreBindRuleProducer.ProtocolPair.pair;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.vpp.jvpp.acl.types.AclRule;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ValueRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.VppAceNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.IpProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.Icmp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.IcmpV6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.Other;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.Tcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.Udp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.icmp.IcmpNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.icmp.v6.IcmpV6Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.tcp.TcpNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.udp.UdpNodes;
+
+/**
+ * Creates ACL rules pre-bind with protocol-related fields.<br>
+ * Support TCP, UDP, ICMP and ICMPv6 protocol numbers according to
+ * <a href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml"> this document </a>
+ */
+public interface ProtoPreBindRuleProducer {
+
+ int ICMP_INDEX = 1;
+ int TCP_INDEX = 6;
+ int UDP_INDEX = 17;
+ int ICMPV6_INDEX = 58;
+
+ Set<ProtocolPair> PROTOCOL_PAIRS = ImmutableSet.of(pair(Icmp.class, ICMP_INDEX), pair(Tcp.class, TCP_INDEX),
+ pair(Udp.class, UDP_INDEX), pair(IcmpV6.class, ICMPV6_INDEX));
+
+ class ProtocolPair {
+ private final Class<? extends IpProtocol> protocolClass;
+ private final int index;
+
+ private ProtocolPair(final Class<? extends IpProtocol> protocolClass, final int index) {
+ this.protocolClass = protocolClass;
+ this.index = index;
+ }
+
+ static ProtocolPair pair(@Nonnull final Class<? extends IpProtocol> protocolClass, @Nonnull final int index) {
+ return new ProtocolPair(protocolClass, index);
+ }
+
+ boolean match(@Nonnull final Class<? extends IpProtocol> protocolClass) {
+ return this.protocolClass.isAssignableFrom(protocolClass);
+ }
+
+ int getIndex() {
+ return this.index;
+ }
+ }
+
+ static byte protocol(final IpProtocol ipProtocol) {
+ final Optional<ProtocolPair> optPair = PROTOCOL_PAIRS.stream()
+ .filter(protocolPair -> protocolPair.match(ipProtocol.getClass()))
+ .findAny();
+
+ if (!optPair.isPresent()) {
+ if (Other.class.isAssignableFrom(ipProtocol.getClass())) {
+ return Other.class.cast(ipProtocol).getOtherNodes().getProtocol().byteValue();
+ }
+
+ throw new IllegalArgumentException(String.format("Unsupported Protocol Type %s", ipProtocol.getClass()));
+ }
+ return (byte) optPair.get().getIndex();
+ }
+
+ static AclRule bindIcmpNodes(AclRule rule, VppAce ace) {
+ final VppAceNodes vppAceNodes = ace.getVppAceNodes();
+ checkArgument(vppAceNodes.getIpProtocol() instanceof Icmp);
+ final IcmpNodes icmp = Icmp.class.cast(vppAceNodes.getIpProtocol()).getIcmpNodes();
+ final ValueRange typesRange = icmp.getIcmpTypeRange();
+ final ValueRange codesRange = icmp.getIcmpCodeRange();
+
+ rule.srcportOrIcmptypeFirst = typesRange.getFirst();
+ rule.srcportOrIcmptypeLast = typesRange.getLast();
+ rule.dstportOrIcmpcodeFirst = codesRange.getFirst();
+ rule.dstportOrIcmpcodeLast = codesRange.getLast();
+
+ return rule;
+ }
+
+ static AclRule bindIcmpv6Nodes(AclRule rule, VppAce ace) {
+ final VppAceNodes vppAceNodes = ace.getVppAceNodes();
+ checkArgument(vppAceNodes.getIpProtocol() instanceof IcmpV6);
+ final IcmpV6Nodes icmpV6 = IcmpV6.class.cast(vppAceNodes.getIpProtocol()).getIcmpV6Nodes();
+ final ValueRange typesRange = icmpV6.getIcmpTypeRange();
+ final ValueRange codesRange = icmpV6.getIcmpCodeRange();
+
+ rule.srcportOrIcmptypeFirst = typesRange.getFirst();
+ rule.srcportOrIcmptypeLast = typesRange.getLast();
+ rule.dstportOrIcmpcodeFirst = codesRange.getFirst();
+ rule.dstportOrIcmpcodeLast = codesRange.getLast();
+
+ return rule;
+ }
+
+
+ static AclRule bindTcpNodes(AclRule rule, VppAce ace) {
+ final VppAceNodes vppAceNodes = ace.getVppAceNodes();
+ checkArgument(vppAceNodes.getIpProtocol() instanceof Tcp);
+
+ final TcpNodes tcp = Tcp.class.cast(vppAceNodes.getIpProtocol()).getTcpNodes();
+ final SourcePortRange sourcePortRange = tcp.getSourcePortRange();
+ final DestinationPortRange destinationPortRange = tcp.getDestinationPortRange();
+
+ rule.srcportOrIcmptypeFirst = portNumber(sourcePortRange.getLowerPort());
+ rule.srcportOrIcmptypeLast = portNumber(sourcePortRange.getUpperPort());
+ rule.dstportOrIcmpcodeFirst = portNumber(destinationPortRange.getLowerPort());
+ rule.dstportOrIcmpcodeLast = portNumber(destinationPortRange.getUpperPort());
+ rule.tcpFlagsMask = tcp.getTcpFlagsMask().byteValue();
+ rule.tcpFlagsValue = tcp.getTcpFlagsValue().byteValue();
+
+ return rule;
+ }
+
+ static AclRule bindUdpNodes(AclRule rule, VppAce ace) {
+ final VppAceNodes vppAceNodes = ace.getVppAceNodes();
+ checkArgument(vppAceNodes.getIpProtocol() instanceof Udp);
+
+ final UdpNodes udp = Udp.class.cast(vppAceNodes.getIpProtocol()).getUdpNodes();
+ final SourcePortRange sourcePortRange = udp.getSourcePortRange();
+ final DestinationPortRange destinationPortRange = udp.getDestinationPortRange();
+
+ rule.srcportOrIcmptypeFirst = portNumber(sourcePortRange.getLowerPort());
+ rule.srcportOrIcmptypeLast = portNumber(sourcePortRange.getUpperPort());
+ rule.dstportOrIcmpcodeFirst = portNumber(destinationPortRange.getLowerPort());
+ rule.dstportOrIcmpcodeLast = portNumber(destinationPortRange.getUpperPort());
+
+ return rule;
+ }
+
+ static AclRule bindDefaultNodes(AclRule rule) {
+ rule.srcportOrIcmptypeFirst = 0;
+ rule.srcportOrIcmptypeLast = (short) 65535;
+ rule.dstportOrIcmpcodeFirst = 0;
+ rule.dstportOrIcmpcodeLast = (short) 65535;
+ rule.tcpFlagsValue = 0;
+ rule.tcpFlagsMask = 0;
+ return rule;
+ }
+
+ static short portNumber(final PortNumber portNumber) {
+ return portNumber.getValue().shortValue();
+ }
+
+ default AclRule createPreBindRule(@Nonnull final VppAce vppAce) {
+ AclRule rule = new AclRule();
+
+ rule.proto = protocol(vppAce.getVppAceNodes().getIpProtocol());
+
+ switch (rule.proto) {
+ case ICMP_INDEX: {
+ return bindIcmpNodes(rule, vppAce);
+ }
+
+ case TCP_INDEX: {
+ return bindTcpNodes(rule, vppAce);
+ }
+
+ case UDP_INDEX: {
+ return bindUdpNodes(rule, vppAce);
+ }
+
+ case ICMPV6_INDEX: {
+ return bindIcmpv6Nodes(rule, vppAce);
+ }
+ default: {
+ return bindDefaultNodes(rule);
+ }
+ }
+
+ }
+
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizer.java
new file mode 100644
index 000000000..3a4fb0cf3
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizer.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write;
+
+import static java.util.stream.Collectors.toList;
+
+import io.fd.hc2vpp.acl.util.FutureJVppAclCustomizer;
+import io.fd.hc2vpp.acl.util.iface.acl.AclInterfaceAssignmentRequest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+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.acl.future.FutureJVppAclFacade;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclsBaseAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAcls;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Handles acl assignments(only standard ones, mac-ip have dedicated customizer)
+ */
+public class InterfaceAclCustomizer extends FutureJVppAclCustomizer implements WriterCustomizer<Acl> {
+
+ private final NamingContext interfaceContext;
+ private final NamingContext standardAclContext;
+
+ public InterfaceAclCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final NamingContext standardAclContext) {
+ super(jVppAclFacade);
+ this.interfaceContext = interfaceContext;
+ this.standardAclContext = standardAclContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ AclInterfaceAssignmentRequest.create(writeContext.getMappingContext())
+ .standardAclContext(standardAclContext)
+ .interfaceContext(interfaceContext)
+ .identifier(id)
+ .inputAclNames(getAclNames(dataAfter.getIngress()))
+ .outputAclNames(getAclNames(dataAfter.getEgress()))
+ .executeAsCreate(getjVppAclFacade());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+ @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ AclInterfaceAssignmentRequest.create(writeContext.getMappingContext())
+ .standardAclContext(standardAclContext)
+ .interfaceContext(interfaceContext)
+ .identifier(id)
+ .inputAclNames(getAclNames(dataAfter.getIngress()))
+ .outputAclNames(getAclNames(dataAfter.getEgress()))
+ .executeAsUpdate(getjVppAclFacade(), dataBefore, dataAfter);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ AclInterfaceAssignmentRequest.create(writeContext.getMappingContext())
+ .standardAclContext(standardAclContext)
+ .interfaceContext(interfaceContext)
+ .identifier(id)
+ .inputAclNames(getAclNames(dataBefore.getIngress()))
+ .outputAclNames(getAclNames(dataBefore.getEgress()))
+ .executeAsDelete(getjVppAclFacade());
+ }
+
+ private static List<String> getAclNames(@Nonnull final VppAclsBaseAttributes acls) {
+ if (acls == null || acls.getVppAcls() == null) {
+ return Collections.emptyList();
+ } else {
+ return acls.getVppAcls().stream().map(VppAcls::getName).collect(toList());
+ }
+ }
+
+
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclMacIpCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclMacIpCustomizer.java
new file mode 100644
index 000000000..4b59c83f5
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/InterfaceAclMacIpCustomizer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write;
+
+import static io.fd.hc2vpp.acl.util.iface.macip.MacIpInterfaceAssignmentRequest.addNew;
+import static io.fd.hc2vpp.acl.util.iface.macip.MacIpInterfaceAssignmentRequest.deleteExisting;
+
+import io.fd.hc2vpp.acl.util.FutureJVppAclCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+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.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+
+public class InterfaceAclMacIpCustomizer extends FutureJVppAclCustomizer implements WriterCustomizer<VppMacipAcl> {
+
+ private final NamingContext macIpAclContext;
+ private final NamingContext interfaceContext;
+
+ public InterfaceAclMacIpCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade,
+ @Nonnull final NamingContext macIpAclContext,
+ @Nonnull final NamingContext interfaceContext) {
+ super(jVppAclFacade);
+ this.macIpAclContext = macIpAclContext;
+ this.interfaceContext = interfaceContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<VppMacipAcl> id,
+ @Nonnull final VppMacipAcl dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ addNew(writeContext.getMappingContext())
+ .identifier(id)
+ .aclName(dataAfter.getName())
+ .macIpAclContext(macIpAclContext)
+ .interfaceContext(interfaceContext)
+ .execute(getjVppAclFacade());
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VppMacipAcl> id,
+ @Nonnull final VppMacipAcl dataBefore,
+ @Nonnull final VppMacipAcl dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
+ new UnsupportedOperationException("Operation not supported"));
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VppMacipAcl> id,
+ @Nonnull final VppMacipAcl dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ deleteExisting(writeContext.getMappingContext())
+ .identifier(id)
+ .aclName(dataBefore.getName())
+ .macIpAclContext(macIpAclContext)
+ .interfaceContext(interfaceContext)
+ .execute(getjVppAclFacade());
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/VppAclCustomizer.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/VppAclCustomizer.java
new file mode 100644
index 000000000..a2956784f
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/VppAclCustomizer.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write;
+
+import io.fd.hc2vpp.acl.util.FutureJVppAclCustomizer;
+import io.fd.hc2vpp.acl.util.acl.AclDataExtractor;
+import io.fd.hc2vpp.acl.util.acl.AclValidator;
+import io.fd.hc2vpp.acl.util.acl.AclWriter;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+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.acl.future.FutureJVppAclFacade;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppAclCustomizer extends FutureJVppAclCustomizer
+ implements ListWriterCustomizer<Acl, AclKey>, AclValidator, AclDataExtractor, AclWriter {
+
+ private final NamingContext standardAclContext;
+ private final NamingContext macIpAclContext;
+
+ public VppAclCustomizer(@Nonnull final FutureJVppAclFacade jVppAclFacade,
+ @Nonnull final NamingContext standardAclContext,
+ @Nonnull final NamingContext macIpAclContext) {
+ super(jVppAclFacade);
+ this.standardAclContext = standardAclContext;
+ this.macIpAclContext = macIpAclContext;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ validateAcl(dataAfter);
+
+ final MappingContext mappingContext = writeContext.getMappingContext();
+
+ if (isStandardAcl(dataAfter)) {
+ addStandardAcl(getjVppAclFacade(), id, dataAfter, standardAclContext, mappingContext);
+ } else if (isMacIpAcl(dataAfter)) {
+ addMacIpAcl(getjVppAclFacade(), id, dataAfter, macIpAclContext, mappingContext);
+ } else {
+ // double check, first one done by validation
+ throw new WriteFailedException.CreateFailedException(id, dataAfter,
+ new IllegalArgumentException("Unsupported acl option"));
+ }
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+ @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ validateAcl(dataAfter);
+
+ final MappingContext mappingContext = writeContext.getMappingContext();
+
+ if (isStandardAcl(dataAfter)) {
+ updateStandardAcl(getjVppAclFacade(), id, dataAfter, standardAclContext, mappingContext);
+ } else if (isMacIpAcl(dataAfter)) {
+ synchronized (macIpAclContext) {
+ // there is no direct support for update of mac-ip acl, but only one is allowed per interface
+ // so it is atomic from vpp standpoint. Enclosed in synchronized block to prevent issues with
+ // multiple threads managing naming context
+ deleteMacIpAcl(getjVppAclFacade(), id, dataBefore, macIpAclContext, mappingContext);
+ addMacIpAcl(getjVppAclFacade(), id, dataAfter, macIpAclContext, mappingContext);
+ }
+ } else {
+ // double check, first one done by validation
+ throw new WriteFailedException.CreateFailedException(id, dataAfter,
+ new IllegalArgumentException("Unsupported acl option"));
+ }
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ // According to VPP team, acl references should be removed before trying to remove ACL
+ // For mac-ip, reference should be removed during removal of mac-ip, so no need to check in hc
+ validateAcl(dataBefore);
+
+ final MappingContext mappingContext = writeContext.getMappingContext();
+
+ if (isStandardAcl(dataBefore)) {
+ deleteStandardAcl(getjVppAclFacade(), id, dataBefore, standardAclContext, mappingContext);
+ } else if (isMacIpAcl(dataBefore)) {
+ deleteMacIpAcl(getjVppAclFacade(), id, dataBefore, macIpAclContext, mappingContext);
+ } else {
+ // double check, first one done by validation
+ throw new WriteFailedException.DeleteFailedException(id,
+ new IllegalArgumentException("Unsupported acl option"));
+ }
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/AbstractAclWriterFactory.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/AbstractAclWriterFactory.java
new file mode 100644
index 000000000..fe22f2fd7
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/AbstractAclWriterFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write.factory;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.acl.AclModule;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+
+/**
+ * Created by jsrnicek on 12.12.2016.
+ */
+class AbstractAclWriterFactory {
+
+ @Inject
+ protected FutureJVppAclFacade futureAclFacade;
+
+ @Inject
+ @Named(AclModule.STANDARD_ACL_CONTEXT_NAME)
+ protected NamingContext standardAclContext;
+
+ @Inject
+ @Named(AclModule.MAC_IP_ACL_CONTEXT_NAME)
+ protected NamingContext macIpAClContext;
+
+ @Inject
+ @Named("interface-context")
+ protected NamingContext interfaceContext;
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/InterfaceAclWriterFactory.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/InterfaceAclWriterFactory.java
new file mode 100644
index 000000000..6598aae9c
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/InterfaceAclWriterFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write.factory;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.acl.write.InterfaceAclCustomizer;
+import io.fd.hc2vpp.acl.write.InterfaceAclMacIpCustomizer;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.acls.base.attributes.VppAcls;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceAclWriterFactory extends AbstractAclWriterFactory implements WriterFactory {
+
+ private static final InstanceIdentifier<Acl> ACL_IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class)
+ .augmentation(VppAclInterfaceAugmentation.class).child(Acl.class);
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ registry.subtreeAdd(aclHandledChildren(InstanceIdentifier.create(Acl.class)),
+ new GenericWriter<>(ACL_IID,
+ new InterfaceAclCustomizer(futureAclFacade, interfaceContext, standardAclContext)));
+
+ registry.add(new GenericWriter<>(ACL_IID.child(Ingress.class).child(VppMacipAcl.class),
+ new InterfaceAclMacIpCustomizer(futureAclFacade, macIpAClContext, interfaceContext)));
+ }
+
+ private Set<InstanceIdentifier<?>> aclHandledChildren(final InstanceIdentifier<Acl> parentId) {
+ return ImmutableSet.of(parentId.child(Ingress.class),
+ parentId.child(Ingress.class).child(VppAcls.class),
+ parentId.child(Egress.class),
+ parentId.child(Egress.class).child(VppAcls.class));
+ }
+}
diff --git a/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/VppAclWriterFactory.java b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/VppAclWriterFactory.java
new file mode 100644
index 000000000..546924ee3
--- /dev/null
+++ b/acl/acl-impl/src/main/java/io/fd/hc2vpp/acl/write/factory/VppAclWriterFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write.factory;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.acl.write.VppAclCustomizer;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Actions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.VppAceNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.macip.ace.VppMacipAceNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.icmp.header.fields.IcmpCodeRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.icmp.header.fields.IcmpTypeRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.icmp.IcmpNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.icmp.v6.IcmpV6Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.other.OtherNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.tcp.TcpNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.ip.protocol.header.fields.ip.protocol.udp.UdpNodes;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppAclWriterFactory extends AbstractAclWriterFactory implements WriterFactory {
+
+ private static Set<InstanceIdentifier<?>> vppAclCustomizerHandledChildren(final InstanceIdentifier<Acl> parentId) {
+ final InstanceIdentifier<Matches> matchesIid =
+ parentId.child(AccessListEntries.class).child(Ace.class).child(Matches.class);
+ return ImmutableSet.of(parentId.child(AccessListEntries.class),
+ parentId.child(AccessListEntries.class).child(Ace.class),
+ parentId.child(AccessListEntries.class).child(Ace.class).child(Matches.class),
+ parentId.child(AccessListEntries.class).child(Ace.class).child(Actions.class),
+ matchesIid,
+ matchesIid.child(VppMacipAceNodes.class),
+ matchesIid.child(VppAceNodes.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpNodes.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpNodes.class).child(IcmpCodeRange.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpNodes.class).child(IcmpTypeRange.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpV6Nodes.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpV6Nodes.class).child(IcmpCodeRange.class),
+ matchesIid.child(VppAceNodes.class).child(IcmpV6Nodes.class).child(IcmpTypeRange.class),
+ matchesIid.child(VppAceNodes.class).child(UdpNodes.class),
+ matchesIid.child(VppAceNodes.class).child(UdpNodes.class).child(SourcePortRange.class),
+ matchesIid.child(VppAceNodes.class).child(UdpNodes.class).child(DestinationPortRange.class),
+ matchesIid.child(VppAceNodes.class).child(TcpNodes.class),
+ matchesIid.child(VppAceNodes.class).child(TcpNodes.class).child(SourcePortRange.class),
+ matchesIid.child(VppAceNodes.class).child(TcpNodes.class).child(DestinationPortRange.class),
+ matchesIid.child(VppAceNodes.class).child(OtherNodes.class)
+
+ );
+ }
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+ final InstanceIdentifier<AccessLists> rootNode = InstanceIdentifier.create(AccessLists.class);
+
+ registry.subtreeAdd(vppAclCustomizerHandledChildren(InstanceIdentifier.create(Acl.class)),
+ new GenericListWriter<>(rootNode.child(Acl.class),
+ new VppAclCustomizer(futureAclFacade, standardAclContext, macIpAClContext)));
+ }
+}
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclModuleTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclModuleTest.java
new file mode 100644
index 000000000..671cd283c
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclModuleTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Named;
+import com.google.inject.testing.fieldbinder.Bind;
+import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+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.write.WriterFactory;
+import io.fd.vpp.jvpp.JVppRegistry;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+
+public class AclModuleTest {
+
+ @Named("honeycomb-context")
+ @Bind
+ @Mock
+ private DataBroker honeycombContext;
+
+ @Named("honeycomb-initializer")
+ @Bind
+ @Mock
+ private DataBroker honeycombInitializer;
+
+ @Named("interface-context")
+ @Bind
+ private NamingContext interfaceContext = new NamingContext("iface", "interface-context");
+
+ @Bind
+ @Mock
+ private JVppRegistry registry;
+
+ @Inject
+ private Set<WriterFactory> writerFactories = new HashSet<>();
+
+ @Inject
+ private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ // AclModule adds readers under InterfacesState
+ // because readers for parents need to be present (are part of V3poModule)
+ // add structural readers here (better than maven dependency).
+
+ Guice.createInjector(binder -> Multibinder.newSetBinder(binder, ReaderFactory.class)
+ .addBinding().toInstance(registry -> {
+ registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class),
+ InterfacesStateBuilder.class);
+ registry.addStructuralReader(InstanceIdentifier.create(InterfacesState.class).child(Interface.class),
+ InterfaceBuilder.class);
+ }), new AclModule(MockJVppAclProvider.class), BoundFieldModule.of(this)).injectMembers(this);
+ }
+
+ @Test
+ public void testWriterFactories() throws Exception {
+ assertThat(writerFactories, is(not(empty())));
+
+ final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder();
+ writerFactories.forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ }
+
+ @Test
+ public void testReaderFactories() throws Exception {
+ assertThat(readerFactories, is(not(empty())));
+
+ final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder();
+ readerFactories.forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ }
+
+ private static final class MockJVppAclProvider implements Provider<FutureJVppAclFacade> {
+
+ @Override
+ public FutureJVppAclFacade get() {
+ return mock(FutureJVppAclFacade.class);
+ }
+ }
+}
+
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclTestSchemaContext.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclTestSchemaContext.java
new file mode 100644
index 000000000..dd3c1caa9
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/AclTestSchemaContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+
+
+public interface AclTestSchemaContext {
+
+ @SchemaContextProvider
+ default ModuleInfoBackedContext context() {
+ ModuleInfoBackedContext context = ModuleInfoBackedContext.create();
+ context.addModuleInfos(ImmutableSet
+ .of(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.$YangModuleInfoImpl
+ .getInstance(),
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.$YangModuleInfoImpl
+ .getInstance()));
+ return context;
+ }
+}
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequestTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequestTest.java
new file mode 100644
index 000000000..2224d11b0
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/acl/AclInterfaceAssignmentRequestTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.iface.acl;
+
+import static io.fd.hc2vpp.acl.util.iface.acl.AclInterfaceAssignmentRequest.create;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.collect.ImmutableList;
+import io.fd.hc2vpp.common.test.util.FutureProducer;
+import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.acl.dto.AclInterfaceSetAclList;
+import io.fd.vpp.jvpp.acl.dto.AclInterfaceSetAclListReply;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclInterfaceAssignmentRequestTest implements NamingContextHelper, FutureProducer {
+
+ private static final String INTERFACE_NAME = "iface";
+ private static final int INTERFACE_INDEX = 4;
+
+ private static final String ACL_NAME_1 = "acl-1";
+ private static final String ACL_NAME_2 = "acl-2";
+ private static final String ACL_NAME_3 = "acl-3";
+ private static final String ACL_NAME_4 = "acl-4";
+ private static final String ACL_NAME_5 = "acl-5";
+
+ private static final int ACL_INDEX_1 = 2;
+ private static final int ACL_INDEX_2 = 7;
+ private static final int ACL_INDEX_3 = 4;
+ private static final int ACL_INDEX_4 = 5;
+ private static final int ACL_INDEX_5 = 1;
+
+ @Captor
+ private ArgumentCaptor<AclInterfaceSetAclList> requestCaptor;
+
+ @Mock
+ private FutureJVppAclFacade api;
+
+ @Mock
+ private MappingContext mappingContext;
+
+ private InstanceIdentifier<Acl> validIdentifier;
+ private NamingContext interfaceContext;
+ private NamingContext aclContext;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+
+ validIdentifier = InstanceIdentifier.create(Interfaces.class).
+ child(Interface.class, new InterfaceKey(INTERFACE_NAME))
+ .augmentation(VppAclInterfaceAugmentation.class)
+ .child(Acl.class);
+
+ interfaceContext = new NamingContext("iface", "interface-context");
+ aclContext = new NamingContext("acl", "acl-context");
+
+ defineMapping(mappingContext, INTERFACE_NAME, INTERFACE_INDEX, "interface-context");
+
+ defineMapping(mappingContext, ACL_NAME_1, ACL_INDEX_1, "acl-context");
+ defineMapping(mappingContext, ACL_NAME_2, ACL_INDEX_2, "acl-context");
+ defineMapping(mappingContext, ACL_NAME_3, ACL_INDEX_3, "acl-context");
+ defineMapping(mappingContext, ACL_NAME_4, ACL_INDEX_4, "acl-context");
+ defineMapping(mappingContext, ACL_NAME_5, ACL_INDEX_5, "acl-context");
+
+ when(api.aclInterfaceSetAclList(any())).thenReturn(future(new AclInterfaceSetAclListReply()));
+ }
+
+ @Test
+ public void verifyNegativeCases() throws WriteFailedException {
+ verifyVariant(create(mappingContext));
+
+ verifyVariant(create(mappingContext).identifier(validIdentifier));
+
+ verifyVariant(create(mappingContext).identifier(validIdentifier).interfaceContext(interfaceContext));
+
+ verifyVariant(create(mappingContext).identifier(validIdentifier).interfaceContext(interfaceContext)
+ .standardAclContext(aclContext));
+
+ verifyVariant(create(mappingContext).identifier(validIdentifier).interfaceContext(interfaceContext)
+ .standardAclContext(aclContext).inputAclNames(Collections.emptyList()));
+
+ verifyVariant(create(mappingContext).identifier(validIdentifier).interfaceContext(interfaceContext)
+ .standardAclContext(aclContext).outputAclNames(Collections.emptyList()));
+ }
+
+ private void verifyVariant(final AclInterfaceAssignmentRequest request) throws WriteFailedException {
+ verifyCreateFailsWithNullPointer(request);
+ verifyUpdateFailsWithNullPointer(request);
+ verifyDeleteFailsWithNullPointer(request);
+ }
+
+ @Test
+ public void executeAsCreate() throws Exception {
+
+ createValidRequest().executeAsCreate(api);
+ createValidRequest().executeAsUpdate(api, mock(Acl.class), mock(Acl.class));
+ createValidRequest().executeAsDelete(api);
+
+ verify(api, times(3)).aclInterfaceSetAclList(requestCaptor.capture());
+ requestCaptor.getAllValues().forEach(AclInterfaceAssignmentRequestTest::verifyValidRequest);
+ }
+
+ private AclInterfaceAssignmentRequest createValidRequest() {
+ return create(mappingContext)
+ .identifier(validIdentifier)
+ .inputAclNames(ImmutableList.of(ACL_NAME_1, ACL_NAME_2, ACL_NAME_3))
+ .outputAclNames(ImmutableList.of(ACL_NAME_4, ACL_NAME_5))
+ .standardAclContext(aclContext)
+ .interfaceContext(interfaceContext);
+ }
+
+ private static void verifyValidRequest(final AclInterfaceSetAclList request) {
+ assertNotNull(request);
+ assertEquals(5, request.count);
+ assertEquals(3, request.nInput);
+ assertTrue(Arrays.equals(new int[]{ACL_INDEX_1, ACL_INDEX_2, ACL_INDEX_3, ACL_INDEX_4, ACL_INDEX_5},
+ request.acls));
+ }
+
+ private void verifyCreateFailsWithNullPointer(final AclInterfaceAssignmentRequest request)
+ throws WriteFailedException {
+ try {
+ request.executeAsCreate(api);
+ } catch (NullPointerException e) {
+ return;
+ }
+ fail("Test should have thrown null pointer");
+ }
+
+ private void verifyUpdateFailsWithNullPointer(final AclInterfaceAssignmentRequest request)
+ throws WriteFailedException {
+ try {
+ request.executeAsUpdate(api, mock(Acl.class), mock(Acl.class));
+ } catch (NullPointerException e) {
+ return;
+ }
+ fail("Test should have thrown null pointer");
+ }
+
+ private void verifyDeleteFailsWithNullPointer(final AclInterfaceAssignmentRequest request)
+ throws WriteFailedException {
+ try {
+ request.executeAsCreate(api);
+ } catch (NullPointerException e) {
+ return;
+ }
+ fail("Test should have thrown null pointer");
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequestTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequestTest.java
new file mode 100644
index 000000000..e81550390
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/iface/macip/MacIpInterfaceAssignmentRequestTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.iface.macip;
+
+import static io.fd.hc2vpp.acl.util.iface.macip.MacIpInterfaceAssignmentRequest.addNew;
+import static io.fd.hc2vpp.acl.util.iface.macip.MacIpInterfaceAssignmentRequest.deleteExisting;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+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 static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.test.util.FutureProducer;
+import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.acl.dto.MacipAclInterfaceAddDel;
+import io.fd.vpp.jvpp.acl.dto.MacipAclInterfaceAddDelReply;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214._interface.acl.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.vpp.macip.acls.base.attributes.VppMacipAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Created by jsrnicek on 13.12.2016.
+ */
+public class MacIpInterfaceAssignmentRequestTest implements NamingContextHelper,FutureProducer {
+
+ private static final String INTERFACE_NAME = "iface";
+ private static final int INTERFACE_INDEX = 4;
+ private static final String ACL_NAME = "mac-ip-acl";
+ private static final int ACL_INDEX = 5;
+
+ @Captor
+ private ArgumentCaptor<MacipAclInterfaceAddDel> requestCaptor;
+
+ @Mock
+ private FutureJVppAclFacade api;
+
+ @Mock
+ private MappingContext mappingContext;
+
+ private InstanceIdentifier<VppMacipAcl> validIdentifier;
+ private NamingContext interfaceContext;
+ private NamingContext macIpAclContext;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+
+ validIdentifier = InstanceIdentifier.create(Interfaces.class).
+ child(Interface.class, new InterfaceKey(INTERFACE_NAME))
+ .augmentation(VppAclInterfaceAugmentation.class)
+ .child(Acl.class)
+ .child(Ingress.class)
+ .child(VppMacipAcl.class);
+
+ interfaceContext = new NamingContext("iface", "interface-context");
+ macIpAclContext = new NamingContext("mac-ip-acl", "mac-ip-acl-context");
+
+ defineMapping(mappingContext, INTERFACE_NAME, INTERFACE_INDEX, "interface-context");
+ defineMapping(mappingContext, ACL_NAME, ACL_INDEX, "mac-ip-acl-context");
+ when(api.macipAclInterfaceAddDel(any())).thenReturn(future(new MacipAclInterfaceAddDelReply()));
+ }
+
+ @Test
+ public void testAddNew() throws Exception {
+ addNew(mappingContext)
+ .aclName(ACL_NAME)
+ .identifier(validIdentifier)
+ .interfaceContext(interfaceContext)
+ .macIpAclContext(macIpAclContext)
+ .execute(api);
+ verify(api, times(1)).macipAclInterfaceAddDel(requestCaptor.capture());
+
+ final MacipAclInterfaceAddDel request = requestCaptor.getValue();
+
+ assertNotNull(request);
+ assertEquals(1, request.isAdd);
+ assertEquals(INTERFACE_INDEX, request.swIfIndex);
+ assertEquals(ACL_INDEX, request.aclIndex);
+ }
+
+ @Test
+ public void testDeleteExisting() throws Exception {
+ deleteExisting(mappingContext)
+ .aclName(ACL_NAME)
+ .identifier(validIdentifier)
+ .interfaceContext(interfaceContext)
+ .macIpAclContext(macIpAclContext)
+ .execute(api);
+ verify(api, times(1)).macipAclInterfaceAddDel(requestCaptor.capture());
+
+ final MacipAclInterfaceAddDel request = requestCaptor.getValue();
+
+ assertNotNull(request);
+ assertEquals(0, request.isAdd);
+ assertEquals(INTERFACE_INDEX, request.swIfIndex);
+ assertEquals(ACL_INDEX, request.aclIndex);
+ }
+
+ @Test
+ public void testInvalidCases() throws Exception {
+ verifyFailsWithNullPointer(addNew(mappingContext));
+ verifyFailsWithNullPointer(addNew(mappingContext).aclName(ACL_NAME));
+ verifyFailsWithNullPointer(addNew(mappingContext).aclName(ACL_NAME).interfaceContext(interfaceContext));
+ verifyFailsWithNullPointer(addNew(mappingContext).aclName(ACL_NAME).interfaceContext(interfaceContext)
+ .macIpAclContext(macIpAclContext));
+ verifyFailsWithNullPointer(addNew(mappingContext).aclName(ACL_NAME).interfaceContext(interfaceContext)
+ .identifier(validIdentifier));
+ }
+
+ private void verifyFailsWithNullPointer(final MacIpInterfaceAssignmentRequest request) throws WriteFailedException {
+ try {
+ request.execute(api);
+ } catch (NullPointerException e) {
+ return;
+ }
+ fail("Test should have thrown null pointer");
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducerTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducerTest.java
new file mode 100644
index 000000000..8f4100349
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/util/protocol/ProtoPreBindRuleProducerTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.util.protocol;
+
+import static org.junit.Assert.assertEquals;
+
+import io.fd.hc2vpp.acl.AclTestSchemaContext;
+import io.fd.honeycomb.test.tools.HoneycombTestRunner;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.vpp.jvpp.acl.types.AclRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
+
+@RunWith(HoneycombTestRunner.class)
+public class ProtoPreBindRuleProducerTest implements ProtoPreBindRuleProducer, AclTestSchemaContext {
+
+ //TODO - remove after resolving how to address identity from different model in textual yang instance identifier
+ private VppAce extractAce(AccessLists accessLists) {
+ return VppAce.class
+ .cast(accessLists.getAcl().get(0).getAccessListEntries().getAce().get(0).getMatches().getAceType());
+ }
+
+ @Test
+ public void testIcmpRule(@InjectTestData(resourcePath = "/rules/icmp-rule.json") AccessLists acls) {
+ final AclRule icmpRule = createPreBindRule(extractAce(acls));
+
+ assertEquals(1, icmpRule.proto);
+ assertEquals(5, icmpRule.srcportOrIcmptypeFirst);
+ assertEquals(8, icmpRule.srcportOrIcmptypeLast);
+ assertEquals(1, icmpRule.dstportOrIcmpcodeFirst);
+ assertEquals(3, icmpRule.dstportOrIcmpcodeLast);
+ assertEquals(0, icmpRule.tcpFlagsMask);
+ assertEquals(0, icmpRule.tcpFlagsValue);
+ }
+
+
+ @Test
+ public void testIcmpv6Rule(@InjectTestData(resourcePath = "/rules/icmp-v6-rule.json") AccessLists acls) {
+ final AclRule icmpv6Rule = createPreBindRule(extractAce(acls));
+
+ assertEquals(58, icmpv6Rule.proto);
+ assertEquals(5, icmpv6Rule.srcportOrIcmptypeFirst);
+ assertEquals(8, icmpv6Rule.srcportOrIcmptypeLast);
+ assertEquals(1, icmpv6Rule.dstportOrIcmpcodeFirst);
+ assertEquals(3, icmpv6Rule.dstportOrIcmpcodeLast);
+ assertEquals(0, icmpv6Rule.tcpFlagsMask);
+ assertEquals(0, icmpv6Rule.tcpFlagsValue);
+ }
+
+ @Test
+ public void testTcpRule(@InjectTestData(resourcePath = "/rules/tcp-rule.json") AccessLists acls) {
+ final AclRule tcpRule = createPreBindRule(extractAce(acls));
+ assertEquals(6, tcpRule.proto);
+ assertEquals(1, tcpRule.srcportOrIcmptypeFirst);
+ assertEquals(5487, tcpRule.srcportOrIcmptypeLast);
+ assertEquals(87, tcpRule.dstportOrIcmpcodeFirst);
+ assertEquals(6745, tcpRule.dstportOrIcmpcodeLast);
+ assertEquals(1, tcpRule.tcpFlagsMask);
+ assertEquals(7, tcpRule.tcpFlagsValue);
+ }
+
+ @Test
+ public void testUdpRule(@InjectTestData(resourcePath = "/rules/udp-rule.json") AccessLists acls) {
+ final AclRule udpRule = createPreBindRule(extractAce(acls));
+ assertEquals(17, udpRule.proto);
+ assertEquals(1, udpRule.srcportOrIcmptypeFirst);
+ assertEquals(5487, udpRule.srcportOrIcmptypeLast);
+ assertEquals(87, udpRule.dstportOrIcmpcodeFirst);
+ assertEquals(6745, udpRule.dstportOrIcmpcodeLast);
+ assertEquals(0, udpRule.tcpFlagsMask);
+ assertEquals(0, udpRule.tcpFlagsValue);
+ }
+
+ @Test
+ public void testOtherRule(@InjectTestData(resourcePath = "/rules/other-rule.json") AccessLists acls) {
+ final AclRule icmpRule = createPreBindRule(extractAce(acls));
+ assertEquals(64, icmpRule.proto);
+ assertEquals(0, icmpRule.srcportOrIcmptypeFirst);
+ assertEquals((short) 65535, icmpRule.srcportOrIcmptypeLast);
+ assertEquals(0, icmpRule.dstportOrIcmpcodeFirst);
+ assertEquals((short) 65535, icmpRule.dstportOrIcmpcodeLast);
+ assertEquals(0, icmpRule.tcpFlagsMask);
+ assertEquals(0, icmpRule.tcpFlagsValue);
+ }
+
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizerTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizerTest.java
new file mode 100644
index 000000000..cd261970e
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/InterfaceAclCustomizerTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write;
+
+import io.fd.hc2vpp.acl.AclTestSchemaContext;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class InterfaceAclCustomizerTest extends WriterCustomizerTest implements AclTestSchemaContext {
+
+ @Mock
+ private FutureJVppAclFacade aclApi;
+
+ @Override
+ protected void setUpTest() throws Exception {
+
+ }
+
+ @Test
+ public void writeCurrentAttributes() throws Exception {
+
+ }
+
+ @Test
+ public void updateCurrentAttributes() throws Exception {
+
+ }
+
+ @Test
+ public void deleteCurrentAttributes() throws Exception {
+
+ }
+
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/VppAclCustomizerTest.java b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/VppAclCustomizerTest.java
new file mode 100644
index 000000000..d076311c9
--- /dev/null
+++ b/acl/acl-impl/src/test/java/io/fd/hc2vpp/acl/write/VppAclCustomizerTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.acl.write;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+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.acl.AclTestSchemaContext;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+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.acl.dto.AclAddReplace;
+import io.fd.vpp.jvpp.acl.dto.AclAddReplaceReply;
+import io.fd.vpp.jvpp.acl.dto.AclDel;
+import io.fd.vpp.jvpp.acl.dto.AclDelReply;
+import io.fd.vpp.jvpp.acl.dto.MacipAclAdd;
+import io.fd.vpp.jvpp.acl.dto.MacipAclAddReply;
+import io.fd.vpp.jvpp.acl.future.FutureJVppAclFacade;
+import io.fd.vpp.jvpp.acl.types.AclRule;
+import io.fd.vpp.jvpp.acl.types.MacipAclRule;
+import java.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppAcl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(HoneycombTestRunner.class)
+public class VppAclCustomizerTest extends WriterCustomizerTest implements AclTestSchemaContext {
+
+ @Mock
+ private FutureJVppAclFacade aclApi;
+
+ @Captor
+ private ArgumentCaptor<AclAddReplace> aclAddReplaceRequestCaptor;
+
+ @Captor
+ private ArgumentCaptor<MacipAclAdd> macipAclAddReplaceRequestCaptor;
+
+ @Captor
+ private ArgumentCaptor<AclDel> aclDelRequestCaptor;
+
+ private InstanceIdentifier<Acl> validId;
+ private InstanceIdentifier<Acl> validMacipId;
+ private VppAclCustomizer aclCustomizer;
+ private NamingContext standardAclContext;
+ private NamingContext macIpAclContext;
+
+
+ @Override
+ protected void setUpTest() throws Exception {
+ validId =
+ InstanceIdentifier.create(AccessLists.class).child(Acl.class, new AclKey("standard-acl", VppAcl.class));
+ validMacipId =
+ InstanceIdentifier.create(AccessLists.class).child(Acl.class, new AclKey("macip-acl", VppAcl.class));
+ standardAclContext = new NamingContext("acl", "acl-context");
+ macIpAclContext = new NamingContext("macip", "macip-context");
+ aclCustomizer = new VppAclCustomizer(aclApi, standardAclContext, macIpAclContext);
+
+ when(aclApi.aclAddReplace(any())).thenReturn(future(new AclAddReplaceReply()));
+ when(aclApi.aclDel(any())).thenReturn(future(new AclDelReply()));
+ when(aclApi.macipAclAdd(any())).thenReturn(future(new MacipAclAddReply()));
+ }
+
+ @Test
+ public void writeCurrentAttributesMacip(@InjectTestData(resourcePath = "/acl/macip/macip-acl.json")
+ AccessLists macipAcl) throws WriteFailedException {
+
+ aclCustomizer.writeCurrentAttributes(validMacipId, macipAcl.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).macipAclAdd(macipAclAddReplaceRequestCaptor.capture());
+
+ final MacipAclAdd request = macipAclAddReplaceRequestCaptor.getValue();
+
+ assertEquals(1, request.count);
+ assertTrue(Arrays.equals("macip-acl".getBytes(), request.tag));
+
+ final MacipAclRule rule = request.r[0];
+
+ assertEquals(0, rule.isIpv6);
+ assertEquals(1, rule.isPermit);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 2}, rule.srcIpAddr));
+ assertEquals(32, rule.srcIpPrefixLen);
+ assertTrue(Arrays.equals(new byte[]{(byte)0xaa, (byte)0xaa, (byte)0xaa, (byte)0xaa, (byte)0xaa, (byte)0xaa}, rule.srcMac));
+ assertTrue(Arrays.equals(new byte[]{(byte)0xff, 0, 0, 0, 0, 0}, rule.srcMacMask));
+ }
+
+ @Test
+ public void writeCurrentAttributesIcmpIpv4(@InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp.json")
+ AccessLists standardAcls) throws Exception {
+ aclCustomizer.writeCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyIcmpIpv4Request(-1);
+ }
+
+ @Test
+ public void updateCurrentAttributesIcmpIpv4(@InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ final Acl data = standardAcls.getAcl().get(0);
+
+ aclCustomizer.updateCurrentAttributes(validId, data, data, writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyIcmpIpv4Request(4);
+ }
+
+
+ @Test
+ public void writeCurrentAttributesIcmpIpv6(@InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp-v6.json")
+ AccessLists standardAcls) throws Exception {
+ aclCustomizer.writeCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyIcmpv6Request(-1);
+ }
+
+ @Test
+ public void updateCurrentAttributesIcmpIpv6(
+ @InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp-v6.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ final Acl data = standardAcls.getAcl().get(0);
+ aclCustomizer.updateCurrentAttributes(validId, data, data, writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyIcmpv6Request(4);
+ }
+
+
+ @Test
+ public void writeCurrentAttributesTcp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-tcp.json")
+ AccessLists standardAcls) throws Exception {
+ aclCustomizer.writeCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyTcpRequest(-1);
+ }
+
+ @Test
+ public void updateCurrentAttributesTcp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-tcp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ final Acl data = standardAcls.getAcl().get(0);
+ aclCustomizer.updateCurrentAttributes(validId, data, data, writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyTcpRequest(4);
+ }
+
+
+ @Test
+ public void writeCurrentAttributesUdp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-udp.json")
+ AccessLists standardAcls) throws Exception {
+ aclCustomizer.writeCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+
+ verifyUdpRequest(-1);
+ }
+
+ @Test
+ public void updateCurrentAttributesUdp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-udp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ final Acl data = standardAcls.getAcl().get(0);
+ aclCustomizer.updateCurrentAttributes(validId, data, data, writeContext);
+
+ verify(aclApi, times(1)).aclAddReplace(aclAddReplaceRequestCaptor.capture());
+ verifyUdpRequest(4);
+ }
+
+
+ @Test
+ public void deleteCurrentAttributesIcmpIpv4(@InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ aclCustomizer.deleteCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclDel(aclDelRequestCaptor.capture());
+ assertEquals(4, aclDelRequestCaptor.getValue().aclIndex);
+ }
+
+ @Test
+ public void deleteCurrentAttributesIcmpIpv6(
+ @InjectTestData(resourcePath = "/acl/standard/standard-acl-icmp-v6.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ aclCustomizer.deleteCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclDel(aclDelRequestCaptor.capture());
+ assertEquals(4, aclDelRequestCaptor.getValue().aclIndex);
+ }
+
+ @Test
+ public void deleteCurrentAttributesTcp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-tcp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ aclCustomizer.deleteCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclDel(aclDelRequestCaptor.capture());
+ assertEquals(4, aclDelRequestCaptor.getValue().aclIndex);
+ }
+
+ @Test
+ public void deleteCurrentAttributesUdp(@InjectTestData(resourcePath = "/acl/standard/standard-acl-udp.json")
+ AccessLists standardAcls) throws Exception {
+ defineMapping(mappingContext, "standard-acl", 4, "acl-context");
+ aclCustomizer.deleteCurrentAttributes(validId, standardAcls.getAcl().get(0), writeContext);
+
+ verify(aclApi, times(1)).aclDel(aclDelRequestCaptor.capture());
+ assertEquals(4, aclDelRequestCaptor.getValue().aclIndex);
+ }
+
+ private void verifyUdpRequest(final int aclIndex) {
+ final AclAddReplace request = aclAddReplaceRequestCaptor.getValue();
+ assertEquals(aclIndex, request.aclIndex);
+ assertEquals(1, request.count);
+ assertTrue(Arrays.equals("standard-acl".getBytes(), request.tag));
+
+ final AclRule udpRule = request.r[0];
+
+ assertEquals(0, udpRule.isIpv6);
+ assertEquals(1, udpRule.isPermit);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 2}, udpRule.srcIpAddr));
+ assertEquals(32, udpRule.srcIpPrefixLen);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 1}, udpRule.dstIpAddr));
+ assertEquals(24, udpRule.dstIpPrefixLen);
+
+ assertEquals(17, udpRule.proto);
+ assertEquals(1, udpRule.srcportOrIcmptypeFirst);
+ assertEquals(5487, udpRule.srcportOrIcmptypeLast);
+ assertEquals(87, udpRule.dstportOrIcmpcodeFirst);
+ assertEquals(6745, udpRule.dstportOrIcmpcodeLast);
+ assertEquals(0, udpRule.tcpFlagsMask);
+ assertEquals(0, udpRule.tcpFlagsValue);
+ }
+
+ private void verifyTcpRequest(final int aclIndex) {
+ final AclAddReplace request = aclAddReplaceRequestCaptor.getValue();
+ assertEquals(aclIndex, request.aclIndex);
+ assertEquals(1, request.count);
+ assertTrue(Arrays.equals("standard-acl".getBytes(), request.tag));
+
+ final AclRule tcpRule = request.r[0];
+
+ assertEquals(0, tcpRule.isIpv6);
+ assertEquals(1, tcpRule.isPermit);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 2}, tcpRule.srcIpAddr));
+ assertEquals(32, tcpRule.srcIpPrefixLen);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 1}, tcpRule.dstIpAddr));
+ assertEquals(24, tcpRule.dstIpPrefixLen);
+
+ assertEquals(6, tcpRule.proto);
+ assertEquals(1, tcpRule.srcportOrIcmptypeFirst);
+ assertEquals(5487, tcpRule.srcportOrIcmptypeLast);
+ assertEquals(87, tcpRule.dstportOrIcmpcodeFirst);
+ assertEquals(6745, tcpRule.dstportOrIcmpcodeLast);
+ assertEquals(1, tcpRule.tcpFlagsMask);
+ assertEquals(7, tcpRule.tcpFlagsValue);
+ }
+
+ private void verifyIcmpv6Request(final int aclIndex) {
+ final AclAddReplace request = aclAddReplaceRequestCaptor.getValue();
+ assertEquals(aclIndex, request.aclIndex);
+ assertEquals(1, request.count);
+ assertTrue(Arrays.equals("standard-acl".getBytes(), request.tag));
+
+ final AclRule icmpv6Rule = request.r[0];
+
+ assertEquals(1, icmpv6Rule.isIpv6);
+ assertEquals(1, icmpv6Rule.isPermit);
+ assertTrue(
+ Arrays.equals(new byte[]{32, 1, 13, -72, 10, 11, 18, -16, 0, 0, 0, 0, 0, 0, 0, 2},
+ icmpv6Rule.srcIpAddr));
+ assertEquals(48, icmpv6Rule.srcIpPrefixLen);
+ assertTrue(
+ Arrays.equals(new byte[]{32, 1, 13, -72, 10, 11, 18, -16, 0, 0, 0, 0, 0, 0, 0, 1},
+ icmpv6Rule.dstIpAddr));
+ assertEquals(64, icmpv6Rule.dstIpPrefixLen);
+
+ assertEquals(58, icmpv6Rule.proto);
+ assertEquals(5, icmpv6Rule.srcportOrIcmptypeFirst);
+ assertEquals(8, icmpv6Rule.srcportOrIcmptypeLast);
+ assertEquals(1, icmpv6Rule.dstportOrIcmpcodeFirst);
+ assertEquals(3, icmpv6Rule.dstportOrIcmpcodeLast);
+ assertEquals(0, icmpv6Rule.tcpFlagsMask);
+ assertEquals(0, icmpv6Rule.tcpFlagsValue);
+ }
+
+ private void verifyIcmpIpv4Request(final int aclIndex) {
+ final AclAddReplace request = aclAddReplaceRequestCaptor.getValue();
+ assertEquals(aclIndex, request.aclIndex);
+ assertEquals(1, request.count);
+ assertTrue(Arrays.equals("standard-acl".getBytes(), request.tag));
+
+ final AclRule icmpRule = request.r[0];
+
+ assertEquals(0, icmpRule.isIpv6);
+ assertEquals(1, icmpRule.isPermit);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 2}, icmpRule.srcIpAddr));
+ assertEquals(32, icmpRule.srcIpPrefixLen);
+ assertTrue(Arrays.equals(new byte[]{-64, -88, 2, 1}, icmpRule.dstIpAddr));
+ assertEquals(24, icmpRule.dstIpPrefixLen);
+
+ assertEquals(1, icmpRule.proto);
+ assertEquals(5, icmpRule.srcportOrIcmptypeFirst);
+ assertEquals(8, icmpRule.srcportOrIcmptypeLast);
+ assertEquals(1, icmpRule.dstportOrIcmpcodeFirst);
+ assertEquals(3, icmpRule.dstportOrIcmpcodeLast);
+ assertEquals(0, icmpRule.tcpFlagsMask);
+ assertEquals(0, icmpRule.tcpFlagsValue);
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/acl/macip/macip-acl.json b/acl/acl-impl/src/test/resources/acl/macip/macip-acl.json
new file mode 100644
index 000000000..b944cd79c
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/acl/macip/macip-acl.json
@@ -0,0 +1,27 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "macip-acl",
+ "acl-type": "vpp-acl:vpp-macip-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "macip-rule",
+ "matches": {
+ "vpp-macip-ace-nodes": {
+ "source-ipv4-network": "192.168.2.2/32",
+ "source-mac-address": "aa:aa:aa:aa:aa:aa",
+ "source-mac-address-mask": "ff:00:00:00:00:00"
+ }
+ },
+ "actions": {
+ "permit": {}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp-v6.json b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp-v6.json
new file mode 100644
index 000000000..08bc61511
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp-v6.json
@@ -0,0 +1,36 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-v6-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv6-network": "2001:0db8:0a0b:12f0:0000:0000:0000:0001/64",
+ "source-ipv6-network": "2001:0db8:0a0b:12f0:0000:0000:0000:0002/48",
+ "icmp-v6-nodes": {
+ "icmp-type-range": {
+ "first": "5",
+ "last": "8"
+ },
+ "icmp-code-range": {
+ "first": "1",
+ "last": "3"
+ }
+ }
+ }
+ },
+ "actions": {
+ "permit": {}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp.json b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp.json
new file mode 100644
index 000000000..ce6ff7c2c
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-icmp.json
@@ -0,0 +1,36 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/24",
+ "source-ipv4-network": "192.168.2.2/32",
+ "icmp-nodes": {
+ "icmp-type-range": {
+ "first": "5",
+ "last": "8"
+ },
+ "icmp-code-range": {
+ "first": "1",
+ "last": "3"
+ }
+ }
+ }
+ },
+ "actions": {
+ "permit": {}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/acl/standard/standard-acl-tcp.json b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-tcp.json
new file mode 100644
index 000000000..f0a1309aa
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-tcp.json
@@ -0,0 +1,38 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "tcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/24",
+ "source-ipv4-network": "192.168.2.2/32",
+ "tcp-nodes": {
+ "source-port-range": {
+ "lower-port": "1",
+ "upper-port": "5487"
+ },
+ "destination-port-range": {
+ "lower-port": "87",
+ "upper-port": "6745"
+ },
+ "tcp-flags-mask": "1",
+ "tcp-flags-value": "7"
+ }
+ }
+ },
+ "actions": {
+ "permit": {}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/acl/standard/standard-acl-udp.json b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-udp.json
new file mode 100644
index 000000000..77dafeb21
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/acl/standard/standard-acl-udp.json
@@ -0,0 +1,36 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "udp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/24",
+ "source-ipv4-network": "192.168.2.2/32",
+ "udp-nodes": {
+ "source-port-range": {
+ "lower-port": "1",
+ "upper-port": "5487"
+ },
+ "destination-port-range": {
+ "lower-port": "87",
+ "upper-port": "6745"
+ }
+ }
+ }
+ },
+ "actions": {
+ "permit": {}
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/rules/icmp-rule.json b/acl/acl-impl/src/test/resources/rules/icmp-rule.json
new file mode 100644
index 000000000..330a448fc
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/rules/icmp-rule.json
@@ -0,0 +1,33 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/32",
+ "source-ipv4-network": "192.168.2.2/32",
+ "icmp-nodes": {
+ "icmp-type-range": {
+ "first": "5",
+ "last": "8"
+ },
+ "icmp-code-range": {
+ "first": "1",
+ "last": "3"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/rules/icmp-v6-rule.json b/acl/acl-impl/src/test/resources/rules/icmp-v6-rule.json
new file mode 100644
index 000000000..9ea82a19a
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/rules/icmp-v6-rule.json
@@ -0,0 +1,33 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv6-network": "2001:0db8:0a0b:12f0:0000:0000:0000:0001/64",
+ "source-ipv6-network": "2001:0db8:0a0b:12f0:0000:0000:0000:0002/64",
+ "icmp-v6-nodes": {
+ "icmp-type-range": {
+ "first": "5",
+ "last": "8"
+ },
+ "icmp-code-range": {
+ "first": "1",
+ "last": "3"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/rules/other-rule.json b/acl/acl-impl/src/test/resources/rules/other-rule.json
new file mode 100644
index 000000000..0e60dccf7
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/rules/other-rule.json
@@ -0,0 +1,26 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/32",
+ "source-ipv4-network": "192.168.2.2/32",
+ "other-nodes": {
+ "protocol": "64"
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/rules/tcp-rule.json b/acl/acl-impl/src/test/resources/rules/tcp-rule.json
new file mode 100644
index 000000000..de3697eef
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/rules/tcp-rule.json
@@ -0,0 +1,35 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/32",
+ "source-ipv4-network": "192.168.2.2/32",
+ "tcp-nodes": {
+ "source-port-range": {
+ "lower-port": "1",
+ "upper-port": "5487"
+ },
+ "destination-port-range": {
+ "lower-port": "87",
+ "upper-port": "6745"
+ },
+ "tcp-flags-mask": "1",
+ "tcp-flags-value": "7"
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/acl/acl-impl/src/test/resources/rules/udp-rule.json b/acl/acl-impl/src/test/resources/rules/udp-rule.json
new file mode 100644
index 000000000..4bc05d4b2
--- /dev/null
+++ b/acl/acl-impl/src/test/resources/rules/udp-rule.json
@@ -0,0 +1,33 @@
+{
+ "access-lists": {
+ "acl": [
+ {
+ "acl-name": "standard-acl",
+ "acl-type": "vpp-acl:vpp-acl",
+ "access-list-entries": {
+ "ace": [
+ {
+ "rule-name": "imcp-rule",
+ "matches": {
+ "vpp-ace-nodes": {
+ "destination-ipv4-network": "192.168.2.1/32",
+ "source-ipv4-network": "192.168.2.2/32",
+ "udp-nodes": {
+ "source-port-range": {
+ "lower-port": "1",
+ "upper-port": "5487"
+ },
+ "destination-port-range": {
+ "lower-port": "87",
+ "upper-port": "6745"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file