From da4561dbaaed3f0724c1f1844dba67566bb1062a Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Sun, 5 Jun 2016 21:53:18 +0200 Subject: HONEYCOMB-49: ACL create/delete support for vpp-interface-augmentation Change-Id: I5c25bac07ce618f69cf86f988749b0f86e9a6498 Signed-off-by: Marek Gradzki --- v3po/api/src/main/yang/vpp-classifier.yang | 5 +- v3po/api/src/main/yang/vpp-vlan.yang | 4 + v3po/v3po2vpp/src/main/config/default-config.xml | 8 + .../translate/v3po/interfaces/AclCustomizer.java | 101 ++++++++++ .../v3po/translate/v3po/interfaces/AclWriter.java | 74 +++++++ .../v3po/interfaces/SubInterfaceAclCustomizer.java | 109 ++++++++++ .../v3po/interfacesstate/AclCustomizer.java | 96 +++++++++ .../translate/v3po/interfacesstate/AclReader.java | 57 ++++++ .../interfacesstate/SubInterfaceAclCustomizer.java | 103 ++++++++++ .../v3po/vppclassifier/ClassifySessionReader.java | 2 +- .../v3po/vppclassifier/ClassifySessionWriter.java | 2 +- .../v3po/vppclassifier/ClassifyTableReader.java | 2 +- .../v3po/vppclassifier/ClassifyTableWriter.java | 7 +- .../rev160406/InterfacesHoneycombWriterModule.java | 64 ++++-- .../InterfacesStateHoneycombReaderModule.java | 11 +- .../SubinterfaceAugmentationWriterFactory.java | 24 ++- ...SubinterfaceStateAugmentationReaderFactory.java | 14 +- .../VppClassifierHoneycombWriterModule.java | 7 +- v3po/v3po2vpp/src/main/yang/v3po2vpp.yang | 18 ++ .../v3po/interfaces/AclCustomizerTest.java | 221 +++++++++++++++++++++ .../v3po/interfacesstate/AclCustomizerTest.java | 131 ++++++++++++ .../vppclassifier/ClassifySessionWriterTest.java | 2 +- .../vppclassifier/ClassifyTableReaderTest.java | 2 +- .../vppclassifier/ClassifyTableWriterTest.java | 7 +- .../translate/v3po/util/SubInterfaceUtils.java | 29 --- 25 files changed, 1029 insertions(+), 71 deletions(-) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclReader.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizerTest.java diff --git a/v3po/api/src/main/yang/vpp-classifier.yang b/v3po/api/src/main/yang/vpp-classifier.yang index 0ba94f1cb..b54798857 100644 --- a/v3po/api/src/main/yang/vpp-classifier.yang +++ b/v3po/api/src/main/yang/vpp-classifier.yang @@ -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."; diff --git a/v3po/api/src/main/yang/vpp-vlan.yang b/v3po/api/src/main/yang/vpp-vlan.yang index fef8e72d8..bd3f265ec 100644 --- a/v3po/api/src/main/yang/vpp-vlan.yang +++ b/v3po/api/src/main/yang/vpp-vlan.yang @@ -158,6 +158,10 @@ module vpp-vlan { uses tag-rewrite; } } + + container acl { + uses v3po:acl-base-attributes; + } } grouping sub-interface-config-attributes { diff --git a/v3po/v3po2vpp/src/main/config/default-config.xml b/v3po/v3po2vpp/src/main/config/default-config.xml index 09c6c54df..176756726 100644 --- a/v3po/v3po2vpp/src/main/config/default-config.xml +++ b/v3po/v3po2vpp/src/main/config/default-config.xml @@ -115,6 +115,10 @@ prefix:naming-context bridge-domain-context + + prefix:naming-context + classify-table-context + prefix:vpp-classifier-honeycomb-reader @@ -161,6 +165,10 @@ prefix:naming-context bridge-domain-context + + prefix:naming-context + classify-table-context + 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 index 000000000..4e681f60a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizer.java @@ -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, 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 extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getAcl()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier 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 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 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 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 index 000000000..75b9121af --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclWriter.java @@ -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 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 index 000000000..9cba9c724 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceAclCustomizer.java @@ -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, 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 extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((SubInterface) parentData).getAcl()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier 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 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 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 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 index 000000000..d8d2d8e30 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizer.java @@ -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, 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 parentBuilder, @Nonnull final Acl readValue) { + ((VppInterfaceStateAugmentationBuilder) parentBuilder).setAcl(readValue); + } + + @Nonnull + @Override + public AclBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new AclBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier 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 index 000000000..8b28b754a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclReader.java @@ -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 index 000000000..a00485f49 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java @@ -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, 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 parentBuilder, @Nonnull final Acl readValue) { + ((SubInterfaceBuilder) parentBuilder).setAcl(readValue); + } + + @Nonnull + @Override + public AclBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new AclBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier 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); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionReader.java index 002fc62fd..1f469c5c4 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionReader.java @@ -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)); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriter.java index 08989ce7d..e56d50dbf 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriter.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriter.java @@ -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()); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReader.java index 7f877ca49..ce29dc97b 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReader.java @@ -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)); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriter.java index 4f59ffe8e..788aac59c 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriter.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriter.java @@ -90,8 +90,7 @@ public class ClassifyTableWriter extends FutureJVppCustomizer public void updateCurrentAttributes(@Nonnull final InstanceIdentifier 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 diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java index 2d440cdd5..64f1e8a7c 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java @@ -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 IFC_ID = - InstanceIdentifier.create(Interfaces.class).child(Interface.class); + InstanceIdentifier.create(Interfaces.class).child(Interface.class); public static final InstanceIdentifier VPP_IFC_AUG_ID = - IFC_ID.augmentation(VppInterfaceAugmentation.class); + IFC_ID.augmentation(VppInterfaceAugmentation.class); public static final InstanceIdentifier L2_ID = VPP_IFC_AUG_ID.child(L2.class); + public static final InstanceIdentifier 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 ifcId, @@ -110,18 +123,19 @@ public class InterfacesHoneycombWriterModule extends final InstanceIdentifier 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 ipv4Id = ifc1AugId.child(Ipv4.class); registry.addWriterAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp, ifcContext)), - ifcId); + ifcId); // Address(after Ipv4) = final InstanceIdentifier
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 ifcId, @@ -129,19 +143,19 @@ public class InterfacesHoneycombWriterModule extends // VhostUser(Needs to be executed before Interface customizer) = final InstanceIdentifier 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 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 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 tapId = VPP_IFC_AUG_ID.child(Tap.class); registry.addWriterBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcContext)), - ifcId); + ifcId); final Set> 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 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) + ); } } diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java index 1b8898dff..5c89961b9 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java @@ -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 interfaceReader = new CompositeListReader<>(Interface.class, @@ -134,6 +138,10 @@ public class InterfacesStateHoneycombReaderModule extends new CompositeChildReader<>(VxlanGpe.class, new VxlanGpeCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); + final ChildReader> aclReader = + new CompositeChildReader<>(Acl.class, + new AclCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency(), getClassifyTableContextDependency())); + final ChildReader> 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 vppInterfaceStateAugmentationChildReader = new CompositeChildReader<>(VppInterfaceStateAugmentation.class, diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceAugmentationWriterFactory.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceAugmentationWriterFactory.java index 657769aad..60a9c2e2c 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceAugmentationWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceAugmentationWriterFactory.java @@ -16,10 +16,14 @@ 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 SUB_IFC_AUG_ID = InterfacesHoneycombWriterModule.IFC_ID.augmentation(SubinterfaceAugmentation.class); public static final InstanceIdentifier SUB_IFC_ID = SUB_IFC_AUG_ID.child(SubInterfaces.class).child(SubInterface.class); public static final InstanceIdentifier L2_ID = SUB_IFC_ID.child( L2.class); + public static final InstanceIdentifier 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 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) + ); + } } diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceStateAugmentationReaderFactory.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceStateAugmentationReaderFactory.java index 9e182b1fe..7dfe4d289 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceStateAugmentationReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/SubinterfaceStateAugmentationReaderFactory.java @@ -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 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 createInstance( @Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext bridgeDomainContext) { + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final NamingContext classifyTableContext) { List>> 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 subInterfaceReader = new CompositeListReader<>(SubInterface.class, childReaders, new SubInterfaceCustomizer(futureJvpp, diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppClassifierHoneycombWriterModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppClassifierHoneycombWriterModule.java index 52e99b295..76b60b786 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppClassifierHoneycombWriterModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppClassifierHoneycombWriterModule.java @@ -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)), diff --git a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang index 0c215707d..f70d3f8b1 100644 --- a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang +++ b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang @@ -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 index 000000000..f08ffd46f --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/AclCustomizerTest.java @@ -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 ifcMappingKey = getMappingIid(IF_NAME, IFC_TEST_INSTANCE); + final Optional ifcMapping = getMapping(IF_NAME, IF_INDEX); + doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey); + + final KeyedInstanceIdentifier ctMappingKey = + getMappingIid(ACL_TABLE_NAME, CT_TEST_INSTANCE); + final Optional ctMapping = getMapping(ACL_TABLE_NAME, ACL_TABLE_INDEX); + doReturn(ctMapping).when(mappingContext).read(ctMappingKey); + + final List 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 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 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.createFutureException()).when(api) + .inputAclSetInterface(any(InputAclSetInterface.class)); + } + + private void verifyInputAclSetInterfaceWasInvoked(final InputAclSetInterface expected) { + final ArgumentCaptor 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 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 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 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 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 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 index 000000000..4e9e5dea4 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/AclCustomizerTest.java @@ -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 { + + 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 ifcMappingKey = getMappingIid(IF_NAME, IFC_TEST_INSTANCE); + final Optional ifcMapping = getMapping(IF_NAME, IF_INDEX); + doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey); + + final KeyedInstanceIdentifier ctMappingKey = getMappingIid(TABLE_NAME, CT_TEST_INSTANCE); + final Optional ctMapping = getMapping(TABLE_NAME, TABLE_INDEX); + doReturn(ctMapping).when(mappingContext).read(ctMappingKey); + + final List 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 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 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 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 id = getAclId(IF_NAME); + final AclBuilder builder = mock(AclBuilder.class); + + final CompletableFuture 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 diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriterTest.java index 04a766fa3..31420e1a7 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifySessionWriterTest.java @@ -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(); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReaderTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReaderTest.java index 14d6c5544..8461f0c4a 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReaderTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableReaderTest.java @@ -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); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriterTest.java index 683bd69c3..015daf344 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppclassifier/ClassifyTableWriterTest.java @@ -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 id = getClassifyTableId(TABLE_NAME); customizer.updateCurrentAttributes(id, classifyTableBefore, new ClassifyTableBuilder().build(), writeContext); - - verifyZeroInteractions(api); } } \ No newline at end of file diff --git a/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/SubInterfaceUtils.java b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/SubInterfaceUtils.java index 0aff6c1a7..1df82af73 100644 --- a/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/SubInterfaceUtils.java +++ b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/SubInterfaceUtils.java @@ -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); -- cgit 1.2.3-korg