Changed RPC to retrieve Vxlan DC GWY Ext. Tunnels
[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 com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.concurrent.Future;
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
28 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
29 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
30 import org.opendaylight.genius.itm.globals.ITMConstants;
31 import org.opendaylight.genius.itm.impl.ItmUtils;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchInfo;
34 import org.opendaylight.genius.mdsalutil.NwConstants;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdEnableOnTunnelInput;
96 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
97 import org.opendaylight.yangtools.yang.common.RpcError;
98 import org.opendaylight.yangtools.yang.common.RpcResult;
99 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
100 import org.slf4j.Logger;
101 import org.slf4j.LoggerFactory;
102
103 @Singleton
104 public class ItmManagerRpcService implements ItmRpcService {
105
106     private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
107     private final DataBroker dataBroker;
108     private final IMdsalApiManager mdsalManager;
109     private final DPNTEPsInfoCache dpnTEPsInfoCache;
110     private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
111
112     @Inject
113     public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
114             final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache) {
115         this.dataBroker = dataBroker;
116         this.mdsalManager = mdsalManager;
117         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
118         this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig, dpnTEPsInfoCache);
119     }
120
121     @PostConstruct
122     public void start() {
123         LOG.info("ItmManagerRpcService Started");
124     }
125
126     @PreDestroy
127     public void close() {
128         LOG.info("ItmManagerRpcService Closed");
129     }
130
131     @Override
132     public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
133         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
134         BigInteger sourceDpn = input.getSourceDpid();
135         BigInteger destinationDpn = input.getDestinationDpid();
136         Optional<InternalTunnel> optTunnel = Optional.absent();
137
138         if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
139             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
140                                                          TunnelTypeLogicalGroup.class, dataBroker);
141             LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
142         }
143         if (!optTunnel.isPresent()) {
144             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
145         }
146         if (optTunnel.isPresent()) {
147             InternalTunnel tunnel = optTunnel.get();
148             GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
149             List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
150             if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
151                 output.setInterfaceName(tunnelInterfaces.get(0));
152                 resultBld = RpcResultBuilder.success();
153                 resultBld.withResult(output.build());
154             } else {
155                 resultBld = RpcResultBuilder.failed();
156             }
157
158         } else {
159             resultBld = RpcResultBuilder.failed();
160         }
161         return Futures.immediateFuture(resultBld.build());
162     }
163
164     @Override
165     public Future<RpcResult<GetEgressActionsForTunnelOutput>> getEgressActionsForTunnel(
166             GetEgressActionsForTunnelInput input) {
167         //TODO
168         return null;
169     }
170
171     @Override
172     public Future<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
173         //TODO
174         return null;
175     }
176
177     @Override
178     public Future<RpcResult<Void>> setBfdEnableOnTunnel(SetBfdEnableOnTunnelInput input) {
179         //TODO
180         return null;
181     }
182
183
184     @Override
185     public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
186             RemoveExternalTunnelEndpointInput input) {
187         //Ignore the Futures for now
188         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
189         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
190         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, meshedDpnList,
191                 input.getDestinationIp(), input.getTunnelType());
192         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
193                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
194         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
195         transaction.delete(LogicalDatastoreType.CONFIGURATION, extPath);
196         ListenableFuture<Void> futureCheck = transaction.submit();
197         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
198
199             @Override public void onSuccess(Void voidInstance) {
200                 result.set(RpcResultBuilder.<Void>success().build());
201             }
202
203             @Override public void onFailure(Throwable error) {
204                 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
205                         + " in datastore and tunnel type " + input.getTunnelType();
206                 LOG.error(msg);
207                 result.set(RpcResultBuilder.<Void>failed()
208                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
209             }
210         });
211         return result;
212     }
213
214     @Override
215     public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
216             RemoveExternalTunnelFromDpnsInput input) {
217         //Ignore the Futures for now
218         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
219         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId()) ;
220         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, cfgDpnList,
221                 input.getDestinationIp(), input.getTunnelType());
222         result.set(RpcResultBuilder.<Void>success().build());
223         return result;
224     }
225
226     @Override
227     public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
228             BuildExternalTunnelFromDpnsInput input) {
229         //Ignore the Futures for now
230         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
231         List<ListenableFuture<Void>> extTunnelResultList = externalTunnelAddWorker
232             .buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(), input.getDestinationIp(),input.getTunnelType());
233         for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
234             Futures.addCallback(extTunnelResult, new FutureCallback<Void>() {
235
236                 @Override
237                 public void onSuccess(Void voidInstance) {
238                     result.set(RpcResultBuilder.<Void>success().build());
239                 }
240
241                 @Override
242                 public void onFailure(Throwable error) {
243                     String msg = "Unable to create ext tunnel";
244                     LOG.error("create ext tunnel failed. {}. {}", msg, error);
245                     result.set(RpcResultBuilder.<Void>failed()
246                             .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
247                 }
248             });
249         }
250         return result;
251     }
252
253     @Override
254     public Future<RpcResult<Void>> addExternalTunnelEndpoint(
255             AddExternalTunnelEndpointInput input) {
256         // TODO Auto-generated method stub
257
258         //Ignore the Futures for now
259         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
260         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
261         externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList,
262                 input.getDestinationIp(), input.getTunnelType());
263         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
264                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
265         DcGatewayIp dcGatewayIp =
266                 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
267                         .setTunnnelType(input.getTunnelType()).build();
268         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
269         writeTransaction.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
270         ListenableFuture<Void> futureCheck = writeTransaction.submit();
271         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
272
273             @Override public void onSuccess(Void voidInstance) {
274                 result.set(RpcResultBuilder.<Void>success().build());
275             }
276
277             @Override public void onFailure(Throwable error) {
278                 String msg =
279                         "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
280                                 + "tunnel type " + input.getTunnelType();
281
282                 LOG.error(msg);
283                 result.set(RpcResultBuilder.<Void>failed()
284                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
285             }
286         });
287         return result;
288     }
289
290     @Override
291     public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
292             GetExternalTunnelInterfaceNameInput input) {
293         SettableFuture.create();
294         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
295         String sourceNode = input.getSourceNode();
296         String dstNode = input.getDestinationNode();
297         ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
298         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
299                 ExternalTunnelList.class)
300                 .child(ExternalTunnel.class, externalTunnelKey);
301         ExternalTunnel exTunnel =
302                 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
303         if (exTunnel != null) {
304             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
305             output.setInterfaceName(exTunnel.getTunnelInterfaceName());
306             resultBld = RpcResultBuilder.success();
307             resultBld.withResult(output.build());
308         } else {
309             resultBld = RpcResultBuilder.failed();
310         }
311
312         return Futures.immediateFuture(resultBld.build());
313     }
314
315     @Override
316     public Future<RpcResult<java.lang.Void>>
317         createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
318         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
319                 input.getDpnId() , input.getServiceId(), input.getInstruction());
320         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
321         int serviceId = input.getServiceId() ;
322         final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
323         byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
324         // Flags Byte
325         byte flags = (byte) 0x08;
326         vxLANHeader[0] = flags;
327
328         // Extract the serviceId details and imprint on the VxLAN Header
329         vxLANHeader[4] = (byte) (serviceId >> 16);
330         vxLANHeader[5] = (byte) (serviceId >> 8);
331         vxLANHeader[6] = (byte) (serviceId >> 0);
332
333         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
334                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5,
335                 String.format("%s:%d","ITM Flow Entry ",serviceId), 0, 0,
336                 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
337
338         ListenableFuture<Void> installFlowResult =
339                 mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
340         Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
341
342             @Override
343             public void onSuccess(Void voidInstance) {
344                 result.set(RpcResultBuilder.<Void>success().build());
345             }
346
347             @Override
348             public void onFailure(Throwable error) {
349                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
350                 LOG.error("create terminating service actions failed. {}. {}", msg, error);
351                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
352                         .build());
353             }
354         });
355         // result.set(RpcResultBuilder.<Void>success().build());
356         return result;
357     }
358
359     @Override
360     public Future<RpcResult<java.lang.Void>>
361         removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
362         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
363                 input.getDpnId(), input.getServiceId());
364         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
365         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
366                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5,
367                 String.format("%s:%d","ITM Flow Entry ",input.getServiceId()), 0, 0,
368                 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),
369                 getTunnelMatchesForServiceId(input.getServiceId()), null);
370
371         ListenableFuture<Void> installFlowResult =
372                 mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
373         Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
374
375             @Override
376             public void onSuccess(Void voidInstance) {
377                 result.set(RpcResultBuilder.<Void>success().build());
378             }
379
380             @Override
381             public void onFailure(Throwable error) {
382                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
383                 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
384                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
385                         .build());
386             }
387         });
388         //result.set(RpcResultBuilder.<Void>success().build());
389
390         return result ;
391     }
392
393
394     public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
395         final List<MatchInfo> mkMatches = new ArrayList<>();
396         byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
397
398         // Flags Byte
399         byte flag = (byte) 0x08;
400         vxLANHeader[0] = flag;
401
402         // Extract the serviceId details and imprint on the VxLAN Header
403         vxLANHeader[4] = (byte) (serviceId >> 16);
404         vxLANHeader[5] = (byte) (serviceId >> 8);
405         vxLANHeader[6] = (byte) (serviceId >> 0);
406
407         // Matching metadata
408         mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
409
410         return mkMatches;
411     }
412
413     private String getFlowRef(long termSvcTable, int svcId) {
414         return String.valueOf(termSvcTable) + svcId;
415     }
416
417     @Override
418     public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
419             GetInternalOrExternalInterfaceNameInput input) {
420         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
421         BigInteger srcDpn = input.getSourceDpid() ;
422         srcDpn.toString();
423         IpAddress dstIp = input.getDestinationIp() ;
424         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
425                 .child(ExternalTunnel.class,
426                         new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), input.getTunnelType()));
427
428         Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
429
430         if (optExtTunnel != null && optExtTunnel.isPresent()) {
431             ExternalTunnel extTunnel = optExtTunnel.get();
432             GetInternalOrExternalInterfaceNameOutputBuilder output =
433                     new GetInternalOrExternalInterfaceNameOutputBuilder()
434                             .setInterfaceName(extTunnel.getTunnelInterfaceName());
435             resultBld = RpcResultBuilder.success();
436             resultBld.withResult(output.build()) ;
437         } else {
438             Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
439             if (meshedDpnList == null) {
440                 LOG.error("There are no tunnel mesh info in config DS");
441                 return Futures.immediateFuture(resultBld.build());
442             }
443             // Look for external tunnels if not look for internal tunnel
444             for (DPNTEPsInfo teps : meshedDpnList) {
445                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
446                 if (dstIp.equals(firstEndPt.getIpAddress())) {
447                     Optional<InternalTunnel> optTunnel = Optional.absent();
448                     if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
449                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
450                                                                      TunnelTypeLogicalGroup.class, dataBroker);
451                         LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
452                     }
453                     if (!optTunnel.isPresent()) {
454                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
455                                                                      input.getTunnelType(), dataBroker);
456                     }
457                     if (optTunnel.isPresent()) {
458                         InternalTunnel tunnel = optTunnel.get();
459                         List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
460                         if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
461                             GetInternalOrExternalInterfaceNameOutputBuilder
462                                     output =
463                                     new GetInternalOrExternalInterfaceNameOutputBuilder()
464                                             .setInterfaceName(tunnelInterfaces.get(0));
465                             resultBld = RpcResultBuilder.success();
466                             resultBld.withResult(output.build());
467                         } else {
468                             LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
469                                     dstIp);
470                         }
471                         break;
472                     } else {
473                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
474                     }
475                 }
476             }
477         }
478         return Futures.immediateFuture(resultBld.build());
479     }
480
481     @SuppressWarnings("checkstyle:IllegalCatch")
482     @Override
483     public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
484         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
485         boolean foundVxlanTzone = false;
486         try {
487             final IpAddress hwIp = input.getIpAddress();
488             final String nodeId = input.getNodeId();
489             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
490             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
491                     containerPath, dataBroker);
492             if (transportZonesOptional.isPresent()) {
493                 TransportZones transportZones = transportZonesOptional.get();
494                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
495                     LOG.error("No teps configured");
496                     result.set(RpcResultBuilder.<Void>failed()
497                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
498                     return result;
499                 }
500                 for (TransportZone tzone : transportZones.getTransportZone()) {
501                     if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
502                         continue;
503                     }
504                     foundVxlanTzone = true;
505                     String transportZone = tzone.getZoneName();
506                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
507                         result.set(RpcResultBuilder.<Void>failed()
508                                 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
509                         return result;
510                     }
511                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
512                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
513                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
514                             .child(TransportZone.class, new TransportZoneKey(transportZone))
515                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
516                             .build();
517                     WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
518                     //TO DO: add retry if it fails
519
520                     transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
521
522                     ListenableFuture<Void> futureCheck = transaction.submit();
523                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
524
525                         @Override public void onSuccess(Void voidInstance) {
526                             result.set(RpcResultBuilder.<Void>success().build());
527                         }
528
529                         @Override public void onFailure(Throwable error) {
530                             String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
531                             LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
532                             result.set(RpcResultBuilder.<Void>failed()
533                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
534                         }
535                     });
536
537                 }
538             } else {
539                 result.set(RpcResultBuilder.<Void>failed()
540                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
541                 return result;
542             }
543
544             if (!foundVxlanTzone) {
545                 result.set(RpcResultBuilder.<Void>failed()
546                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
547                         .build());
548             }
549
550             return result;
551         } catch (Exception e) {
552             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
553                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
554             return Futures.immediateFuture(resultBuilder.build());
555         }
556     }
557
558     @SuppressWarnings("checkstyle:IllegalCatch")
559     @Override
560     public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
561
562         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
563         boolean foundVxlanTzone = false;
564         try {
565             final IpAddress hwIp = input.getIpAddress();
566             final String nodeId = input.getNodeId();
567             //iterate through all transport zones and put TORs under vxlan
568             //if no vxlan tzone is cnfigured, return an error.
569             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
570             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
571                     containerPath, dataBroker);
572             if (transportZonesOptional.isPresent()) {
573                 TransportZones transportZones = transportZonesOptional.get();
574                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
575                     LOG.error("No transportZone configured");
576                     result.set(RpcResultBuilder.<Void>failed()
577                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
578                     return result;
579                 }
580                 for (TransportZone tzone : transportZones.getTransportZone()) {
581                     if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
582                         continue;
583                     }
584                     String transportZone = tzone.getZoneName();
585                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
586                         continue;
587                     }
588                     foundVxlanTzone = true;
589                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
590                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
591                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
592                             .child(TransportZone.class, new TransportZoneKey(transportZone))
593                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
594                             .build();
595                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
596                             .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
597                     WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
598                     //TO DO: add retry if it fails
599                     transaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
600
601                     ListenableFuture<Void> futureCheck = transaction.submit();
602                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
603
604                         @Override public void onSuccess(Void voidInstance) {
605                             result.set(RpcResultBuilder.<Void>success().build());
606                         }
607
608                         @Override public void onFailure(Throwable error) {
609                             String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
610                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
611                             result.set(RpcResultBuilder.<Void>failed()
612                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
613                         }
614                     });
615
616                 }
617             } else {
618                 result.set(RpcResultBuilder.<Void>failed()
619                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
620                 return result;
621             }
622
623             if (!foundVxlanTzone) {
624                 result.set(RpcResultBuilder.<Void>failed()
625                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
626                         .build());
627             }
628
629             return result;
630         } catch (Exception e) {
631             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
632                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
633             return Futures.immediateFuture(resultBuilder.build());
634         }
635     }
636
637     @SuppressWarnings("checkstyle:IllegalCatch")
638     @Override
639     public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
640
641         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
642         try {
643             final IpAddress hwIp = input.getIpAddress();
644             final List<String> nodeId = input.getNodeId();
645             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
646             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
647                     containerPath, dataBroker);
648             if (transportZonesOptional.isPresent()) {
649                 TransportZones transportZones = transportZonesOptional.get();
650                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
651                     LOG.error("No teps configured");
652                     result.set(RpcResultBuilder.<Void>failed()
653                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
654                     return result;
655                 }
656                 String transportZone = transportZones.getTransportZone().get(0).getZoneName();
657                 if (transportZones.getTransportZone().get(0).getSubnets() == null
658                         || transportZones.getTransportZone().get(0).getSubnets().isEmpty()) {
659                     result.set(RpcResultBuilder.<Void>failed()
660                             .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
661                     return result;
662                 }
663                 SubnetsKey subnetsKey = transportZones.getTransportZone().get(0).getSubnets().get(0).getKey();
664                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
665                 InstanceIdentifier<DeviceVteps> path =
666                         InstanceIdentifier.builder(TransportZones.class)
667                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
668                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
669                 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
670                         .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
671                 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
672                 //TO DO: add retry if it fails
673                 LOG.trace("writing hWvtep{}",deviceVtep);
674                 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
675
676                 if (nodeId.size() == 2) {
677                     LOG.trace("second node-id {}",nodeId.get(1));
678                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
679                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
680                             .child(TransportZone.class, new TransportZoneKey(transportZone))
681                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
682                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp)
683                             .setNodeId(nodeId.get(1))
684                             .setTopologyId(input.getTopologyId()).build();
685                     //TO DO: add retry if it fails
686                     LOG.trace("writing {}",deviceVtep2);
687                     writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
688                 }
689                 ListenableFuture<Void> futureCheck = writeTransaction.submit();
690                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
691
692                     @Override
693                     public void onSuccess(Void voidInstance) {
694                         result.set(RpcResultBuilder.<Void>success().build());
695                     }
696
697                     @Override
698                     public void onFailure(Throwable error) {
699                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
700                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
701                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
702                                 .build());
703                     }
704                 });
705             }
706             return result;
707         } catch (Exception e) {
708             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
709                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
710             return Futures.immediateFuture(resultBuilder.build());
711         }
712     }
713
714     @SuppressWarnings("checkstyle:IllegalCatch")
715     @Override
716     public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
717
718         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
719         try {
720             final IpAddress hwIp = input.getIpAddress();
721             final List<String> nodeId = input.getNodeId();
722             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
723             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
724                     containerPath, dataBroker);
725             if (transportZonesOptional.isPresent()) {
726                 TransportZones tzones = transportZonesOptional.get();
727                 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
728                     LOG.error("No teps configured");
729                     result.set(RpcResultBuilder.<Void>failed()
730                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
731                     return result;
732                 }
733                 String transportZone = tzones.getTransportZone().get(0).getZoneName();
734                 if (tzones.getTransportZone().get(0).getSubnets() == null || tzones.getTransportZone()
735                         .get(0).getSubnets().isEmpty()) {
736                     result.set(RpcResultBuilder.<Void>failed()
737                             .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
738                     return result;
739                 }
740                 SubnetsKey subnetsKey = tzones.getTransportZone().get(0).getSubnets().get(0).getKey();
741                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
742                 InstanceIdentifier<DeviceVteps> path =
743                         InstanceIdentifier.builder(TransportZones.class)
744                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
745                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
746                                 deviceVtepKey).build();
747                 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
748                 //TO DO: add retry if it fails
749                 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
750
751                 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
752                 InstanceIdentifier<DeviceVteps> path2 =
753                         InstanceIdentifier.builder(TransportZones.class)
754                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
755                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
756                                 deviceVtepKey2).build();
757                 //TO DO: add retry if it fails
758                 transaction.delete(LogicalDatastoreType.CONFIGURATION, path2);
759
760                 ListenableFuture<Void> futureCheck = transaction.submit();
761                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
762
763                     @Override
764                     public void onSuccess(Void voidInstance) {
765                         result.set(RpcResultBuilder.<Void>success().build());
766                     }
767
768                     @Override
769                     public void onFailure(Throwable error) {
770                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
771                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
772                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
773                                 .build());
774                     }
775                 });
776             }
777             return result;
778         } catch (Exception e) {
779             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
780                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
781             return Futures.immediateFuture(resultBuilder.build());
782         }
783     }
784
785     @Override
786     public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
787             IsTunnelInternalOrExternalInput input) {
788         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
789         String tunIfName = input.getTunnelInterfaceName();
790         long tunVal = 0;
791         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
792                         .setTunnelType(tunVal);
793
794         if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
795             tunVal = 1;
796         } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
797             tunVal = 2;
798         }
799         output.setTunnelType(tunVal);
800         resultBld = RpcResultBuilder.success();
801         resultBld.withResult(output.build());
802         return Futures.immediateFuture(resultBld.build());
803     }
804
805     @Override
806     public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
807         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
808
809         List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
810         String dcgwIpStr = input.getDcgwIp();
811         IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
812         long retVal;
813
814         if (dcGatewayIpList != null
815                 && !dcGatewayIpList.isEmpty()
816                 && dcGatewayIpList.contains(dcgwIpAddr)) {
817             //Match found
818             retVal = 1;
819             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
820             resultBld.withResult(output.build());
821         } else {
822             //Match not found
823             retVal = 2;
824             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
825             resultBld.withResult(output.build());
826         }
827         return Futures.immediateFuture(resultBld.build());
828     }
829
830     @Override
831     public Future<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
832         BigInteger srcDpn = input.getSourceDpid() ;
833         RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = RpcResultBuilder.failed();
834         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
835                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
836                         new DPNTEPsInfoKey(srcDpn)).build();
837         Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
838         if (!tunnelInfo.isPresent()) {
839             LOG.error("tunnelInfo is not present");
840             return Futures.immediateFuture(resultBld.build());
841         }
842
843         List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
844         if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
845             LOG.error("tunnelEndPointList is null or empty");
846             return Futures.immediateFuture(resultBld.build());
847         }
848
849         List<IpAddress> nexthopIpList = new ArrayList<>();
850         tunnelEndPointList.forEach(tunnelEndPoint -> {
851             nexthopIpList.add(tunnelEndPoint.getIpAddress());
852         });
853
854         GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
855         resultBld = RpcResultBuilder.success();
856         resultBld.withResult(output.build()) ;
857         return Futures.immediateFuture(resultBld.build());
858     }
859
860 }