Bump version odlparent->6.0.0,mdsal->5.0.3
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / impl / ItmUtils.java
1 /*
2  * Copyright © 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.impl;
9
10 import static java.util.Collections.emptyList;
11
12 import com.google.common.base.Optional;
13 import com.google.common.collect.BiMap;
14 import com.google.common.collect.ImmutableBiMap;
15 import com.google.common.collect.ImmutableMap;
16 import com.google.common.net.InetAddresses;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21 import java.net.InetAddress;
22 import java.nio.charset.StandardCharsets;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Objects;
28 import java.util.UUID;
29 import java.util.concurrent.ExecutionException;
30 import org.eclipse.jdt.annotation.NonNull;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
33 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.infra.Datastore.Configuration;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
40 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
41 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
42 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
43 import org.opendaylight.genius.itm.confighelpers.HwVtep;
44 import org.opendaylight.genius.itm.confighelpers.ItmTunnelAggregationHelper;
45 import org.opendaylight.genius.itm.globals.ITMConstants;
46 import org.opendaylight.genius.mdsalutil.ActionInfo;
47 import org.opendaylight.genius.mdsalutil.FlowEntity;
48 import org.opendaylight.genius.mdsalutil.InstructionInfo;
49 import org.opendaylight.genius.mdsalutil.MDSALUtil;
50 import org.opendaylight.genius.mdsalutil.MatchInfo;
51 import org.opendaylight.genius.mdsalutil.NwConstants;
52 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
53 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
54 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
55 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnelBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.interfaces._interface.NodeIdentifier;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.interfaces._interface.NodeIdentifierBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.interfaces._interface.NodeIdentifierKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.tunnel.optional.params.TunnelOptions;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.tunnel.optional.params.TunnelOptionsBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.tunnel.optional.params.TunnelOptionsKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeBase;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPointsKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembershipBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.state.tunnel.list.DstInfoBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.state.tunnel.list.SrcInfoBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.NotHostedTransportZones;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZone;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneKey;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
121 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
122 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
123 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
124 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
125 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
126 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
127 import org.opendaylight.yangtools.yang.binding.DataObject;
128 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
129 import org.opendaylight.yangtools.yang.common.Uint64;
130 import org.slf4j.Logger;
131 import org.slf4j.LoggerFactory;
132
133 public final class ItmUtils {
134
135     private static final Logger LOG = LoggerFactory.getLogger(ItmUtils.class);
136
137     private static final String TUNNEL = "tun";
138     private static final IpPrefix DUMMY_IP_PREFIX = IpPrefixBuilder.getDefaultInstance(ITMConstants.DUMMY_PREFIX);
139     private static final long DEFAULT_MONITORING_INTERVAL = 100L;
140     public static final ItmCache ITM_CACHE = new ItmCache();
141
142     public static final ImmutableMap<String, Class<? extends TunnelTypeBase>>
143             TUNNEL_TYPE_MAP =
144             new ImmutableMap.Builder<String, Class<? extends TunnelTypeBase>>()
145                     .put(ITMConstants.TUNNEL_TYPE_GRE, TunnelTypeGre.class)
146                     .put(ITMConstants.TUNNEL_TYPE_MPLSoGRE, TunnelTypeMplsOverGre.class)
147                     .put(ITMConstants.TUNNEL_TYPE_VXLAN, TunnelTypeVxlan.class)
148                     .build();
149
150     private static final BiMap<String,Class<? extends TunnelTypeBase>> STRING_CLASS_IMMUTABLE_BI_MAP =
151             ImmutableBiMap.copyOf(TUNNEL_TYPE_MAP);
152     private static final Uint64 COOKIE_ITM_LLD = Uint64.fromLongBits(
153         ITMConstants.COOKIE_ITM.longValue() + ITMConstants.LLDP_SERVICE_ID).intern();
154
155     private ItmUtils() {
156     }
157
158     public static final FutureCallback<Void> DEFAULT_WRITE_CALLBACK = new FutureCallback<>() {
159         @Override
160         public void onSuccess(Void result) {
161             LOG.debug("Success in Datastore write operation");
162         }
163
164         @Override
165         public void onFailure(Throwable error) {
166             LOG.error("Error in Datastore write operation", error);
167         }
168     };
169
170     /**
171      * Synchronous blocking read from data store.
172      *
173      * @deprecated Use
174      * {@link SingleTransactionDataBroker#syncReadOptional(DataBroker, LogicalDatastoreType, InstanceIdentifier)}
175      *             instead of this.
176      */
177     @Deprecated
178     @SuppressWarnings("checkstyle:IllegalCatch")
179     public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
180                                                           InstanceIdentifier<T> path, DataBroker broker) {
181         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
182             return tx.read(datastoreType, path).get();
183         } catch (Exception e) {
184             throw new RuntimeException(e);
185         }
186     }
187
188
189     /**
190      * Asynchronous non-blocking write to data store.
191      *
192      * @deprecated Use {@link ManagedNewTransactionRunner} instead of this.
193      */
194     @Deprecated
195     public static <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
196                                                          InstanceIdentifier<T> path, T data, DataBroker broker,
197                                                          FutureCallback<Void> callback) {
198         WriteTransaction tx = broker.newWriteOnlyTransaction();
199         tx.put(datastoreType, path, data, true);
200         Futures.addCallback(tx.submit(), callback, MoreExecutors.directExecutor());
201     }
202
203     /**
204      * Asynchronous non-blocking update to data store.
205      *
206      * @deprecated Use {@link ManagedNewTransactionRunner} instead of this.
207      */
208     @Deprecated
209     public static <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
210                                                           InstanceIdentifier<T> path, T data, DataBroker broker,
211                                                           FutureCallback<Void> callback) {
212         WriteTransaction tx = broker.newWriteOnlyTransaction();
213         tx.merge(datastoreType, path, data, true);
214         Futures.addCallback(tx.submit(), callback, MoreExecutors.directExecutor());
215     }
216
217     /**
218      * Asynchronous non-blocking single delete to data store.
219      *
220      * @deprecated Use {@link ManagedNewTransactionRunner} instead of this.
221      */
222     @Deprecated
223     public static <T extends DataObject> void asyncDelete(LogicalDatastoreType datastoreType,
224                                                           InstanceIdentifier<T> path, DataBroker broker,
225                                                           FutureCallback<Void> callback) {
226         WriteTransaction tx = broker.newWriteOnlyTransaction();
227         tx.delete(datastoreType, path);
228         Futures.addCallback(tx.submit(), callback, MoreExecutors.directExecutor());
229     }
230
231     /**
232      * Asynchronous non-blocking bulk delete to data store.
233      *
234      * @deprecated Use {@link ManagedNewTransactionRunner} instead of this.
235      */
236     @Deprecated
237     public static <T extends DataObject> void asyncBulkRemove(final DataBroker broker,
238                                                               final LogicalDatastoreType datastoreType,
239                                                               List<InstanceIdentifier<T>> pathList,
240                                                               FutureCallback<Void> callback) {
241         if (!pathList.isEmpty()) {
242             WriteTransaction tx = broker.newWriteOnlyTransaction();
243             for (InstanceIdentifier<T> path : pathList) {
244                 tx.delete(datastoreType, path);
245             }
246             Futures.addCallback(tx.submit(), callback ,MoreExecutors.directExecutor());
247         }
248     }
249
250     //ITM cleanup:portname and vlanId are removed, causes change in generated
251     //interface name: This has upgrade impact
252     public static String getInterfaceName(final Uint64 datapathid, final String portName, final Integer vlanId) {
253         return String.format("%s:%s:%s", datapathid, portName, vlanId);
254     }
255
256     public static String getTrunkInterfaceName(String parentInterfaceName,
257                                                String localHostName, String remoteHostName, String tunnelType) {
258         String tunnelTypeStr;
259         if (tunnelType.contains("TunnelTypeGre")) {
260             tunnelTypeStr = ITMConstants.TUNNEL_TYPE_GRE;
261         } else if (tunnelType.contains("TunnelTypeLogicalGroup")) {
262             tunnelTypeStr = ITMConstants.TUNNEL_TYPE_LOGICAL_GROUP_VXLAN;
263         } else {
264             tunnelTypeStr = ITMConstants.TUNNEL_TYPE_VXLAN;
265         }
266         String trunkInterfaceName = String.format("%s:%s:%s:%s", parentInterfaceName, localHostName,
267                 remoteHostName, tunnelTypeStr);
268         LOG.trace("trunk interface name is {}", trunkInterfaceName);
269         trunkInterfaceName = String.format("%s%s", TUNNEL, getUniqueIdString(trunkInterfaceName));
270         return trunkInterfaceName;
271     }
272
273     public static void releaseIdForTrunkInterfaceName(String parentInterfaceName,
274                                                       String localHostName, String remoteHostName, String tunnelType) {
275         String tunnelTypeStr;
276         if (tunnelType.contains("TunnelTypeGre")) {
277             tunnelTypeStr = ITMConstants.TUNNEL_TYPE_GRE;
278         } else {
279             tunnelTypeStr = ITMConstants.TUNNEL_TYPE_VXLAN;
280         }
281         String trunkInterfaceName = String.format("%s:%s:%s:%s", parentInterfaceName, localHostName,
282                 remoteHostName, tunnelTypeStr);
283         LOG.trace("Releasing Id for trunkInterface - {}", trunkInterfaceName);
284     }
285
286     public static String getLogicalTunnelGroupName(Uint64 srcDpnId, Uint64 destDpnId) {
287         String tunnelTypeStr = ITMConstants.TUNNEL_TYPE_LOGICAL_GROUP_VXLAN;
288         String groupName = String.format("%s:%s:%s", srcDpnId.toString(), destDpnId.toString(), tunnelTypeStr);
289         LOG.trace("logical tunnel group name is {}", groupName);
290         groupName = String.format("%s%s", TUNNEL, getUniqueIdString(groupName));
291         return groupName;
292     }
293
294     public static InetAddress getInetAddressFromIpAddress(IpAddress ip) {
295         return IetfInetUtil.INSTANCE.inetAddressFor(ip);
296     }
297
298     public static InstanceIdentifier<DPNTEPsInfo> getDpnTepInstance(Uint64 dpIdKey) {
299         return InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpIdKey))
300                 .build();
301     }
302
303     public static DPNTEPsInfo createDPNTepInfo(Uint64 dpId, List<TunnelEndPoints> endpoints) {
304         return new DPNTEPsInfoBuilder().withKey(new DPNTEPsInfoKey(dpId)).setTunnelEndPoints(endpoints).build();
305     }
306
307     public static TunnelEndPoints createTunnelEndPoints(Uint64 dpnId, IpAddress ipAddress, String portName,
308                                                         boolean isOfTunnel, int vlanId, List<TzMembership> zones,
309                                                         Class<? extends TunnelTypeBase>  tunnelType,
310                                                         String tos) {
311         // when Interface Mgr provides support to take in Dpn Id
312         return new TunnelEndPointsBuilder().withKey(new TunnelEndPointsKey(ipAddress, tunnelType))
313                 .setTzMembership(zones)
314                 .setOptionOfTunnel(isOfTunnel).setInterfaceName(ItmUtils.getInterfaceName(dpnId, portName, vlanId))
315                 .setTunnelType(tunnelType)
316                 .setOptionTunnelTos(tos)
317                 .build();
318     }
319
320     public static TunnelEndPoints createDummyTunnelEndPoints(Uint64 dpnID, IpAddress ipAddress, boolean ofTunnel,
321                                                              String tos, List<TzMembership> zones,
322                                                              Class<? extends TunnelTypeBase>  tunnelType,
323                                                              String port, int vlanID) {
324
325         return ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, ofTunnel,vlanID, zones,
326                 tunnelType, tos);
327     }
328
329     public static InstanceIdentifier<Interface> buildId(String interfaceName) {
330         return InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName))
331                 .build();
332     }
333
334     public static InstanceIdentifier<IfTunnel> buildTunnelId(String ifName) {
335         return InstanceIdentifier.builder(Interfaces.class)
336                 .child(Interface.class, new InterfaceKey(ifName)).augmentation(IfTunnel.class).build();
337     }
338
339     public static Interface buildLogicalTunnelInterface(Uint64 dpn, String ifName, String desc, boolean enabled) {
340         InterfaceBuilder builder = new InterfaceBuilder().withKey(new InterfaceKey(ifName)).setName(ifName)
341                 .setDescription(desc).setEnabled(enabled).setType(Tunnel.class);
342         ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).build();
343         builder.addAugmentation(ParentRefs.class, parentRefs);
344
345         IfTunnel tunnel = new IfTunnelBuilder()
346                 .setTunnelDestination(IpAddressBuilder.getDefaultInstance(ITMConstants.DUMMY_IP_ADDRESS))
347                 .setTunnelSource(IpAddressBuilder.getDefaultInstance(ITMConstants.DUMMY_IP_ADDRESS)).setInternal(true)
348                 .setMonitorEnabled(false).setTunnelInterfaceType(TunnelTypeLogicalGroup.class)
349                 .setTunnelRemoteIpFlow(false).build();
350         builder.addAugmentation(IfTunnel.class, tunnel);
351         return builder.build();
352     }
353
354     public static Interface buildTunnelInterface(Uint64 dpn, String ifName, String desc, boolean enabled,
355                                                  Class<? extends TunnelTypeBase> tunType, IpAddress localIp,
356                                                  IpAddress remoteIp, boolean internal,
357                                                  Boolean monitorEnabled,
358                                                  Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
359                                                  Integer monitorInterval, boolean useOfTunnel,
360                                                  List<TunnelOptions> tunOptions) {
361
362         return buildTunnelInterface(dpn, ifName, desc, enabled, tunType, localIp, remoteIp, internal,
363                 monitorEnabled, monitorProtocol, monitorInterval,  useOfTunnel, null,
364                 tunOptions);
365     }
366
367     public static Interface buildTunnelInterface(Uint64 dpn, String ifName, String desc, boolean enabled,
368                                                  Class<? extends TunnelTypeBase> tunType, IpAddress localIp,
369                                                  IpAddress remoteIp, boolean internal,
370                                                  Boolean monitorEnabled,
371                                                  Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
372                                                  Integer monitorInterval, boolean useOfTunnel, String parentIfaceName,
373                                                  List<TunnelOptions> tunnelOptions) {
374         InterfaceBuilder builder = new InterfaceBuilder().withKey(new InterfaceKey(ifName)).setName(ifName)
375                 .setDescription(desc).setEnabled(enabled).setType(Tunnel.class);
376         ParentRefs parentRefs =
377                 new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).setParentInterface(parentIfaceName).build();
378         builder.addAugmentation(ParentRefs.class, parentRefs);
379         Long monitoringInterval = null;
380         LOG.debug("buildTunnelInterface: monitorProtocol = {} and monitorInterval = {}",
381                 monitorProtocol.getName(),monitorInterval);
382
383         if (monitorInterval != null) {
384             monitoringInterval = monitorInterval.longValue();
385         }
386
387         IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(remoteIp)
388                 .setTunnelSource(localIp).setTunnelInterfaceType(tunType)
389                 .setMonitorEnabled(monitorEnabled).setMonitorProtocol(monitorProtocol)
390                 .setMonitorInterval(monitoringInterval).setTunnelRemoteIpFlow(useOfTunnel)
391                 .setTunnelOptions(tunnelOptions).setInternal(internal)
392                 .build();
393         builder.addAugmentation(IfTunnel.class, tunnel);
394         return builder.build();
395     }
396
397     public static Interface buildHwTunnelInterface(String tunnelIfName, String desc, boolean enabled, String topoId,
398                                                    String nodeId, Class<? extends TunnelTypeBase> tunType,
399                                                    IpAddress srcIp, IpAddress destIp, IpAddress gwIp,
400                                                    Boolean monitorEnabled,
401                                                    Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
402                                                    Integer monitorInterval) {
403         InterfaceBuilder builder = new InterfaceBuilder().withKey(new InterfaceKey(tunnelIfName))
404                 .setName(tunnelIfName).setDescription(desc).setEnabled(enabled).setType(Tunnel.class);
405         List<NodeIdentifier> nodeIds = new ArrayList<>();
406         NodeIdentifier hwNode = new NodeIdentifierBuilder().withKey(new NodeIdentifierKey(topoId))
407                 .setTopologyId(topoId).setNodeId(nodeId).build();
408         nodeIds.add(hwNode);
409         ParentRefs parent = new ParentRefsBuilder().setNodeIdentifier(nodeIds).build();
410         builder.addAugmentation(ParentRefs.class, parent);
411         IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(destIp).setTunnelGateway(gwIp)
412                 .setTunnelSource(srcIp).setMonitorEnabled(monitorEnabled == null || monitorEnabled)
413                 .setMonitorProtocol(monitorProtocol == null ? ITMConstants.DEFAULT_MONITOR_PROTOCOL : monitorProtocol)
414                 .setMonitorInterval(DEFAULT_MONITORING_INTERVAL).setTunnelInterfaceType(tunType).setInternal(false)
415                 .build();
416         builder.addAugmentation(IfTunnel.class, tunnel);
417         LOG.trace("iftunnel {} built from hwvtep {} ", tunnel, nodeId);
418         return builder.build();
419     }
420
421     public static InternalTunnel buildInternalTunnel(Uint64 srcDpnId, Uint64 dstDpnId,
422                                                      Class<? extends TunnelTypeBase> tunType,
423                                                      String trunkInterfaceName) {
424         return new InternalTunnelBuilder().withKey(new InternalTunnelKey(dstDpnId, srcDpnId, tunType))
425                 .setDestinationDPN(dstDpnId)
426                 .setSourceDPN(srcDpnId).setTransportType(tunType)
427                 .setTunnelInterfaceNames(Collections.singletonList(trunkInterfaceName)).build();
428     }
429
430     public static ExternalTunnel buildExternalTunnel(String srcNode, String dstNode,
431                                                      Class<? extends TunnelTypeBase> tunType,
432                                                      String trunkInterfaceName) {
433         return new ExternalTunnelBuilder().withKey(
434                 new ExternalTunnelKey(dstNode, srcNode, tunType))
435                 .setSourceDevice(srcNode).setDestinationDevice(dstNode)
436                 .setTunnelInterfaceName(trunkInterfaceName)
437                 .setTransportType(tunType).build();
438     }
439
440     private static String getUniqueIdString(String idKey) {
441         return UUID.nameUUIDFromBytes(idKey.getBytes(StandardCharsets.UTF_8)).toString().substring(0, 12)
442                 .replace("-", "");
443     }
444
445     public static List<DPNTEPsInfo> getDpnTepListFromDpnId(DPNTEPsInfoCache dpnTEPsInfoCache, List<Uint64> dpnIds) {
446         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
447         List<DPNTEPsInfo> cfgDpnList = new ArrayList<>();
448         for (Uint64 dpnId : dpnIds) {
449             for (DPNTEPsInfo teps : meshedDpnList) {
450                 if (dpnId.equals(teps.getDPNID())) {
451                     cfgDpnList.add(teps);
452                 }
453             }
454         }
455
456         return cfgDpnList;
457     }
458
459     @SuppressWarnings("checkstyle:IllegalCatch")
460     public static void addTerminatingServiceTable(TypedReadWriteTransaction<Configuration> tx,
461                                                   Uint64 dpnId, IMdsalApiManager mdsalManager) {
462         LOG.trace("Installing PUNT to Controller flow in DPN {} ", dpnId);
463         List<ActionInfo> listActionInfo = new ArrayList<>();
464         listActionInfo.add(new ActionPuntToController());
465
466         try {
467             List<MatchInfo> mkMatches = new ArrayList<>();
468
469             mkMatches.add(new MatchTunnelId(Uint64.valueOf(ITMConstants.LLDP_SERVICE_ID)));
470
471             List<InstructionInfo> mkInstructions = new ArrayList<>();
472             mkInstructions.add(new InstructionApplyActions(listActionInfo));
473
474             FlowEntity terminatingServiceTableFlowEntity = MDSALUtil
475                     .buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE,
476                             getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, ITMConstants.LLDP_SERVICE_ID),
477                             5, String.format("%s:%d","ITM Flow Entry :", ITMConstants.LLDP_SERVICE_ID), 0, 0,
478                             COOKIE_ITM_LLD, mkMatches, mkInstructions);
479             mdsalManager.addFlow(tx, terminatingServiceTableFlowEntity);
480         } catch (Exception e) {
481             LOG.error("Error while setting up Table 36 for {}", dpnId, e);
482         }
483     }
484
485     @SuppressWarnings("checkstyle:IllegalCatch")
486     public static void removeTerminatingServiceTable(TypedReadWriteTransaction<Configuration> tx,
487                                                      Uint64 dpnId, IMdsalApiManager mdsalManager) {
488         LOG.trace("Removing PUNT to Controller flow in DPN {} ", dpnId);
489
490         try {
491             mdsalManager.removeFlow(tx, dpnId,
492                     getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, ITMConstants.LLDP_SERVICE_ID),
493                     NwConstants.INTERNAL_TUNNEL_TABLE);
494         } catch (Exception e) {
495             LOG.error("Error while setting up Table 36 for {}", dpnId, e);
496         }
497     }
498
499     private static String getFlowRef(long termSvcTable, int svcId) {
500         return String.valueOf(termSvcTable) + svcId;
501     }
502
503     public static <T> boolean isEmpty(Collection<T> collection) {
504         return collection == null || collection.isEmpty();
505     }
506
507     public static @NonNull HwVtep createHwVtepObject(String topoId, String nodeId, IpAddress ipAddress,
508                                                      Class<? extends TunnelTypeBase> tunneltype,
509                                                      TransportZone transportZone) {
510         HwVtep hwVtep = new HwVtep();
511         hwVtep.setHwIp(ipAddress);
512         hwVtep.setNodeId(nodeId);
513         hwVtep.setTopoId(topoId);
514         hwVtep.setTransportZone(transportZone.getZoneName());
515         hwVtep.setTunnelType(tunneltype);
516         return hwVtep;
517     }
518
519     public static String getHwParentIf(String topoId, String srcNodeid) {
520         return String.format("%s:%s", topoId, srcNodeid);
521     }
522
523     /**
524      * Synchronous blocking write to data store.
525      *
526      * @deprecated Use
527      * {@link SingleTransactionDataBroker#syncWrite(DataBroker, LogicalDatastoreType, InstanceIdentifier, DataObject)}
528      *             instead of this.
529      */
530     @Deprecated
531     public static <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
532                                                         InstanceIdentifier<T> path, T data, DataBroker broker) {
533         WriteTransaction tx = broker.newWriteOnlyTransaction();
534         tx.put(datastoreType, path, data, true);
535         try {
536             tx.submit().get();
537         } catch (InterruptedException | ExecutionException e) {
538             LOG.error("ITMUtils:SyncWrite , Error writing to datastore (path, data) : ({}, {})", path, data);
539             throw new RuntimeException(e.getMessage(), e);
540         }
541     }
542
543     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
544             .rev140508.interfaces.state.Interface> buildStateInterfaceId(
545             String interfaceName) {
546         return InstanceIdentifier.builder(InterfacesState.class)
547                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
548                                 .state.Interface.class,
549                         new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
550                                 .rev140508.interfaces.state.InterfaceKey(
551                                 interfaceName)).build();
552     }
553
554     @NonNull
555     public static List<String> getInternalTunnelInterfaces(DataBroker dataBroker) {
556         Collection<String> internalInterfaces = ITM_CACHE.getAllInternalInterfaces();
557         List<String> tunnelList = new ArrayList<>();
558         if (internalInterfaces.isEmpty()) {
559             tunnelList = getAllInternalTunnlInterfacesFromDS(dataBroker);
560         }
561         else {
562             LOG.debug("Internal Interfaces from Cache size: {}", internalInterfaces.size());
563             tunnelList.addAll(internalInterfaces);
564         }
565         LOG.trace("ItmUtils Internal TunnelList: {}", tunnelList);
566         return tunnelList;
567     }
568
569     public static List<InternalTunnel> getInternalTunnelsFromCache(DataBroker dataBroker) {
570         Collection<InternalTunnel> internalInterfaces = ITM_CACHE.getAllInternalTunnel();
571         LOG.trace("getInternalTunnelsFromCache - List of InternalTunnels in the Cache: {} ", internalInterfaces);
572         List<InternalTunnel> tunnelList = new ArrayList<>();
573         if (internalInterfaces.isEmpty()) {
574             LOG.trace("ItmUtils.getInternalTunnelsFromCache invoking getAllInternalTunnlInterfacesFromDS");
575             tunnelList = getAllInternalTunnels(dataBroker);
576         }
577         else {
578             LOG.debug("No. of Internal Tunnel Interfaces in cache: {} ", internalInterfaces.size());
579             tunnelList.addAll(internalInterfaces);
580         }
581         LOG.trace("List of Internal Tunnels: {}", tunnelList);
582         return tunnelList;
583     }
584
585     @SuppressFBWarnings("RV_CHECK_FOR_POSITIVE_INDEXOF")
586     public static ExternalTunnelKey getExternalTunnelKey(String dst , String src,
587                                                          Class<? extends TunnelTypeBase> tunType) {
588         final int srcIndex = src.indexOf("physicalswitch");
589         if (srcIndex > 0) {
590             src = src.substring(0, srcIndex - 1);
591         }
592         final int dstIndex = dst.indexOf("physicalswitch");
593         if (dstIndex > 0) {
594             dst = dst.substring(0, dstIndex - 1);
595         }
596         return new ExternalTunnelKey(dst, src, tunType);
597     }
598
599     public static List<TunnelEndPoints> getTEPsForDpn(Uint64 srcDpn, Collection<DPNTEPsInfo> dpnList) {
600         for (DPNTEPsInfo dpn : dpnList) {
601             if (Objects.equals(dpn.getDPNID(), srcDpn)) {
602                 return new ArrayList<>(dpn.nonnullTunnelEndPoints());
603             }
604         }
605         return null;
606     }
607
608     public static List<InternalTunnel> getAllInternalTunnels(DataBroker dataBroker) {
609         List<InternalTunnel> result = null;
610         InstanceIdentifier<TunnelList> iid = InstanceIdentifier.builder(TunnelList.class).build();
611         Optional<TunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
612
613         if (tunnelList.isPresent()) {
614             result = tunnelList.get().getInternalTunnel();
615         }
616         if (result == null) {
617             result = emptyList();
618         }
619         return result;
620     }
621
622     public static InternalTunnel getInternalTunnel(String interfaceName, DataBroker broker) {
623         InternalTunnel internalTunnel = ITM_CACHE.getInternalTunnel(interfaceName);
624         LOG.trace("ItmUtils getInternalTunnel List of InternalTunnels in the Cache {} ", internalTunnel);
625         if (internalTunnel == null) {
626             internalTunnel = getInternalTunnelFromDS(interfaceName, broker);
627         }
628         return internalTunnel;
629     }
630
631     private static List<String> getAllInternalTunnlInterfacesFromDS(DataBroker broker) {
632         List<String> tunnelList = new ArrayList<>();
633         List<InternalTunnel> internalTunnels = getAllInternalTunnels(broker);
634         if (internalTunnels != null) {
635             for (InternalTunnel tunnel : internalTunnels) {
636                 List<String> tunnelInterfaceNames = tunnel.getTunnelInterfaceNames();
637                 if (tunnelInterfaceNames != null) {
638                     for (String tunnelInterfaceName : tunnelInterfaceNames) {
639                         tunnelList.add(tunnelInterfaceName);
640                     }
641                 }
642             }
643         }
644         LOG.debug("Internal Tunnel Interfaces list: {} ", tunnelList);
645         return tunnelList;
646     }
647
648     private static ExternalTunnel getExternalTunnelFromDS(String interfaceName, DataBroker broker) {
649         List<ExternalTunnel> externalTunnels = getAllExternalTunnels(broker);
650         if (externalTunnels !=  null) {
651             for (ExternalTunnel tunnel : externalTunnels) {
652                 String tunnelInterfaceName = tunnel.getTunnelInterfaceName();
653                 if (tunnelInterfaceName != null && tunnelInterfaceName.equalsIgnoreCase(interfaceName)) {
654                     LOG.trace("getExternalTunnelFromDS tunnelInterfaceName: {} ", tunnelInterfaceName);
655                     return tunnel;
656                 }
657             }
658         }
659         return null;
660     }
661
662     public static ExternalTunnel getExternalTunnel(String interfaceName, DataBroker broker) {
663         ExternalTunnel externalTunnel = ITM_CACHE.getExternalTunnel(interfaceName);
664         if (externalTunnel == null) {
665             externalTunnel = getExternalTunnelFromDS(interfaceName, broker);
666         }
667         LOG.trace("getExternalTunnel externalTunnel: {} ", externalTunnel);
668         return externalTunnel;
669     }
670
671     private static List<ExternalTunnel> getAllExternalTunnels(DataBroker dataBroker) {
672         List<ExternalTunnel> result = null;
673         InstanceIdentifier<ExternalTunnelList> iid = InstanceIdentifier.builder(ExternalTunnelList.class).build();
674         Optional<ExternalTunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
675         if (tunnelList.isPresent()) {
676             result = tunnelList.get().getExternalTunnel();
677         }
678         if (result == null) {
679             result = emptyList();
680         }
681         return result;
682     }
683
684     public static String convertTunnelTypetoString(Class<? extends TunnelTypeBase> tunType) {
685         String tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
686         if (tunType.equals(TunnelTypeVxlan.class)) {
687             tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
688         } else if (tunType.equals(TunnelTypeGre.class)) {
689             tunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
690         } else if (tunType.equals(TunnelTypeMplsOverGre.class)) {
691             tunnelType = ITMConstants.TUNNEL_TYPE_MPLSoGRE;
692         } else if (tunType.equals(TunnelTypeLogicalGroup.class)) {
693             tunnelType = ITMConstants.TUNNEL_TYPE_LOGICAL_GROUP_VXLAN;
694         }
695         return tunnelType;
696     }
697
698
699     public static boolean isItmIfType(Class<? extends InterfaceType> ifType) {
700         return ifType != null && ifType.isAssignableFrom(Tunnel.class);
701     }
702
703     public static StateTunnelListKey getTunnelStateKey(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
704                                                                .interfaces.rev140508.interfaces.state.Interface iface) {
705         StateTunnelListKey key = null;
706         if (isItmIfType(iface.getType())) {
707             key = new StateTunnelListKey(iface.getName());
708         }
709         return key;
710     }
711
712     public static Interface getInterface(
713             String name, IInterfaceManager ifaceManager) {
714         Interface result = ITM_CACHE.getInterface(name);
715         if (result == null) {
716             result = ifaceManager.getInterfaceInfoFromConfigDataStore(name);
717             if (result != null) {
718                 ITM_CACHE.addInterface(result);
719             }
720         }
721         return result;
722     }
723
724     public static boolean falseIfNull(Boolean value) {
725         return value == null ? false : value;
726     }
727
728     public static <T> List<T> getIntersection(List<T> list1, List<T> list2) {
729         List<T> list = new ArrayList<>();
730         for (T iter : list1) {
731             if (list2.contains(iter)) {
732                 list.add(iter);
733             }
734         }
735         LOG.debug(" getIntersection - L1 {}, L2 - {}, Intersection - {}", list1, list2, list);
736         return list;
737     }
738
739     public static void addTransportZoneMembership(List<TzMembership> zones, String zoneName) {
740         zones.add(new TzMembershipBuilder().setZoneName(zoneName).build());
741     }
742
743     public static  List<TzMembership> createTransportZoneMembership(String zoneName) {
744         List<TzMembership> zones = new ArrayList<>();
745         zones.add(new TzMembershipBuilder().setZoneName(zoneName).build());
746         return zones;
747     }
748
749     /**
750      * Gets the transport zone in TepsNotHosted list in the Operational Datastore, based on transport zone name.
751      *
752      * @param unknownTz transport zone name
753      *
754      * @param dataBroker data broker handle to perform read operations on Oper datastore
755      *
756      * @return the TepsInNotHostedTransportZone object in the TepsNotHosted list in Oper DS
757      */
758     public static TepsInNotHostedTransportZone getUnknownTransportZoneFromITMOperDS(
759             String unknownTz, DataBroker dataBroker) {
760         InstanceIdentifier<TepsInNotHostedTransportZone> unknownTzPath =
761                 InstanceIdentifier.builder(NotHostedTransportZones.class)
762                         .child(TepsInNotHostedTransportZone.class,
763                                 new TepsInNotHostedTransportZoneKey(unknownTz)).build();
764         Optional<TepsInNotHostedTransportZone> unknownTzOptional =
765                 ItmUtils.read(LogicalDatastoreType.OPERATIONAL, unknownTzPath, dataBroker);
766         if (unknownTzOptional.isPresent()) {
767             return unknownTzOptional.get();
768         }
769         return null;
770     }
771
772     /**
773      * Gets the bridge datapath ID from Network topology Node's OvsdbBridgeAugmentation, in the Operational DS.
774      *
775      * @param node Network Topology Node
776      *
777      * @param bridge bridge name
778      *
779      * @param dataBroker data broker handle to perform operations on datastore
780      *
781      * @return the datapath ID of bridge in string form
782      */
783     public static String getBridgeDpid(Node node, String bridge, DataBroker dataBroker) {
784         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
785         Node bridgeNode = null;
786         String datapathId = null;
787
788         NodeId ovsdbNodeId = node.key().getNodeId();
789
790         NodeId brNodeId = new NodeId(ovsdbNodeId.getValue()
791                 + "/" + ITMConstants.BRIDGE_URI_PREFIX + "/" + bridge);
792
793         InstanceIdentifier<Node> bridgeIid =
794                 InstanceIdentifier
795                         .create(NetworkTopology.class)
796                         .child(Topology.class, new TopologyKey(IfmConstants.OVSDB_TOPOLOGY_ID))
797                         .child(Node.class,new NodeKey(brNodeId));
798
799         Optional<Node> opBridgeNode = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid, dataBroker);
800
801         if (opBridgeNode.isPresent()) {
802             bridgeNode = opBridgeNode.get();
803         }
804         if (bridgeNode != null) {
805             ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
806         }
807
808         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
809             datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
810         }
811         return datapathId;
812     }
813
814     /**
815      * Gets the Network topology Node from Operational Datastore
816      * based on Bridge Augmentation.
817      *
818      * @param bridgeAugmentation bridge augmentation of OVSDB node
819      *
820      * @param dataBroker data broker handle to perform operations on datastore
821      *
822      * @return the Network Topology Node i.e. OVSDB node which is managing the specified bridge
823      */
824     public static Node getOvsdbNode(OvsdbBridgeAugmentation bridgeAugmentation,
825                                     DataBroker dataBroker) {
826         Node ovsdbNode = null;
827         Optional<Node> opOvsdbNode = Optional.absent();
828         if (bridgeAugmentation != null) {
829             InstanceIdentifier<Node> ovsdbNodeIid =
830                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
831             opOvsdbNode = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid, dataBroker);
832         }
833         if (opOvsdbNode.isPresent()) {
834             ovsdbNode = opOvsdbNode.get();
835         }
836         return ovsdbNode;
837     }
838
839     /**
840      * Gets the bridge datapath ID in string form from
841      * Network topology Node's OvsdbBridgeAugmentation in the Operational DS.
842      *
843      * @param augmentedNode Ovsdb Augmented Network Topology Node
844      *
845      * @return the datapath ID of bridge in string form
846      */
847     public static String getStrDatapathId(OvsdbBridgeAugmentation augmentedNode) {
848         String datapathId = null;
849         if (augmentedNode != null && augmentedNode.getDatapathId() != null) {
850             datapathId = augmentedNode.getDatapathId().getValue();
851         }
852         return datapathId;
853     }
854
855     /**
856      * Returns the dummy subnet (255.255.255.255/32) as IpPrefix object.
857      *
858      * @return the dummy subnet (255.255.255.255/32) in IpPrefix object
859      */
860     public static IpPrefix getDummySubnet() {
861         return DUMMY_IP_PREFIX;
862     }
863
864     /**
865      * Deletes the transport zone from Configuration datastore.
866      *
867      * @param tzName transport zone name
868      * @param dataBroker data broker handle to perform operations on datastore
869      */
870     public static void deleteTransportZoneFromConfigDS(String tzName, DataBroker dataBroker) {
871         // check whether transport-zone exists in config DS.
872         TransportZone transportZoneFromConfigDS = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
873         if (transportZoneFromConfigDS != null) {
874             // it exists, delete default-TZ now
875             InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class)
876                     .child(TransportZone.class, new TransportZoneKey(tzName)).build();
877             LOG.debug("Removing {} transport-zone from config DS.", tzName);
878             try {
879                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
880             } catch (TransactionCommitFailedException e) {
881                 LOG.error("deleteTransportZoneFromConfigDS failed. {} could not be deleted.", tzName, e);
882             }
883         }
884     }
885
886     /**
887      * Validates the tunnelType argument and returnsTunnelTypeBase class object
888      * corresponding to tunnelType obtained in String format.
889      *
890      * @param tunnelType type of tunnel in string form
891      *
892      * @return tunnel-type in TunnelTypeBase object
893      */
894     public static Class<? extends TunnelTypeBase> getTunnelType(String tunnelType) {
895         // validate tunnelType string, in case it is NULL or empty, then
896         // take VXLAN tunnel type by default
897         if (tunnelType == null || tunnelType.isEmpty()) {
898             return TUNNEL_TYPE_MAP.get(ITMConstants.TUNNEL_TYPE_VXLAN);
899         } else if (!tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN)
900                 && !tunnelType.equals(ITMConstants.TUNNEL_TYPE_GRE)) {
901             // if tunnel type is some incorrect value, then
902             // take VXLAN tunnel type by default
903             return TUNNEL_TYPE_MAP.get(ITMConstants.TUNNEL_TYPE_VXLAN);
904         }
905
906         // return TunnelTypeBase object corresponding to tunnel-type
907         return TUNNEL_TYPE_MAP.get(tunnelType);
908     }
909
910     public static List<TzMembership> removeTransportZoneMembership(TunnelEndPoints endPts, List<TzMembership> zones) {
911         LOG.trace(" RemoveTransportZoneMembership TEPs {}, Membership to be removed {} ", endPts, zones);
912         List<TzMembership> existingTzList = new ArrayList<>(endPts.nonnullTzMembership()) ;
913         for (TzMembership membership : zones) {
914             existingTzList.remove(new TzMembershipBuilder().setZoneName(membership.getZoneName()).build());
915         }
916         LOG.debug("Modified Membership List {}", existingTzList);
917         return existingTzList;
918     }
919
920     @NonNull
921     public static List<TzMembership> getOriginalTzMembership(TunnelEndPoints srcTep, Uint64 dpnId,
922                                                              Collection<DPNTEPsInfo> meshedDpnList) {
923         LOG.trace("Original Membership for source DPN {}, source TEP {}", dpnId, srcTep);
924         for (DPNTEPsInfo dstDpn : meshedDpnList) {
925             if (dpnId.equals(dstDpn.getDPNID())) {
926                 for (TunnelEndPoints tep : dstDpn.nonnullTunnelEndPoints()) {
927                     if (Objects.equals(tep.getIpAddress(), srcTep.getIpAddress())) {
928                         List<TzMembership> tzMemberships = tep.nonnullTzMembership();
929                         LOG.debug("Original Membership size {}", tzMemberships.size()) ;
930                         return tzMemberships;
931                     }
932                 }
933             }
934         }
935         return emptyList();
936     }
937
938     public static StateTunnelList buildStateTunnelList(StateTunnelListKey tlKey, String name, boolean state,
939                                                        TunnelOperStatus tunOpStatus, IInterfaceManager  ifaceManager,
940                                                        DataBroker broker) {
941         StateTunnelListBuilder stlBuilder = new StateTunnelListBuilder();
942         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
943                 ItmUtils.getInterface(name, ifaceManager);
944         IfTunnel ifTunnel = iface.augmentation(IfTunnel.class);
945         ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
946         if (ifTunnel == null || parentRefs == null) {
947             return null;
948         }
949         DstInfoBuilder dstInfoBuilder = new DstInfoBuilder();
950         SrcInfoBuilder srcInfoBuilder = new SrcInfoBuilder();
951         dstInfoBuilder.setTepIp(ifTunnel.getTunnelDestination());
952         srcInfoBuilder.setTepIp(ifTunnel.getTunnelSource());
953         // TODO: Add/Improve logic for device type
954         InternalTunnel internalTunnel = ItmUtils.ITM_CACHE.getInternalTunnel(name);
955         ExternalTunnel externalTunnel = ItmUtils.ITM_CACHE.getExternalTunnel(name);
956         if (internalTunnel == null && externalTunnel == null) {
957             // both not present in cache. let us update and try again.
958             internalTunnel = getInternalTunnel(name, broker);
959             externalTunnel = getExternalTunnel(name, broker);
960         }
961         if (internalTunnel != null) {
962             srcInfoBuilder.setTepDeviceId(internalTunnel.getSourceDPN().toString())
963                     .setTepDeviceType(TepTypeInternal.class);
964             dstInfoBuilder.setTepDeviceId(internalTunnel.getDestinationDPN().toString())
965                     .setTepDeviceType(TepTypeInternal.class);
966             stlBuilder.setTransportType(internalTunnel.getTransportType());
967         } else if (externalTunnel != null) {
968             ExternalTunnel tunnel = ItmUtils.ITM_CACHE.getExternalTunnel(name);
969             srcInfoBuilder.setTepDeviceId(tunnel.getSourceDevice())
970                     .setTepDeviceType(getDeviceType(tunnel.getSourceDevice()));
971             dstInfoBuilder.setTepDeviceId(tunnel.getDestinationDevice())
972                     .setTepDeviceType(getDeviceType(tunnel.getDestinationDevice()))
973                     .setTepIp(ifTunnel.getTunnelDestination());
974             stlBuilder.setTransportType(tunnel.getTransportType());
975         }
976         stlBuilder.withKey(tlKey).setTunnelInterfaceName(name).setOperState(tunOpStatus).setTunnelState(state)
977                 .setDstInfo(dstInfoBuilder.build()).setSrcInfo(srcInfoBuilder.build());
978         return stlBuilder.build();
979     }
980
981     private static Class<? extends TepTypeBase> getDeviceType(String device) {
982         if (device.startsWith("hwvtep")) {
983             return TepTypeHwvtep.class;
984         } else if (InetAddresses.isInetAddress(device)) {
985             // In case of external tunnel, destination-device will be of IP address type.
986             return TepTypeExternal.class;
987         } else {
988             return TepTypeInternal.class;
989         }
990     }
991
992     public static InstanceIdentifier<StateTunnelList> buildStateTunnelListId(StateTunnelListKey tlKey) {
993         return InstanceIdentifier.builder(TunnelsState.class).child(StateTunnelList.class, tlKey).build();
994     }
995
996     @NonNull
997     public static  Optional<InternalTunnel> getInternalTunnelFromDS(Uint64 srcDpn, Uint64 destDpn,
998                                                                     Class<? extends TunnelTypeBase> type,
999                                                                     DataBroker dataBroker) {
1000         InstanceIdentifier<InternalTunnel> pathLogicTunnel = InstanceIdentifier.create(TunnelList.class)
1001                 .child(InternalTunnel.class,
1002                         new InternalTunnelKey(destDpn, srcDpn, type));
1003         //TODO: need to be replaced by cached copy
1004         return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, pathLogicTunnel, dataBroker);
1005     }
1006
1007     private static InternalTunnel getInternalTunnelFromDS(String interfaceName, DataBroker broker) {
1008         List<InternalTunnel> internalTunnels = getAllInternalTunnels(broker);
1009         if (internalTunnels != null) {
1010             for (InternalTunnel tunnel : internalTunnels) {
1011                 List<String> tunnelInterfaceNames = tunnel.getTunnelInterfaceNames();
1012                 if (tunnelInterfaceNames != null) {
1013                     for (String tunnelInterfaceName : tunnelInterfaceNames) {
1014                         if (tunnelInterfaceName.equalsIgnoreCase(interfaceName)) {
1015                             LOG.trace("ItmUtils getInternalTunnelFromDS {} ", tunnelInterfaceName);
1016                             return tunnel;
1017                         }
1018                     }
1019                 }
1020             }
1021         }
1022         return null;
1023     }
1024
1025     public static boolean isTunnelAggregationUsed(Class<? extends TunnelTypeBase> tunType) {
1026         return ItmTunnelAggregationHelper.isTunnelAggregationEnabled()
1027                 && (tunType.isAssignableFrom(TunnelTypeVxlan.class)
1028                 || tunType.isAssignableFrom(TunnelTypeLogicalGroup.class));
1029     }
1030
1031     public static List<TunnelOptions> buildTunnelOptions(TunnelEndPoints tep, ItmConfig itmConfig) {
1032         List<TunnelOptions> tunOptions = new ArrayList<>();
1033
1034         String tos = tep.getOptionTunnelTos();
1035         if (tos == null) {
1036             tos = itmConfig.getDefaultTunnelTos();
1037         }
1038         /* populate tos option only if its not default value of 0 */
1039         if (tos != null && !tos.equals("0")) {
1040             TunnelOptionsBuilder optionsBuilder = new TunnelOptionsBuilder();
1041             optionsBuilder.withKey(new TunnelOptionsKey("tos"));
1042             optionsBuilder.setTunnelOption("tos");
1043             optionsBuilder.setValue(tos);
1044             tunOptions.add(optionsBuilder.build());
1045         }
1046
1047         if (tep.getTunnelType() == TunnelTypeVxlan.class && itmConfig.isGpeExtensionEnabled()) {
1048             TunnelOptionsBuilder optionsBuilder = new TunnelOptionsBuilder();
1049             optionsBuilder.withKey(new TunnelOptionsKey("exts"));
1050             optionsBuilder.setTunnelOption("exts");
1051             optionsBuilder.setValue("gpe");
1052             tunOptions.add(optionsBuilder.build());
1053         }
1054         return tunOptions.isEmpty() ? null : tunOptions;
1055     }
1056
1057     public static ExternalTunnel getExternalTunnelbyExternalTunnelKey(ExternalTunnelKey externalTunnelKey,
1058                                                                       InstanceIdentifier<ExternalTunnel> path,
1059                                                                       DataBroker dataBroker) {
1060         ExternalTunnel exTunnel = ITM_CACHE.getExternalTunnelKeyToExternalTunnels().get(externalTunnelKey);
1061         if (exTunnel == null) {
1062             Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
1063             if (ext.isPresent()) {
1064                 exTunnel = ext.get();
1065             }
1066         }
1067         return exTunnel;
1068     }
1069
1070     public static List<DPNTEPsInfo> getDpnTEPsInfos(DataBroker dataBroker) {
1071         InstanceIdentifier<DpnEndpoints> iid = InstanceIdentifier.builder(DpnEndpoints.class).build();
1072         Optional<DpnEndpoints> dpnEndpoints = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
1073         if (dpnEndpoints.isPresent()) {
1074             return dpnEndpoints.get().getDPNTEPsInfo();
1075         } else {
1076             return new ArrayList<>();
1077         }
1078     }
1079
1080     public static InstanceIdentifier<TransportZone> getTZInstanceIdentifier(String tzName) {
1081         return InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class,
1082                 new TransportZoneKey(tzName)).build();
1083     }
1084
1085     /**
1086      * Returns the transport zone from Configuration datastore.
1087      *
1088      * @param tzName transport zone name
1089      * @param dataBroker data broker handle to perform operations on datastore
1090      * @return the TransportZone object in Config DS
1091      */
1092     // FIXME: Better is to implement cache to avoid datastore read.
1093     public static TransportZone getTransportZoneFromConfigDS(String tzName, DataBroker dataBroker) {
1094         InstanceIdentifier<TransportZone> tzonePath = getTZInstanceIdentifier(tzName);
1095         Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
1096                 dataBroker);
1097         if (transportZoneOptional.isPresent()) {
1098             return transportZoneOptional.get();
1099         }
1100         return null;
1101     }
1102
1103     public static Class<? extends TunnelTypeBase> convertStringToTunnelType(String tunnelType) {
1104         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
1105         if (STRING_CLASS_IMMUTABLE_BI_MAP.containsKey(tunnelType)) {
1106             tunType = STRING_CLASS_IMMUTABLE_BI_MAP.get(tunnelType);
1107         }
1108         return tunType ;
1109     }
1110
1111     public static List<Uint64> getDpIdFromTransportzone(DataBroker dataBroker, String tzone) {
1112         List<Uint64> listOfDpId = new ArrayList<>();
1113         InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class)
1114                 .child(TransportZone.class, new TransportZoneKey(tzone)).build();
1115         Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
1116                 path, dataBroker);
1117         if (transportZoneOptional.isPresent()) {
1118             TransportZone transportZone = transportZoneOptional.get();
1119             if (transportZone.getVteps() != null && !transportZone.getVteps().isEmpty()) {
1120                 List<Vteps> vtepsList = transportZone.getVteps();
1121                 if (vtepsList != null && !vtepsList.isEmpty()) {
1122                     for (Vteps vtep : vtepsList) {
1123                         listOfDpId.add(vtep.getDpnId());
1124                     }
1125                 }
1126             }
1127         }
1128         return listOfDpId;
1129     }
1130 }