b57274a88de89be8f29aaed2665ad86b92922363
[hc2vpp.git] /
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.v3po.translate.v3po.interfacesstate;
18
19 import static com.google.common.base.Preconditions.checkState;
20 import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType;
21
22 import io.fd.honeycomb.v3po.translate.read.ReadContext;
23 import io.fd.honeycomb.v3po.translate.read.ReadFailedException;
24 import io.fd.honeycomb.v3po.translate.spi.read.ReaderCustomizer;
25 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
26 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
27 import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
28 import java.net.InetAddress;
29 import java.net.UnknownHostException;
30 import java.util.Arrays;
31 import java.util.concurrent.CompletionStage;
32 import javax.annotation.Nonnull;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanBuilder;
43 import org.opendaylight.yangtools.concepts.Builder;
44 import org.opendaylight.yangtools.yang.binding.DataObject;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.openvpp.jvpp.VppBaseCallException;
47 import org.openvpp.jvpp.dto.VxlanTunnelDetails;
48 import org.openvpp.jvpp.dto.VxlanTunnelDetailsReplyDump;
49 import org.openvpp.jvpp.dto.VxlanTunnelDump;
50 import org.openvpp.jvpp.future.FutureJVpp;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class VxlanCustomizer extends FutureJVppCustomizer
55         implements ReaderCustomizer<Vxlan, VxlanBuilder> {
56
57     private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class);
58     private final NamingContext interfaceContext;
59
60     public VxlanCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext) {
61         super(jvpp);
62         this.interfaceContext = interfaceContext;
63     }
64
65     @Override
66     public void merge(@Nonnull Builder<? extends DataObject> parentBuilder,
67                       @Nonnull Vxlan readValue) {
68         ((VppInterfaceStateAugmentationBuilder) parentBuilder).setVxlan(readValue);
69     }
70
71     @Nonnull
72     @Override
73     public VxlanBuilder getBuilder(@Nonnull InstanceIdentifier<Vxlan> id) {
74         return new VxlanBuilder();
75     }
76
77     @Override
78     public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Vxlan> id,
79                                       @Nonnull final VxlanBuilder builder,
80                                       @Nonnull final ReadContext ctx) throws ReadFailedException {
81         try {
82             final InterfaceKey key = id.firstKeyOf(Interface.class);
83             final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext());
84             if (!isInterfaceOfType(getFutureJVpp(), ctx.getModificationCache(), id, index, VxlanTunnel.class)) {
85                 return;
86             }
87
88             LOG.debug("Reading attributes for vxlan tunnel: {}", key.getName());
89             // Dump just a single
90             final VxlanTunnelDump request = new VxlanTunnelDump();
91             request.swIfIndex = index;
92
93             final CompletionStage<VxlanTunnelDetailsReplyDump> swInterfaceVxlanDetailsReplyDumpCompletionStage =
94                 getFutureJVpp().vxlanTunnelDump(request);
95             final VxlanTunnelDetailsReplyDump reply =
96                 TranslateUtils.getReplyForRead(swInterfaceVxlanDetailsReplyDumpCompletionStage.toCompletableFuture(), id);
97
98             // VPP keeps vxlan tunnel interfaces even after they were deleted (optimization)
99             // However there ar no longer any vxlan tunnel specific fields assigned to it and this call
100             // returns nothing
101             if (reply == null || reply.vxlanTunnelDetails == null || reply.vxlanTunnelDetails.isEmpty()) {
102                 LOG.debug(
103                     "Vxlan tunnel {}, id {} has no attributes assigned in VPP. Probably is a leftover interface placeholder" +
104                         "after delete", key.getName(), index);
105                 return;
106             }
107
108             checkState(reply.vxlanTunnelDetails.size() == 1,
109                 "Unexpected number of returned vxlan tunnels: {} for tunnel: {}", reply.vxlanTunnelDetails, key.getName());
110             LOG.trace("Vxlan tunnel: {} attributes returned from VPP: {}", key.getName(), reply);
111
112             final VxlanTunnelDetails swInterfaceVxlanDetails = reply.vxlanTunnelDetails.get(0);
113             if (swInterfaceVxlanDetails.isIpv6 == 1) {
114                 final Ipv6Address dstIpv6 =
115                     new Ipv6Address(parseAddress(swInterfaceVxlanDetails.dstAddress).getHostAddress());
116                 builder.setDst(new IpAddress(dstIpv6));
117                 final Ipv6Address srcIpv6 =
118                     new Ipv6Address(parseAddress(swInterfaceVxlanDetails.srcAddress).getHostAddress());
119                 builder.setSrc(new IpAddress(srcIpv6));
120             } else {
121                 final byte[] dstBytes = Arrays.copyOfRange(swInterfaceVxlanDetails.dstAddress, 0, 4);
122                 final Ipv4Address dstIpv4 = new Ipv4Address(parseAddress(dstBytes).getHostAddress());
123                 builder.setDst(new IpAddress(dstIpv4));
124                 final byte[] srcBytes = Arrays.copyOfRange(swInterfaceVxlanDetails.srcAddress, 0, 4);
125                 final Ipv4Address srcIpv4 = new Ipv4Address(parseAddress(srcBytes).getHostAddress());
126                 builder.setSrc(new IpAddress(srcIpv4));
127             }
128             builder.setEncapVrfId((long) swInterfaceVxlanDetails.encapVrfId);
129             builder.setVni( new VxlanVni((long) swInterfaceVxlanDetails.vni));
130             LOG.debug("Vxlan tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder);
131         } catch (VppBaseCallException e) {
132             LOG.warn("Failed to readCurrentAttributes for: {}", id);
133             throw new ReadFailedException( id, e );
134         }
135     }
136
137     @Nonnull
138     private static InetAddress parseAddress(@Nonnull final byte[] addr) {
139         try {
140             return InetAddress.getByAddress(addr);
141         } catch (UnknownHostException e) {
142             throw new IllegalArgumentException("Cannot create InetAddress from " + Arrays.toString(addr), e);
143         }
144     }
145 }