HONEYCOMB-118: extend classifer model to support node names.
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / vppclassifier / ClassifySessionWriter.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package io.fd.honeycomb.translate.v3po.vppclassifier;
18
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;
22 import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte;
23
24 import com.google.common.base.Optional;
25 import io.fd.honeycomb.translate.MappingContext;
26 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
27 import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
28 import io.fd.honeycomb.translate.write.WriteContext;
29 import io.fd.honeycomb.translate.write.WriteFailedException;
30 import java.util.concurrent.CompletionStage;
31 import javax.annotation.Nonnull;
32 import javax.annotation.Nullable;
33 import javax.xml.bind.DatatypeConverter;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.OpaqueIndex;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySession;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySessionKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableKey;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.openvpp.jvpp.VppBaseCallException;
41 import org.openvpp.jvpp.core.dto.ClassifyAddDelSession;
42 import org.openvpp.jvpp.core.dto.ClassifyAddDelSessionReply;
43 import org.openvpp.jvpp.core.future.FutureJVppCore;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Writer customizer responsible for classify session create/delete.<br> Sends {@code classify_add_del_session} message
49  * to VPP.<br> Equivalent to invoking {@code vppctl classify table} command.
50  */
51 public class ClassifySessionWriter extends VppNodeWriter
52     implements ListWriterCustomizer<ClassifySession, ClassifySessionKey> {
53
54     private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionWriter.class);
55     private final VppClassifierContextManager classifyTableContext;
56
57     public ClassifySessionWriter(@Nonnull final FutureJVppCore futureJVppCore,
58                                  @Nonnull final VppClassifierContextManager classifyTableContext) {
59         super(futureJVppCore);
60         this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
61     }
62
63     @Override
64     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
65                                        @Nonnull final ClassifySession dataAfter,
66                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
67         LOG.debug("Creating classify session: iid={} dataAfter={}", id, dataAfter);
68         try {
69             classifyAddDelSession(true, id, dataAfter, writeContext);
70             LOG.debug("Successfully created classify session: iid={} dataAfter={}", id, dataAfter);
71         } catch (VppBaseCallException e) {
72             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
73         }
74     }
75
76     @Override
77     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
78                                         @Nonnull final ClassifySession dataBefore,
79                                         @Nonnull final ClassifySession dataAfter,
80                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
81         throw new UnsupportedOperationException("Classify session update is not supported");
82     }
83
84     @Override
85     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
86                                         @Nonnull final ClassifySession dataBefore,
87                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
88         LOG.debug("Removing classify session: iid={} dataBefore={}", id, dataBefore);
89         try {
90             classifyAddDelSession(false, id, dataBefore, writeContext);
91             LOG.debug("Successfully removed classify session: iid={} dataBefore={}", id, dataBefore);
92         } catch (VppBaseCallException e) {
93             throw new WriteFailedException.DeleteFailedException(id, e);
94         }
95     }
96
97     private void classifyAddDelSession(final boolean isAdd, @Nonnull final InstanceIdentifier<ClassifySession> id,
98                                        @Nonnull final ClassifySession classifySession,
99                                        @Nonnull final WriteContext writeContext)
100         throws VppBaseCallException, WriteFailedException {
101         final ClassifyTableKey tableKey = id.firstKeyOf(ClassifyTable.class);
102         checkArgument(tableKey != null, "could not find classify table key in {}", id);
103
104         final String tableName = tableKey.getName();
105         checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()),
106             "Could not find classify table index for {} in the classify table context", tableName);
107         final int tableIndex = classifyTableContext.getTableIndex(tableName, writeContext.getMappingContext());
108
109         final ClassifyTable classifyTable =
110             getClassifyTable(writeContext, id.firstIdentifierOf(ClassifyTable.class), isAdd);
111         final int hitNextIndex = getNodeIndex(classifySession.getHitNext(), classifyTable, classifyTableContext,
112             writeContext.getMappingContext(), id);
113         final int opaqueIndex =
114             getOpaqueIndex(classifySession.getOpaqueIndex(), classifyTable, writeContext.getMappingContext(), id);
115
116         final CompletionStage<ClassifyAddDelSessionReply> createClassifyTableReplyCompletionStage = getFutureJVpp()
117             .classifyAddDelSession(
118                 getClassifyAddDelSessionRequest(isAdd, classifySession, tableIndex, hitNextIndex, opaqueIndex));
119
120         TranslateUtils.getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id);
121     }
122
123     private ClassifyTable getClassifyTable(final WriteContext writeContext,
124                                             @Nonnull final InstanceIdentifier<ClassifyTable> id,
125                                             final boolean isAdd) {
126         final Optional<ClassifyTable> classifyTable;
127         if (isAdd) {
128             classifyTable = writeContext.readAfter(id);
129         } else {
130             classifyTable = writeContext.readBefore(id);
131         }
132         return classifyTable.get();
133     }
134
135     private static ClassifyAddDelSession getClassifyAddDelSessionRequest(final boolean isAdd,
136                                                                          @Nonnull final ClassifySession classifySession,
137                                                                          final int tableIndex,
138                                                                          final int hitNextIndex,
139                                                                          final int opaqueIndex) {
140         ClassifyAddDelSession request = new ClassifyAddDelSession();
141         request.isAdd = booleanToByte(isAdd);
142         request.tableIndex = tableIndex;
143         request.hitNextIndex = hitNextIndex;
144         request.opaqueIndex = opaqueIndex;
145
146         // default 0:
147         request.advance = classifySession.getAdvance();
148
149         request.match = DatatypeConverter.parseHexBinary(classifySession.getMatch().getValue().replace(":", ""));
150         return request;
151     }
152
153     private int getOpaqueIndex(@Nullable final OpaqueIndex opaqueIndex, final ClassifyTable classifyTable,
154                                final MappingContext ctx, final InstanceIdentifier<ClassifySession> id)
155         throws VppBaseCallException, WriteFailedException {
156         if (opaqueIndex == null) {
157             return ~0; // value not specified
158         }
159         if (opaqueIndex.getUint32() != null) {
160             return opaqueIndex.getUint32().intValue();
161         } else {
162             return getNodeIndex(opaqueIndex.getVppNode(), classifyTable, classifyTableContext, ctx, id);
163         }
164     }
165 }