e56d50dbf8296bf3dfae72b8bad756e49dd11e22
[hc2vpp.git] /
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.v3po.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.v3po.translate.v3po.util.TranslateUtils.booleanToByte;
23
24 import com.google.common.base.Optional;
25 import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer;
26 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
27 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
28 import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
29 import io.fd.honeycomb.v3po.translate.v3po.util.WriteTimeoutException;
30 import io.fd.honeycomb.v3po.translate.write.WriteContext;
31 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
32 import java.util.List;
33 import java.util.concurrent.CompletionStage;
34 import javax.annotation.Nonnull;
35 import javax.xml.bind.DatatypeConverter;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.OpaqueIndex;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.attributes.ClassifySession;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.attributes.ClassifySessionKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableKey;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.openvpp.jvpp.VppBaseCallException;
44 import org.openvpp.jvpp.dto.ClassifyAddDelSession;
45 import org.openvpp.jvpp.dto.ClassifyAddDelSessionReply;
46 import org.openvpp.jvpp.future.FutureJVpp;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 /**
51  * Writer customizer responsible for classify session create/delete.<br> Sends {@code classify_add_del_session} message
52  * to VPP.<br> Equivalent to invoking {@code vppctl classify table} command.
53  */
54 public class ClassifySessionWriter extends FutureJVppCustomizer
55     implements ListWriterCustomizer<ClassifySession, ClassifySessionKey> {
56
57     private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionWriter.class);
58     private final NamingContext classifyTableContext;
59
60     public ClassifySessionWriter(@Nonnull final FutureJVpp futureJvpp,
61                                  @Nonnull final NamingContext classifyTableContext) {
62         super(futureJvpp);
63         this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
64     }
65
66     @Nonnull
67     @Override
68     public Optional<List<ClassifySession>> extract(@Nonnull final InstanceIdentifier<ClassifySession> currentId,
69                                                    @Nonnull final DataObject parentData) {
70         return Optional.fromNullable(((ClassifyTable) parentData).getClassifySession());
71     }
72
73     @Override
74     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
75                                        @Nonnull final ClassifySession dataAfter,
76                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
77         LOG.debug("Creating classify session: iid={} dataAfter={}", id, dataAfter);
78         try {
79             classifyAddDelSession(true, id, dataAfter, writeContext);
80             LOG.debug("Successfully created classify session: iid={} dataAfter={}", id, dataAfter);
81         } catch (VppBaseCallException e) {
82             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
83         }
84     }
85
86     @Override
87     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
88                                         @Nonnull final ClassifySession dataBefore,
89                                         @Nonnull final ClassifySession dataAfter,
90                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
91         throw new UnsupportedOperationException("Classify session update is not supported");
92     }
93
94     @Override
95     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<ClassifySession> id,
96                                         @Nonnull final ClassifySession dataBefore,
97                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
98         LOG.debug("Removing classify session: iid={} dataBefore={}", id, dataBefore);
99         try {
100             classifyAddDelSession(false, id, dataBefore, writeContext);
101             LOG.debug("Successfully removed classify session: iid={} dataBefore={}", id, dataBefore);
102         } catch (VppBaseCallException e) {
103             throw new WriteFailedException.DeleteFailedException(id, e);
104         }
105     }
106
107     private void classifyAddDelSession(final boolean isAdd, @Nonnull final InstanceIdentifier<ClassifySession> id,
108                                        @Nonnull final ClassifySession classifySession,
109                                        @Nonnull final WriteContext writeContext)
110         throws VppBaseCallException, WriteTimeoutException {
111         final ClassifyTableKey tableKey = id.firstKeyOf(ClassifyTable.class);
112         checkArgument(tableKey != null, "could not find classify table key in {}", id);
113
114         final String tableName = tableKey.getName();
115         checkState(classifyTableContext.containsIndex(tableName, writeContext.getMappingContext()),
116             "Could not find classify table index for {} in the classify table context", tableName);
117         final int tableIndex = classifyTableContext.getIndex(tableName, writeContext.getMappingContext());
118
119         final CompletionStage<ClassifyAddDelSessionReply> createClassifyTableReplyCompletionStage = getFutureJVpp()
120             .classifyAddDelSession(
121                 getClassifyAddDelSessionRequest(isAdd, tableIndex, classifySession));
122
123         TranslateUtils.getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id);
124     }
125
126     private static ClassifyAddDelSession getClassifyAddDelSessionRequest(final boolean isAdd, final int tableIndex,
127                                                                          @Nonnull final ClassifySession classifySession) {
128         ClassifyAddDelSession request = new ClassifyAddDelSession();
129         request.isAdd = booleanToByte(isAdd);
130         request.tableIndex = tableIndex;
131
132         // mandatory:
133         // TODO implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed
134         request.hitNextIndex = classifySession.getHitNext().getPacketHandlingAction().getIntValue();
135
136         if (classifySession.getOpaqueIndex() != null) {
137             request.opaqueIndex = getOpaqueIndexValue(classifySession.getOpaqueIndex());
138         } else {
139             request.opaqueIndex = ~0; // value not specified
140         }
141
142         // default 0:
143         request.advance = classifySession.getAdvance();
144
145         request.match = DatatypeConverter.parseHexBinary(classifySession.getMatch().getValue().replace(":", ""));
146         return request;
147     }
148
149     private static int getOpaqueIndexValue(@Nonnull final OpaqueIndex opaqueIndex) {
150         if (opaqueIndex.getUint32() != null) {
151             return opaqueIndex.getUint32().intValue();
152         } else {
153             // TODO: implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed
154             return opaqueIndex.getVppNode().getPacketHandlingAction().getIntValue();
155         }
156     }
157 }