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