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.math.BigInteger;
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.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
38 import org.opendaylight.yangtools.yang.common.RpcResult;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 public class ElanItmUtils {
44 private static final Logger LOG = LoggerFactory.getLogger(ElanItmUtils.class);
46 private final DataBroker broker;
47 private final ItmRpcService itmRpcService;
48 private final OdlInterfaceRpcService interfaceManagerRpcService;
51 public ElanItmUtils(DataBroker broker, ItmRpcService itmRpcService,
52 OdlInterfaceRpcService interfaceManagerRpcService) {
54 this.itmRpcService = itmRpcService;
55 this.interfaceManagerRpcService = interfaceManagerRpcService;
59 * Builds the list of actions to be taken when sending the packet over an
60 * external VxLan tunnel interface, such as stamping the VNI on the VxLAN
61 * header, setting the vlanId if it proceeds and output the packet over the
65 * Dpn where the tunnelInterface is located
67 * NodeId of the ExternalDevice where the packet must be sent to.
69 * Vni to be stamped on the VxLAN Header.
70 * @return the external itm egress action
72 public List<Action> getExternalTunnelItmEgressAction(BigInteger srcDpnId, NodeId torNode, long vni) {
73 List<Action> result = Collections.emptyList();
75 GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
76 .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString())
77 .setTunnelType(TunnelTypeVxlan.class).build();
78 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
79 .getExternalTunnelInterfaceName(input);
81 if (output.get().isSuccessful()) {
82 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
83 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
84 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
86 result = buildTunnelItmEgressActions(tunnelIfaceName, vni);
89 } catch (InterruptedException | ExecutionException e) {
90 LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
96 public List<Action> getExternalTunnelItmEgressAction(BigInteger srcDpnId, String nexthopIP, long vni) {
97 List<Action> result = Collections.emptyList();
99 GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
100 .setDestinationNode(nexthopIP).setSourceNode(srcDpnId.toString())
101 .setTunnelType(TunnelTypeVxlan.class).build();
102 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
103 .getExternalTunnelInterfaceName(input);
105 if (output.get().isSuccessful()) {
106 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
107 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
108 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
110 result = buildTunnelItmEgressActions(tunnelIfaceName, vni);
113 } catch (InterruptedException | ExecutionException e) {
114 LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
121 * Builds the list of actions to be taken when sending the packet over an internal VxLAN tunnel interface, such
122 * as setting the serviceTag/segmentationID on the VNI field of the VxLAN header, setting the vlanId if it proceeds
123 * and output the packet over the right port.
126 * Dpn where the tunnelInterface is located
127 * @param destinationDpnId
128 * Dpn where the packet must be sent to. It is used here in order
129 * to select the right tunnel interface.
131 * Tunnel key to be sent on the VxLAN header.
132 * @return the internal itm egress action
134 public List<Action> getInternalTunnelItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId, long
136 List<Action> result = Collections.emptyList();
137 LOG.trace("In getInternalItmEgressAction Action source {}, destination {}, serviceTag/Vni {}", sourceDpnId,
138 destinationDpnId, tunnelKey);
139 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
140 GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
141 .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
142 Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService.getTunnelInterfaceName(input);
144 if (output.get().isSuccessful()) {
145 GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
146 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
147 LOG.info("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
148 result = buildTunnelItmEgressActions(tunnelIfaceName, tunnelKey);
150 LOG.trace("Tunnel interface doesn't exist between srcDpId {} dstDpId {}", sourceDpnId,
153 } catch (InterruptedException | ExecutionException e) {
154 LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
160 * Builds the list of actions to be taken when sending the packet over a VxLan Tunnel Interface, such as setting
161 * the network VNI in the tunnel_id field.
163 * @param tunnelIfaceName
164 * the tunnel iface name
169 public List<Action> buildTunnelItmEgressActions(String tunnelIfaceName, Long tunnelKey) {
170 if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
171 return buildItmEgressActions(tunnelIfaceName, tunnelKey);
174 return Collections.emptyList();
178 * Build the list of actions to be taken when sending the packet to external
181 * @param interfaceName
183 * @return the external port itm egress actions
185 public List<Action> getExternalPortItmEgressAction(String interfaceName) {
186 return buildItmEgressActions(interfaceName, null);
190 * Builds the list of actions to be taken when sending the packet over external port such as tunnel, physical
193 * @param interfaceName
196 * can be VNI for VxLAN tunnel interfaces, Gre Key for GRE
200 @SuppressWarnings("checkstyle:IllegalCatch")
201 public List<Action> buildItmEgressActions(String interfaceName, Long tunnelKey) {
202 List<Action> result = Collections.emptyList();
204 GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
205 .setIntfName(interfaceName).setTunnelKey(tunnelKey).build();
207 Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture = interfaceManagerRpcService
208 .getEgressActionsForInterface(getEgressActInput);
209 if (egressActionsOutputFuture.get().isSuccessful()) {
210 GetEgressActionsForInterfaceOutput egressActionsOutput = egressActionsOutputFuture.get().getResult();
211 result = egressActionsOutput.getAction();
213 } catch (Exception e) {
214 LOG.error("Error in RPC call getEgressActionsForInterface {}", e);
217 if (result == null || result.isEmpty()) {
218 LOG.warn("Could not build Egress actions for interface {} and tunnelId {}", interfaceName, tunnelKey);
224 * Gets the source dpn tep ip.
228 * @param dstHwVtepNodeId
229 * the dst hw vtep node id
230 * @return the dpn tep ip
232 public IpAddress getSourceDpnTepIp(BigInteger srcDpnId,
233 org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId dstHwVtepNodeId) {
234 IpAddress dpnTepIp = null;
235 String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(srcDpnId),
236 dstHwVtepNodeId.getValue());
237 if (tunnelInterfaceName != null) {
238 Interface tunnelInterface =
239 ElanL2GatewayUtils.getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
240 if (tunnelInterface != null) {
241 dpnTepIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
243 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
246 LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
253 * Gets the external tunnel interface name.
259 * @return the external tunnel interface name
261 public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
262 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
263 String tunnelInterfaceName = null;
265 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
266 .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
267 .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
269 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
270 if (rpcResult.isSuccessful()) {
271 tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
272 LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
273 sourceNode, dstNode);
275 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}", rpcResult.getErrors());
277 } catch (NullPointerException | InterruptedException | ExecutionException e) {
278 LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}",
279 sourceNode, dstNode, e);
281 return tunnelInterfaceName;