89f398d4dcb9bec04d76c3d3a735e8a72db8e15a
[honeycomb.git] / lisp / lisp2vpp / src / main / java / io / fd / honeycomb / lisp / translate / write / AdjacencyCustomizer.java
1 /*
2  * Copyright (c) 2015 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.lisp.translate.write;
18
19
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static io.fd.honeycomb.lisp.translate.read.dump.executor.params.MappingsDumpParams.EidType;
23
24 import io.fd.honeycomb.lisp.context.util.EidMappingContext;
25 import io.fd.honeycomb.lisp.translate.util.EidTranslator;
26 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
27 import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator;
28 import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer;
29 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
30 import io.fd.honeycomb.translate.write.WriteContext;
31 import io.fd.honeycomb.translate.write.WriteFailedException;
32 import io.fd.vpp.jvpp.VppBaseCallException;
33 import io.fd.vpp.jvpp.core.dto.LispAddDelAdjacency;
34 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
35 import java.util.concurrent.TimeoutException;
36 import javax.annotation.Nonnull;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.adjacencies.grouping.adjacencies.Adjacency;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.adjacencies.grouping.adjacencies.AdjacencyKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.adjacencies.grouping.adjacencies.adjacency.LocalEid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.adjacencies.grouping.adjacencies.adjacency.RemoteEid;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.eid.table.grouping.eid.table.VniTable;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43
44 public class AdjacencyCustomizer extends FutureJVppCustomizer
45         implements ListWriterCustomizer<Adjacency, AdjacencyKey>, ByteDataTranslator, EidTranslator,
46         JvppReplyConsumer {
47
48     private final EidMappingContext localEidsMappingContext;
49     private final EidMappingContext remoteEidsMappingContext;
50
51     public AdjacencyCustomizer(@Nonnull final FutureJVppCore futureJvpp,
52                                @Nonnull EidMappingContext localEidsMappingContext,
53                                @Nonnull EidMappingContext remoteEidsMappingContext) {
54         super(futureJvpp);
55         this.localEidsMappingContext =
56                 checkNotNull(localEidsMappingContext, "Eid context for local eid's cannot be null");
57         this.remoteEidsMappingContext =
58                 checkNotNull(remoteEidsMappingContext, "Eid context for remote eid's cannot be null");
59     }
60
61     @Override
62     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Adjacency> id,
63                                        @Nonnull final Adjacency dataAfter, @Nonnull final WriteContext writeContext)
64             throws WriteFailedException {
65
66         try {
67             addDelAdjacency(true, id, dataAfter, writeContext);
68         } catch (TimeoutException | VppBaseCallException e) {
69             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
70         }
71     }
72
73     @Override
74     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Adjacency> id,
75                                         @Nonnull final Adjacency dataBefore, @Nonnull final Adjacency dataAfter,
76                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
77         throw new UnsupportedOperationException("Operation not supported");
78     }
79
80     @Override
81     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Adjacency> id,
82                                         @Nonnull final Adjacency dataBefore, @Nonnull final WriteContext writeContext)
83             throws WriteFailedException {
84         try {
85             addDelAdjacency(false, id, dataBefore, writeContext);
86         } catch (TimeoutException | VppBaseCallException e) {
87             throw new WriteFailedException.CreateFailedException(id, dataBefore, e);
88         }
89     }
90
91     private void addDelAdjacency(boolean add, final InstanceIdentifier<Adjacency> id, final Adjacency data,
92                                  final WriteContext writeContext)
93             throws TimeoutException, VppBaseCallException {
94
95         final int vni = checkNotNull(id.firstKeyOf(VniTable.class), "Unable to find parent VNI for {}", id)
96                 .getVirtualNetworkIdentifier().intValue();
97
98         // both local and remote eids must be referenced to have respective mapping,
99         // if there is an attempt to add adjacency.
100         // In our case its enough to check if local/remote mapping exist for respective eid,
101         // because such mappings are created while creating mappings
102         final LocalEid localEid = add
103                 ? verifiedLocalEid(data.getLocalEid(), writeContext)
104                 : data.getLocalEid();
105         final RemoteEid remoteEid = add
106                 ? verifiedRemoteEid(data.getRemoteEid(), writeContext)
107                 : data.getRemoteEid();
108         final EidType localEidType = getEidType(localEid);
109         final EidType remoteEidType = getEidType(data.getRemoteEid());
110
111         checkArgument(localEidType ==
112                 remoteEidType, "Local[%s] and Remote[%s] eid types must be the same", localEidType, remoteEidType);
113
114         LispAddDelAdjacency request = new LispAddDelAdjacency();
115
116         request.isAdd = booleanToByte(add);
117         request.leid = getEidAsByteArray(localEid);
118         request.leidLen = getPrefixLength(localEid);
119         request.reid = getEidAsByteArray(remoteEid);
120         request.reidLen = getPrefixLength(remoteEid);
121         request.eidType = (byte) localEidType.getValue();
122         request.vni = vni;
123
124         getReply(getFutureJVpp().lispAddDelAdjacency(request).toCompletableFuture());
125     }
126
127     private LocalEid verifiedLocalEid(final LocalEid localEid, final WriteContext writeContext) {
128         if (localEidsMappingContext.containsId(toLocalEid(localEid), writeContext.getMappingContext())) {
129             return localEid;
130         }
131         throw new IllegalStateException(
132                 "Referenced Local Eid[" + localEid +
133                         "] doesn't have local mapping defined, therefore it can't be used in adjacency");
134     }
135
136     private RemoteEid verifiedRemoteEid(final RemoteEid remoteEid, final WriteContext writeContext) {
137         if (remoteEidsMappingContext.containsId(toRemoteEid(remoteEid), writeContext.getMappingContext())) {
138             return remoteEid;
139         }
140         throw new IllegalStateException(
141                 "Referenced Remote Eid[" + remoteEid +
142                         "] doesn't have remote mapping defined, therefore it can't be used in adjacency");
143     }
144
145     private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.dp.subtable.grouping.remote.mappings.remote.mapping.Eid toRemoteEid(
146             final RemoteEid remoteEid) {
147         return newRemoteEidBuilder(remoteEid.getAddressType(), remoteEid.getVirtualNetworkId().getValue().intValue())
148                 .setAddress(remoteEid.getAddress()).build();
149     }
150
151     private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev160520.dp.subtable.grouping.local.mappings.local.mapping.Eid toLocalEid(
152             LocalEid localEid) {
153         return newLocalEidBuilder(localEid.getAddressType(), localEid.getVirtualNetworkId().getValue().intValue())
154                 .setAddress(localEid.getAddress()).build();
155     }
156 }