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