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.v3po.translate.v3po.interfacesstate;
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump;
22 import com.google.common.base.Preconditions;
23 import com.google.common.collect.Iterables;
24 import io.fd.honeycomb.v3po.translate.ModificationCache;
25 import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
26 import java.math.BigInteger;
28 import java.util.Objects;
29 import java.util.concurrent.CompletionStage;
30 import java.util.stream.Collectors;
31 import javax.annotation.Nonnull;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
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.state.InterfaceKey;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
40 import org.openvpp.jvpp.dto.SwInterfaceDetails;
41 import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump;
42 import org.openvpp.jvpp.dto.SwInterfaceDump;
43 import org.openvpp.jvpp.future.FutureJVpp;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public final class InterfaceUtils {
48 private static final Logger LOG = LoggerFactory.getLogger(InterfaceUtils.class);
50 private static final Gauge64 vppLinkSpeed0 = new Gauge64(BigInteger.ZERO);
51 private static final Gauge64 vppLinkSpeed1 = new Gauge64(BigInteger.valueOf(10 * 1000000));
52 private static final Gauge64 vppLinkSpeed2 = new Gauge64(BigInteger.valueOf(100 * 1000000));
53 private static final Gauge64 vppLinkSpeed4 = new Gauge64(BigInteger.valueOf(1000 * 1000000));
54 private static final Gauge64 vppLinkSpeed8 = new Gauge64(BigInteger.valueOf(10000L * 1000000));
55 private static final Gauge64 vppLinkSpeed16 = new Gauge64(BigInteger.valueOf(40000L * 1000000));
56 private static final Gauge64 vppLinkSpeed32 = new Gauge64(BigInteger.valueOf(100000L * 1000000));
58 private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
60 private static final int PHYSICAL_ADDRESS_LENGTH = 6;
62 private InterfaceUtils() {
63 throw new UnsupportedOperationException("This utility class cannot be instantiated");
67 * Convert VPP's link speed bitmask to Yang type. 1 = 10M, 2 = 100M, 4 = 1G, 8 = 10G, 16 = 40G, 32 = 100G
69 * @param vppLinkSpeed Link speed in bitmask format from VPP.
70 * @return Converted value from VPP link speed
72 public static Gauge64 vppInterfaceSpeedToYang(byte vppLinkSpeed) {
73 switch (vppLinkSpeed) {
83 return vppLinkSpeed16;
85 return vppLinkSpeed32;
91 private static final void appendHexByte(final StringBuilder sb, final byte b) {
92 final int v = b & 0xFF;
93 sb.append(HEX_CHARS[v >>> 4]);
94 sb.append(HEX_CHARS[v & 15]);
97 // TODO rename and move to V3poUtils
100 * Reads first 6 bytes of supplied byte array and converts to string as Yang dictates <p> Replace later with
101 * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- util/src/main/
102 * java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java
104 * @param vppPhysAddress byte array of bytes in big endian order, constructing the network IF physical address.
105 * @return String like "aa:bb:cc:dd:ee:ff"
106 * @throws NullPointerException if vppPhysAddress is null
107 * @throws IllegalArgumentException if vppPhysAddress.length < 6
109 public static String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) {
110 Objects.requireNonNull(vppPhysAddress, "Empty physical address bytes");
111 Preconditions.checkArgument(PHYSICAL_ADDRESS_LENGTH <= vppPhysAddress.length,
112 "Invalid physical address size %s, expected >= 6", vppPhysAddress.length);
113 StringBuilder physAddr = new StringBuilder();
115 appendHexByte(physAddr, vppPhysAddress[0]);
116 for (int i = 1; i < PHYSICAL_ADDRESS_LENGTH; i++) {
117 physAddr.append(":");
118 appendHexByte(physAddr, vppPhysAddress[i]);
121 return physAddr.toString();
125 * VPP's interface index is counted from 0, whereas ietf-interface's if-index is from 1. This function converts from
126 * VPP's interface index to YANG's interface index.
128 * @param vppIfIndex the sw interface index VPP reported.
129 * @return VPP's interface index incremented by one
131 public static int vppIfIndexToYang(int vppIfIndex) {
132 return vppIfIndex + 1;
136 * This function does the opposite of what {@link #vppIfIndexToYang(int)} does.
138 * @param yangIfIndex if-index from ietf-interfaces.
139 * @return VPP's representation of the if-index
141 public static int yangIfIndexToVpp(int yangIfIndex) {
142 Preconditions.checkArgument(yangIfIndex >= 1, "YANG if-index has invalid value %s", yangIfIndex);
143 return yangIfIndex - 1;
148 * Queries VPP for interface description given interface key.
150 * @param futureJvpp VPP Java Future API
151 * @param key interface key
152 * @param index VPP index of the interface
153 * @param ctx per-tx scope context containing cached dump with all the interfaces. If the cache is not
154 * available or outdated, another dump will be performed.
155 * @return SwInterfaceDetails DTO or null if interface was not found
156 * @throws IllegalArgumentException If interface cannot be found
159 public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp,
160 @Nonnull InterfaceKey key, final int index,
161 @Nonnull final ModificationCache ctx) {
162 final SwInterfaceDump request = new SwInterfaceDump();
163 request.nameFilter = key.getName().getBytes();
164 request.nameFilterValid = 1;
166 final Map<Integer, SwInterfaceDetails> allInterfaces = getCachedInterfaceDump(ctx);
168 // Returned cached if available
169 if (allInterfaces.containsKey(index)) {
170 return allInterfaces.get(index);
173 CompletionStage<SwInterfaceDetailsReplyDump> requestFuture = futureJvpp.swInterfaceDump(request);
174 SwInterfaceDetailsReplyDump ifaces = TranslateUtils.getReply(requestFuture.toCompletableFuture());
175 if (null == ifaces || null == ifaces.swInterfaceDetails || ifaces.swInterfaceDetails.isEmpty()) {
176 request.nameFilterValid = 0;
178 LOG.warn("VPP returned null instead of interface by key {} and its not cached", key.getName());
179 LOG.warn("Iterating through all the interfaces to find interface: {}", key.getName());
181 // Or else just perform full dump and do inefficient filtering
182 requestFuture = futureJvpp.swInterfaceDump(request);
183 ifaces = TranslateUtils.getReply(requestFuture.toCompletableFuture());
186 allInterfaces.clear();
188 .putAll(ifaces.swInterfaceDetails.stream().collect(Collectors.toMap(d -> d.swIfIndex, d -> d)));
190 if (allInterfaces.containsKey(index)) {
191 return allInterfaces.get(index);
193 throw new IllegalArgumentException("Unable to find interface " + key.getName());
196 final SwInterfaceDetails iface = Iterables.getOnlyElement(ifaces.swInterfaceDetails);
197 allInterfaces.put(index, iface); // update the cache
202 * Determine interface type based on its VPP name (relying on VPP's interface naming conventions)
204 * @param interfaceName VPP generated interface name
205 * @return Interface type
208 public static Class<? extends InterfaceType> getInterfaceType(@Nonnull final String interfaceName) {
209 if (interfaceName.startsWith("tap")) {
213 if (interfaceName.startsWith("vxlan")) {
214 return VxlanTunnel.class;
217 if (interfaceName.startsWith("VirtualEthernet")) {
218 return VhostUser.class;
221 if (interfaceName.contains(".")) {
222 return SubInterface.class;
225 return EthernetCsmacd.class;
228 static boolean isInterfaceOfType(final ModificationCache ctx, final int index,
229 final Class<? extends InterfaceType> ifcType) {
230 final SwInterfaceDetails cachedDetails =
231 checkNotNull(getCachedInterfaceDump(ctx).get(index),
232 "Interface {} cannot be found in context", index);
233 return isInterfaceOfType(ifcType, cachedDetails);
236 static boolean isInterfaceOfType(final Class<? extends InterfaceType> ifcType,
237 final SwInterfaceDetails cachedDetails) {
238 return ifcType.equals(getInterfaceType(TranslateUtils.toString(cachedDetails.interfaceName)));