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