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