2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.honeycomb.translate.v3po.vppclassifier;
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Preconditions.checkState;
23 import io.fd.honeycomb.translate.MappingContext;
24 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
25 import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator;
26 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
27 import io.fd.honeycomb.translate.write.WriteContext;
28 import io.fd.honeycomb.translate.write.WriteFailedException;
29 import java.util.concurrent.CompletionStage;
30 import javax.annotation.Nonnull;
31 import javax.xml.bind.DatatypeConverter;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableKey;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.openvpp.jvpp.VppBaseCallException;
36 import org.openvpp.jvpp.core.dto.ClassifyAddDelTable;
37 import org.openvpp.jvpp.core.dto.ClassifyAddDelTableReply;
38 import org.openvpp.jvpp.core.future.FutureJVppCore;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * Writer customizer responsible for classify table create/delete. <br> Sends {@code classify_add_del_table} message to
44 * VPP.<br> Equivalent to invoking {@code vppctl classify table} command.
46 public class ClassifyTableWriter extends VppNodeWriter
47 implements ListWriterCustomizer<ClassifyTable, ClassifyTableKey>, ByteDataTranslator, JvppReplyConsumer {
49 private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableWriter.class);
50 private final VppClassifierContextManager classifyTableContext;
52 public ClassifyTableWriter(@Nonnull final FutureJVppCore futureJVppCore,
53 @Nonnull final VppClassifierContextManager classifyTableContext) {
54 super(futureJVppCore);
55 this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
59 public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifyTable> id,
60 @Nonnull final ClassifyTable dataAfter, @Nonnull final WriteContext writeContext)
61 throws WriteFailedException {
62 LOG.debug("Creating classify table: iid={} dataAfter={}", id, dataAfter);
64 final int newTableIndex =
65 classifyAddDelTable(true, id, dataAfter, ~0 /* value not present */,
66 writeContext.getMappingContext());
68 // Add classify table name <-> vpp index mapping to the naming context:
69 classifyTableContext.addTable(newTableIndex, dataAfter.getName(), dataAfter.getClassifierNode(),
70 writeContext.getMappingContext());
71 LOG.debug("Successfully created classify table(id={]): iid={} dataAfter={}", newTableIndex, id, dataAfter);
72 } catch (VppBaseCallException e) {
73 throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
78 public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifyTable> id,
79 @Nonnull final ClassifyTable dataBefore, @Nonnull final ClassifyTable dataAfter,
80 @Nonnull final WriteContext writeContext) throws WriteFailedException {
81 throw new UnsupportedOperationException("Classify table update is not supported");
85 public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifyTable> id,
86 @Nonnull final ClassifyTable dataBefore,
87 @Nonnull final WriteContext writeContext) throws WriteFailedException {
88 LOG.debug("Removing classify table: iid={} dataBefore={}", id, dataBefore);
89 final String tableName = dataBefore.getName();
90 checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()),
91 "Removing classify table {}, but index could not be found in the classify table context", tableName);
93 final int tableIndex = classifyTableContext.getTableIndex(tableName, writeContext.getMappingContext());
95 classifyAddDelTable(false, id, dataBefore, tableIndex, writeContext.getMappingContext());
97 // Remove deleted interface from interface context:
98 classifyTableContext.removeTable(dataBefore.getName(), writeContext.getMappingContext());
99 LOG.debug("Successfully removed classify table(id={]): iid={} dataAfter={}", tableIndex, id, dataBefore);
100 } catch (VppBaseCallException e) {
101 throw new WriteFailedException.DeleteFailedException(id, e);
105 private int classifyAddDelTable(final boolean isAdd, @Nonnull final InstanceIdentifier<ClassifyTable> id,
106 @Nonnull final ClassifyTable table, final int tableId, final MappingContext ctx)
107 throws VppBaseCallException, WriteFailedException {
109 final int missNextIndex =
110 getNodeIndex(table.getMissNext(), table, classifyTableContext, ctx, id);
112 final CompletionStage<ClassifyAddDelTableReply> createClassifyTableReplyCompletionStage =
114 .classifyAddDelTable(getClassifyAddDelTableRequest(isAdd, tableId, table, missNextIndex, ctx));
116 final ClassifyAddDelTableReply reply =
117 getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id);
118 return reply.newTableIndex;
121 private ClassifyAddDelTable getClassifyAddDelTableRequest(final boolean isAdd, final int tableIndex,
122 @Nonnull final ClassifyTable table,
123 final int missNextIndex,
124 @Nonnull final MappingContext ctx) {
125 final ClassifyAddDelTable request = new ClassifyAddDelTable();
126 request.isAdd = booleanToByte(isAdd);
127 request.tableIndex = tableIndex;
129 // mandatory, all u32 values are permitted:
130 request.nbuckets = table.getNbuckets().intValue();
131 request.memorySize = table.getMemorySize().intValue();
132 request.skipNVectors = table.getSkipNVectors().intValue();
135 request.missNextIndex = missNextIndex;
137 final String nextTable = table.getNextTable();
138 if (isAdd && nextTable != null) {
139 request.nextTableIndex = classifyTableContext.getTableIndex(nextTable, ctx);
141 request.nextTableIndex = ~0; // value not specified
143 request.mask = DatatypeConverter.parseHexBinary(table.getMask().getValue().replace(":", ""));
144 checkArgument(request.mask.length % 16 == 0, "Number of mask bytes must be multiple of 16.");
145 request.matchNVectors = request.mask.length / 16;