HONEYCOMB-49: ACL create/delete support for vpp-interface-augmentation 10/1410/11
authorMarek Gradzki <mgradzki@cisco.com>
Sun, 5 Jun 2016 19:53:18 +0000 (21:53 +0200)
committerMarek Gradzki <mgradzki@cisco.com>
Thu, 14 Jul 2016 13:28:02 +0000 (15:28 +0200)
Change-Id: I5c25bac07ce618f69cf86f988749b0f86e9a6498
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
25 files changed:
v3po/api/src/main/yang/vpp-classifier.yang
v3po/api/src/main/yang/vpp-vlan.yang
v3po/v3po2vpp/src/main/config/default-config.xml
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclWriter.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceAclCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclReader.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionReader.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriter.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReader.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriter.java
v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java
v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java
v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceAugmentationWriterFactory.java
v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceStateAugmentationReaderFactory.java
v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppClassifierHoneycombWriterModule.java
v3po/v3po2vpp/src/main/yang/v3po2vpp.yang
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriterTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReaderTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriterTest.java
v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/SubInterfaceUtils.java

index 0ba94f1..b547988 100644 (file)
@@ -63,7 +63,7 @@ module vpp-classifier {
       "Defines classify session attributes that are mapped to classify_add_del_session
        and classify_session_details messages parameters.";
 
-    leaf hit_next_index {
+    leaf hit_next {
       type vpp-node;
       mandatory true;
       description
@@ -110,7 +110,7 @@ module vpp-classifier {
       description
         "Reference to the next classify table. Required when multiple table chaining is used.";
     }
-    leaf miss_next_index {
+    leaf miss_next {
       mandatory true;
       type vpp-node;
       description
@@ -124,7 +124,6 @@ module vpp-classifier {
     }
     leaf active_sessions {
       type uint32;
-      mandatory true;
       config false;
       description
         "Number of sessions defined for the classify table.";
index fef8e72..bd3f265 100644 (file)
@@ -158,6 +158,10 @@ module vpp-vlan {
         uses tag-rewrite;
       }
     }
+
+    container acl {
+      uses v3po:acl-base-attributes;
+    }
   }
 
   grouping sub-interface-config-attributes {
index 09c6c54..1767567 100644 (file)
                         <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
                         <name>bridge-domain-context</name>
                     </bridge-domain-context-ifc-state>
+                    <classify-table-context>
+                        <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
+                        <name>classify-table-context</name>
+                    </classify-table-context>
                 </module>
                 <module>
                     <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:v3po2vpp">prefix:vpp-classifier-honeycomb-reader</type>
                         <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
                         <name>bridge-domain-context</name>
                     </bridge-domain-context>
+                    <classify-table-context>
+                        <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
+                        <name>classify-table-context</name>
+                    </classify-table-context>
                 </module>
 
                 <module>
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizer.java
new file mode 100644 (file)
index 0000000..4e681f6
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.v3po.translate.write.WriteContext;
+import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
+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.v3po.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Acl;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for enabling/disabling ACLs on given interface
+ */
+public class AclCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Acl>, AclWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class);
+    private final NamingContext interfaceContext;
+    private final NamingContext classifyTableContext;
+
+    public AclCustomizer(@Nonnull final FutureJVpp vppApi, @Nonnull final NamingContext interfaceContext,
+                         @Nonnull final NamingContext classifyTableContext) {
+        super(vppApi);
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Nonnull
+    @Override
+    public Optional<Acl> extract(@Nonnull final InstanceIdentifier<Acl> currentId,
+                                 @Nonnull final DataObject parentData) {
+        return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getAcl());
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            setAcl(true, id, dataAfter, writeContext);
+        } catch (VppBaseCallException e) {
+            throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+                                        @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first.");
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            setAcl(false, id, dataBefore, writeContext);
+        } catch (VppBaseCallException e) {
+            throw new WriteFailedException.DeleteFailedException(id, e);
+        }
+    }
+
+    private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+                        @Nonnull final WriteContext writeContext)
+        throws VppBaseCallException, WriteTimeoutException {
+        final String ifName = id.firstKeyOf(Interface.class).getName();
+        final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext());
+
+        LOG.debug("Setting ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl);
+
+        inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, ifIndex, classifyTableContext,
+            writeContext.getMappingContext());
+        LOG.debug("Successfully set ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclWriter.java
new file mode 100644 (file)
index 0000000..75b9121
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils.booleanToByte;
+
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
+import io.fd.honeycomb.v3po.translate.v3po.util.WriteTimeoutException;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnegative;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.AclBaseAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.dto.InputAclSetInterface;
+import org.openvpp.jvpp.dto.InputAclSetInterfaceReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+
+interface AclWriter {
+
+    default void inputAclSetInterface(@Nonnull final FutureJVpp futureJvpp, final boolean isAdd,
+                                      @Nonnull final InstanceIdentifier<?> id, @Nonnull final AclBaseAttributes acl,
+                                      @Nonnegative final int ifIndex, @Nonnull final NamingContext classifyTableContext,
+                                      @Nonnull final MappingContext mappingContext)
+        throws VppBaseCallException, WriteTimeoutException {
+        final InputAclSetInterface request = new InputAclSetInterface();
+        request.isAdd = booleanToByte(isAdd);
+        request.swIfIndex = ifIndex;
+        request.l2TableIndex = ~0; // skip
+        request.ip4TableIndex = ~0; // skip
+        request.ip6TableIndex = ~0; // skip
+
+        final L2Acl l2Acl = acl.getL2Acl();
+        if (l2Acl != null) {
+            final String tableName = checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null");
+            request.l2TableIndex = classifyTableContext.getIndex(tableName, mappingContext);
+        }
+        final Ip4Acl ip4Acl = acl.getIp4Acl();
+        if (ip4Acl != null) {
+            final String tableName = checkNotNull(ip4Acl.getClassifyTable(), "IPv4 classify table is null");
+            request.ip4TableIndex = classifyTableContext.getIndex(tableName, mappingContext);
+        }
+        final Ip6Acl ip6Acl = acl.getIp6Acl();
+        if (ip6Acl != null) {
+            final String tableName = checkNotNull(ip6Acl.getClassifyTable(), "IPv6 classify table is null");
+            request.ip6TableIndex = classifyTableContext.getIndex(tableName, mappingContext);
+        }
+
+        final CompletionStage<InputAclSetInterfaceReply> inputAclSetInterfaceReplyCompletionStage =
+            futureJvpp.inputAclSetInterface(request);
+
+        TranslateUtils.getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceAclCustomizer.java
new file mode 100644 (file)
index 0000000..9cba9c7
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils;
+import io.fd.honeycomb.v3po.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.v3po.translate.write.WriteContext;
+import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for enabling/disabling ACLs on given sub-interface
+ */
+public class SubInterfaceAclCustomizer extends FutureJVppCustomizer
+    implements ChildWriterCustomizer<Acl>, AclWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class);
+    private final NamingContext interfaceContext;
+    private final NamingContext classifyTableContext;
+
+    public SubInterfaceAclCustomizer(@Nonnull final FutureJVpp vppApi, @Nonnull final NamingContext interfaceContext,
+                                     @Nonnull final NamingContext classifyTableContext) {
+        super(vppApi);
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Nonnull
+    @Override
+    public Optional<Acl> extract(@Nonnull final InstanceIdentifier<Acl> currentId,
+                                 @Nonnull final DataObject parentData) {
+        return Optional.fromNullable(((SubInterface) parentData).getAcl());
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataAfter,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            setAcl(true, id, dataAfter, writeContext);
+        } catch (VppBaseCallException e) {
+            throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+                                        @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext)
+        throws WriteFailedException {
+        throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first.");
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl dataBefore,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            setAcl(false, id, dataBefore, writeContext);
+        } catch (VppBaseCallException e) {
+            throw new WriteFailedException.DeleteFailedException(id, e);
+        }
+    }
+
+    private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier<Acl> id, @Nonnull final Acl acl,
+                        @Nonnull final WriteContext writeContext)
+        throws VppBaseCallException, WriteTimeoutException {
+        final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class);
+        final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class);
+        final String subInterfaceName = SubInterfaceUtils
+            .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue());
+        final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext());
+
+        LOG.debug("Setting ACL(isAdd={}) on sub-interface={}(id={}): {}",
+            isAdd, subInterfaceName, subInterfaceIndex, acl);
+        inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, subInterfaceIndex, classifyTableContext,
+            writeContext.getMappingContext());
+        LOG.debug("Successfully set ACL(isAdd={}) on sub-interface={}(id={}): {}",
+            isAdd, subInterfaceName, subInterfaceIndex, acl);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizer.java
new file mode 100644 (file)
index 0000000..d8d2d8e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfacesstate;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.honeycomb.v3po.translate.read.ReadContext;
+import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
+import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
+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.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.AclBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.dto.ClassifyTableByInterface;
+import org.openvpp.jvpp.dto.ClassifyTableByInterfaceReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for reading ACLs enabled on given interface
+ */
+public class AclCustomizer extends FutureJVppCustomizer
+    implements ChildReaderCustomizer<Acl, AclBuilder>, AclReader {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class);
+    private final NamingContext interfaceContext;
+    private final NamingContext classifyTableContext;
+
+    public AclCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext,
+                         @Nonnull final NamingContext classifyTableContext) {
+        super(jvpp);
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Acl readValue) {
+        ((VppInterfaceStateAugmentationBuilder) parentBuilder).setAcl(readValue);
+    }
+
+    @Nonnull
+    @Override
+    public AclBuilder getBuilder(@Nonnull final InstanceIdentifier<Acl> id) {
+        return new AclBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final AclBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
+        LOG.debug("Reading attributes for interface ACL: {}", id);
+        final InterfaceKey interfaceKey = id.firstKeyOf(Interface.class);
+        checkArgument(interfaceKey != null, "No parent interface key found");
+
+        final ClassifyTableByInterface request = new ClassifyTableByInterface();
+        request.swIfIndex = interfaceContext.getIndex(interfaceKey.getName(), ctx.getMappingContext());
+        try {
+            final ClassifyTableByInterfaceReply reply = TranslateUtils
+                .getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id);
+
+            builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext()));
+            builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext()));
+            builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext()));
+
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build());
+            }
+        } catch (VppBaseCallException e) {
+            throw new ReadFailedException(id, e);
+        }
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclReader.java
new file mode 100644 (file)
index 0000000..8b28b75
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfacesstate;
+
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2AclBuilder;
+
+interface AclReader {
+
+    default L2Acl readL2Acl(final int l2TableId, @Nonnull final NamingContext classifyTableContext,
+                            @Nonnull final MappingContext mappingContext) {
+        if (l2TableId == ~0) {
+            return null;
+        }
+        return new L2AclBuilder()
+            .setClassifyTable(classifyTableContext.getName(l2TableId, mappingContext)).build();
+    }
+
+    default Ip4Acl readIp4Acl(final int ip4TableId, @Nonnull final NamingContext classifyTableContext,
+                              @Nonnull final MappingContext mappingContext) {
+        if (ip4TableId == ~0) {
+            return null;
+        }
+        return new Ip4AclBuilder()
+            .setClassifyTable(classifyTableContext.getName(ip4TableId, mappingContext)).build();
+    }
+
+    default Ip6Acl readIp6Acl(final int ip6TableId, @Nonnull final NamingContext classifyTableContext,
+                              @Nonnull final MappingContext mappingContext) {
+        if (ip6TableId == ~0) {
+            return null;
+        }
+        return new Ip6AclBuilder()
+            .setClassifyTable(classifyTableContext.getName(ip6TableId, mappingContext)).build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java
new file mode 100644 (file)
index 0000000..a00485f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfacesstate;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils.getSubInterfaceName;
+
+import io.fd.honeycomb.v3po.translate.read.ReadContext;
+import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
+import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
+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.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.AclBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.dto.ClassifyTableByInterface;
+import org.openvpp.jvpp.dto.ClassifyTableByInterfaceReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Customizer for reading ACLs enabled on given sub-interface
+ */
+public class SubInterfaceAclCustomizer extends FutureJVppCustomizer
+    implements ChildReaderCustomizer<Acl, AclBuilder>, AclReader {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class);
+    private final NamingContext interfaceContext;
+    private final NamingContext classifyTableContext;
+
+    public SubInterfaceAclCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext,
+                                     @Nonnull final NamingContext classifyTableContext) {
+        super(jvpp);
+        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Acl readValue) {
+        ((SubInterfaceBuilder) parentBuilder).setAcl(readValue);
+    }
+
+    @Nonnull
+    @Override
+    public AclBuilder getBuilder(@Nonnull final InstanceIdentifier<Acl> id) {
+        return new AclBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Acl> id, @Nonnull final AclBuilder builder,
+                                      @Nonnull final ReadContext ctx) throws ReadFailedException {
+        LOG.debug("Reading attributes for sub-interface ACL: {}", id);
+        final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class);
+        checkArgument(parentInterfacekey != null, "No parent interface key found");
+        final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class);
+        checkArgument(subInterfacekey != null, "No sub-interface key found");
+        final String subInterfaceName =
+            getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue());
+
+        final ClassifyTableByInterface request = new ClassifyTableByInterface();
+        request.swIfIndex = interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext());
+        try {
+            final ClassifyTableByInterfaceReply reply = TranslateUtils
+                .getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id);
+
+            builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext()));
+            builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext()));
+            builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext()));
+
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build());
+            }
+        } catch (VppBaseCallException e) {
+            throw new ReadFailedException(id, e);
+        }
+    }
+}
index 002fc62..1f469c5 100644 (file)
@@ -102,7 +102,7 @@ public class ClassifySessionReader extends FutureJVppCustomizer
 
         if (classifySession.isPresent()) {
             final ClassifySessionDetails detail = classifySession.get();
-            builder.setHitNextIndex(readVppNode(detail.hitNextIndex, LOG));
+            builder.setHitNext(readVppNode(detail.hitNextIndex, LOG));
             if (detail.opaqueIndex != ~0) {
                 // value is specified:
                 builder.setOpaqueIndex(readOpaqueIndex(detail.opaqueIndex));
index 08989ce..e56d50d 100644 (file)
@@ -131,7 +131,7 @@ public class ClassifySessionWriter extends FutureJVppCustomizer
 
         // mandatory:
         // TODO implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed
-        request.hitNextIndex = classifySession.getHitNextIndex().getPacketHandlingAction().getIntValue();
+        request.hitNextIndex = classifySession.getHitNext().getPacketHandlingAction().getIntValue();
 
         if (classifySession.getOpaqueIndex() != null) {
             request.opaqueIndex = getOpaqueIndexValue(classifySession.getOpaqueIndex());
index 7f877ca..ce29dc9 100644 (file)
@@ -106,7 +106,7 @@ public class ClassifyTableReader extends FutureJVppCustomizer
             builder.setSkipNVectors(UnsignedInts.toLong(reply.skipNVectors));
 
 
-            builder.setMissNextIndex(readVppNode(reply.missNextIndex, LOG));
+            builder.setMissNext(readVppNode(reply.missNextIndex, LOG));
             builder.setMask(new HexString(printHexBinary(reply.mask)));
             builder.setActiveSessions(UnsignedInts.toLong(reply.activeSessions));
 
index 4f59ffe..788aac5 100644 (file)
@@ -90,8 +90,7 @@ public class ClassifyTableWriter extends FutureJVppCustomizer
     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifyTable> id,
                                         @Nonnull final ClassifyTable dataBefore, @Nonnull final ClassifyTable dataAfter,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
-        LOG.warn("ClassifyTable update is not supported, ignoring configuration {}", dataAfter);
-        // TODO if only leaves were updated (but not child/aug nodes), we should throw exception to deny config change
+        throw new UnsupportedOperationException("Classify table update is not supported");
     }
 
     @Override
@@ -141,10 +140,10 @@ public class ClassifyTableWriter extends FutureJVppCustomizer
 
         // mandatory
         // TODO implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed
-        request.missNextIndex = table.getMissNextIndex().getPacketHandlingAction().getIntValue();
+        request.missNextIndex = table.getMissNext().getPacketHandlingAction().getIntValue();
 
         final String nextTable = table.getNextTable();
-        if (nextTable != null) {
+        if (isAdd && nextTable != null) {
             request.nextTableIndex = classifyTableContext.getIndex(nextTable, ctx);
         } else {
             request.nextTableIndex = ~0; // value not specified
index 2d440cd..64f1e8a 100644 (file)
@@ -1,8 +1,12 @@
 package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406;
 
+import static org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.VppClassifierHoneycombWriterModule.CLASSIFY_SESSION_ID;
+import static org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.VppClassifierHoneycombWriterModule.CLASSIFY_TABLE_ID;
+
 import com.google.common.collect.Sets;
 import io.fd.honeycomb.v3po.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.v3po.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.v3po.translate.v3po.interfaces.AclCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.EthernetCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.InterfaceCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.L2Customizer;
@@ -27,6 +31,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Ethernet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing;
@@ -38,15 +46,16 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.openvpp.jvpp.future.FutureJVpp;
 
 public class InterfacesHoneycombWriterModule extends
-        org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesHoneycombWriterModule {
+    org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesHoneycombWriterModule {
 
     // TODO split configuration and translation code into 2 or more bundles
 
     public static final InstanceIdentifier<Interface> IFC_ID =
-            InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+        InstanceIdentifier.create(Interfaces.class).child(Interface.class);
     public static final InstanceIdentifier<VppInterfaceAugmentation> VPP_IFC_AUG_ID =
-            IFC_ID.augmentation(VppInterfaceAugmentation.class);
+        IFC_ID.augmentation(VppInterfaceAugmentation.class);
     public static final InstanceIdentifier<L2> L2_ID = VPP_IFC_AUG_ID.child(L2.class);
+    public static final InstanceIdentifier<Acl> ACL_ID = VPP_IFC_AUG_ID.child(Acl.class);
 
     public InterfacesHoneycombWriterModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
                                            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@@ -68,8 +77,9 @@ public class InterfacesHoneycombWriterModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         return new InterfacesWriterFactory(getVppJvppIfcDependency(),
-                                           getBridgeDomainContextDependency(),
-                                           getInterfaceContextDependency());
+            getBridgeDomainContextDependency(),
+            getInterfaceContextDependency(),
+            getClassifyTableContextDependency());
     }
 
 
@@ -78,13 +88,16 @@ public class InterfacesHoneycombWriterModule extends
         private final FutureJVpp jvpp;
         private final NamingContext bdContext;
         private final NamingContext ifcContext;
+        private final NamingContext classifyTableContext;
 
         InterfacesWriterFactory(final FutureJVpp vppJvppIfcDependency,
-                                       final NamingContext bridgeDomainContextDependency,
-                                       final NamingContext interfaceContextDependency) {
+                                final NamingContext bridgeDomainContextDependency,
+                                final NamingContext interfaceContextDependency,
+                                final NamingContext classifyTableContextDependency) {
             this.jvpp = vppJvppIfcDependency;
             this.bdContext = bridgeDomainContextDependency;
             this.ifcContext = interfaceContextDependency;
+            this.classifyTableContext = classifyTableContextDependency;
         }
 
         @Override
@@ -102,7 +115,7 @@ public class InterfacesHoneycombWriterModule extends
             //   Interface1 (ietf-ip augmentation)
             addInterface1AugmentationWriters(IFC_ID, registry);
             //   SubinterfaceAugmentation TODO make dedicated module for subIfc writer factory
-            new SubinterfaceAugmentationWriterFactory(jvpp, ifcContext, bdContext).init(registry);
+            new SubinterfaceAugmentationWriterFactory(jvpp, ifcContext, bdContext, classifyTableContext).init(registry);
         }
 
         private void addInterface1AugmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -110,18 +123,19 @@ public class InterfacesHoneycombWriterModule extends
             final InstanceIdentifier<Interface1> ifc1AugId = ifcId.augmentation(Interface1.class);
             // Ipv6(after interface) TODO unfinished customizer =
             registry.addWriterAfter(new GenericWriter<>(ifc1AugId.child(Ipv6.class), new Ipv6Customizer(jvpp)),
-                    ifcId);
+                ifcId);
             // Ipv4(after interface)
             final InstanceIdentifier<Ipv4> ipv4Id = ifc1AugId.child(Ipv4.class);
             registry.addWriterAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp, ifcContext)),
-                    ifcId);
+                ifcId);
             //  Address(after Ipv4) =
             final InstanceIdentifier<Address> ipv4AddressId = ipv4Id.child(Address.class);
             registry.addWriterAfter(new GenericListWriter<>(ipv4AddressId, new Ipv4AddressCustomizer(jvpp, ifcContext)),
-                    ipv4Id);
+                ipv4Id);
             //  Neighbor(after ipv4Address)
-            registry.addWriterAfter(new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp, ifcContext)),
-                    ipv4AddressId);
+            registry.addWriterAfter(
+                new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp, ifcContext)),
+                ipv4AddressId);
         }
 
         private void addVppInterfaceAgmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -129,19 +143,19 @@ public class InterfacesHoneycombWriterModule extends
             // VhostUser(Needs to be executed before Interface customizer) =
             final InstanceIdentifier<VhostUser> vhostId = VPP_IFC_AUG_ID.child(VhostUser.class);
             registry.addWriterBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcContext)),
-                    ifcId);
+                ifcId);
             // Vxlan(Needs to be executed before Interface customizer) =
             final InstanceIdentifier<Vxlan> vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class);
             registry.addWriterBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcContext)),
-                    ifcId);
+                ifcId);
             // VxlanGpe(Needs to be executed before Interface customizer) =
             final InstanceIdentifier<VxlanGpe> vxlanGpeId = VPP_IFC_AUG_ID.child(VxlanGpe.class);
             registry.addWriterBefore(new GenericWriter<>(vxlanGpeId, new VxlanGpeCustomizer(jvpp, ifcContext)),
-                    ifcId);
+                ifcId);
             // Tap(Needs to be executed before Interface customizer) =
             final InstanceIdentifier<Tap> tapId = VPP_IFC_AUG_ID.child(Tap.class);
             registry.addWriterBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcContext)),
-                    ifcId);
+                ifcId);
 
             final Set<InstanceIdentifier<?>> specificIfcTypes = Sets.newHashSet(vhostId, vxlanGpeId, vxlanGpeId, tapId);
 
@@ -149,11 +163,21 @@ public class InterfacesHoneycombWriterModule extends
             registry.addWriter(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class), new EthernetCustomizer(jvpp)));
             // Routing(Execute only after specific interface customizers) =
             registry.addWriterAfter(
-                    new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcContext)),
-                    specificIfcTypes);
+                new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcContext)),
+                specificIfcTypes);
             // Routing(Execute only after specific interface customizers) =
             registry.addWriterAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcContext, bdContext)),
-                    specificIfcTypes);
+                specificIfcTypes);
+
+            // ACL (execute after classify table and session writers)
+            // also handles L2Acl, Ip4Acl and Ip6Acl:
+            final InstanceIdentifier<Acl> aclId = InstanceIdentifier.create(Acl.class);
+            registry
+                .addSubtreeWriterAfter(
+                    Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)),
+                    new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcContext, classifyTableContext)),
+                    Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID)
+                );
         }
 
     }
index 1b8898d..5c89961 100644 (file)
@@ -14,6 +14,7 @@ import io.fd.honeycomb.v3po.translate.util.RWUtils;
 import io.fd.honeycomb.v3po.translate.util.read.CloseableReader;
 import io.fd.honeycomb.v3po.translate.util.read.ReflexiveAugmentReaderCustomizer;
 import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.AclCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.EthernetCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.L2Customizer;
@@ -40,6 +41,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Neighbor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Tap;
@@ -74,7 +76,9 @@ public class InterfacesStateHoneycombReaderModule extends
                 interfaceAugReaders = new ArrayList<>();
         interfaceAugReaders.add(getVppInterfaceStateAugmentationReader());
         interfaceAugReaders.add(getInterface1AugmentationReader());
-        interfaceAugReaders.add(SubinterfaceStateAugmentationReaderFactory.createInstance(getVppJvppDependency(), getInterfaceContextIfcStateDependency(), getBridgeDomainContextIfcStateDependency()));
+        interfaceAugReaders.add(SubinterfaceStateAugmentationReaderFactory.createInstance(getVppJvppDependency(),
+            getInterfaceContextIfcStateDependency(), getBridgeDomainContextIfcStateDependency(),
+            getClassifyTableContextDependency()));
 
         final CompositeListReader<Interface, InterfaceKey, InterfaceBuilder> interfaceReader =
                 new CompositeListReader<>(Interface.class,
@@ -134,6 +138,10 @@ public class InterfacesStateHoneycombReaderModule extends
                 new CompositeChildReader<>(VxlanGpe.class,
                         new VxlanGpeCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency()));
 
+        final ChildReader<? extends ChildOf<VppInterfaceStateAugmentation>> aclReader =
+                new CompositeChildReader<>(Acl.class,
+                        new AclCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency(), getClassifyTableContextDependency()));
+
         final ChildReader<? extends ChildOf<VppInterfaceStateAugmentation>> l2Reader =
                 new CompositeChildReader<>(L2.class,
                         new L2Customizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency(), getBridgeDomainContextIfcStateDependency()));
@@ -145,6 +153,7 @@ public class InterfacesStateHoneycombReaderModule extends
         childReaders.add(vxlanReader);
         childReaders.add(vxlanGpeReader);
         childReaders.add(l2Reader);
+        childReaders.add(aclReader);
 
         final ChildReader<VppInterfaceStateAugmentation> vppInterfaceStateAugmentationChildReader =
                 new CompositeChildReader<>(VppInterfaceStateAugmentation.class,
index 657769a..60a9c2e 100644 (file)
 
 package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406;
 
+import static org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.VppClassifierHoneycombWriterModule.CLASSIFY_SESSION_ID;
+import static org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.VppClassifierHoneycombWriterModule.CLASSIFY_TABLE_ID;
+
 import com.google.common.collect.Sets;
 import io.fd.honeycomb.v3po.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.v3po.translate.impl.write.GenericWriter;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.RewriteCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.interfaces.SubInterfaceAclCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.SubInterfaceCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.SubInterfaceL2Customizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfaces.ip.SubInterfaceIpv4AddressCustomizer;
@@ -27,10 +31,14 @@ import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
 import io.fd.honeycomb.v3po.translate.write.ModifiableWriterRegistry;
 import io.fd.honeycomb.v3po.translate.write.WriterFactory;
 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubinterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.vlan.tagged.VlanTagged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Tags;
@@ -47,18 +55,22 @@ final class SubinterfaceAugmentationWriterFactory implements WriterFactory {
     private final FutureJVpp jvpp;
     private final NamingContext ifcContext;
     private final NamingContext bdContext;
+    private final NamingContext classifyTableContext;
+
     public static final InstanceIdentifier<SubinterfaceAugmentation> SUB_IFC_AUG_ID =
             InterfacesHoneycombWriterModule.IFC_ID.augmentation(SubinterfaceAugmentation.class);
     public static final InstanceIdentifier<SubInterface> SUB_IFC_ID =
             SUB_IFC_AUG_ID.child(SubInterfaces.class).child(SubInterface.class);
     public static final InstanceIdentifier<L2> L2_ID = SUB_IFC_ID.child(
             L2.class);
+    public static final InstanceIdentifier<Acl> SUBIF_ACL_ID = SUB_IFC_ID.child(Acl.class);
 
     public SubinterfaceAugmentationWriterFactory(final FutureJVpp jvpp,
-            final NamingContext ifcContext, final NamingContext bdContext) {
+            final NamingContext ifcContext, final NamingContext bdContext, final NamingContext classifyTableContext) {
         this.jvpp = jvpp;
         this.ifcContext = ifcContext;
         this.bdContext = bdContext;
+        this.classifyTableContext = classifyTableContext;
     }
 
     @Override
@@ -94,5 +106,15 @@ final class SubinterfaceAugmentationWriterFactory implements WriterFactory {
                 new SubInterfaceIpv4AddressCustomizer(jvpp, ifcContext)),
                 rewriteId);
 
+        // ACL (execute after classify table and session writers)
+        // also handles L2Acl, Ip4Acl and Ip6Acl:
+        final InstanceIdentifier<Acl> aclId = InstanceIdentifier.create(Acl.class);
+        registry
+            .addSubtreeWriterAfter(
+                Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)),
+                new GenericWriter<>(SUBIF_ACL_ID, new SubInterfaceAclCustomizer(jvpp, ifcContext, classifyTableContext)),
+                Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID)
+            );
+
     }
 }
index 9e182b1..7dfe4d2 100644 (file)
@@ -25,6 +25,7 @@ import io.fd.honeycomb.v3po.translate.util.RWUtils;
 import io.fd.honeycomb.v3po.translate.util.read.ReflexiveAugmentReaderCustomizer;
 import io.fd.honeycomb.v3po.translate.util.read.ReflexiveChildReaderCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.RewriteCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.SubInterfaceAclCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.SubInterfaceCustomizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.SubInterfaceL2Customizer;
 import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.ip.SubInterfaceIpv4AddressCustomizer;
@@ -39,6 +40,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.Rewrite;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.Ipv4;
@@ -76,15 +78,25 @@ final class SubinterfaceStateAugmentationReaderFactory {
 
     }
 
+    private static ChildReader<Acl> getAclReader(@Nonnull final FutureJVpp futureJvpp,
+                                                 @Nonnull final NamingContext interfaceContext,
+                                                 @Nonnull final NamingContext classifyTableContext) {
+        return new CompositeChildReader<>(Acl.class,
+            new SubInterfaceAclCustomizer(futureJvpp, interfaceContext, classifyTableContext));
+
+    }
+
     static ChildReader<SubinterfaceStateAugmentation> createInstance(
         @Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext interfaceContext,
-        @Nonnull final NamingContext bridgeDomainContext) {
+        @Nonnull final NamingContext bridgeDomainContext,
+        @Nonnull final NamingContext classifyTableContext) {
 
         List<ChildReader<? extends ChildOf<SubInterface>>> childReaders = new ArrayList<>();
 
         // TODO can get rid of that cast?
         childReaders.add((ChildReader) getL2Reader(futureJvpp, interfaceContext, bridgeDomainContext));
         childReaders.add((ChildReader) getIpv4Reader(futureJvpp, interfaceContext));
+        childReaders.add((ChildReader) getAclReader(futureJvpp, interfaceContext, classifyTableContext));
 
         final CompositeListReader<SubInterface, SubInterfaceKey, SubInterfaceBuilder> subInterfaceReader =
             new CompositeListReader<>(SubInterface.class, childReaders, new SubInterfaceCustomizer(futureJvpp,
index 52e99b2..76b60b7 100644 (file)
@@ -1,5 +1,7 @@
 package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406;
 
+import static org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.InterfacesHoneycombWriterModule.ACL_ID;
+
 import io.fd.honeycomb.v3po.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
 import io.fd.honeycomb.v3po.translate.v3po.vppclassifier.ClassifySessionWriter;
@@ -66,8 +68,9 @@ public class VppClassifierHoneycombWriterModule extends
         @Override
         public void init(final ModifiableWriterRegistry registry) {
 
-            registry.addWriter(
-                new GenericListWriter<>(CLASSIFY_TABLE_ID, new ClassifyTableWriter(jvpp, classifyTableContext)));
+            registry.addWriterBefore(
+                new GenericListWriter<>(CLASSIFY_TABLE_ID, new ClassifyTableWriter(jvpp, classifyTableContext)),
+                ACL_ID);
 
             registry.addWriterAfter(
                 new GenericListWriter<>(CLASSIFY_SESSION_ID, new ClassifySessionWriter(jvpp, classifyTableContext)),
index 0c21570..f70d3f8 100644 (file)
@@ -143,6 +143,15 @@ module v3po2vpp {
                 }
             }
 
+            container classify-table-context {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity vpp-u:naming-context;
+                    }
+                }
+            }
+
         }
     }
 
@@ -250,6 +259,15 @@ module v3po2vpp {
                 }
             }
 
+            container classify-table-context {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity vpp-u:naming-context;
+                    }
+                }
+            }
+
         }
     }
 
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizerTest.java
new file mode 100644 (file)
index 0000000..f08ffd4
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfaces;
+
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMapping;
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMappingIid;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.v3po.test.TestHelperUtils;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.write.WriteContext;
+import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey;
+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.v3po.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.AclBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.dto.InputAclSetInterface;
+import org.openvpp.jvpp.dto.InputAclSetInterfaceReply;
+import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewriteReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+
+public class AclCustomizerTest {
+
+    @Mock
+    private FutureJVpp api;
+    @Mock
+    private WriteContext writeContext;
+    @Mock
+    private MappingContext mappingContext;
+
+    private NamingContext interfaceContext;
+    private NamingContext classifyTableContext;
+    private AclCustomizer customizer;
+
+    private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+    private static final String CT_TEST_INSTANCE = "ct-test-instance";
+    private static final String IF_NAME = "local0";
+    private static final int IF_INDEX = 1;
+
+    private static final int ACL_TABLE_INDEX = 0;
+    private static final String ACL_TABLE_NAME = "table0";
+
+    @Before
+    public void setUp() throws Exception {
+        initMocks(this);
+        interfaceContext = new NamingContext("generatedInterfaceName", IFC_TEST_INSTANCE);
+        classifyTableContext = new NamingContext("generatedClassifyTable", CT_TEST_INSTANCE);
+        doReturn(mappingContext).when(writeContext).getMappingContext();
+        customizer = new AclCustomizer(api, interfaceContext, classifyTableContext);
+
+        final KeyedInstanceIdentifier<Mapping, MappingKey> ifcMappingKey = getMappingIid(IF_NAME, IFC_TEST_INSTANCE);
+        final Optional<Mapping> ifcMapping = getMapping(IF_NAME, IF_INDEX);
+        doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey);
+
+        final KeyedInstanceIdentifier<Mapping, MappingKey> ctMappingKey =
+            getMappingIid(ACL_TABLE_NAME, CT_TEST_INSTANCE);
+        final Optional<Mapping> ctMapping = getMapping(ACL_TABLE_NAME, ACL_TABLE_INDEX);
+        doReturn(ctMapping).when(mappingContext).read(ctMappingKey);
+
+        final List<Mapping> allCtMappings = Lists.newArrayList(ctMapping.get());
+        final Mappings allCtMappingsBaObject = new MappingsBuilder().setMapping(allCtMappings).build();
+        doReturn(Optional.of(allCtMappingsBaObject)).when(mappingContext)
+            .read(ctMappingKey.firstIdentifierOf(Mappings.class));
+    }
+
+
+    private InstanceIdentifier<Acl> getAclId(final String name) {
+        return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+            VppInterfaceAugmentation.class).child(Acl.class);
+    }
+
+    private Acl generateAcl(final String tableName) {
+        final AclBuilder builder = new AclBuilder();
+        final L2Acl l2Acl = new L2AclBuilder().setClassifyTable(tableName).build();
+        builder.setL2Acl(l2Acl);
+        return builder.build();
+    }
+
+    private void whenInputAclSetInterfaceThenSuccess() throws ExecutionException, InterruptedException {
+        final CompletableFuture<InputAclSetInterfaceReply> replyFuture = new CompletableFuture<>();
+        final InputAclSetInterfaceReply reply = new InputAclSetInterfaceReply();
+        replyFuture.complete(reply);
+        doReturn(replyFuture).when(api).inputAclSetInterface(any(InputAclSetInterface.class));
+    }
+
+    private void whenInputAclSetInterfaceThenFailure() throws ExecutionException, InterruptedException {
+        doReturn(TestHelperUtils.<L2InterfaceVlanTagRewriteReply>createFutureException()).when(api)
+            .inputAclSetInterface(any(InputAclSetInterface.class));
+    }
+
+    private void verifyInputAclSetInterfaceWasInvoked(final InputAclSetInterface expected) {
+        final ArgumentCaptor<InputAclSetInterface> argumentCaptor = ArgumentCaptor.forClass(InputAclSetInterface.class);
+        verify(api).inputAclSetInterface(argumentCaptor.capture());
+        final InputAclSetInterface actual = argumentCaptor.getValue();
+        assertEquals(expected.swIfIndex, actual.swIfIndex);
+        assertEquals(expected.l2TableIndex, actual.l2TableIndex);
+        assertEquals(expected.ip4TableIndex, actual.ip4TableIndex);
+        assertEquals(expected.ip6TableIndex, actual.ip6TableIndex);
+        assertEquals(expected.isAdd, actual.isAdd);
+    }
+
+    private void verifyInputAclSetInterfaceDisableWasInvoked(final InputAclSetInterface expected) {
+        final ArgumentCaptor<InputAclSetInterface> argumentCaptor = ArgumentCaptor.forClass(InputAclSetInterface.class);
+        verify(api).inputAclSetInterface(argumentCaptor.capture());
+        final InputAclSetInterface actual = argumentCaptor.getValue();
+        assertEquals(expected.swIfIndex, actual.swIfIndex);
+        assertEquals(expected.l2TableIndex, actual.l2TableIndex);
+        assertEquals(0, actual.isAdd);
+    }
+
+    private static InputAclSetInterface generateInputAclSetInterface(final byte isAdd, final int ifIndex,
+                                                                     final int l2TableIndex) {
+        final InputAclSetInterface request = new InputAclSetInterface();
+        request.isAdd = isAdd;
+        request.l2TableIndex = l2TableIndex;
+        request.ip4TableIndex = ~0;
+        request.ip6TableIndex = ~0;
+        request.swIfIndex = ifIndex;
+        return request;
+    }
+
+    @Test
+    public void testCreate() throws Exception {
+        final Acl acl = generateAcl(ACL_TABLE_NAME);
+        final InstanceIdentifier<Acl> id = getAclId(IF_NAME);
+
+        whenInputAclSetInterfaceThenSuccess();
+
+        customizer.writeCurrentAttributes(id, acl, writeContext);
+
+        verifyInputAclSetInterfaceWasInvoked(generateInputAclSetInterface((byte) 1, IF_INDEX, ACL_TABLE_INDEX));
+    }
+
+    @Test
+    public void testCreateFailed() throws Exception {
+        final Acl acl = generateAcl(ACL_TABLE_NAME);
+        final InstanceIdentifier<Acl> id = getAclId(IF_NAME);
+
+        whenInputAclSetInterfaceThenFailure();
+
+        try {
+            customizer.writeCurrentAttributes(id, acl, writeContext);
+        } catch (WriteFailedException.CreateFailedException e) {
+            assertTrue(e.getCause() instanceof VppBaseCallException);
+            verifyInputAclSetInterfaceWasInvoked(generateInputAclSetInterface((byte) 1, IF_INDEX, ACL_TABLE_INDEX));
+            return;
+        }
+        fail("WriteFailedException.CreateFailedException was expected");
+    }
+
+    @Test
+    public void testDelete() throws Exception {
+        final Acl acl = generateAcl(ACL_TABLE_NAME);
+        final InstanceIdentifier<Acl> id = getAclId(IF_NAME);
+
+        whenInputAclSetInterfaceThenSuccess();
+
+        customizer.deleteCurrentAttributes(id, acl, writeContext);
+
+        verifyInputAclSetInterfaceDisableWasInvoked(generateInputAclSetInterface((byte) 0, IF_INDEX, ACL_TABLE_INDEX));
+    }
+
+    @Test
+    public void testDeleteFailed() throws Exception {
+        final Acl acl = generateAcl(ACL_TABLE_NAME);
+        final InstanceIdentifier<Acl> id = getAclId(IF_NAME);
+
+        whenInputAclSetInterfaceThenFailure();
+
+        try {
+            customizer.deleteCurrentAttributes(id, acl, writeContext);
+        } catch (WriteFailedException.DeleteFailedException e) {
+            assertTrue(e.getCause() instanceof VppBaseCallException);
+            verifyInputAclSetInterfaceDisableWasInvoked(
+                generateInputAclSetInterface((byte) 0, IF_INDEX, ACL_TABLE_INDEX));
+            return;
+        }
+        fail("WriteFailedException.DeleteFailedException was expected");
+    }
+}
\ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizerTest.java
new file mode 100644 (file)
index 0000000..4e9e5de
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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.honeycomb.v3po.translate.v3po.interfacesstate;
+
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMapping;
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMappingIid;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.AclBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.openvpp.jvpp.dto.ClassifyTableByInterface;
+import org.openvpp.jvpp.dto.ClassifyTableByInterfaceReply;
+
+public class AclCustomizerTest extends ChildReaderCustomizerTest<Acl, AclBuilder> {
+
+    private static final String IF_NAME = "local0";
+    private static final int IF_INDEX = 1;
+    private static final int TABLE_INDEX = 123;
+    private static final String TABLE_NAME = "table123";
+
+    private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+    private static final String CT_TEST_INSTANCE = "ct-test-instance";
+
+    private NamingContext interfaceContext;
+    private NamingContext classifyTableContext;
+
+    public AclCustomizerTest() {
+        super(Acl.class);
+    }
+
+    @Override
+    public void setUpBefore() {
+        interfaceContext = new NamingContext("generatedIfaceName", IFC_TEST_INSTANCE);
+        classifyTableContext = new NamingContext("generatedTableContext", CT_TEST_INSTANCE);
+
+        final KeyedInstanceIdentifier<Mapping, MappingKey> ifcMappingKey = getMappingIid(IF_NAME, IFC_TEST_INSTANCE);
+        final Optional<Mapping> ifcMapping = getMapping(IF_NAME, IF_INDEX);
+        doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey);
+
+        final KeyedInstanceIdentifier<Mapping, MappingKey> ctMappingKey = getMappingIid(TABLE_NAME, CT_TEST_INSTANCE);
+        final Optional<Mapping> ctMapping = getMapping(TABLE_NAME, TABLE_INDEX);
+        doReturn(ctMapping).when(mappingContext).read(ctMappingKey);
+
+        final List<Mapping> allCtMappings = Lists.newArrayList(ctMapping.get());
+        final Mappings allCtMappingsBaObject = new MappingsBuilder().setMapping(allCtMappings).build();
+        doReturn(Optional.of(allCtMappingsBaObject)).when(mappingContext)
+            .read(ctMappingKey.firstIdentifierOf(Mappings.class));
+
+        final List<Mapping> allIfcMappings = Lists.newArrayList(ifcMapping.get());
+        final Mappings allIfcMappingsBaObject = new MappingsBuilder().setMapping(allIfcMappings).build();
+        doReturn(Optional.of(allIfcMappingsBaObject)).when(mappingContext)
+            .read(ifcMappingKey.firstIdentifierOf(Mappings.class));
+    }
+
+    @Override
+    protected RootReaderCustomizer<Acl, AclBuilder> initCustomizer() {
+        return new AclCustomizer(api, interfaceContext, classifyTableContext);
+    }
+
+    @Test
+    public void testMerge() {
+        final VppInterfaceStateAugmentationBuilder builder = mock(VppInterfaceStateAugmentationBuilder.class);
+        final Acl value = mock(Acl.class);
+        getCustomizer().merge(builder, value);
+        verify(builder).setAcl(value);
+    }
+
+    private InstanceIdentifier<Acl> getAclId(final String name) {
+        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name))
+            .augmentation(
+                VppInterfaceStateAugmentation.class).child(Acl.class);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        final InstanceIdentifier<Acl> id = getAclId(IF_NAME);
+        final AclBuilder builder = mock(AclBuilder.class);
+
+        final CompletableFuture<ClassifyTableByInterfaceReply> replyFuture = new CompletableFuture<>();
+        final ClassifyTableByInterfaceReply reply = new ClassifyTableByInterfaceReply();
+        reply.l2TableId = TABLE_INDEX;
+        reply.ip4TableId = ~0;
+        reply.ip6TableId = ~0;
+        replyFuture.complete(reply);
+        doReturn(replyFuture).when(api).classifyTableByInterface(any(ClassifyTableByInterface.class));
+
+        getCustomizer().readCurrentAttributes(id, builder, ctx);
+
+        verify(builder).setL2Acl(new L2AclBuilder().setClassifyTable(TABLE_NAME).build());
+        verify(builder).setIp4Acl(null);
+        verify(builder).setIp6Acl(null);
+    }
+
+}
\ No newline at end of file
index 04a766f..31420e1 100644 (file)
@@ -86,7 +86,7 @@ public class ClassifySessionWriterTest {
     private static ClassifySession generateClassifySession(final long opaqueIndex, final String match) {
         final ClassifySessionBuilder builder = new ClassifySessionBuilder();
         builder.setOpaqueIndex(new OpaqueIndex(opaqueIndex));
-        builder.setHitNextIndex(new VppNode(PacketHandlingAction.Deny));
+        builder.setHitNext(new VppNode(PacketHandlingAction.Deny));
         builder.setAdvance(123);
         builder.setMatch(new HexString(match));
         return builder.build();
index 14d6c55..8461f0c 100644 (file)
@@ -111,7 +111,7 @@ public class ClassifyTableReaderTest extends
         verify(builder).setName(TABLE_NAME_1);
         verify(builder).setNbuckets(2L);
         verify(builder, times(0)).setNextTable(anyString());
-        verify(builder).setMissNextIndex(new VppNode(PacketHandlingAction.Permit));
+        verify(builder).setMissNext(new VppNode(PacketHandlingAction.Permit));
         verify(builder).setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
         verify(builder).setActiveSessions(0L);
     }
index 683bd69..015daf3 100644 (file)
@@ -27,7 +27,6 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.MockitoAnnotations.initMocks;
 
 import com.google.common.base.Optional;
@@ -87,7 +86,7 @@ public class ClassifyTableWriterTest {
         builder.setSkipNVectors(0L);
         builder.setNbuckets(2L);
         builder.setMemorySize(2L << 20);
-        builder.setMissNextIndex(new VppNode(PacketHandlingAction.Permit));
+        builder.setMissNext(new VppNode(PacketHandlingAction.Permit));
         builder.setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
         return builder.build();
     }
@@ -220,12 +219,10 @@ public class ClassifyTableWriterTest {
         customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
     }
 
-    @Test
+    @Test(expected = UnsupportedOperationException.class)
     public void testUpdate() throws Exception {
         final ClassifyTable classifyTableBefore = generateClassifyTable(TABLE_NAME);
         final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
         customizer.updateCurrentAttributes(id, classifyTableBefore, new ClassifyTableBuilder().build(), writeContext);
-
-        verifyZeroInteractions(api);
     }
 }
\ No newline at end of file
index 0aff6c1..1df82af 100644 (file)
@@ -21,35 +21,6 @@ public final class SubInterfaceUtils {
     private SubInterfaceUtils() {
         throw new UnsupportedOperationException("Utility class cannot be instantiated.");
     }
-//
-//    @Nullable
-//    private static String getCfgIfaceName(@Nonnull final InstanceIdentifier<?> id) {
-//        final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey key = id.firstKeyOf(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class);
-//        if (key == null) {
-//            return null;
-//        } else {
-//            return key.getName();
-//        }
-//    }
-//
-//    @Nullable
-//    private static String getOperIfaceName(@Nonnull final InstanceIdentifier<?> id) {
-//        final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey key = id.firstKeyOf(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
-//        if (key == null) {
-//            return null;
-//        } else {
-//            return key.getName();
-//        }
-//    }
-//
-//    @Nullable
-//    public static String getSubInterfaceName(@Nonnull final InstanceIdentifier<?> id) {
-//        String ifaceName = getCfgIfaceName(id);
-//        if (ifaceName == null) {
-//            ifaceName = getOperIfaceName(id);
-//        }
-//        if (i)
-//    }
 
     public static String getSubInterfaceName(final String superIfName, final int subIfaceId) {
         return String.format("%s.%d", superIfName, subIfaceId);