From 6509e0875c394fa122e56bbaa93b2f11205d1d67 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Wed, 20 Jul 2016 09:48:14 +0200 Subject: HONEYCOMB-118: extend classifer model to support node names. * configuration write is supported (updates local cache with relative node mapping) * operational read is supported only for nodes with existing relative node mapping * ACL support (using vpp-classfier or ietf-acl model) is not affected by the patch (tables/sessions for access controll refer to neighbour nodes as packet-handling-action, not vpp-node-name) Change-Id: Ice0c846803cc7e8960c3571fd2a13ed46ba53702 Signed-off-by: Marek Gradzki --- .../VppClassifierContextManagerImpl.java | 176 +++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java (limited to 'v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java new file mode 100644 index 000000000..9f61ab021 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java @@ -0,0 +1,176 @@ +/* + * 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.translate.v3po.vppclassifier; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.BindingBrokerReader; +import java.util.stream.Collector; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Named; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Facade on top of {@link MappingContext} that manages {@link ClassifyTableContext}. + */ +public final class VppClassifierContextManagerImpl implements VppClassifierContextManager { + private static final Collector SINGLE_ITEM_COLLECTOR = + RWUtils.singleItemCollector(); + + @VisibleForTesting + static final InstanceIdentifier + VPP_CLASSIFIER_CONTEXT_IID = KeyedInstanceIdentifier.create(VppClassifierContext.class); + private final String artificialNamePrefix; + + /** + * Creates new VppClassifierContextManagerImpl. + * + * @param artificialNamePrefix artificial name to be used to generate names for classify tables without existing + * metadata + */ + public VppClassifierContextManagerImpl(@Nonnull final String artificialNamePrefix) { + this.artificialNamePrefix = + Preconditions.checkNotNull(artificialNamePrefix, "artificialNamePrefix should not be null"); + } + + private KeyedInstanceIdentifier getMappingIid(final String name) { + return VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(name)); + } + + @Override + public void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier mappingIid = getMappingIid(name); + final ClassifyTableContextBuilder tableCtx = new ClassifyTableContextBuilder().setIndex(id).setName(name); + if (classifierNode != null) { + tableCtx.setClassifierNodeName(classifierNode.getValue()); + } + ctx.put(mappingIid, tableCtx.build()); + } + + @Override + public boolean containsTable(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional read = ctx.read(getMappingIid(name)); + return read.isPresent(); + } + + @Override + public int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional read = ctx.read(getMappingIid(name)); + checkArgument(read.isPresent(), "No mapping stored for name: %s", name); + return read.get().getIndex(); + } + + @Override + public String getTableName(final int id, @Nonnull final MappingContext ctx) { + if (!containsName(id, ctx)) { + final String artificialName = getArtificialName(id); + addTable(id, artificialName, null, ctx); + } + + final Optional read = ctx.read(VPP_CLASSIFIER_CONTEXT_IID); + checkState(read.isPresent(), "VppClassifierContext for index: %s is not present. But should be", id); + + return read.get().getClassifyTableContext().stream() + .filter(t -> t.getIndex().equals(id)) + .collect(SINGLE_ITEM_COLLECTOR).getName(); + } + + private boolean containsName(final int index, @Nonnull final MappingContext mappingContext) { + final Optional read = mappingContext.read(VPP_CLASSIFIER_CONTEXT_IID); + return read.isPresent() + ? read.get().getClassifyTableContext().stream().anyMatch(t -> t.getIndex().equals(index)) + : false; + } + + @Override + public Optional getTableBaseNode(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional read = ctx.read(getMappingIid(name)); + if (read.isPresent()) { + return Optional.fromNullable(read.get().getClassifierNodeName()); + } + return Optional.absent(); + } + + @Override + public void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx) { + ctx.delete(getMappingIid(name)); + } + + @Override + public void addNodeName(@Nonnull final String tableName, final int nodeIndex, + @Nonnull final String nodeName, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier iid = + getMappingIid(tableName).child(NodeContext.class, new NodeContextKey(nodeName)); + ctx.put(iid, new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build()); + } + + @Override + public Optional getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx) { + if (!containsName(tableIndex, ctx)) { + return Optional.absent(); + } + final String tableName = getTableName(tableIndex, ctx); + final Optional tableCtx = ctx.read(getMappingIid(tableName)); + return Optional.fromNullable(tableCtx.get().getNodeContext().stream() + .filter(n -> n.getIndex().equals(nodeIndex)) + .findFirst() + .map(nodes -> nodes.getName()) + .orElse(null)); + } + + private String getArtificialName(final int index) { + return artificialNamePrefix + index; + } + + public static final class ContextsReaderFactory implements ReaderFactory { + + @Inject + @Named("honeycomb-context") + private DataBroker contextBindingBrokerDependency; + + @Override + public void init(final ModifiableReaderRegistryBuilder registry) { + registry.add(new BindingBrokerReader<>(VPP_CLASSIFIER_CONTEXT_IID, + contextBindingBrokerDependency, + LogicalDatastoreType.OPERATIONAL, VppClassifierContextBuilder.class)); + } + } +} -- cgit 1.2.3-korg