logging issues in elanmanager
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / utils / ElanItmUtils.java
1 /*
2  * Copyright © 2017 Red Hat, Inc. and others.
3  *
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
7  */
8 package org.opendaylight.netvirt.elan.utils;
9
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;
41
42 @Singleton
43 public class ElanItmUtils {
44     private static final Logger LOG = LoggerFactory.getLogger(ElanItmUtils.class);
45
46     private final DataBroker broker;
47     private final ItmRpcService itmRpcService;
48     private final OdlInterfaceRpcService interfaceManagerRpcService;
49
50     @Inject
51     public ElanItmUtils(DataBroker broker, ItmRpcService itmRpcService,
52             OdlInterfaceRpcService interfaceManagerRpcService) {
53         this.broker = broker;
54         this.itmRpcService = itmRpcService;
55         this.interfaceManagerRpcService = interfaceManagerRpcService;
56     }
57
58     /**
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
62      * right port.
63      *
64      * @param srcDpnId
65      *            Dpn where the tunnelInterface is located
66      * @param torNode
67      *            NodeId of the ExternalDevice where the packet must be sent to.
68      * @param vni
69      *            Vni to be stamped on the VxLAN Header.
70      * @return the external itm egress action
71      */
72     public List<Action> getExternalTunnelItmEgressAction(BigInteger srcDpnId, NodeId torNode, long vni) {
73         List<Action> result = Collections.emptyList();
74
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);
80         try {
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);
85
86                 result = buildTunnelItmEgressActions(tunnelIfaceName, vni);
87             }
88
89         } catch (InterruptedException | ExecutionException e) {
90             LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
91         }
92
93         return result;
94     }
95
96     public List<Action> getExternalTunnelItmEgressAction(BigInteger srcDpnId, String nexthopIP, long vni) {
97         List<Action> result = Collections.emptyList();
98
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);
104         try {
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);
109
110                 result = buildTunnelItmEgressActions(tunnelIfaceName, vni);
111             }
112
113         } catch (InterruptedException | ExecutionException e) {
114             LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
115         }
116
117         return result;
118     }
119
120     /**
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.
124      *
125      * @param sourceDpnId
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.
130      * @param tunnelKey
131      *            Tunnel key to be sent on the VxLAN header.
132      * @return the internal itm egress action
133      */
134     public List<Action> getInternalTunnelItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId, long
135             tunnelKey) {
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);
143         try {
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);
149             } else {
150                 LOG.trace("Tunnel interface doesn't exist between srcDpId {} dstDpId {}", sourceDpnId,
151                         destinationDpnId);
152             }
153         } catch (InterruptedException | ExecutionException e) {
154             LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
155         }
156         return result;
157     }
158
159     /**
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.
162      *
163      * @param tunnelIfaceName
164      *            the tunnel iface name
165      * @param tunnelKey
166      *            the tunnel key
167      * @return the list
168      */
169     public List<Action> buildTunnelItmEgressActions(String tunnelIfaceName, Long tunnelKey) {
170         if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
171             return buildItmEgressActions(tunnelIfaceName, tunnelKey);
172         }
173
174         return Collections.emptyList();
175     }
176
177     /**
178      * Build the list of actions to be taken when sending the packet to external
179      * (physical) port.
180      *
181      * @param interfaceName
182      *            Interface name
183      * @return the external port itm egress actions
184      */
185     public List<Action> getExternalPortItmEgressAction(String interfaceName) {
186         return buildItmEgressActions(interfaceName, null);
187     }
188
189     /**
190      * Builds the list of actions to be taken when sending the packet over external port such as tunnel, physical
191      * port etc.
192      *
193      * @param interfaceName
194      *            the interface name
195      * @param tunnelKey
196      *            can be VNI for VxLAN tunnel interfaces, Gre Key for GRE
197      *            tunnels, etc.
198      * @return the list
199      */
200     @SuppressWarnings("checkstyle:IllegalCatch")
201     public List<Action> buildItmEgressActions(String interfaceName, Long tunnelKey) {
202         List<Action> result = Collections.emptyList();
203         try {
204             GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
205                     .setIntfName(interfaceName).setTunnelKey(tunnelKey).build();
206
207             Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture = interfaceManagerRpcService
208                     .getEgressActionsForInterface(getEgressActInput);
209             if (egressActionsOutputFuture.get().isSuccessful()) {
210                 GetEgressActionsForInterfaceOutput egressActionsOutput = egressActionsOutputFuture.get().getResult();
211                 result = egressActionsOutput.getAction();
212             }
213         } catch (Exception e) {
214             LOG.error("Error in RPC call getEgressActionsForInterface {}", e);
215         }
216
217         if (result == null || result.isEmpty()) {
218             LOG.warn("Could not build Egress actions for interface {} and tunnelId {}", interfaceName, tunnelKey);
219         }
220         return result;
221     }
222
223     /**
224      * Gets the source dpn tep ip.
225      *
226      * @param srcDpnId
227      *            the src dpn id
228      * @param dstHwVtepNodeId
229      *            the dst hw vtep node id
230      * @return the dpn tep ip
231      */
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();
242             } else {
243                 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
244             }
245         } else {
246             LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
247                     dstHwVtepNodeId);
248         }
249         return dpnTepIp;
250     }
251
252     /**
253      * Gets the external tunnel interface name.
254      *
255      * @param sourceNode
256      *            the source node
257      * @param dstNode
258      *            the dst node
259      * @return the external tunnel interface name
260      */
261     public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
262         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
263         String tunnelInterfaceName = null;
264         try {
265             Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
266                     .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
267                             .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
268
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);
274             } else {
275                 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}", rpcResult.getErrors());
276             }
277         } catch (NullPointerException | InterruptedException | ExecutionException e) {
278             LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}",
279                     sourceNode, dstNode, e);
280         }
281         return tunnelInterfaceName;
282     }
283 }