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