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.write.WriteContext;
27 import io.fd.honeycomb.translate.write.WriteFailedException;
28 import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnel;
29 import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
30 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
31 import java.net.InetAddress;
32 import java.util.concurrent.CompletionStage;
33 import javax.annotation.Nonnull;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanGpeTunnel;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VxlanGpe;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe> implements JvppReplyConsumer {
45 private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class);
46 private final NamingContext interfaceNamingContext;
47 private final DisabledInterfacesManager interfaceDisableContext;
49 public VxlanGpeCustomizer(@Nonnull final FutureJVppCore vppApi,
50 @Nonnull final NamingContext interfaceNamingContext,
51 @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
53 this.interfaceNamingContext = interfaceNamingContext;
54 this.interfaceDisableContext = interfaceDisableContext;
58 protected Class<? extends InterfaceType> getExpectedInterfaceType() {
59 return VxlanGpeTunnel.class;
63 protected final void writeInterface(@Nonnull final InstanceIdentifier<VxlanGpe> id,
64 @Nonnull final VxlanGpe dataAfter,
65 @Nonnull final WriteContext writeContext)
66 throws WriteFailedException {
67 final String swIfName = id.firstKeyOf(Interface.class).getName();
68 createVxlanGpeTunnel(id, swIfName, dataAfter, writeContext);
72 public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id,
73 @Nonnull final VxlanGpe dataBefore,
74 @Nonnull final VxlanGpe dataAfter, @Nonnull final WriteContext writeContext)
75 throws WriteFailedException.UpdateFailedException {
76 throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
77 new UnsupportedOperationException("VxlanGpe tunnel update is not supported"));
81 public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id,
82 @Nonnull final VxlanGpe dataBefore,
83 @Nonnull final WriteContext writeContext)
84 throws WriteFailedException {
85 final String swIfName = id.firstKeyOf(Interface.class).getName();
86 deleteVxlanGpeTunnel(id, swIfName, dataBefore, writeContext);
89 private void createVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
90 final VxlanGpe vxlanGpe, final WriteContext writeContext)
91 throws WriteFailedException {
92 final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
95 final InetAddress Local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
96 final InetAddress Remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
98 int vni = vxlanGpe.getVni().getValue().intValue();
99 byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
100 int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
101 int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
103 LOG.debug("Setting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
104 final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
105 getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, Local.getAddress(),
106 Remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
108 final VxlanGpeAddDelTunnelReply reply =
109 getReplyForCreate(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, vxlanGpe);
110 LOG.debug("VxlanGpe tunnel set successfully for: {}, VxlanGpe: {}", swIfName, vxlanGpe);
111 if (interfaceNamingContext.containsName(reply.swIfIndex, writeContext.getMappingContext())) {
112 final String formerName = interfaceNamingContext.getName(reply.swIfIndex, writeContext.getMappingContext());
113 LOG.debug("Removing updated mapping of a vxlan-gpe tunnel, id: {}, former name: {}, new name: {}",
114 reply.swIfIndex, formerName, swIfName);
115 interfaceNamingContext.removeName(formerName, writeContext.getMappingContext());
118 // Removing disability of an interface in case a vxlan-gpe tunnel formerly deleted is being reused in VPP
119 // further details in above comment
120 if (interfaceDisableContext.isInterfaceDisabled(reply.swIfIndex, writeContext.getMappingContext())) {
121 LOG.debug("Removing disability of vxlan tunnel, id: {}, name: {}", reply.swIfIndex, swIfName);
122 interfaceDisableContext.removeDisabledInterface(reply.swIfIndex, writeContext.getMappingContext());
125 // Add new interface to our interface context
126 interfaceNamingContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
129 private boolean isIpv6(final VxlanGpe vxlanGpe) {
130 if (vxlanGpe.getLocal().getIpv4Address() == null) {
131 checkArgument(vxlanGpe.getRemote().getIpv4Address() == null, "Inconsistent ip addresses: %s, %s",
133 vxlanGpe.getRemote());
136 checkArgument(vxlanGpe.getRemote().getIpv6Address() == null, "Inconsistent ip addresses: %s, %s",
138 vxlanGpe.getRemote());
143 private String getAddressString(final IpAddress addr) {
144 return addr.getIpv4Address() == null
145 ? addr.getIpv6Address().getValue()
146 : addr.getIpv4Address().getValue();
149 private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
150 final VxlanGpe vxlanGpe, final WriteContext writeContext)
151 throws WriteFailedException {
152 final byte isIpv6 = (byte) (isIpv6(vxlanGpe)
155 final InetAddress local = InetAddresses.forString(getAddressString(vxlanGpe.getLocal()));
156 final InetAddress remote = InetAddresses.forString(getAddressString(vxlanGpe.getRemote()));
158 int vni = vxlanGpe.getVni().getValue().intValue();
159 byte protocol = (byte) vxlanGpe.getNextProtocol().getIntValue();
160 int encapVrfId = vxlanGpe.getEncapVrfId().intValue();
161 int decapVrfId = vxlanGpe.getDecapVrfId().intValue();
163 LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
164 final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
166 .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, local.getAddress(),
167 remote.getAddress(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
168 getReplyForDelete(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
169 final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
170 // Mark this interface as disabled to not include it in operational reads
171 // because VPP will keep the interface there
172 LOG.debug("Marking vxlan tunnel as disabled, id: {}, name: {}", index, swIfName);
173 interfaceDisableContext.disableInterface(index, writeContext.getMappingContext());
174 // Remove interface from our interface naming context
175 interfaceNamingContext.removeName(swIfName, writeContext.getMappingContext());
178 private static VxlanGpeAddDelTunnel getVxlanGpeTunnelRequest(final byte isAdd, final byte[] local,
180 final int vni, final byte protocol,
181 final int encapVrfId, final int decapVrfId,
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;