Merge "BUG 6952: DPN can't be added in multiple TZ"
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / ItmExternalTunnelAddWorker.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.itm.confighelpers;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import org.apache.commons.net.util.SubnetUtils;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.itm.globals.ITMConstants;
18 import org.opendaylight.genius.itm.impl.ItmUtils;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import java.math.BigInteger;
45 import java.util.ArrayList;
46 import java.util.List;
47
48 public class ItmExternalTunnelAddWorker {
49     private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
50
51     private static Boolean monitorEnabled;
52     private static Integer monitorInterval;
53     private static Class<? extends TunnelMonitoringTypeBase> monitorProtocol;
54
55     private static final FutureCallback<Void> DEFAULT_CALLBACK =
56             new FutureCallback<Void>() {
57                 @Override
58                 public void onSuccess(Void result) {
59                     logger.debug("Success in Datastore operation");
60                 }
61
62                 @Override
63                 public void onFailure(Throwable error) {
64                     logger.error("Error in Datastore operation", error);
65                 }
66
67             };
68
69     public static List<ListenableFuture<Void>> buildTunnelsToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
70                                                                               List<DPNTEPsInfo> cfgDpnList, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
71         List<ListenableFuture<Void>> futures = new ArrayList<>();
72         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
73         if (null != cfgDpnList) {
74             for (DPNTEPsInfo teps : cfgDpnList) {
75                 // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
76                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
77                 String interfaceName = firstEndPt.getInterfaceName();
78                 String tunTypeStr = tunType.getName();
79                 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue(), tunTypeStr);
80                 char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
81                 boolean useOfTunnel = ItmUtils.falseIfNull(firstEndPt.isOptionOfTunnel());
82                 String subnetMaskStr = String.valueOf(subnetMaskArray);
83                 SubnetUtils utils = new SubnetUtils(subnetMaskStr);
84                 String dcGwyIpStr = String.valueOf(extIp.getValue());
85                 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
86                 IpAddress gwyIpAddress = utils.getInfo().isInRange(dcGwyIpStr) ? gatewayIpObj : firstEndPt.getGwIpAddress();
87                 logger.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress);
88                 Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName,
89                     String.format("%s %s", ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"), true,
90                     tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false, false,
91                     ITMConstants.DEFAULT_MONITOR_PROTOCOL, null, useOfTunnel);
92
93                 logger.debug(" Trunk Interface builder - {} ", iface);
94                 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
95                 logger.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
96                 logger.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
97                 t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
98                 // update external_tunnel_list ds
99                 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
100                         ExternalTunnelList.class)
101                         .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(), teps.getDPNID().toString(), tunType));
102                 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(  teps.getDPNID().toString(), extIp.toString(),
103                         tunType, trunkInterfaceName);
104                 t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
105             }
106             futures.add(t.submit());
107         }
108         return futures;
109     }
110
111     public static List<ListenableFuture<Void>> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
112                                                                                      List<BigInteger> dpnId, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
113         List<ListenableFuture<Void>> futures = new ArrayList<>();
114         List<DPNTEPsInfo> cfgDpnList = dpnId == null ? ItmUtils.getTunnelMeshInfo(dataBroker) : ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId);
115         futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType);
116         return futures;
117     }
118
119     public static List<ListenableFuture<Void>> buildHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps) {
120         List<ListenableFuture<Void>> futures = new ArrayList<>();
121         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
122         monitorInterval = ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL;
123         monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
124         monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
125         if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
126             logger.trace("calling tunnels from css {}",cfgdDpnList);
127             tunnelsFromCSS(cfgdDpnList, idManagerService , futures, t , dataBroker);
128
129         }
130         if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty() ) {
131             logger.trace("calling tunnels from hwTep {}",cfgdHwVteps);
132             tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker);
133         }
134
135         if (cfgdDpnList != null && !cfgdDpnList.isEmpty() || cfgdHwVteps != null && !cfgdHwVteps.isEmpty()) {
136             futures.add(t.submit());
137         }
138         return futures;
139     }
140
141     private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
142         Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
143         Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
144         for (DPNTEPsInfo dpn : cfgdDpnList) {
145             logger.trace("processing dpn {}" , dpn);
146             if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) {
147                 for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
148                     for(TzMembership zone: tep.getTzMembership()) {
149                         createTunnelsFromCSSinTransportZone(zone.getZoneName(), dpn, tep, idManagerService, futures, t, dataBroker);
150                     }
151                 }
152             }
153         }
154     }
155
156     private static void createTunnelsFromCSSinTransportZone(String zoneName, DPNTEPsInfo dpn, TunnelEndPoints tep, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
157         InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey(zoneName)).build();
158         Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
159         if (tZoneOptional.isPresent()) {
160             TransportZone tZone = tZoneOptional.get();
161             //do we need to check tunnel type?
162             if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
163                 for (Subnets sub : tZone.getSubnets()) {
164                     if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
165                         for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
166                             //dont mesh if hwVteps and CSS-tep have same ip-address
167                             if(hwVtepDS.getIpAddress().equals(tep.getIpAddress())) {
168                                 continue;
169                             }
170                             String cssID = dpn.getDPNID().toString();
171                             String nodeId = hwVtepDS.getNodeId();
172                             boolean useOfTunnel = ItmUtils.falseIfNull(tep.isOptionOfTunnel());
173                             logger.trace("wire up {} and {}",tep, hwVtepDS);
174                             if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(),
175                                     tep.getIpAddress(), useOfTunnel, nodeId, hwVtepDS.getIpAddress(),
176                                     tep.getSubnetMask(), sub.getGatewayIp(), sub.getPrefix(),
177                                     tZone.getTunnelType(), false, monitorProtocol, monitorInterval,
178                                     idManagerService, dataBroker, futures, t)) {
179                                 logger.error("Unable to build tunnel {} -- {}", tep.getIpAddress(), hwVtepDS.getIpAddress());
180                             }
181                             //TOR-CSS
182                             logger.trace("wire up {} and {}", hwVtepDS,tep);
183                             if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), cssID, tep.getIpAddress(), sub.getPrefix(),
184                                     sub.getGatewayIp(), tep.getSubnetMask(), tZone.getTunnelType(), false, monitorProtocol, monitorInterval, idManagerService, dataBroker, futures, t)) {
185                                 logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), tep.getIpAddress());
186                             }
187
188                         }
189                     }
190                 }
191             }
192         }
193     }
194
195     private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
196         for (HwVtep hwTep : cfgdHwVteps) {
197             InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey(hwTep.getTransportZone())).build();
198             Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
199             Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
200             Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
201             Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
202             if (tZoneOptional.isPresent()) {
203                 TransportZone tZone = tZoneOptional.get();
204                 //do we need to check tunnel type?
205                 if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
206                     for (Subnets sub : tZone.getSubnets()) {
207                         if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
208                             for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
209                                 if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp()))
210                                  {
211                                     continue;//dont mesh with self
212                                 }
213                                 logger.trace("wire up {} and {}",hwTep, hwVtepDS);
214                                 if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
215                                         hwTep.getIpPrefix(), hwTep.getGatewayIP(), sub.getPrefix(), tunType,false,monitorProtocol,
216                                                 monitorInterval, idManagerService, dataBroker, futures, t)) {
217                                     logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), hwVtepDS.getIpAddress());
218                                 }
219                                 //TOR2-TOR1
220                                 logger.trace("wire up {} and {}", hwVtepDS,hwTep);
221                                 if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getNode_id(), hwTep.getHwIp(),
222                                         sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tunType, false,monitorProtocol, monitorInterval, idManagerService, dataBroker, futures, t)) {
223                                     logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), hwTep.getHwIp());
224                                 }
225                             }
226                         }
227                         if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
228                             for (Vteps vtep : sub.getVteps()) {
229                                 if(vtep.getIpAddress().equals(hwTep.getHwIp())) {
230                                     continue;
231                                 }
232                                 //TOR-CSS
233                                 String cssID = vtep.getDpnId().toString();
234                                 logger.trace("wire up {} and {}",hwTep, vtep);
235                                 if(!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID, vtep.getIpAddress(), hwTep.getIpPrefix(),
236                                         hwTep.getGatewayIP(), sub.getPrefix(), tunType,false, monitorProtocol, monitorInterval, idManagerService, dataBroker, futures, t )) {
237                                     logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), vtep.getIpAddress());
238                                 }
239                                 //CSS-TOR
240                                 logger.trace("wire up {} and {}", vtep,hwTep);
241                                 boolean useOfTunnel = ItmUtils.falseIfNull(vtep.isOptionOfTunnel());
242                                 if(!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(),
243                                         useOfTunnel, hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(),
244                                         sub.getGatewayIp(),hwTep.getIpPrefix(), tunType,false,monitorProtocol,
245                                         monitorInterval, idManagerService, dataBroker, futures, t )) {
246                                     ;
247                                 }
248                             }
249
250                         }
251                     }
252                 }
253             }
254         }
255     }
256
257     //for tunnels from TOR device
258     private static boolean wireUp(String topo_id, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
259                                   IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled,  Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
260                                   Integer monitorInterval,IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
261         IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
262         IpAddress gwyIpAddress = srcSubnet.equals(dstSubnet) ? gatewayIpObj : gWIp;
263         String parentIf =  ItmUtils.getHwParentIf(topo_id, srcNodeid);
264         String tunTypeStr = tunType.getName();
265         String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
266                 srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
267         logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
268         Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"),
269                 true, topo_id, srcNodeid, tunType, srcIp, dstIp, gwyIpAddress, monitorEnabled, monitorProtocol, monitorInterval);
270         InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
271         logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
272         ItmUtils.itmCache.addInterface(hwTunnelIf);
273         t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true);
274         // also update itm-state ds?
275         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
276                 ExternalTunnelList.class)
277                 .child(ExternalTunnel.class, new ExternalTunnelKey( getExternalTunnelKey(dstNodeId), getExternalTunnelKey(srcNodeid), tunType));
278         ExternalTunnel tnl = ItmUtils.buildExternalTunnel(  getExternalTunnelKey(srcNodeid),
279                 getExternalTunnelKey(dstNodeId),
280                 tunType, tunnelIfName);
281         t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
282         ItmUtils.itmCache.addExternalTunnel(tnl);
283         return true;
284     }
285
286     //for tunnels from CSS
287     private static boolean wireUp(BigInteger dpnId, String portname, Integer vlanId, IpAddress srcIp, Boolean remoteIpFlow, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
288                                   IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType, Boolean monitorEnabled, Class<? extends TunnelMonitoringTypeBase> monitorProtocol, Integer monitorInterval,
289                                   IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
290         IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
291         IpAddress gwyIpAddress = srcSubnet.equals(dstSubnet) ? gatewayIpObj : gWIp;
292         String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
293         String tunTypeStr = tunType.getName();
294         String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
295                 srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
296         logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
297         Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName,
298                 String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress,
299                 vlanId, false,monitorEnabled, monitorProtocol, monitorInterval, remoteIpFlow);
300         InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
301         logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
302         t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true);
303         ItmUtils.itmCache.addInterface(extTunnelIf);
304         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
305                 ExternalTunnelList.class)
306                 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), dpnId.toString(), tunType));
307         ExternalTunnel tnl = ItmUtils.buildExternalTunnel(  dpnId.toString(),
308                 getExternalTunnelKey(dstNodeId),
309                 tunType, tunnelIfName);
310         t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
311         ItmUtils.itmCache.addExternalTunnel(tnl);
312         return true;
313     }
314
315     static String getExternalTunnelKey(String nodeid) {
316         if (nodeid.indexOf("physicalswitch") > 0) {
317             nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1);
318         }
319         return nodeid;
320     }
321
322 }
323