Handle nullable lists
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / ItmInternalTunnelAddWorker.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.confighelpers;
9
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.genius.itm.impl.ItmUtils.nullToEmpty;
14
15 import com.google.common.base.Optional;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Objects;
23 import java.util.concurrent.Callable;
24 import java.util.concurrent.ExecutionException;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
28 import org.opendaylight.genius.infra.Datastore.Configuration;
29 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
32 import org.opendaylight.genius.infra.TypedWriteTransaction;
33 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
34 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
35 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
36 import org.opendaylight.genius.itm.impl.ItmUtils;
37 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
38 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
39 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.tunnel.optional.params.TunnelOptions;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpointsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsStateBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.opendaylight.yangtools.yang.common.OperationFailedException;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 public final class ItmInternalTunnelAddWorker {
76
77     private static final Logger LOG = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ;
78
79     private final ItmConfig itmCfg;
80     private final Integer monitorInterval;
81     private final boolean isTunnelMonitoringEnabled;
82     private final Class<? extends TunnelMonitoringTypeBase> monitorProtocol;
83
84     private final DataBroker dataBroker;
85     private final ManagedNewTransactionRunner txRunner;
86     private final JobCoordinator jobCoordinator;
87     private final DirectTunnelUtils directTunnelUtils;
88     private final IInterfaceManager interfaceManager;
89     private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
90
91     public ItmInternalTunnelAddWorker(DataBroker dataBroker, JobCoordinator jobCoordinator,
92                                       TunnelMonitoringConfig tunnelMonitoringConfig, ItmConfig itmCfg,
93                                       DirectTunnelUtils directTunnelUtil,
94                                       IInterfaceManager interfaceManager,
95                                       OvsBridgeRefEntryCache ovsBridgeRefEntryCache) {
96         this.dataBroker = dataBroker;
97         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
98         this.jobCoordinator = jobCoordinator;
99         this.itmCfg = itmCfg;
100         this.directTunnelUtils = directTunnelUtil;
101         this.interfaceManager = interfaceManager;
102         this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
103
104         isTunnelMonitoringEnabled = tunnelMonitoringConfig.isTunnelMonitoringEnabled();
105         monitorProtocol = tunnelMonitoringConfig.getMonitorProtocol();
106         monitorInterval = tunnelMonitoringConfig.getMonitorInterval();
107     }
108
109     public List<ListenableFuture<Void>> buildAllTunnels(IMdsalApiManager mdsalManager, List<DPNTEPsInfo> cfgdDpnList,
110                                                         Collection<DPNTEPsInfo> meshedDpnList) {
111         LOG.trace("Building tunnels with DPN List {} " , cfgdDpnList);
112         if (null == cfgdDpnList || cfgdDpnList.isEmpty()) {
113             LOG.error(" Build Tunnels was invoked with empty list");
114             return Collections.emptyList();
115         }
116
117         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
118             for (DPNTEPsInfo dpn : cfgdDpnList) {
119                 //#####if dpn is not in meshedDpnList
120                 buildTunnelFrom(tx, dpn, meshedDpnList, mdsalManager);
121                 if (meshedDpnList != null) {
122                     meshedDpnList.add(dpn);
123                 }
124                 // Update the config datastore -- FIXME -- Error Handling
125                 updateDpnTepInfoToConfig(tx, dpn);
126             }
127         }));
128     }
129
130     private static void updateDpnTepInfoToConfig(TypedWriteTransaction<Configuration> tx, DPNTEPsInfo dpn) {
131         LOG.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
132         InstanceIdentifier<DpnEndpoints> dep = InstanceIdentifier.builder(DpnEndpoints.class).build() ;
133         List<DPNTEPsInfo> dpnList = new ArrayList<>() ;
134         dpnList.add(dpn) ;
135         DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ;
136         tx.merge(dep, tnlBuilder);
137     }
138
139     private void buildTunnelFrom(TypedReadWriteTransaction<Configuration> tx, DPNTEPsInfo srcDpn,
140         Collection<DPNTEPsInfo> meshedDpnList, IMdsalApiManager mdsalManager)
141         throws ExecutionException, InterruptedException, OperationFailedException {
142         LOG.trace("Building tunnels from DPN {} " , srcDpn);
143         if (null == meshedDpnList || meshedDpnList.isEmpty()) {
144             LOG.debug("No DPN in the mesh ");
145             return ;
146         }
147         for (DPNTEPsInfo dstDpn: meshedDpnList) {
148             if (!srcDpn.equals(dstDpn)) {
149                 wireUpWithinTransportZone(tx, srcDpn, dstDpn, mdsalManager);
150             }
151         }
152
153     }
154
155     private void wireUpWithinTransportZone(TypedReadWriteTransaction<Configuration> tx, DPNTEPsInfo srcDpn,
156         DPNTEPsInfo dstDpn, IMdsalApiManager mdsalManager)
157         throws ExecutionException, InterruptedException, OperationFailedException {
158         LOG.trace("Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn);
159         List<TunnelEndPoints> srcEndPts = srcDpn.getTunnelEndPoints();
160         List<TunnelEndPoints> dstEndPts = dstDpn.getTunnelEndPoints();
161
162         for (TunnelEndPoints srcte : nullToEmpty(srcEndPts)) {
163             for (TunnelEndPoints dstte : nullToEmpty(dstEndPts)) {
164                 // Compare the Transport zones
165                 if (!Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
166                     if (!ItmUtils.getIntersection(nullToEmpty(srcte.getTzMembership()),
167                             nullToEmpty(dstte.getTzMembership())).isEmpty()) {
168                         // wire them up
169                         wireUpBidirectionalTunnel(tx, srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(),
170                                 mdsalManager);
171                         if (!ItmTunnelAggregationHelper.isTunnelAggregationEnabled()) {
172                             // CHECK THIS -- Assumption -- One end point per Dpn per transport zone
173                             break;
174                         }
175                     }
176                 }
177             }
178         }
179     }
180
181     private void wireUpBidirectionalTunnel(TypedReadWriteTransaction<Configuration> tx, TunnelEndPoints srcte,
182         TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId, IMdsalApiManager mdsalManager)
183         throws ExecutionException, InterruptedException, OperationFailedException {
184         // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER
185
186         if (monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
187             ItmUtils.addTerminatingServiceTable(tx, srcDpnId, mdsalManager);
188             ItmUtils.addTerminatingServiceTable(tx, dstDpnId, mdsalManager);
189         }
190         // Create the forward direction tunnel
191         if (!wireUp(tx, srcte, dstte, srcDpnId, dstDpnId)) {
192             LOG.error("Could not build tunnel between end points {}, {} " , srcte, dstte);
193         }
194
195         // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT
196         // Create the tunnel for the reverse direction
197         if (!wireUp(tx, dstte, srcte, dstDpnId, srcDpnId)) {
198             LOG.error("Could not build tunnel between end points {}, {} " , dstte, srcte);
199         }
200     }
201
202     private boolean wireUp(TypedWriteTransaction<Configuration> tx, TunnelEndPoints srcte, TunnelEndPoints dstte,
203         BigInteger srcDpnId, BigInteger dstDpnId)
204         throws ExecutionException, InterruptedException, OperationFailedException {
205         // Wire Up logic
206         LOG.trace("Wiring between source tunnel end points {}, destination tunnel end points {}", srcte, dstte);
207         String interfaceName = srcte.getInterfaceName();
208         Class<? extends TunnelTypeBase> tunType = srcte.getTunnelType();
209         String tunTypeStr = srcte.getTunnelType().getName();
210         // Form the trunk Interface Name
211
212         String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName,
213                 srcte.getIpAddress().stringValue(), dstte.getIpAddress().stringValue(), tunTypeStr);
214         String parentInterfaceName = null;
215         if (tunType.isAssignableFrom(TunnelTypeVxlan.class)) {
216             parentInterfaceName = createLogicalGroupTunnel(srcDpnId, dstDpnId);
217         }
218         if (interfaceManager.isItmDirectTunnelsEnabled()) {
219             createInternalDirectTunnels(srcte, dstte, srcDpnId, dstDpnId, tunType, trunkInterfaceName,
220                     parentInterfaceName);
221         } else {
222             createTunnelInterface(srcte, dstte, srcDpnId, tunType, trunkInterfaceName, parentInterfaceName);
223             // also update itm-state ds?
224             createInternalTunnel(tx, srcDpnId, dstDpnId, tunType, trunkInterfaceName);
225         }
226         return true;
227     }
228
229     private void createTunnelInterface(TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId,
230             Class<? extends TunnelTypeBase> tunType, String trunkInterfaceName, String parentInterfaceName) {
231         String gateway = srcte.getIpAddress().getIpv4Address() != null ? "0.0.0.0" : "::";
232         IpAddress gatewayIpObj = IpAddressBuilder.getDefaultInstance(gateway);
233         IpAddress gwyIpAddress =
234                 Objects.equals(srcte.getSubnetMask(), dstte.getSubnetMask()) ? gatewayIpObj : srcte.getGwIpAddress();
235         LOG.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, "
236                 + "source IP - {}, destination IP - {} gateway IP - {}",
237                 trunkInterfaceName, srcte.getInterfaceName(), srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress);
238         boolean useOfTunnel = ItmUtils.falseIfNull(srcte.isOptionOfTunnel());
239
240         List<TunnelOptions> tunOptions = ItmUtils.buildTunnelOptions(srcte, itmCfg);
241         Boolean isMonitorEnabled = !tunType.isAssignableFrom(TunnelTypeLogicalGroup.class) && isTunnelMonitoringEnabled;
242         Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName,
243                 String.format("%s %s",ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"),
244                 true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true,
245                 isMonitorEnabled, monitorProtocol, monitorInterval, useOfTunnel, parentInterfaceName, tunOptions);
246         LOG.debug(" Trunk Interface builder - {} ", iface);
247         InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
248         LOG.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
249         LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
250         ITMBatchingUtils.update(trunkIdentifier, iface, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
251         ItmUtils.ITM_CACHE.addInterface(iface);
252     }
253
254     private static void createLogicalTunnelInterface(BigInteger srcDpnId,
255             Class<? extends TunnelTypeBase> tunType, String interfaceName) {
256         Interface iface = ItmUtils.buildLogicalTunnelInterface(srcDpnId, interfaceName,
257                 String.format("%s %s",ItmUtils.convertTunnelTypetoString(tunType), "Interface"), true);
258         InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(interfaceName);
259         ITMBatchingUtils.update(trunkIdentifier, iface, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
260         ItmUtils.ITM_CACHE.addInterface(iface);
261     }
262
263     private static void createInternalTunnel(TypedWriteTransaction<Configuration> tx, BigInteger srcDpnId,
264         BigInteger dstDpnId, Class<? extends TunnelTypeBase> tunType, String trunkInterfaceName) {
265         InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
266                 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, tunType));
267         InternalTunnel tnl = ItmUtils.buildInternalTunnel(srcDpnId, dstDpnId, tunType, trunkInterfaceName);
268         // Switching to individual transaction submit as batching latencies is causing ELAN failures.
269         // Will revert when ELAN can handle this.
270         // ITMBatchingUtils.update(path, tnl, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
271         tx.merge(path, tnl, CREATE_MISSING_PARENTS);
272         ItmUtils.ITM_CACHE.addInternalTunnel(tnl);
273     }
274
275     private String createLogicalGroupTunnel(BigInteger srcDpnId, BigInteger dstDpnId) {
276         boolean tunnelAggregationEnabled = ItmTunnelAggregationHelper.isTunnelAggregationEnabled();
277         if (!tunnelAggregationEnabled) {
278             return null;
279         }
280         String logicTunnelGroupName = ItmUtils.getLogicalTunnelGroupName(srcDpnId, dstDpnId);
281         ItmTunnelAggregationWorker addWorker =
282                 new ItmTunnelAggregationWorker(logicTunnelGroupName, srcDpnId, dstDpnId, dataBroker);
283         jobCoordinator.enqueueJob(logicTunnelGroupName, addWorker);
284         return logicTunnelGroupName;
285     }
286
287     private static class ItmTunnelAggregationWorker implements Callable<List<ListenableFuture<Void>>> {
288
289         private final String logicTunnelGroupName;
290         private final BigInteger srcDpnId;
291         private final BigInteger dstDpnId;
292         private final ManagedNewTransactionRunner txRunner;
293
294         ItmTunnelAggregationWorker(String logicGroupName, BigInteger srcDpnId, BigInteger dstDpnId, DataBroker broker) {
295             this.logicTunnelGroupName = logicGroupName;
296             this.srcDpnId = srcDpnId;
297             this.dstDpnId = dstDpnId;
298             this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
299         }
300
301         @Override
302         public List<ListenableFuture<Void>> call() {
303             return singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
304                 //The logical tunnel interface be created only when the first tunnel interface on each OVS is created
305                 InternalTunnel tunnel = ItmUtils.ITM_CACHE.getInternalTunnel(logicTunnelGroupName);
306                 if (tunnel == null) {
307                     LOG.info("MULTIPLE_VxLAN_TUNNELS: add the logical tunnel group {} because a first tunnel"
308                         + " interface on srcDpnId {} dstDpnId {} is created", logicTunnelGroupName, srcDpnId, dstDpnId);
309                     createLogicalTunnelInterface(srcDpnId, TunnelTypeLogicalGroup.class, logicTunnelGroupName);
310                     createInternalTunnel(tx, srcDpnId, dstDpnId, TunnelTypeLogicalGroup.class, logicTunnelGroupName);
311                 } else {
312                     LOG.debug("MULTIPLE_VxLAN_TUNNELS: not first tunnel on srcDpnId {} dstDpnId {}", srcDpnId,
313                             dstDpnId);
314                 }
315             }));
316         }
317     }
318
319     private void createInternalDirectTunnels(TunnelEndPoints srcte, TunnelEndPoints dstte,
320             BigInteger srcDpnId, BigInteger dstDpnId, Class<? extends TunnelTypeBase> tunType,
321             String trunkInterfaceName, String parentInterfaceName) throws ExecutionException, InterruptedException,
322             OperationFailedException {
323         IpAddress gatewayIpObj = IpAddressBuilder.getDefaultInstance("0.0.0.0");
324         IpAddress gwyIpAddress = Objects.equals(srcte.getSubnetMask(), dstte.getSubnetMask())
325                 ? gatewayIpObj : srcte.getGwIpAddress() ;
326         LOG.debug("Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {},"
327                         + " destination IP - {} gateway IP - {}", trunkInterfaceName, parentInterfaceName,
328                 srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress) ;
329
330         boolean useOfTunnel = ItmUtils.falseIfNull(srcte.isOptionOfTunnel());
331
332         List<TunnelOptions> tunOptions = ItmUtils.buildTunnelOptions(srcte, itmCfg);
333         Boolean isMonitorEnabled = !tunType.isAssignableFrom(TunnelTypeLogicalGroup.class) && isTunnelMonitoringEnabled;
334         Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName,
335                 String.format("%s %s",ItmUtils.convertTunnelTypetoString(srcte.getTunnelType()), "Trunk Interface"),
336                 true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(),
337                 true, isMonitorEnabled, monitorProtocol, monitorInterval, useOfTunnel, parentInterfaceName, tunOptions);
338         LOG.debug("Trunk Interface builder - {} ", iface);
339
340         final DpnTepsStateBuilder dpnTepsStateBuilder = new DpnTepsStateBuilder();
341         final DpnsTepsBuilder dpnsTepsBuilder = new DpnsTepsBuilder();
342         final List<DpnsTeps> dpnTeps = new ArrayList<>();
343         final List<RemoteDpns> remoteDpns = new ArrayList<>();
344         dpnsTepsBuilder.withKey(new DpnsTepsKey(srcDpnId));
345         dpnsTepsBuilder.setTunnelType(srcte.getTunnelType());
346         dpnsTepsBuilder.setSourceDpnId(srcDpnId);
347
348         RemoteDpnsBuilder remoteDpn = new RemoteDpnsBuilder();
349         remoteDpn.withKey(new RemoteDpnsKey(dstDpnId));
350         remoteDpn.setDestinationDpnId(dstDpnId);
351         remoteDpn.setTunnelName(trunkInterfaceName);
352         remoteDpn.setMonitoringEnabled(isTunnelMonitoringEnabled);
353         remoteDpn.setMonitoringInterval(monitorInterval);
354         remoteDpn.setInternal(true);
355         remoteDpns.add(remoteDpn.build());
356         dpnsTepsBuilder.setRemoteDpns(remoteDpns);
357         dpnTeps.add(dpnsTepsBuilder.build());
358         dpnTepsStateBuilder.setDpnsTeps(dpnTeps);
359         updateDpnTepInterfaceInfoToConfig(dpnTepsStateBuilder.build());
360         addTunnelConfiguration(iface);
361     }
362
363     private static void updateDpnTepInterfaceInfoToConfig(DpnTepsState dpnTeps) {
364         LOG.debug("Updating CONFIGURATION datastore with DPN-Teps {} ", dpnTeps);
365         InstanceIdentifier<DpnTepsState> dpnTepsII = InstanceIdentifier.builder(DpnTepsState.class).build() ;
366         ITMBatchingUtils.update(dpnTepsII, dpnTeps, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
367     }
368
369     private List<ListenableFuture<Void>> addTunnelConfiguration(Interface iface) throws ReadFailedException {
370         // ITM Direct Tunnels This transaction is not being used -- CHECK
371         final WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
372         ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
373         if (parentRefs == null) {
374             LOG.warn("ParentRefs for interface: {} Not Found. Creation of Tunnel OF-Port not supported"
375                     + " when dpid not provided.", iface.getName());
376             return Collections.emptyList();
377         }
378
379         BigInteger dpId = parentRefs.getDatapathNodeIdentifier();
380         if (dpId == null) {
381             LOG.warn("dpid for interface: {} Not Found. No DPID provided. Creation of OF-Port not supported.",
382                     iface.getName());
383             return Collections.emptyList();
384         }
385
386         LOG.info("adding tunnel configuration for {}", iface.getName());
387         LOG.debug("creating bridge interfaceEntry in ConfigDS {}", dpId);
388         DirectTunnelUtils.createBridgeTunnelEntryInConfigDS(dpId, iface.getName());
389
390         // create bridge on switch, if switch is connected
391         Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpId);
392
393         if (ovsBridgeRefEntry.isPresent()) {
394             LOG.debug("creating bridge interface on dpn {}", dpId);
395             InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
396                     (InstanceIdentifier<OvsdbBridgeAugmentation>) ovsBridgeRefEntry.get()
397                             .getOvsBridgeReference().getValue();
398             addPortToBridge(bridgeIid, iface, iface.getName());
399         }
400         return Collections.singletonList(transaction.submit());
401     }
402
403     private void addPortToBridge(InstanceIdentifier<?> bridgeIid, Interface iface, String portName) {
404         IfTunnel ifTunnel = iface.augmentation(IfTunnel.class);
405         if (ifTunnel != null) {
406             directTunnelUtils.addTunnelPortToBridge(ifTunnel, bridgeIid, iface, portName);
407         }
408     }
409 }