HONEYCOMB-204 exclude deleted interfaces from operational data
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / interfaces / VxlanGpeCustomizer.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.interfaces;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20
21 import com.google.common.net.InetAddresses;
22 import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
23 import io.fd.honeycomb.translate.v3po.util.AbstractInterfaceTypeCustomizer;
24 import io.fd.honeycomb.translate.v3po.util.NamingContext;
25 import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
26 import io.fd.honeycomb.translate.write.WriteContext;
27 import io.fd.honeycomb.translate.write.WriteFailedException;
28 import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
29 import java.net.InetAddress;
30 import java.util.concurrent.CompletionStage;
31 import javax.annotation.Nonnull;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeTunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpe;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.openvpp.jvpp.VppBaseCallException;
39 import org.openvpp.jvpp.core.dto.VxlanGpeAddDelTunnel;
40 import org.openvpp.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
41 import org.openvpp.jvpp.core.future.FutureJVppCore;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe> {
46
47     private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
48     private final NamingContext interfaceNamingContext;
49     private final DisabledInterfacesManager interfaceDisableContext;
50
51     public VxlanGpeCustomizer(@Nonnull final FutureJVppCore vppApi,
52                               @Nonnull final NamingContext interfaceNamingContext,
53                               @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
54         super(vppApi);
55         this.interfaceNamingContext = interfaceNamingContext;
56         this.interfaceDisableContext = interfaceDisableContext;
57     }
58
59     @Override
60     protected Class<? extends InterfaceType> getExpectedInterfaceType() {
61         return VxlanGpeTunnel.class;
62     }
63
64     @Override
65     protected final void writeInterface(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataAfter,
66                                        @Nonnull final WriteContext writeContext)
67             throws WriteFailedException {
68         final String swIfName = id.firstKeyOf(Interface.class).getName();
69         try {
70             createVxlanGpeTunnel(id, swIfName, dataAfter, writeContext);
71         } catch (VppBaseCallException | IllegalInterfaceTypeException e) {
72             LOG.warn("Failed to set VxlanGpe tunnel for interface: {}, VxlanGpe: {}", swIfName, dataAfter);
73             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
74         }
75     }
76
77     @Override
78     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataBefore,
79                                         @Nonnull final VxlanGpe dataAfter, @Nonnull final WriteContext writeContext)
80             throws WriteFailedException.UpdateFailedException {
81         throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
82                 new UnsupportedOperationException("VxlanGpe tunnel update is not supported"));
83     }
84
85     @Override
86     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataBefore,
87                                         @Nonnull final WriteContext writeContext)
88             throws WriteFailedException {
89         final String swIfName = id.firstKeyOf(Interface.class).getName();
90         try {
91             deleteVxlanGpeTunnel(id, swIfName, dataBefore, writeContext);
92         } catch (VppBaseCallException e) {
93             LOG.warn("Failed to delete VxlanGpe tunnel for interface: {}, VxlanGpe: {}", swIfName, dataBefore);
94             throw new WriteFailedException.DeleteFailedException(id, e);
95         }
96     }
97
98     private void createVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
99                                       final VxlanGpe vxlanGpe, final WriteContext writeContext)
100         throws VppBaseCallException, WriteTimeoutException {
101         final byte isIpv6 = (byte) (isIpv6(vxlanGpe) ? 1 : 0);
102         final InetAddress Local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
103         final InetAddress Remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
104
105         int vni = vxlanGpe.getVni().getValue().intValue();
106         byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
107         int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
108         int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
109
110         LOG.debug("Setting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
111         final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
112                 getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, Local.getAddress(),
113                     Remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
114
115         final VxlanGpeAddDelTunnelReply reply =
116                 TranslateUtils.getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
117         LOG.debug("VxlanGpe tunnel set successfully for: {}, VxlanGpe: {}", swIfName, vxlanGpe);
118         if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
119             final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
120             LOG.debug("Removing updated mapping of a vxlan-gpe tunnel, id: {}, former name: {}, new name: {}",
121                 reply.swIfIndex, formerName, swIfName);
122             interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
123         }
124
125         // Removing disability of an interface in case a vxlan-gpe tunnel formerly deleted is being reused in VPP
126         // further details in above comment
127         if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
128             LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
129             interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
130         }
131
132         // Add new interface to our interface context
133         interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
134     }
135
136     private boolean isIpv6(final VxlanGpe vxlanGpe) {
137         if (vxlanGpe.getLocal().getIpv4Address() == null) {
138             checkArgument(vxlanGpe.getRemote().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s", vxlanGpe.getLocal(),
139                 vxlanGpe.getRemote());
140             return true;
141         } else {
142             checkArgument(vxlanGpe.getRemote().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s", vxlanGpe.getLocal(),
143                 vxlanGpe.getRemote());
144             return false;
145         }
146     }
147
148     private String getAddressString(final IpAddress addr) {
149         return addr.getIpv4Address() == null ? addr.getIpv6Address().getValue() : addr.getIpv4Address().getValue();
150     }
151
152     private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
153                                       final VxlanGpe vxlanGpe, final WriteContext writeContext)
154         throws VppBaseCallException, WriteTimeoutException {
155         final byte isIpv6 = (byte) (isIpv6(vxlanGpe) ? 1 : 0);
156         final InetAddress local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
157         final InetAddress remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
158
159         int vni = vxlanGpe.getVni().getValue().intValue();
160         byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
161         int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
162         int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
163
164         LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
165         final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
166                 getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, local.getAddress(),
167                     remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
168
169         TranslateUtils.getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
170
171         final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
172         // Mark this interface as disabled to not include it in operational reads
173         // because VPP will keep the interface there
174         LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
175         interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
176         // Remove interface from our interface naming context
177         interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
178     }
179
180     private static VxlanGpeAddDelTunnel getVxlanGpeTunnelRequest(final byte isAdd, final byte[] local, final byte[] remote,
181                                         final int vni, final byte protocol, final int encapVrfId, final int decapVrfId,
182                                         final byte isIpv6) {
183         final VxlanGpeAddDelTunnel VxlanGpeAddDelTunnel = new VxlanGpeAddDelTunnel();
184         VxlanGpeAddDelTunnel.isAdd = isAdd;
185         VxlanGpeAddDelTunnel.local = local;
186         VxlanGpeAddDelTunnel.remote = remote;
187         VxlanGpeAddDelTunnel.vni = vni;
188         VxlanGpeAddDelTunnel.protocol = protocol;
189         VxlanGpeAddDelTunnel.encapVrfId = encapVrfId;
190         VxlanGpeAddDelTunnel.decapVrfId = decapVrfId;
191         VxlanGpeAddDelTunnel.isIpv6 = isIpv6;
192         return VxlanGpeAddDelTunnel;
193     }
194 }