2 * Copyright (c) 2016 Cisco and/or its affiliates.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package io.fd.honeycomb.translate.v3po.interfaces;
19 import static com.google.common.base.Preconditions.checkArgument;
21 import com.google.common.net.InetAddresses;
22 import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
23 import io.fd.honeycomb.translate.vpp.util.AbstractInterfaceTypeCustomizer;
24 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
25 import io.fd.honeycomb.translate.vpp.util.NamingContext;
26 import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
27 import io.fd.honeycomb.translate.write.WriteContext;
28 import io.fd.honeycomb.translate.write.WriteFailedException;
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 io.fd.vpp.jvpp.VppBaseCallException;
39 import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnel;
40 import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
41 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe> implements JvppReplyConsumer {
47 private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
48 private final NamingContext interfaceNamingContext;
49 private final DisabledInterfacesManager interfaceDisableContext;
51 public VxlanGpeCustomizer(@Nonnull final FutureJVppCore vppApi,
52 @Nonnull final NamingContext interfaceNamingContext,
53 @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
55 this.interfaceNamingContext = interfaceNamingContext;
56 this.interfaceDisableContext = interfaceDisableContext;
60 protected Class<? extends InterfaceType> getExpectedInterfaceType() {
61 return VxlanGpeTunnel.class;
65 protected final void writeInterface(@Nonnull final InstanceIdentifier<VxlanGpe> id,
66 @Nonnull final VxlanGpe dataAfter,
67 @Nonnull final WriteContext writeContext)
68 throws WriteFailedException {
69 final String swIfName = id.firstKeyOf(Interface.class).getName();
71 createVxlanGpeTunnel(id, swIfName, dataAfter, writeContext);
72 } catch (VppBaseCallException | IllegalInterfaceTypeException e) {
73 LOG.warn("Failed to set VxlanGpe tunnel for interface: {}, VxlanGpe: {}", swIfName, dataAfter);
74 throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
79 public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id,
80 @Nonnull final VxlanGpe dataBefore,
81 @Nonnull final VxlanGpe dataAfter, @Nonnull final WriteContext writeContext)
82 throws WriteFailedException.UpdateFailedException {
83 throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
84 new UnsupportedOperationException("VxlanGpe tunnel update is not supported"));
88 public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id,
89 @Nonnull final VxlanGpe dataBefore,
90 @Nonnull final WriteContext writeContext)
91 throws WriteFailedException {
92 final String swIfName = id.firstKeyOf(Interface.class).getName();
94 deleteVxlanGpeTunnel(id, swIfName, dataBefore, writeContext);
95 } catch (VppBaseCallException e) {
96 LOG.warn("Failed to delete VxlanGpe tunnel for interface: {}, VxlanGpe: {}", swIfName, dataBefore);
97 throw new WriteFailedException.DeleteFailedException(id, e);
101 private void createVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
102 final VxlanGpe vxlanGpe, final WriteContext writeContext)
103 throws VppBaseCallException, WriteTimeoutException {
104 final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
107 final InetAddress Local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
108 final InetAddress Remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
110 int vni = vxlanGpe.getVni().getValue().intValue();
111 byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
112 int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
113 int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
115 LOG.debug("Setting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
116 final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
117 getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, Local.getAddress(),
118 Remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
120 final VxlanGpeAddDelTunnelReply reply =
121 getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
122 LOG.debug("VxlanGpe tunnel set successfully for: {}, VxlanGpe: {}", swIfName, vxlanGpe);
123 if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
124 final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
125 LOG.debug("Removing updated mapping of a vxlan-gpe tunnel, id: {}, former name: {}, new name: {}",
126 reply.swIfIndex, formerName, swIfName);
127 interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
130 // Removing disability of an interface in case a vxlan-gpe tunnel formerly deleted is being reused in VPP
131 // further details in above comment
132 if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
133 LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
134 interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
137 // Add new interface to our interface context
138 interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
141 private boolean isIpv6(final VxlanGpe vxlanGpe) {
142 if (vxlanGpe.getLocal().getIpv4Address() == null) {
143 checkArgument(vxlanGpe.getRemote().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s",
145 vxlanGpe.getRemote());
148 checkArgument(vxlanGpe.getRemote().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s",
150 vxlanGpe.getRemote());
155 private String getAddressString(final IpAddress addr) {
156 return addr.getIpv4Address() == null
157 ? addr.getIpv6Address().getValue()
158 : addr.getIpv4Address().getValue();
161 private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
162 final VxlanGpe vxlanGpe, final WriteContext writeContext)
163 throws VppBaseCallException, WriteTimeoutException {
164 final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
167 final InetAddress local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
168 final InetAddress remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
170 int vni = vxlanGpe.getVni().getValue().intValue();
171 byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
172 int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
173 int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
175 LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
176 final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
178 .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, local.getAddress(),
179 remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
181 getReplyForWrite(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
183 final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
184 // Mark this interface as disabled to not include it in operational reads
185 // because VPP will keep the interface there
186 LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
187 interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
188 // Remove interface from our interface naming context
189 interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
192 private static VxlanGpeAddDelTunnel getVxlanGpeTunnelRequest(final byte isAdd, final byte[] local,
194 final int vni, final byte protocol,
195 final int encapVrfId, final int decapVrfId,
197 final VxlanGpeAddDelTunnel VxlanGpeAddDelTunnel = new VxlanGpeAddDelTunnel();
198 VxlanGpeAddDelTunnel.isAdd = isAdd;
199 VxlanGpeAddDelTunnel.local = local;
200 VxlanGpeAddDelTunnel.remote = remote;
201 VxlanGpeAddDelTunnel.vni = vni;
202 VxlanGpeAddDelTunnel.protocol = protocol;
203 VxlanGpeAddDelTunnel.encapVrfId = encapVrfId;
204 VxlanGpeAddDelTunnel.decapVrfId = decapVrfId;
205 VxlanGpeAddDelTunnel.isIpv6 = isIpv6;
206 return VxlanGpeAddDelTunnel;