208ae6d9235ecade5fb135459aa61566b9902a6a
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / rpc / ItmManagerRpcService.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
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.genius.itm.rpc;
9
10 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11 import static org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.fromListenableFuture;
12 import static org.opendaylight.yangtools.yang.common.RpcResultBuilder.failed;
13
14 import com.google.common.base.Objects;
15 import com.google.common.util.concurrent.FluentFuture;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import java.math.BigInteger;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.concurrent.ExecutionException;
30 import java.util.stream.Collectors;
31 import javax.annotation.PostConstruct;
32 import javax.annotation.PreDestroy;
33 import javax.inject.Inject;
34 import javax.inject.Singleton;
35 import org.eclipse.jdt.annotation.NonNull;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
38 import org.opendaylight.genius.interfacemanager.interfaces.InterfaceManagerService;
39 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
40 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
41 import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache;
42 import org.opendaylight.genius.itm.cache.OfTepStateCache;
43 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
44 import org.opendaylight.genius.itm.cache.TunnelStateCache;
45 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
46 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
47 import org.opendaylight.genius.itm.globals.ITMConstants;
48 import org.opendaylight.genius.itm.impl.ItmUtils;
49 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
50 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
51 import org.opendaylight.genius.mdsalutil.ActionInfo;
52 import org.opendaylight.genius.mdsalutil.MDSALUtil;
53 import org.opendaylight.genius.mdsalutil.MatchInfo;
54 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
55 import org.opendaylight.genius.mdsalutil.NwConstants;
56 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
57 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
58 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
59 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
60 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
61 import org.opendaylight.mdsal.binding.api.DataBroker;
62 import org.opendaylight.mdsal.binding.util.Datastore;
63 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
64 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
65 import org.opendaylight.mdsal.binding.util.RetryingManagedNewTransactionRunner;
66 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
67 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
68 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
69 import org.opendaylight.mdsal.common.api.ReadFailedException;
70 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults;
71 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.LogLevel;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVteps;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsKey;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpInput;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpOutput;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpOutputBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutputBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelInput;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelOutput;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsOutput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelInput;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutput;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
170 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
171 import org.opendaylight.yangtools.yang.common.OperationFailedException;
172 import org.opendaylight.yangtools.yang.common.RpcError;
173 import org.opendaylight.yangtools.yang.common.RpcResult;
174 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
175 import org.opendaylight.yangtools.yang.common.Uint16;
176 import org.opendaylight.yangtools.yang.common.Uint64;
177 import org.slf4j.Logger;
178 import org.slf4j.LoggerFactory;
179
180 @Singleton
181 public class ItmManagerRpcService implements ItmRpcService {
182
183     private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
184
185     private final DataBroker dataBroker;
186     private final IMdsalApiManager mdsalManager;
187     private final DPNTEPsInfoCache dpnTEPsInfoCache;
188     private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
189     private final SingleTransactionDataBroker singleTransactionDataBroker;
190     private final IInterfaceManager interfaceManager;
191     private final InterfaceManagerService interfaceManagerService;
192     private final DpnTepStateCache dpnTepStateCache;
193     private final TunnelStateCache tunnelStateCache;
194     private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
195     private final DirectTunnelUtils directTunnelUtils;
196     private final ManagedNewTransactionRunner txRunner;
197     private final RetryingManagedNewTransactionRunner retryingTxRunner;
198     private final ItmConfig itmConfig;
199     private final OfDpnTepConfigCache ofDpnTepConfigCache;
200     private final OfTepStateCache ofTepStateCache;
201
202     @Inject
203     public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
204                                 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache,
205                                 final IInterfaceManager interfaceManager, final DpnTepStateCache dpnTepStateCache,
206                                 final TunnelStateCache tunnelStateCache,
207                                 final InterfaceManagerService interfaceManagerService,
208                                 final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
209                                 final DirectTunnelUtils directTunnelUtils, OfDpnTepConfigCache ofDpnTepConfigCache,
210                                 OfTepStateCache ofTepStateCache) {
211         this.dataBroker = dataBroker;
212         this.mdsalManager = mdsalManager;
213         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
214         this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig, dpnTEPsInfoCache);
215         this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
216         this.interfaceManager = interfaceManager;
217         this.interfaceManagerService = interfaceManagerService;
218         this.dpnTepStateCache = dpnTepStateCache;
219         this.tunnelStateCache = tunnelStateCache;
220         this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
221         this.directTunnelUtils = directTunnelUtils;
222         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
223         this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker);
224         this.itmConfig = itmConfig;
225         this.ofDpnTepConfigCache = ofDpnTepConfigCache;
226         this.ofTepStateCache = ofTepStateCache;
227     }
228
229     @PostConstruct
230     public void start() {
231         LOG.info("ItmManagerRpcService Started");
232     }
233
234     @PreDestroy
235     public void close() {
236         LOG.info("ItmManagerRpcService Closed");
237     }
238
239     @Override
240     public ListenableFuture<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(
241             GetTunnelInterfaceNameInput input) {
242         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
243         Uint64 sourceDpn = input.getSourceDpid();
244         Uint64 destinationDpn = input.getDestinationDpid();
245         Optional<InternalTunnel> optTunnel = Optional.empty();
246
247         if (interfaceManager.isItmOfTunnelsEnabled()) {
248             //Destination DPN Id is not relevant in OF Tunnel scenario and so is ignored
249             try {
250                 Optional<OfDpnTep> dpnstep = ofDpnTepConfigCache.get(sourceDpn.toJava());
251                 if (dpnstep.isPresent()) {
252                     resultBld = RpcResultBuilder.success();
253                     resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
254                             .setInterfaceName(dpnstep.get().getOfPortName())).build();
255                     return Futures.immediateFuture(resultBld.build());
256                 } else {
257                     LOG.error("OF tunnel is not available in ITM for source dpn {}", sourceDpn);
258                     resultBld = RpcResultBuilder.failed();
259                     return Futures.immediateFuture(resultBld.build());
260                 }
261             } catch (ReadFailedException e) {
262                 LOG.error("ReadFailedException: cache read failed for source dpn {} reason: {}", sourceDpn,
263                         e.getMessage());
264                 resultBld = RpcResultBuilder.failed();
265                 return Futures.immediateFuture(resultBld.build());
266             }
267         }
268         if (interfaceManager.isItmDirectTunnelsEnabled()) {
269             DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getDpnTepInterface(sourceDpn, destinationDpn);
270             if (interfaceInfo != null) {
271                 resultBld = RpcResultBuilder.success();
272                 resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
273                         .setInterfaceName(interfaceInfo.getTunnelName())).build();
274                 return Futures.immediateFuture(resultBld.build());
275             }
276         }
277         if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
278             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
279                     TunnelTypeLogicalGroup.class, dataBroker);
280             LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
281         }
282         if (!optTunnel.isPresent()) {
283             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
284         }
285         if (optTunnel.isPresent()) {
286             InternalTunnel tunnel = optTunnel.get();
287             GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
288             List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
289             if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
290                 output.setInterfaceName(tunnelInterfaces.get(0));
291                 resultBld = RpcResultBuilder.success();
292                 resultBld.withResult(output.build());
293             } else {
294                 resultBld = failed();
295             }
296
297         } else {
298             resultBld = failed();
299         }
300         return Futures.immediateFuture(resultBld.build());
301     }
302
303     @Override
304     public ListenableFuture<RpcResult<GetEgressActionsForTunnelOutput>>
305         getEgressActionsForTunnel(GetEgressActionsForTunnelInput input) {
306         String tunnelName = input.getIntfName();
307         if (tunnelName == null) {
308             return Futures.immediateFuture(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
309                     .withError(RpcError.ErrorType.APPLICATION,
310                             "tunnel name not set for GetEgressActionsForTunnel call").build());
311         }
312         if (tunnelName.startsWith("of")
313                 || (interfaceManager.isItmDirectTunnelsEnabled() && dpnTepStateCache.isInternal(tunnelName))) {
314             return fromListenableFuture(LOG, input, () -> getEgressActionsForInternalTunnels(input.getIntfName(),
315                     input.getTunnelKey() != null ? input.getTunnelKey().toJava() : null,
316                     input.getActionKey())).onFailureLogLevel(LogLevel.ERROR).build();
317         } else {
318             // Re-direct the RPC to Interface Manager
319             // From the rpc input and get the output and copy to output
320             org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
321                     .GetEgressActionsForInterfaceInputBuilder inputIfmBuilder =
322                     new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
323                             .GetEgressActionsForInterfaceInputBuilder().setIntfName(input.getIntfName())
324                             .setTunnelKey(input.getTunnelKey()).setActionKey(input.getActionKey());
325             SettableFuture<RpcResult<GetEgressActionsForTunnelOutput>> settableFuture = SettableFuture.create();
326             Futures.addCallback(interfaceManagerService.getEgressActionsForInterface(inputIfmBuilder.build()),
327                     new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
328                             .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput>() {
329                         @Override
330                         public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
331                                                       .rev160406.@NonNull GetEgressActionsForInterfaceOutput result) {
332                             GetEgressActionsForTunnelOutputBuilder output =
333                                     new GetEgressActionsForTunnelOutputBuilder().setAction(result.getAction());
334                             settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>success()
335                                     .withResult(output.build()).build());
336                         }
337
338                         @Override
339                         public void onFailure(Throwable throwable) {
340                             LOG.debug("RPC Call to Get egress actions failed for interface {}", tunnelName);
341                             String errMsg = String.format("RPC call to get egress actions failed for interface %s",
342                                     tunnelName);
343                             settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
344                                     .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
345                         }
346                     } ,MoreExecutors.directExecutor());
347             return  settableFuture;
348         }
349     }
350
351     @Override
352     public ListenableFuture<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
353         String tunnelName = input.getIntfName();
354         if (tunnelName == null) {
355             return Futures.immediateFuture(RpcResultBuilder.<GetTunnelTypeOutput>failed()
356                     .withError(RpcError.ErrorType.APPLICATION,
357                             "tunnel name not set for getTunnelType call").build());
358         }
359
360         if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
361             org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
362                     .GetTunnelTypeInputBuilder inputBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
363                     .genius.interfacemanager.rpcs.rev160406.GetTunnelTypeInputBuilder()
364                     .setIntfName(input.getIntfName());
365             SettableFuture<RpcResult<GetTunnelTypeOutput>> settableFuture = SettableFuture.create();
366             Futures.addCallback(interfaceManagerService.getTunnelType(inputBuilder.build()),
367                     new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
368                             .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput>() {
369                         @Override
370                         public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
371                                                       .rev160406.@NonNull GetTunnelTypeOutput result) {
372                             GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder()
373                                     .setTunnelType(result.getTunnelType());
374                             settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>success()
375                                     .withResult(output.build()).build());
376                         }
377
378                         @Override
379                         public void onFailure(Throwable throwable) {
380                             LOG.debug("RPC Call to Get tunnel type failed for interface {}", tunnelName);
381                             String errMsg = String.format("RPC to Get tunnel type failed for interface %s",
382                                     tunnelName);
383                             settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>failed()
384                                     .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
385                         }
386                     },MoreExecutors.directExecutor());
387             return settableFuture;
388         } else {
389             LOG.debug("get tunnel type from ITM for interface name {}", input.getIntfName());
390             return FutureRpcResults.fromBuilder(LOG, input, () -> {
391                 DpnTepInterfaceInfo ifInfo = dpnTepStateCache.getTunnelFromCache(input.getIntfName());
392                 return new GetTunnelTypeOutputBuilder().setTunnelType(ifInfo.getTunnelType());
393             }).build();
394         }
395     }
396
397     @Override
398     public ListenableFuture<RpcResult<SetBfdParamOnTunnelOutput>> setBfdParamOnTunnel(
399             SetBfdParamOnTunnelInput input) {
400         final Uint64 srcDpnId = Uint64.valueOf(input.getSourceNode());
401         final Uint64 destDpnId = Uint64.valueOf(input.getDestinationNode());
402         LOG.debug("setBfdParamOnTunnel srcDpnId: {}, destDpnId: {}", srcDpnId, destDpnId);
403         final SettableFuture<RpcResult<SetBfdParamOnTunnelOutput>> result = SettableFuture.create();
404         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
405             enableBFD(tx, srcDpnId, destDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
406             enableBFD(tx, destDpnId, srcDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
407         });
408
409         future.addCallback(new FutureCallback<Object>() {
410             @Override
411             public void onSuccess(Object voidInstance) {
412                 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>success().build());
413             }
414
415             @Override
416             public void onFailure(Throwable error) {
417                 String msg = "Unable to remove external tunnel from DPN";
418                 LOG.error("remove ext tunnel failed. {}.", msg, error);
419                 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>failed()
420                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
421             }
422         }, MoreExecutors.directExecutor());
423         return result;
424     }
425
426     private void enableBFD(TypedWriteTransaction<Datastore.Configuration> tx, Uint64 srcDpnId, Uint64 destDpnId,
427                            final Boolean enabled, final Integer interval) throws ReadFailedException {
428         DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, destDpnId);
429         RemoteDpnsBuilder remoteDpnsBuilder = new RemoteDpnsBuilder();
430         remoteDpnsBuilder.withKey(new RemoteDpnsKey(destDpnId)).setDestinationDpnId(destDpnId)
431                 .setTunnelName(dpnTepInterfaceInfo.getTunnelName()).setInternal(dpnTepInterfaceInfo.isInternal())
432                 .setMonitoringEnabled(enabled);
433         if (enabled && interval != null) {
434             remoteDpnsBuilder.setMonitoringInterval(interval);
435         }
436         RemoteDpns remoteDpn = remoteDpnsBuilder.build();
437         Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(srcDpnId);
438         LOG.debug("setBfdParamOnTunnel TunnelName: {}, ovsBridgeRefEntry: {}", dpnTepInterfaceInfo.getTunnelName(),
439                 ovsBridgeRefEntry);
440         directTunnelUtils.updateBfdConfiguration(srcDpnId, remoteDpn, ovsBridgeRefEntry);
441         InstanceIdentifier<RemoteDpns> iid = InstanceIdentifier.builder(DpnTepsState.class)
442                 .child(DpnsTeps.class, new DpnsTepsKey(srcDpnId))
443                 .child(RemoteDpns.class,
444                         new RemoteDpnsKey(destDpnId)).build();
445         tx.mergeParentStructureMerge(iid, remoteDpn);
446     }
447
448     @Override
449     public ListenableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> removeExternalTunnelEndpoint(
450             RemoveExternalTunnelEndpointInput input) {
451         //Ignore the Futures for now
452         final SettableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> result = SettableFuture.create();
453         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
454         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
455             tx -> {
456                 ItmExternalTunnelDeleteWorker.deleteTunnels(meshedDpnList, input.getDestinationIp(),
457                         input.getTunnelType(), tx);
458                 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
459                         .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
460                 tx.delete(extPath);
461             }
462         );
463         future.addCallback(new FutureCallback<Object>() {
464             @Override public void onSuccess(Object voidInstance) {
465                 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>success().build());
466             }
467
468             @Override public void onFailure(Throwable error) {
469                 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
470                         + " in datastore and tunnel type " + input.getTunnelType();
471                 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
472                         input.getTunnelType());
473                 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>failed()
474                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
475             }
476         }, MoreExecutors.directExecutor());
477         return result;
478     }
479
480     @Override
481     public ListenableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> removeExternalTunnelFromDpns(
482             RemoveExternalTunnelFromDpnsInput input) {
483         //Ignore the Futures for now
484         final SettableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
485         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId());
486         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
487             tx -> ItmExternalTunnelDeleteWorker.deleteTunnels(cfgDpnList, input.getDestinationIp(),
488                     input.getTunnelType(), tx));
489
490         future.addCallback(new FutureCallback<Object>() {
491             @Override
492             public void onSuccess(Object voidInstance) {
493                 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>success().build());
494             }
495
496             @Override
497             public void onFailure(Throwable error) {
498                 String msg = "Unable to remove external tunnel from DPN";
499                 LOG.error("remove ext tunnel failed. {}.", msg, error);
500                 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>failed()
501                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
502             }
503         }, MoreExecutors.directExecutor());
504         return result;
505     }
506
507     @Override
508     public ListenableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> buildExternalTunnelFromDpns(
509             BuildExternalTunnelFromDpnsInput input) {
510         //Ignore the Futures for now
511         final SettableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
512         FluentFuture<?> extTunnelResultList =
513             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
514                 tx -> externalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(),
515                     input.getDestinationIp(),input.getTunnelType(), tx));
516
517         extTunnelResultList.addCallback(new FutureCallback<Object>() {
518             @Override
519             public void onSuccess(Object voidInstance) {
520                 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
521             }
522
523             @Override
524             public void onFailure(Throwable error) {
525                 String msg = "Unable to create ext tunnel";
526                 LOG.error("create ext tunnel failed. {}.", msg, error);
527                 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
528                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
529             }
530         }, MoreExecutors.directExecutor());
531         return result;
532     }
533
534     @Override
535     public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
536             AddExternalTunnelEndpointInput input) {
537         // TODO Auto-generated method stub
538
539         //Ignore the Futures for now
540         final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
541         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
542         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
543                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
544         DcGatewayIp dcGatewayIp =
545                 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
546                         .setTunnnelType(input.getTunnelType()).build();
547
548         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
549             tx -> {
550                 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList, input.getDestinationIp(),
551                     input.getTunnelType(), tx);
552                 tx.mergeParentStructurePut(extPath, dcGatewayIp);
553             }
554         );
555         future.addCallback(new FutureCallback<Object>() {
556             @Override public void onSuccess(Object voidInstance) {
557                 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
558             }
559
560             @Override public void onFailure(Throwable error) {
561                 String msg =
562                         "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
563                                 + "tunnel type " + input.getTunnelType();
564
565                 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
566                         input.getDestinationIp() , input.getTunnelType());
567                 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
568                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
569             }
570         }, MoreExecutors.directExecutor());
571         return result;
572     }
573
574     @Override
575     public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
576             GetExternalTunnelInterfaceNameInput input) {
577         SettableFuture.create();
578         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
579         String sourceNode = input.getSourceNode();
580         String dstNode = input.getDestinationNode();
581         if (interfaceManager.isItmOfTunnelsEnabled()) {
582             Optional<OfDpnTep> tepDetail;
583             try {
584                 tepDetail = ofDpnTepConfigCache.get(new BigInteger(sourceNode));
585             } catch (ReadFailedException e) {
586                 LOG.error("ReadFailedException: OF tunnel interface is not available in config DS for "
587                         + "source dpn {} reason: {}", sourceNode, e.getMessage());
588                 resultBld = failed();
589                 return Futures.immediateFuture(resultBld.build());
590             }
591             if (tepDetail.isPresent()) {
592                 GetExternalTunnelInterfaceNameOutputBuilder output =
593                         new GetExternalTunnelInterfaceNameOutputBuilder()
594                                 .setInterfaceName(tepDetail.get().getOfPortName());
595                 resultBld = RpcResultBuilder.success();
596                 resultBld.withResult(output.build());
597                 return Futures.immediateFuture(resultBld.build());
598             } else {
599                 LOG.error("OF tunnel interface is not available in config DS for source dpn {}", sourceNode);
600                 resultBld = failed();
601                 return Futures.immediateFuture(resultBld.build());
602             }
603         }
604         ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
605         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
606                 ExternalTunnelList.class)
607                 .child(ExternalTunnel.class, externalTunnelKey);
608         ExternalTunnel exTunnel =
609                 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
610         if (exTunnel != null) {
611             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
612             output.setInterfaceName(exTunnel.getTunnelInterfaceName());
613             resultBld = RpcResultBuilder.success();
614             resultBld.withResult(output.build());
615         } else {
616             resultBld = failed();
617         }
618
619         return Futures.immediateFuture(resultBld.build());
620     }
621
622     @Override
623     public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
624         createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
625         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
626                 input.getDpnId() , input.getServiceId(), input.getInstruction());
627         final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
628         Uint16 serviceId = input.getServiceId();
629         final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
630
631         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
632                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5,
633                 "ITM Flow Entry :" + serviceId, 0, 0,
634                 Uint64.fromLongBits(ITMConstants.COOKIE_ITM.longValue() + serviceId.toJava()), mkMatches,
635                 input.getInstruction());
636
637         ListenableFuture<?> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
638             tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
639         Futures.addCallback(installFlowResult, new FutureCallback<Object>() {
640
641             @Override
642             public void onSuccess(Object voidInstance) {
643                 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
644             }
645
646             @Override
647             public void onFailure(Throwable error) {
648                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
649                 LOG.error("create terminating service actions failed. {}", msg, error);
650                 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
651                         .withError(RpcError.ErrorType.APPLICATION, msg, error)
652                         .build());
653             }
654         }, MoreExecutors.directExecutor());
655         // result.set(RpcResultBuilder.<Void>success().build());
656         return result;
657     }
658
659     @Override
660     public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
661         removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
662         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
663                 input.getDpnId(), input.getServiceId());
664         final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
665
666         ListenableFuture<?> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
667             tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
668                         getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
669                         NwConstants.INTERNAL_TUNNEL_TABLE));
670         Futures.addCallback(removeFlowResult, new FutureCallback<Object>() {
671
672             @Override
673             public void onSuccess(Object voidInstance) {
674                 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
675             }
676
677             @Override
678             public void onFailure(Throwable error) {
679                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
680                 LOG.error("remove terminating service actions failed. {}", msg, error);
681                 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
682                         .withError(RpcError.ErrorType.APPLICATION, msg, error)
683                         .build());
684             }
685         }, MoreExecutors.directExecutor());
686         //result.set(RpcResultBuilder.<Void>success().build());
687
688         return result ;
689     }
690
691     public List<MatchInfo> getTunnelMatchesForServiceId(Uint16 serviceId) {
692         final List<MatchInfo> mkMatches = new ArrayList<>();
693
694         // Matching metadata
695         mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
696
697         return mkMatches;
698     }
699
700     private String getFlowRef(long termSvcTable, Uint16 svcId) {
701         return String.valueOf(termSvcTable) + svcId;
702     }
703
704     @Override
705     public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
706             GetInternalOrExternalInterfaceNameInput input) {
707         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
708         Uint64 srcDpn = input.getSourceDpid();
709         IpAddress dstIp = input.getDestinationIp();
710         if (interfaceManager.isItmOfTunnelsEnabled()) {
711             Optional<OfDpnTep> tepDetail;
712             try {
713                 tepDetail = ofDpnTepConfigCache.get(srcDpn.toJava());
714             } catch (ReadFailedException e) {
715                 LOG.error("ReadFailedException: OF tunnel interface is not available in config DS for "
716                         + "source dpn {} reason: {}", srcDpn, e.getMessage());
717                 return Futures.immediateFuture(resultBld.build());
718             }
719             if (tepDetail.isPresent()) {
720                 GetInternalOrExternalInterfaceNameOutputBuilder output =
721                         new GetInternalOrExternalInterfaceNameOutputBuilder()
722                                 .setInterfaceName(tepDetail.get().getOfPortName());
723                 resultBld = RpcResultBuilder.success();
724                 resultBld.withResult(output.build());
725                 return Futures.immediateFuture(resultBld.build());
726             } else {
727                 LOG.error("OF tunnel interface is not available in config DS for source dpn {}", srcDpn);
728                 return Futures.immediateFuture(resultBld.build());
729             }
730         }
731         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
732                 .child(ExternalTunnel.class,
733                         new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
734
735         Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
736
737         if (optExtTunnel != null && optExtTunnel.isPresent()) {
738             ExternalTunnel extTunnel = optExtTunnel.get();
739             GetInternalOrExternalInterfaceNameOutputBuilder output =
740                     new GetInternalOrExternalInterfaceNameOutputBuilder()
741                             .setInterfaceName(extTunnel.getTunnelInterfaceName());
742             resultBld = RpcResultBuilder.success();
743             resultBld.withResult(output.build()) ;
744         } else {
745             Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
746
747             // Look for external tunnels if not look for internal tunnel
748             for (DPNTEPsInfo teps : meshedDpnList) {
749                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
750                 if (dstIp.equals(firstEndPt.getIpAddress())) {
751                     Optional<InternalTunnel> optTunnel = Optional.empty();
752                     if (interfaceManager.isItmDirectTunnelsEnabled()) {
753                         DpnTepInterfaceInfo interfaceInfo =
754                                 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
755                         if (interfaceInfo != null) {
756                             resultBld = RpcResultBuilder.success();
757                             resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
758                                     .setInterfaceName(interfaceInfo.getTunnelName())).build();
759                             return Futures.immediateFuture(resultBld.build());
760                         }
761                     }
762
763                     if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
764                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
765                                 TunnelTypeLogicalGroup.class, dataBroker);
766                         LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
767                     }
768                     if (!optTunnel.isPresent()) {
769                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
770                                 input.getTunnelType(), dataBroker);
771                     }
772                     if (optTunnel.isPresent()) {
773                         InternalTunnel tunnel = optTunnel.get();
774                         List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
775                         if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
776                             GetInternalOrExternalInterfaceNameOutputBuilder
777                                     output =
778                                     new GetInternalOrExternalInterfaceNameOutputBuilder()
779                                             .setInterfaceName(tunnelInterfaces.get(0));
780                             resultBld = RpcResultBuilder.success();
781                             resultBld.withResult(output.build());
782                         } else {
783                             LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
784                                     dstIp);
785                         }
786                         break;
787                     } else {
788                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
789                     }
790                 }
791             }
792         }
793         return Futures.immediateFuture(resultBld.build());
794     }
795
796     @SuppressWarnings("checkstyle:IllegalCatch")
797     @Override
798     public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
799         final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
800         boolean foundVxlanTzone = false;
801         try {
802             final IpAddress hwIp = input.getIpAddress();
803             final String nodeId = input.getNodeId();
804             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
805             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
806                     containerPath, dataBroker);
807             if (transportZonesOptional.isPresent()) {
808                 TransportZones transportZones = transportZonesOptional.get();
809                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
810                     LOG.error("No teps configured");
811                     result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
812                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
813                     return result;
814                 }
815                 for (TransportZone tzone : transportZones.getTransportZone()) {
816                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
817                         continue;
818                     }
819                     foundVxlanTzone = true;
820                     String transportZone = tzone.getZoneName();
821                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
822                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
823                             .builder(TransportZones.class)
824                             .child(TransportZone.class,
825                                     new TransportZoneKey(transportZone))
826                             .child(DeviceVteps.class, deviceVtepKey)
827                             .build();
828                     FluentFuture<?> future =
829                         retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path));
830                     future.addCallback(new FutureCallback<Object>() {
831                         @Override public void onSuccess(Object voidInstance) {
832                             result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
833                         }
834
835                         @Override public void onFailure(Throwable error) {
836                             String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
837                             LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
838                             result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
839                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
840                         }
841                     }, MoreExecutors.directExecutor());
842                 }
843             } else {
844                 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
845                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
846                 return result;
847             }
848
849             if (!foundVxlanTzone) {
850                 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
851                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
852                         .build());
853             }
854
855             return result;
856         } catch (Exception e) {
857             RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
858                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
859             return Futures.immediateFuture(resultBuilder.build());
860         }
861     }
862
863     @SuppressWarnings("checkstyle:IllegalCatch")
864     @Override
865     public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
866
867         final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
868         boolean foundVxlanTzone = false;
869         try {
870             final IpAddress hwIp = input.getIpAddress();
871             final String nodeId = input.getNodeId();
872             //iterate through all transport zones and put TORs under vxlan
873             //if no vxlan tzone is cnfigured, return an error.
874             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
875             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
876                     containerPath, dataBroker);
877             if (transportZonesOptional.isPresent()) {
878                 TransportZones transportZones = transportZonesOptional.get();
879                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
880                     LOG.error("No transportZone configured");
881                     result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
882                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
883                     return result;
884                 }
885                 for (TransportZone tzone : transportZones.getTransportZone()) {
886                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
887                         continue;
888                     }
889                     String transportZone = tzone.getZoneName();
890                     foundVxlanTzone = true;
891                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
892                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
893                             .builder(TransportZones.class)
894                             .child(TransportZone.class,
895                                     new TransportZoneKey(transportZone))
896                             .child(DeviceVteps.class, deviceVtepKey)
897                             .build();
898                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
899                             .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
900                     //TO DO: add retry if it fails
901                     FluentFuture<?> future = retryingTxRunner
902                             .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
903                                 tx -> tx.mergeParentStructurePut(path, deviceVtep));
904
905                     future.addCallback(new FutureCallback<Object>() {
906
907                         @Override public void onSuccess(Object voidInstance) {
908                             result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
909                         }
910
911                         @Override public void onFailure(Throwable error) {
912                             String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
913                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
914                             result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
915                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
916                         }
917                     }, MoreExecutors.directExecutor());
918
919                 }
920             } else {
921                 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
922                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
923                 return result;
924             }
925
926             if (!foundVxlanTzone) {
927                 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
928                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
929                         .build());
930             }
931
932             return result;
933         } catch (Exception e) {
934             RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
935                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
936             return Futures.immediateFuture(resultBuilder.build());
937         }
938     }
939
940     @Override
941     public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
942             GetWatchPortForTunnelInput input) {
943         throw new UnsupportedOperationException("TODO");
944     }
945
946     public ListenableFuture<RpcResult<GetTepIpOutput>> getTepIp(GetTepIpInput input) {
947         RpcResultBuilder<GetTepIpOutput> resultBld;
948         Uint64 sourceDpn = input.getDpnId();
949         Optional<OfDpnTep> dpnstep;
950         try {
951             dpnstep = ofDpnTepConfigCache.get(sourceDpn.toJava());
952         } catch (ReadFailedException e) {
953             LOG.error("ReadFailedException: OF tunnel is not available in ITM for source dpn {} reason: {}",sourceDpn,
954                     e.getMessage());
955             resultBld = RpcResultBuilder.failed();
956             return Futures.immediateFuture(resultBld.build());
957         }
958         if (dpnstep.isPresent()) {
959             resultBld = RpcResultBuilder.success();
960             resultBld.withResult(new GetTepIpOutputBuilder()
961                     .setTepIp(dpnstep.get().getTepIp())).build();
962             return Futures.immediateFuture(resultBld.build());
963         } else {
964             LOG.error("OF tunnel is not available in ITM for source dpn {}",sourceDpn);
965             resultBld = RpcResultBuilder.failed();
966             return Futures.immediateFuture(resultBld.build());
967         }
968     }
969
970     @SuppressWarnings("checkstyle:IllegalCatch")
971     @Override
972     public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
973
974         final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
975         try {
976             final IpAddress hwIp = input.getIpAddress();
977             final List<String> nodeId = input.getNodeId();
978             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
979             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
980                     containerPath, dataBroker);
981             if (transportZonesOptional.isPresent()) {
982                 TransportZones transportZones = transportZonesOptional.get();
983                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone()
984                     .isEmpty()) {
985                     LOG.error("No teps configured");
986                     result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
987                         .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
988                     return result;
989                 }
990                 for (TransportZone tzone : transportZones.getTransportZone()) {
991                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
992                         continue;
993                     }
994                     String transportZone = tzone.getZoneName();
995                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
996                     InstanceIdentifier<DeviceVteps> path =
997                         InstanceIdentifier.builder(TransportZones.class)
998                             .child(TransportZone.class, new TransportZoneKey(transportZone))
999                             .child(DeviceVteps.class, deviceVtepKey).build();
1000                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey)
1001                         .setIpAddress(hwIp)
1002                         .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
1003                     LOG.trace("writing hWvtep{}", deviceVtep);
1004                     FluentFuture<?> future =
1005                         retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1006                             tx -> {
1007                                 tx.mergeParentStructurePut(path, deviceVtep);
1008                                 if (nodeId.size() == 2) {
1009                                     LOG.trace("second node-id {}", nodeId.get(1));
1010                                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp,
1011                                         nodeId.get(1));
1012                                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier
1013                                         .builder(TransportZones.class)
1014                                         .child(TransportZone.class, new TransportZoneKey(transportZone))
1015                                         .child(DeviceVteps.class, deviceVtepKey2).build();
1016                                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder()
1017                                         .withKey(deviceVtepKey2)
1018                                         .setIpAddress(hwIp).setNodeId(nodeId.get(1))
1019                                         .setTopologyId(input.getTopologyId()).build();
1020                                     LOG.trace("writing {}", deviceVtep2);
1021                                     tx.mergeParentStructurePut(path2, deviceVtep2);
1022                                 }
1023                             });
1024                     future.addCallback(new FutureCallback<Object>() {
1025                         @Override
1026                         public void onSuccess(Object voidInstance) {
1027                             result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
1028                         }
1029
1030                         @Override
1031                         public void onFailure(Throwable error) {
1032                             String msg = String
1033                                 .format("Unable to write HwVtep %s to datastore", nodeId);
1034                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
1035                             result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
1036                                 .withError(RpcError.ErrorType.APPLICATION, msg, error)
1037                                 .build());
1038                         }
1039                     }, MoreExecutors.directExecutor());
1040                 }
1041             }
1042             return result;
1043         } catch (RuntimeException e) {
1044             RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
1045                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
1046             return Futures.immediateFuture(resultBuilder.build());
1047         }
1048     }
1049
1050     @SuppressWarnings("checkstyle:IllegalCatch")
1051     @Override
1052     public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
1053             DeleteL2GwMlagDeviceInput input) {
1054         final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
1055         try {
1056             final IpAddress hwIp = input.getIpAddress();
1057             final List<String> nodeId = input.getNodeId();
1058             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
1059             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
1060                     containerPath, dataBroker);
1061             if (transportZonesOptional.isPresent()) {
1062                 TransportZones tzones = transportZonesOptional.get();
1063                 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
1064                     LOG.error("No teps configured");
1065                     result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
1066                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
1067                     return result;
1068                 }
1069                 String transportZone = tzones.getTransportZone().get(0).getZoneName();
1070                 FluentFuture<?> future =
1071                     retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1072                         tx -> {
1073                             DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
1074                             InstanceIdentifier<DeviceVteps> path =
1075                                     InstanceIdentifier.builder(TransportZones.class)
1076                                             .child(TransportZone.class, new TransportZoneKey(transportZone))
1077                                             .child(DeviceVteps.class,
1078                                                     deviceVtepKey).build();
1079                             tx.delete(path);
1080                             DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
1081                             InstanceIdentifier<DeviceVteps> path2 =
1082                                     InstanceIdentifier.builder(TransportZones.class)
1083                                             .child(TransportZone.class, new TransportZoneKey(transportZone))
1084                                             .child(DeviceVteps.class,
1085                                                     deviceVtepKey2).build();
1086                             tx.delete(path2);
1087                         }
1088                     );
1089
1090                 future.addCallback(new FutureCallback<Object>() {
1091
1092                     @Override
1093                     public void onSuccess(Object voidInstance) {
1094                         result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
1095                     }
1096
1097                     @Override
1098                     public void onFailure(Throwable error) {
1099                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
1100                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
1101                         result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
1102                                 .withError(RpcError.ErrorType.APPLICATION, msg, error)
1103                                 .build());
1104                     }
1105                 }, MoreExecutors.directExecutor());
1106             }
1107             return result;
1108         } catch (Exception e) {
1109             RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
1110                     RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
1111                             "Deleting l2 Gateway to DS Failed", e);
1112             return Futures.immediateFuture(resultBuilder.build());
1113         }
1114     }
1115
1116     @Override
1117     public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
1118             IsTunnelInternalOrExternalInput input) {
1119         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
1120         String tunIfName = input.getTunnelInterfaceName();
1121         long tunVal = 0;
1122         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
1123                 .setTunnelType(tunVal);
1124
1125         if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
1126             tunVal = 1;
1127         } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
1128             tunVal = 2;
1129         }
1130         output.setTunnelType(tunVal);
1131         resultBld = RpcResultBuilder.success();
1132         resultBld.withResult(output.build());
1133         return Futures.immediateFuture(resultBld.build());
1134     }
1135
1136     @Override
1137     public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1138         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1139
1140         Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1141         txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
1142             tx -> dcGatewayIpList.putAll(getDcGatewayIpList(tx))).isDone();
1143         String dcgwIpStr = input.getDcgwIp();
1144         IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1145         long retVal;
1146
1147         if (!dcGatewayIpList.isEmpty()
1148                 && dcGatewayIpList.values().stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1149             //Match found
1150             retVal = 1;
1151             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1152             resultBld.withResult(output.build());
1153         } else {
1154             //Match not found
1155             retVal = 2;
1156             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1157             resultBld.withResult(output.build());
1158         }
1159         return Futures.immediateFuture(resultBld.build());
1160     }
1161
1162     @Override
1163     public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1164         Uint64 srcDpn = input.getSourceDpid();
1165         RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1166         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1167                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1168                         new DPNTEPsInfoKey(srcDpn)).build();
1169         Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1170         if (!tunnelInfo.isPresent()) {
1171             LOG.error("tunnelInfo is not present");
1172             return Futures.immediateFuture(resultBld.build());
1173         }
1174
1175         List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1176         if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1177             LOG.error("tunnelEndPointList is null or empty");
1178             return Futures.immediateFuture(resultBld.build());
1179         }
1180
1181         List<IpAddress> nexthopIpList = new ArrayList<>();
1182         tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1183
1184         GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1185         resultBld = RpcResultBuilder.success();
1186         resultBld.withResult(output.build()) ;
1187         return Futures.immediateFuture(resultBld.build());
1188     }
1189
1190     @Override
1191     public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1192         return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1193             () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1194     }
1195
1196     private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1197         Map<String, Uint64> computeNamesVsDpnIds
1198                 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1199         Map<Uint64, ComputesBuilder> dpnIdVsVtepsComputes
1200                 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1201         List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1202                 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1203                 .collect(Collectors.toList());
1204         return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1205     }
1206
1207     private Map<Uint64, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<Uint64> dpnIds)
1208             throws ReadFailedException {
1209         TransportZones transportZones = singleTransactionDataBroker.syncRead(
1210                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1211         if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1212             throw new IllegalStateException("Failed to find transport zones in config datastore");
1213         }
1214         Map<Uint64, ComputesBuilder> result = new HashMap<>();
1215         for (TransportZone transportZone : transportZones.getTransportZone()) {
1216             for (Vteps vtep : transportZone.getVteps().values()) {
1217                 if (dpnIds.contains(vtep.getDpnId())) {
1218                     result.putIfAbsent(vtep.getDpnId(),
1219                             new ComputesBuilder()
1220                                     .setZoneName(transportZone.getZoneName())
1221                                     .setDpnId(vtep.getDpnId())
1222                                     .setNodeId(getNodeId(vtep.getDpnId()))
1223                                     .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1224                 }
1225             }
1226         }
1227         for (Uint64 dpnId : dpnIds) {
1228             if (!result.containsKey(dpnId)) {
1229                 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1230             }
1231         }
1232         return result;
1233     }
1234
1235     private Map<String, Uint64> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1236             throws ReadFailedException {
1237         Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1238                 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1239         if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1240             throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1241         }
1242         Map<String, Uint64> result = new HashMap<>();
1243         for (Node node : operInventoryNodes.getNode().values()) {
1244             String name = node.augmentation(FlowCapableNode.class).getDescription();
1245             if (nodeNames.contains(name)) {
1246                 String[] nodeId = node.getId().getValue().split(":");
1247                 result.put(name, Uint64.valueOf(nodeId[1]));
1248             }
1249         }
1250         for (String nodeName : nodeNames) {
1251             if (!result.containsKey(nodeName)) {
1252                 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1253                         + nodeName);
1254             }
1255         }
1256         return result;
1257     }
1258
1259     private String getNodeId(Uint64 dpnId) throws ReadFailedException {
1260         InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1261                 .builder(BridgeRefInfo.class)
1262                 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1263         BridgeRefEntry bridgeRefEntry =
1264                 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1265         return bridgeRefEntry.getBridgeReference().getValue()
1266                 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1267                         .network.topology.topology.Node.class).getNodeId().getValue();
1268     }
1269
1270     private ListenableFuture<GetEgressActionsForTunnelOutput>
1271         getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
1272             throws ExecutionException, InterruptedException, OperationFailedException {
1273
1274         if (interfaceName.startsWith("of")) {
1275             Optional<OfTep> oftep = ofTepStateCache.get(interfaceName);
1276             if (!oftep.isPresent()) {
1277                 throw new IllegalStateException("Interface information not present in oper DS for" + interfaceName);
1278             }
1279             List<ActionInfo> actions = getEgressActionInfosForOpenFlowTunnel(oftep.get().getIfIndex(),
1280                     oftep.get().getTepIp(), tunnelKey, actionKey);
1281             return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1282                     .setAction(actions.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1283         } else {
1284             DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1285             if (interfaceInfo == null) {
1286                 throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1287             }
1288
1289             String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1290             if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
1291                 throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
1292             }
1293
1294             Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier
1295                     .builder(DpnEndpoints.class)
1296                     .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(
1297                             // FIXME: the cache should be caching this value, not just as a String
1298                             Uint64.valueOf(dpnTepStateCache.getTunnelEndPointInfoFromCache(
1299                                     interfaceInfo.getTunnelName()).getDstEndPointInfo())))
1300                     .build());
1301             Integer dstId;
1302             if (dpntePsInfoOptional.isPresent()) {
1303                 dstId = dpntePsInfoOptional.get().getDstId();
1304             } else {
1305                 dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME,
1306                         interfaceInfo.getRemoteDPN().toString());
1307             }
1308
1309             List<ActionInfo> result = new ArrayList<>();
1310             long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
1311             int actionKeyStart = actionKey == null ? 0 : actionKey;
1312             result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1313                     Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1314             result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
1315                     MetaDataUtil.REG6_END_INDEX, regValue));
1316             result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
1317
1318             return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1319                     .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1320         }
1321     }
1322
1323     private static List<ActionInfo> getEgressActionInfosForOpenFlowTunnel(Uint16 ifIndex, IpAddress ipAddress,
1324                                                                           Long tunnelKey, Integer actionKey) {
1325         List<ActionInfo> result = new ArrayList<>();
1326         int actionKeyStart = actionKey == null ? 0 : actionKey;
1327         result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1328                 Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1329         long regValue = MetaDataUtil.getReg6ValueForLPortDispatcher(ifIndex.intValue() ,
1330                 NwConstants.DEFAULT_SERVICE_INDEX);
1331         result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, ITMConstants.REG6_START_INDEX,
1332                 ITMConstants.REG6_END_INDEX, regValue));
1333         result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE));
1334
1335         return result;
1336     }
1337
1338     public static Map<DcGatewayIpKey, DcGatewayIp>
1339         getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
1340             throws ExecutionException, InterruptedException {
1341         Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpMap = new HashMap<>();
1342         FluentFuture<Optional<DcGatewayIpList>> future =
1343                 tx.read(InstanceIdentifier.builder(DcGatewayIpList.class).build());
1344         future.addCallback(new FutureCallback<Optional<DcGatewayIpList>>() {
1345             @Override
1346             public void onSuccess(Optional<DcGatewayIpList> optional) {
1347                 try {
1348                     // FIXME: why not just use the provided optional?
1349                     Optional<DcGatewayIpList> opt = future.get();
1350                     if (opt.isPresent()) {
1351                         DcGatewayIpList list = opt.get();
1352                         if (list != null) {
1353                             dcGatewayIpMap.putAll(list.getDcGatewayIp());
1354                         }
1355                     }
1356                 } catch (ExecutionException | InterruptedException e) {
1357                     LOG.error("DcGateway IpList read failed", e);
1358                 }
1359             }
1360
1361             @Override
1362             public void onFailure(Throwable error) {
1363                 LOG.error("DcGateway IpList read failed", error);
1364             }
1365         }, MoreExecutors.directExecutor());
1366         return dcGatewayIpMap;
1367     }
1368 }