2 * Copyright © 2017 Red Hat, Inc. and others.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.elan.utils;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.Uint64;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 public class ElanItmUtils {
50 private static final Logger LOG = LoggerFactory.getLogger(ElanItmUtils.class);
52 private final DataBroker broker;
53 private final ItmRpcService itmRpcService;
54 private final OdlInterfaceRpcService interfaceManagerRpcService;
55 private final IInterfaceManager interfaceManager;
58 public ElanItmUtils(final DataBroker broker, final ItmRpcService itmRpcService,
59 final OdlInterfaceRpcService interfaceManagerRpcService, final IInterfaceManager interfaceManager) {
61 this.itmRpcService = itmRpcService;
62 this.interfaceManagerRpcService = interfaceManagerRpcService;
63 this.interfaceManager = interfaceManager;
67 * Builds the list of actions to be taken when sending the packet over an
68 * external VxLan tunnel interface, such as stamping the VNI on the VxLAN
69 * header, setting the vlanId if it proceeds and output the packet over the
73 * Dpn where the tunnelInterface is located
75 * NodeId of the ExternalDevice where the packet must be sent to.
77 * Vni to be stamped on the VxLAN Header.
78 * @return the external itm egress action
80 public List<Action> getExternalTunnelItmEgressAction(Uint64 srcDpnId, NodeId torNode, long vni) {
81 List<Action> result = Collections.emptyList();
83 GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
84 .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString())
85 .setTunnelType(TunnelTypeVxlan.class).build();
86 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
87 .getExternalTunnelInterfaceName(input);
89 if (output.get().isSuccessful()) {
90 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
91 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
92 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
94 result = buildTunnelItmEgressActions(tunnelIfaceName, vni, false);
97 } catch (InterruptedException | ExecutionException e) {
98 LOG.error("Error in RPC call getTunnelInterfaceName", e);
104 public List<Action> getExternalTunnelItmEgressAction(Uint64 srcDpnId, String nexthopIP, long vni) {
105 List<Action> result = Collections.emptyList();
107 GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
108 .setDestinationNode(nexthopIP).setSourceNode(srcDpnId.toString())
109 .setTunnelType(TunnelTypeVxlan.class).build();
110 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
111 .getExternalTunnelInterfaceName(input);
113 if (output.get().isSuccessful()) {
114 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
115 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
116 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
118 result = buildTunnelItmEgressActions(tunnelIfaceName, vni, false);
121 } catch (InterruptedException | ExecutionException e) {
122 LOG.error("Error in RPC call getTunnelInterfaceName", e);
129 * Builds the list of actions to be taken when sending the packet over an internal VxLAN tunnel interface, such
130 * as setting the serviceTag/segmentationID on the VNI field of the VxLAN header, setting the vlanId if it proceeds
131 * and output the packet over the right port.
134 * Dpn where the tunnelInterface is located
135 * @param destinationDpnId
136 * Dpn where the packet must be sent to. It is used here in order
137 * to select the right tunnel interface.
139 * Tunnel key to be sent on the VxLAN header.
140 * @return the internal itm egress action
142 public List<Action> getInternalTunnelItmEgressAction(Uint64 sourceDpnId, Uint64 destinationDpnId, long
144 List<Action> result = Collections.emptyList();
145 LOG.trace("In getInternalItmEgressAction Action source {}, destination {}, serviceTag/Vni {}", sourceDpnId,
146 destinationDpnId, tunnelKey);
147 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
148 GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
149 .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
150 Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService.getTunnelInterfaceName(input);
152 if (output.get().isSuccessful()) {
153 GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
154 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
155 LOG.info("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
156 result = buildTunnelItmEgressActions(tunnelIfaceName, tunnelKey, true);
158 LOG.trace("Tunnel interface doesn't exist between srcDpId {} dstDpId {}", sourceDpnId,
161 } catch (InterruptedException | ExecutionException e) {
162 LOG.error("Error in RPC call getTunnelInterfaceName", e);
168 * Builds the list of actions to be taken when sending the packet over a VxLan Tunnel Interface, such as setting
169 * the network VNI in the tunnel_id field.
171 * @param tunnelIfaceName
172 * the tunnel iface name
177 public List<Action> buildTunnelItmEgressActions(String tunnelIfaceName, Long tunnelKey, boolean ineternal) {
178 if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
179 return buildItmEgressActions(tunnelIfaceName, tunnelKey, ineternal);
181 return Collections.emptyList();
185 * Build the list of actions to be taken when sending the packet to external
188 * @param interfaceName
190 * @return the external port itm egress actions
192 public List<Action> getExternalPortItmEgressAction(String interfaceName) {
193 return buildItmEgressActions(interfaceName, null, false);
197 * Builds the list of actions to be taken when sending the packet over external port such as tunnel, physical
200 * @param interfaceName
203 * can be VNI for VxLAN tunnel interfaces, Gre Key for GRE
207 @SuppressWarnings("checkstyle:IllegalCatch")
208 public List<Action> buildItmEgressActions(String interfaceName, @Nullable Long tunnelKey, boolean internal) {
210 if (internal && interfaceManager.isItmDirectTunnelsEnabled()) {
211 GetEgressActionsForTunnelInput getEgressActInputItm = new GetEgressActionsForTunnelInputBuilder()
212 .setIntfName(interfaceName).setTunnelKey(tunnelKey).build();
213 Future<RpcResult<GetEgressActionsForTunnelOutput>> egressActionsOutputItm =
214 itmRpcService.getEgressActionsForTunnel(getEgressActInputItm);
215 if (egressActionsOutputItm.get().isSuccessful()) {
216 return new ArrayList<Action>(egressActionsOutputItm.get().getResult().nonnullAction().values());
219 GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
220 .setIntfName(interfaceName).setTunnelKey(tunnelKey).build();
221 Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture =
222 interfaceManagerRpcService.getEgressActionsForInterface(getEgressActInput);
223 if (egressActionsOutputFuture.get().isSuccessful()) {
224 return new ArrayList<Action>(egressActionsOutputFuture.get().getResult().nonnullAction().values());
227 } catch (Exception e) {
228 LOG.error("Error in RPC call getEgressActionsForInterface", e);
230 LOG.warn("Could not build Egress actions for interface {} and tunnelId {}", interfaceName, tunnelKey);
231 return Collections.emptyList();
235 * Gets the source dpn tep ip.
239 * @param dstHwVtepNodeId
240 * the dst hw vtep node id
241 * @return the dpn tep ip
243 public IpAddress getSourceDpnTepIp(Uint64 srcDpnId,
244 org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId dstHwVtepNodeId) {
245 IpAddress dpnTepIp = null;
246 String tunnelInterfaceName = getExternalTunnelInterfaceName(srcDpnId.toString(),
247 dstHwVtepNodeId.getValue());
248 if (tunnelInterfaceName != null) {
249 Interface tunnelInterface =
250 ElanL2GatewayUtils.getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
251 if (tunnelInterface != null) {
252 dpnTepIp = tunnelInterface.augmentation(IfTunnel.class).getTunnelSource();
254 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
257 LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
264 * Gets the external tunnel interface name.
270 * @return the external tunnel interface name
272 public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
273 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
274 String tunnelInterfaceName = null;
276 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
277 .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
278 .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
280 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
281 if (rpcResult.isSuccessful()) {
282 tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
283 LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
284 sourceNode, dstNode);
286 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}", rpcResult.getErrors());
288 } catch (NullPointerException | InterruptedException | ExecutionException e) {
289 LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}",
290 sourceNode, dstNode, e);
292 return tunnelInterfaceName;