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