HONEYCOMB-58 - Routing Api
[honeycomb.git] / nsh / impl / src / main / java / io / fd / honeycomb / vppnsh / impl / config / NshEntryWriterCustomizer.java
1 /*
2  * Copyright (c) 2016 Intel 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.vppnsh.impl.config;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21
22 import io.fd.honeycomb.translate.MappingContext;
23 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
24 import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator;
25 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
26 import io.fd.honeycomb.translate.vpp.util.NamingContext;
27 import io.fd.honeycomb.translate.write.WriteContext;
28 import io.fd.honeycomb.translate.write.WriteFailedException;
29 import io.fd.honeycomb.vppnsh.impl.util.FutureJVppNshCustomizer;
30 import io.fd.vpp.jvpp.nsh.dto.NshAddDelEntry;
31 import io.fd.vpp.jvpp.nsh.dto.NshAddDelEntryReply;
32 import io.fd.vpp.jvpp.nsh.future.FutureJVppNsh;
33 import java.util.concurrent.CompletionStage;
34 import javax.annotation.Nonnull;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ethernet;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv4;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.Ipv6;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.MdType1;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.NshMdType1Augment;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntry;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.nsh.rev160624.vpp.nsh.nsh.entries.NshEntryKey;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * Writer customizer responsible for NshEntry create/delete.
48  */
49 public class NshEntryWriterCustomizer extends FutureJVppNshCustomizer
50         implements ListWriterCustomizer<NshEntry, NshEntryKey>, ByteDataTranslator, JvppReplyConsumer {
51
52     private static final Logger LOG = LoggerFactory.getLogger(NshEntryWriterCustomizer.class);
53     private final NamingContext nshEntryContext;
54
55     public NshEntryWriterCustomizer(@Nonnull final FutureJVppNsh futureJVppNsh,
56                                     @Nonnull final NamingContext nshEntryContext) {
57         super(futureJVppNsh);
58         this.nshEntryContext = checkNotNull(nshEntryContext, "nshEntryContext should not be null");
59     }
60
61     @Override
62     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
63                                        @Nonnull final NshEntry dataAfter, @Nonnull final WriteContext writeContext)
64             throws WriteFailedException {
65         LOG.debug("Creating nsh entry: iid={} dataAfter={}", id, dataAfter);
66         final int newEntryIndex =
67                 nshAddDelEntry(true, id, dataAfter, ~0 /* value not present */, writeContext.getMappingContext());
68         // Add nsh entry name <-> vpp index mapping to the naming context:
69         nshEntryContext.addName(newEntryIndex, dataAfter.getName(), writeContext.getMappingContext());
70         LOG.debug("Successfully created nsh entry(id={]): iid={} dataAfter={}", newEntryIndex, id, dataAfter);
71     }
72
73     @Override
74     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
75                                         @Nonnull final NshEntry dataBefore, @Nonnull final NshEntry dataAfter,
76                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
77         throw new UnsupportedOperationException("Nsh entry update is not supported");
78     }
79
80     @Override
81     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<NshEntry> id,
82                                         @Nonnull final NshEntry dataBefore,
83                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
84         LOG.debug("Removing nsh entry: iid={} dataBefore={}", id, dataBefore);
85         final String entryName = dataBefore.getName();
86         checkState(nshEntryContext.containsIndex(entryName, writeContext.getMappingContext()),
87                 "Removing nsh entry {}, but index could not be found in the nsh entry context", entryName);
88
89         final int entryIndex = nshEntryContext.getIndex(entryName, writeContext.getMappingContext());
90         nshAddDelEntry(false, id, dataBefore, entryIndex, writeContext.getMappingContext());
91
92         // Remove deleted interface from interface context:
93         nshEntryContext.removeName(dataBefore.getName(), writeContext.getMappingContext());
94         LOG.debug("Successfully removed nsh entry(id={]): iid={} dataAfter={}", entryIndex, id, dataBefore);
95     }
96
97     private int nshAddDelEntry(final boolean isAdd, @Nonnull final InstanceIdentifier<NshEntry> id,
98                                @Nonnull final NshEntry entry, final int entryId, final MappingContext ctx)
99             throws WriteFailedException {
100         final CompletionStage<NshAddDelEntryReply> createNshEntryReplyCompletionStage =
101                 getFutureJVppNsh().nshAddDelEntry(getNshAddDelEntryRequest(isAdd, entryId, entry, ctx));
102
103         final NshAddDelEntryReply reply =
104                 getReplyForWrite(createNshEntryReplyCompletionStage.toCompletableFuture(), id);
105         return reply.entryIndex;
106
107     }
108
109     private void getNshEntryMdType1Request(@Nonnull final NshEntry entry,
110                                            @Nonnull NshAddDelEntry request) {
111         final NshMdType1Augment nshMdType1Augment = entry.getAugmentation(NshMdType1Augment.class);
112         if (nshMdType1Augment != null) {
113             request.c1 = (int) nshMdType1Augment.getC1().longValue();
114             request.c2 = (int) nshMdType1Augment.getC2().longValue();
115             request.c3 = (int) nshMdType1Augment.getC3().longValue();
116             request.c4 = (int) nshMdType1Augment.getC4().longValue();
117         }
118     }
119
120     private NshAddDelEntry getNshAddDelEntryRequest(final boolean isAdd, final int entryIndex,
121                                                     @Nonnull final NshEntry entry,
122                                                     @Nonnull final MappingContext ctx) {
123         final NshAddDelEntry request = new NshAddDelEntry();
124         request.isAdd = booleanToByte(isAdd);
125
126         request.verOC = (byte) entry.getVersion().shortValue();
127         request.length = (byte) entry.getLength().intValue();
128         if (entry.getNextProtocol() == Ipv4.class) {
129             request.nextProtocol = 1;
130         } else if (entry.getNextProtocol() == Ipv6.class) {
131             request.nextProtocol = 2;
132         } else if (entry.getNextProtocol() == Ethernet.class) {
133             request.nextProtocol = 3;
134         } else {
135             request.nextProtocol = 0;
136         }
137
138         if (entry.getMdType() == MdType1.class) {
139             request.mdType = 1;
140             getNshEntryMdType1Request(entry, request);
141         } else if (entry.getMdType() == MdType1.class) {
142             request.mdType = 2;
143         } else {
144             request.mdType = 0;
145         }
146
147         request.nspNsi = (entry.getNsp().intValue() << 8) | entry.getNsi();
148
149         return request;
150     }
151 }