2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.elan.l2gw.utils;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Lists;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Objects;
21 import java.util.Timer;
22 import java.util.TimerTask;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import java.util.stream.Collectors;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
32 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
35 import org.opendaylight.genius.interfacemanager.IfmUtil;
36 import org.opendaylight.genius.mdsalutil.MDSALUtil;
37 import org.opendaylight.genius.utils.SystemPropertyReader;
38 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
39 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
40 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
41 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
42 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
43 import org.opendaylight.netvirt.elan.l2gw.listeners.HwvtepTerminationPointListener;
44 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
45 import org.opendaylight.netvirt.elan.utils.ElanConstants;
46 import org.opendaylight.netvirt.elan.utils.ElanUtils;
47 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
48 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.opendaylight.yangtools.yang.common.RpcResult;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
90 * It gathers a set of utility methods that handle ELAN configuration in
91 * external Devices (where external means "not-CSS". As of now: TORs).
93 * <p>It makes use of HwvtepUtils class located under ovsdb/hwvtepsouthbound
94 * project for low-level mdsal operations
98 public class ElanL2GatewayUtils {
99 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayUtils.class);
101 private final DataBroker broker;
102 private final ItmRpcService itmRpcService;
103 private final ElanUtils elanUtils;
104 private final EntityOwnershipService entityOwnershipService;
105 private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
107 private final DataStoreJobCoordinator dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
108 private static Timer LogicalSwitchDeleteJobTimer = new Timer();
109 private static final int LOGICAL_SWITCH_DELETE_DELAY = 120000;
110 private final ConcurrentMap<Pair<NodeId, String>, TimerTask> logicalSwitchDeletedTasks = new ConcurrentHashMap<>();
112 public ElanL2GatewayUtils(DataBroker broker, ItmRpcService itmRpcService, ElanUtils elanUtils,
113 EntityOwnershipService entityOwnershipService,
114 ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils) {
115 this.broker = broker;
116 this.itmRpcService = itmRpcService;
117 this.elanUtils = elanUtils;
118 this.entityOwnershipService = entityOwnershipService;
119 this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
123 * Installs dpn macs in external device. first it checks if the physical
124 * locator towards this dpn tep is present or not if the physical locator is
125 * present go ahead and add the ucast macs otherwise update the mcast mac
126 * entry to include this dpn tep ip and schedule the job to put ucast macs
127 * once the physical locator is programmed in device
131 * @param lstElanInterfaceNames
132 * the lst Elan interface names
135 * @param externalNodeId
136 * the external node id
138 public void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames, BigInteger dpnId,
139 NodeId externalNodeId) {
140 L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName,
141 externalNodeId.getValue());
142 if (elanL2GwDevice == null) {
143 LOG.debug("L2 gw device not found in elan cache for device name {}", externalNodeId);
146 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, externalNodeId);
147 if (dpnTepIp == null) {
148 LOG.warn("Could not install dpn macs in l2gw device , dpnTepIp not found dpn : {} , nodeid : {}", dpnId,
153 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
154 RemoteMcastMacs remoteMcastMac = readRemoteMcastMac(externalNodeId, logicalSwitchName,
155 LogicalDatastoreType.OPERATIONAL);
156 boolean phyLocAlreadyExists = checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(externalNodeId, remoteMcastMac,
158 LOG.debug("phyLocAlreadyExists = {} for locator [{}] in remote mcast entry for elan [{}], nodeId [{}]",
159 phyLocAlreadyExists, String.valueOf(dpnTepIp.getValue()), elanName, externalNodeId.getValue());
160 List<PhysAddress> staticMacs = null;
161 staticMacs = getElanDpnMacsFromInterfaces(lstElanInterfaceNames);
163 if (phyLocAlreadyExists) {
164 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
167 elanL2GatewayMulticastUtils.scheduleMcastMacUpdateJob(elanName, elanL2GwDevice);
168 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
172 * gets the macs addresses for elan interfaces.
174 * @param lstElanInterfaceNames
175 * the lst elan interface names
178 private List<PhysAddress> getElanDpnMacsFromInterfaces(Set<String> lstElanInterfaceNames) {
179 List<PhysAddress> result = new ArrayList<>();
180 for (String interfaceName : lstElanInterfaceNames) {
181 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
182 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
183 for (MacEntry macEntry : elanInterfaceMac.getMacEntry()) {
184 result.add(macEntry.getMacAddress());
192 * Check if phy locator already exists in remote mcast entry.
196 * @param remoteMcastMac
197 * the remote mcast mac
198 * @param expectedPhyLocatorIp
199 * the expected phy locator ip
200 * @return true, if successful
202 public static boolean checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(NodeId nodeId,
203 RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
204 if (remoteMcastMac != null) {
205 HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
206 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
207 HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
208 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
209 if (remoteMcastMac.getLocatorSet() != null) {
210 for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
211 if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
212 LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
222 * Gets the remote mcast mac.
226 * @param logicalSwitchName
227 * the logical switch name
228 * @param datastoreType
230 * @return the remote mcast mac
232 public RemoteMcastMacs readRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
233 LogicalDatastoreType datastoreType) {
234 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
235 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
236 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
237 new MacAddress(ElanConstants.UNKNOWN_DMAC));
238 RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
240 return remoteMcastMac;
244 * Removes the given MAC Addresses from all the External Devices belonging
245 * to the specified ELAN.
247 * @param elanInstance
249 * @param macAddresses
252 public void removeMacsFromElanExternalDevices(ElanInstance elanInstance, List<PhysAddress> macAddresses) {
253 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
254 .getInvolvedL2GwDevices(elanInstance.getElanInstanceName());
255 for (L2GatewayDevice l2GatewayDevice : elanL2GwDevices.values()) {
256 removeRemoteUcastMacsFromExternalDevice(l2GatewayDevice.getHwvtepNodeId(),
257 elanInstance.getElanInstanceName(), macAddresses);
262 * Removes the given MAC Addresses from the specified External Device.
264 * @param deviceNodeId
266 * @param macAddresses
268 * @return the listenable future
270 private ListenableFuture<Void> removeRemoteUcastMacsFromExternalDevice(String deviceNodeId,
271 String logicalSwitchName, List<PhysAddress> macAddresses) {
272 NodeId nodeId = new NodeId(deviceNodeId);
275 List<MacAddress> lstMac = Lists.transform(macAddresses,
276 physAddress -> physAddress != null ? new MacAddress(physAddress.getValue()) : null);
277 return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
280 public ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
281 Optional<LogicalSwitches> lsOpc = elanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
282 (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
283 if (lsOpc.isPresent()) {
284 LogicalSwitches ls = lsOpc.get();
286 // Logical switch name is Elan name
287 String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
288 return ElanUtils.getElanInstanceByName(broker, elanName);
290 String macAddress = localUcastMac.getMacEntryKey().getValue();
291 LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
298 * Install external device local macs in dpn.
302 * @param l2gwDeviceNodeId
303 * the l2gw device node id
306 * @param interfaceName
309 public void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan,
310 String interfaceName) {
311 L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
312 l2gwDeviceNodeId.getValue());
313 if (l2gwDevice == null) {
314 LOG.debug("L2 gw device not found in elan cache for device name {}", l2gwDeviceNodeId.getValue());
318 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
322 * Install dmac flows on dpn.
330 * @param interfaceName
333 public void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan,
334 String interfaceName) {
335 String elanName = elan.getElanInstanceName();
337 List<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
338 if (l2gwDeviceLocalMacs != null && !l2gwDeviceLocalMacs.isEmpty()) {
339 for (LocalUcastMacs localUcastMac : l2gwDeviceLocalMacs) {
340 // TODO batch these ops
341 elanUtils.installDmacFlowsToExternalRemoteMac(dpnId, l2gwDevice.getHwvtepNodeId(), elan.getElanTag(),
342 elan.getSegmentationId(), localUcastMac.getMacEntryKey().getValue(), elanName, interfaceName);
344 LOG.debug("Installing L2gw device [{}] local macs [size: {}] in dpn [{}] for elan [{}]",
345 l2gwDevice.getHwvtepNodeId(), l2gwDeviceLocalMacs.size(), dpnId, elanName);
350 * Install elan l2gw devices local macs in dpn.
356 * @param interfaceName
359 public void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan, String interfaceName) {
360 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
361 .getInvolvedL2GwDevices(elan.getElanInstanceName());
362 if (elanL2GwDevicesFromCache != null) {
363 for (L2GatewayDevice l2gwDevice : elanL2GwDevicesFromCache.values()) {
364 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
367 LOG.debug("No Elan l2 gateway devices in cache for [{}] ", elan.getElanInstanceName());
371 public void installL2GwUcastMacInElan(final ElanInstance elan, final L2GatewayDevice extL2GwDevice,
372 final String macToBeAdded, String interfaceName) {
373 final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
374 final String elanInstanceName = elan.getElanInstanceName();
376 // Retrieve all participating DPNs in this Elan. Populate this MAC in
378 // Looping through all DPNs in order to add/remove mac flows in their
380 final List<DpnInterfaces> elanDpns = elanUtils.getInvolvedDpnsInElan(elanInstanceName);
381 if (elanDpns != null && elanDpns.size() > 0) {
382 String jobKey = elan.getElanInstanceName() + ":" + macToBeAdded;
383 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "install l2gw macs in dmac table",
385 List<ListenableFuture<Void>> fts = Lists.newArrayList();
386 if (doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
387 for (DpnInterfaces elanDpn : elanDpns) {
388 // TODO batch the below call
389 fts.addAll(elanUtils.installDmacFlowsToExternalRemoteMac(elanDpn.getDpId(),
390 extDeviceNodeId, elan.getElanTag(), elan.getSegmentationId(), macToBeAdded,
391 elanInstanceName, interfaceName));
394 LOG.trace("Skipping install of dmac flows for mac {} as it is not found in cache",
400 final IpAddress extL2GwDeviceTepIp = extL2GwDevice.getTunnelIp();
401 final List<PhysAddress> macList = new ArrayList<>();
402 macList.add(new PhysAddress(macToBeAdded));
404 String jobKey = "hwvtep:" + elan.getElanInstanceName() + ":" + macToBeAdded;
405 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "install remote ucast macs in l2gw device",
407 List<ListenableFuture<Void>> fts = Lists.newArrayList();
408 if (!doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
410 "Skipping install of remote ucast macs {} in l2gw device as it is not found in cache",
414 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
415 .getInvolvedL2GwDevices(elanInstanceName);
416 for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
417 if (!otherDevice.getHwvtepNodeId().equals(extDeviceNodeId)
418 && !areMLAGDevices(extL2GwDevice, otherDevice)) {
419 final String hwvtepId = otherDevice.getHwvtepNodeId();
420 InstanceIdentifier<Node> iid = HwvtepSouthboundUtils
421 .createInstanceIdentifier(new NodeId(hwvtepId));
422 final String logicalSwitchName = elanInstanceName;
424 ListenableFuture<Void> ft = HwvtepUtils.installUcastMacs(broker, hwvtepId, macList,
425 logicalSwitchName, extL2GwDeviceTepIp);
426 // TODO batch the above call
427 Futures.addCallback(ft, new FutureCallback<Void>() {
429 public void onSuccess(Void noarg) {
430 LOG.trace("Successful in initiating ucast_remote_macs addition"
431 + "related to {} in {}", logicalSwitchName, hwvtepId);
435 public void onFailure(Throwable error) {
436 LOG.error(String.format(
437 "Failed adding ucast_remote_macs related to " + "%s in %s",
438 logicalSwitchName, hwvtepId), error);
449 * Does local ucast mac exists in cache.
451 * @param elanL2GwDevice
452 * the elan L2 Gw device
454 * the mac address to be verified
455 * @return true, if successful
457 private static boolean doesLocalUcastMacExistsInCache(L2GatewayDevice elanL2GwDevice, String macAddress) {
458 java.util.Optional<LocalUcastMacs> macExistsInCache = elanL2GwDevice.getUcastLocalMacs().stream()
459 .filter(mac -> mac.getMacEntryKey().getValue().equalsIgnoreCase(macAddress)).findFirst();
460 return macExistsInCache.isPresent();
464 * Un install l2 gw ucast mac from elan.
470 * @param macAddresses
473 public void unInstallL2GwUcastMacFromElan(final ElanInstance elan, final L2GatewayDevice l2GwDevice,
474 final List<MacAddress> macAddresses) {
475 if (macAddresses == null || macAddresses.isEmpty()) {
478 final String elanName = elan.getElanInstanceName();
480 // Retrieve all participating DPNs in this Elan. Populate this MAC in
481 // DMAC table. Looping through all DPNs in order to add/remove mac flows
482 // in their DMAC table
483 for (final MacAddress mac : macAddresses) {
484 final List<DpnInterfaces> elanDpns = elanUtils.getInvolvedDpnsInElan(elanName);
485 if (elanDpns != null && !elanDpns.isEmpty()) {
486 String jobKey = elanName + ":" + mac.getValue();
487 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "delete l2gw macs from dmac table",
489 List<ListenableFuture<Void>> fts = Lists.newArrayList();
490 for (DpnInterfaces elanDpn : elanDpns) {
491 BigInteger dpnId = elanDpn.getDpId();
492 // never batch deletes
493 fts.addAll(elanUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
494 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
501 DeleteL2GwDeviceMacsFromElanJob job = new DeleteL2GwDeviceMacsFromElanJob(broker, elanName, l2GwDevice,
503 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, job.getJobKey(),
504 "delete remote ucast macs in l2gw devices", job);
508 * Delete elan l2 gateway devices ucast local macs from dpn.
515 public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
516 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
517 if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
518 LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
521 final ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
523 LOG.error("Could not find Elan by name: {}", elanName);
526 LOG.info("Deleting Elan [{}] L2GatewayDevices UcastLocalMacs from Dpn [{}]", elanName, dpnId);
528 final Long elanTag = elan.getElanTag();
529 for (final L2GatewayDevice l2GwDevice : elanL2GwDevices.values()) {
530 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GwDevice);
531 if (localMacs != null && !localMacs.isEmpty()) {
532 for (final MacAddress mac : localMacs) {
533 String jobKey = elanName + ":" + mac.getValue();
534 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey,
535 "delete l2gw macs from dmac table", () -> {
536 List<ListenableFuture<Void>> futures = Lists.newArrayList();
538 futures.addAll(elanUtils.deleteDmacFlowsToExternalMac(elanTag, dpnId,
539 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
548 * Gets the l2 gw device local macs.
552 * @return the l2 gw device local macs
554 public static List<MacAddress> getL2GwDeviceLocalMacs(L2GatewayDevice l2gwDevice) {
555 List<MacAddress> macs = new ArrayList<>();
556 if (l2gwDevice == null) {
559 List<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
560 if (lstUcastLocalMacs != null && !lstUcastLocalMacs.isEmpty()) {
561 macs = Lists.transform(lstUcastLocalMacs,
562 localUcastMac -> localUcastMac != null ? localUcastMac.getMacEntryKey() : null);
568 * Delete elan macs from L2 gateway device.<br>
569 * This includes deleting ELAN mac table entries plus external device
570 * UcastLocalMacs which are part of the same ELAN.
572 * @param l2GatewayDevice
573 * the l2 gateway device
576 * @return the listenable future
578 public ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(L2GatewayDevice l2GatewayDevice,
580 String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
581 String logicalSwitch = getLogicalSwitchFromElan(elanName);
583 List<MacAddress> lstElanMacs = getRemoteUcastMacs(new NodeId(hwvtepNodeId), logicalSwitch,
584 LogicalDatastoreType.CONFIGURATION);
585 ListenableFuture<Void> future = HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(hwvtepNodeId),
586 logicalSwitch, lstElanMacs);
588 Futures.addCallback(future, new FutureCallback<Void>() {
590 public void onSuccess(Void noarg) {
591 LOG.trace("Successful in batch deletion of elan [{}] macs from l2gw device [{}]", elanName,
596 public void onFailure(Throwable error) {
597 LOG.warn(String.format("Failed during batch delete of elan [%s] macs from l2gw device [%s]. "
598 + "Retrying with sequential deletes.", elanName, hwvtepNodeId), error);
599 if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
600 for (MacAddress mac : lstElanMacs) {
601 HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
607 if (LOG.isDebugEnabled()) {
608 List<String> elanMacs = lstElanMacs.stream().map(mac -> mac.getValue()).collect(Collectors.toList());
609 LOG.debug("Deleting elan [{}] macs from node [{}]. Deleted macs = {}", elanName, hwvtepNodeId, elanMacs);
615 * Gets the remote ucast macs from hwvtep node filtering based on logical
618 * @param hwvtepNodeId
620 * @param logicalSwitch
622 * @param datastoreType
624 * @return the remote ucast macs
626 public List<MacAddress> getRemoteUcastMacs(NodeId hwvtepNodeId, String logicalSwitch,
627 LogicalDatastoreType datastoreType) {
628 List<MacAddress> lstMacs = Collections.emptyList();
629 Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
630 if (hwvtepNode != null) {
631 List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class)
632 .getRemoteUcastMacs();
633 if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
634 // Filtering remoteUcastMacs based on the logical switch and
635 // forming a list of MacAddress
636 lstMacs = remoteUcastMacs.stream()
637 .filter(mac -> logicalSwitch.equals(mac.getLogicalSwitchRef().getValue()
638 .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue()))
639 .map(mac -> mac.getMacEntryKey()).collect(Collectors.toList());
646 * Install ELAN macs in L2 Gateway device.<br>
647 * This includes installing ELAN mac table entries plus external device
648 * UcastLocalMacs which are part of the same ELAN.
652 * @param l2GatewayDevice
653 * the l2 gateway device which has to be configured
654 * @return the listenable future
656 public ListenableFuture<Void> installElanMacsInL2GatewayDevice(String elanName,
657 L2GatewayDevice l2GatewayDevice) {
658 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
659 NodeId hwVtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
661 List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName, l2GatewayDevice, hwVtepNodeId,
663 List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName, l2GatewayDevice,
664 hwVtepNodeId, logicalSwitchName);
666 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
667 lstRemoteUcastMacs.addAll(lstElanMacTableEntries);
669 ListenableFuture<Void> future = HwvtepUtils.addRemoteUcastMacs(broker, hwVtepNodeId, lstRemoteUcastMacs);
671 LOG.info("Added RemoteUcastMacs entries [{}] in config DS. NodeID: {}, LogicalSwitch: {}",
672 lstRemoteUcastMacs.size(), hwVtepNodeId.getValue(), logicalSwitchName);
677 * Gets the l2 gateway devices ucast local macs as remote ucast macs.
681 * @param l2GatewayDeviceToBeConfigured
682 * the l2 gateway device to be configured
683 * @param hwVtepNodeId
684 * the hw vtep node Id to be configured
685 * @param logicalSwitchName
686 * the logical switch name
687 * @return the l2 gateway devices macs as remote ucast macs
689 public static List<RemoteUcastMacs> getOtherDevicesMacs(String elanName,
690 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
691 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
692 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
693 .getInvolvedL2GwDevices(elanName);
695 if (elanL2GwDevicesFromCache != null) {
696 for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
697 if (l2GatewayDeviceToBeConfigured.getHwvtepNodeId().equals(otherDevice.getHwvtepNodeId())) {
700 if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
701 List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
702 if (lstUcastLocalMacs != null) {
703 for (LocalUcastMacs localUcastMac : lstUcastLocalMacs) {
704 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
705 .createHwvtepPhysicalLocatorAugmentation(
706 String.valueOf(otherDevice.getTunnelIp().getValue()));
707 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
708 localUcastMac.getMacEntryKey().getValue(), localUcastMac.getIpaddr(),
709 logicalSwitchName, physLocatorAug);
710 lstRemoteUcastMacs.add(remoteUcastMac);
716 return lstRemoteUcastMacs;
722 * @param l2GatewayDevice
723 * the l2 gateway device
724 * @param otherL2GatewayDevice
725 * the other l2 gateway device
726 * @return true, if both the specified l2 gateway devices are part of same
729 public static boolean areMLAGDevices(L2GatewayDevice l2GatewayDevice, L2GatewayDevice otherL2GatewayDevice) {
730 // If tunnel IPs are same, then it is considered to be part of same MLAG
731 return Objects.equals(l2GatewayDevice.getTunnelIp(), otherL2GatewayDevice.getTunnelIp());
735 * Gets the elan mac table entries as remote ucast macs. <br>
736 * Note: ELAN MAC table only contains internal switches MAC's. It doesn't
737 * contain external device MAC's.
741 * @param l2GatewayDeviceToBeConfigured
742 * the l2 gateway device to be configured
743 * @param hwVtepNodeId
744 * the hw vtep node id
745 * @param logicalSwitchName
746 * the logical switch name
747 * @return the elan mac table entries as remote ucast macs
749 public List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
750 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
751 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
753 MacTable macTable = elanUtils.getElanMacTable(elanName);
754 if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
755 LOG.trace("MacTable is empty for elan: {}", elanName);
756 return lstRemoteUcastMacs;
759 for (MacEntry macEntry : macTable.getMacEntry()) {
760 BigInteger dpnId = elanUtils.getDpidFromInterface(macEntry.getInterface());
762 LOG.error("DPN ID not found for interface {}", macEntry.getInterface());
766 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, hwVtepNodeId);
767 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpnId, hwVtepNodeId.getValue());
768 if (dpnTepIp == null) {
769 LOG.error("TEP IP not found for dpnId {} and nodeId {}", dpnId, hwVtepNodeId.getValue());
772 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
773 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
774 // TODO: Query ARP cache to get IP address corresponding to the
776 IpAddress ipAddress = null;
777 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
778 macEntry.getMacAddress().getValue(), ipAddress, logicalSwitchName, physLocatorAug);
779 lstRemoteUcastMacs.add(remoteUcastMac);
781 return lstRemoteUcastMacs;
785 * Gets the external tunnel interface name.
791 * @return the external tunnel interface name
793 public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
794 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
795 String tunnelInterfaceName = null;
797 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
798 .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
799 .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
801 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
802 if (rpcResult.isSuccessful()) {
803 tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
804 LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
805 sourceNode, dstNode);
807 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}", rpcResult.getErrors());
809 } catch (NullPointerException | InterruptedException | ExecutionException e) {
810 LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}: {} ",
811 sourceNode, dstNode, e);
813 return tunnelInterfaceName;
817 * Gets the source dpn tep ip.
821 * @param dstHwVtepNodeId
822 * the dst hw vtep node id
823 * @return the dpn tep ip
825 public IpAddress getSourceDpnTepIp(BigInteger srcDpnId, NodeId dstHwVtepNodeId) {
826 IpAddress dpnTepIp = null;
827 String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(srcDpnId),
828 dstHwVtepNodeId.getValue());
829 if (tunnelInterfaceName != null) {
830 Interface tunnelInterface = getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
831 if (tunnelInterface != null) {
832 dpnTepIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
834 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
837 LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
844 * Update vlan bindings in l2 gateway device.
848 * @param logicalSwitchName
849 * the logical switch name
850 * @param hwVtepDevice
851 * the hardware device
852 * @param defaultVlanId
853 * the default vlan id
854 * @return the listenable future
856 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String logicalSwitchName,
857 Devices hwVtepDevice, Integer defaultVlanId) {
858 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
859 String errMsg = "HwVtepDevice is null or interfaces are empty.";
861 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
864 WriteTransaction transaction = broker.newWriteOnlyTransaction();
865 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
866 .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
868 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId,
869 hwVtepDevice.getDeviceName());
870 TerminationPoint portTerminationPoint = HwvtepUtils.getPhysicalPortTerminationPoint(broker,
871 LogicalDatastoreType.OPERATIONAL, physicalSwitchNodeId, deviceInterface.getInterfaceName());
872 if (portTerminationPoint == null) {
873 // port is not present in Hwvtep; don't configure VLAN bindings
877 List<VlanBindings> vlanBindings = new ArrayList<>();
878 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
879 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
880 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
883 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
884 // ID not specified at interface level.
885 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
887 HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
888 deviceInterface.getInterfaceName(), vlanBindings);
890 ListenableFuture<Void> future = transaction.submit();
891 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
897 * Update vlan bindings in l2 gateway device.
902 * the physical switch name
903 * @param interfaceName
904 * the interface in physical switch
905 * @param vlanBindings
906 * the vlan bindings to be configured
907 * @return the listenable future
909 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String psName,
910 String interfaceName, List<VlanBindings> vlanBindings) {
911 WriteTransaction transaction = broker.newWriteOnlyTransaction();
912 HwvtepUtils.mergeVlanBindings(transaction, nodeId, psName, interfaceName, vlanBindings);
913 ListenableFuture<Void> future = transaction.submit();
914 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
919 * Delete vlan bindings from l2 gateway device.
923 * @param hwVtepDevice
925 * @param defaultVlanId
926 * the default vlan id
927 * @return the listenable future
929 public ListenableFuture<Void> deleteVlanBindingsFromL2GatewayDevice(NodeId nodeId, Devices hwVtepDevice,
930 Integer defaultVlanId) {
931 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
932 String errMsg = "HwVtepDevice is null or interfaces are empty.";
934 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
936 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
938 WriteTransaction transaction = broker.newWriteOnlyTransaction();
939 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
940 .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
941 String phyPortName = deviceInterface.getInterfaceName();
942 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
943 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
944 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
947 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
948 // ID not specified at interface level.
949 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
952 ListenableFuture<Void> future = transaction.submit();
954 LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
955 nodeId.getValue(), hwVtepDevice, defaultVlanId);
960 * Gets the elan name from logical switch name.
962 * @param logicalSwitchName
963 * the logical switch name
964 * @return the elan name from logical switch name
966 public static String getElanFromLogicalSwitch(String logicalSwitchName) {
967 // Assuming elan name is same as logical switch name
968 String elanName = logicalSwitchName;
973 * Gets the logical switch name from elan name.
977 * @return the logical switch from elan name
979 public static String getLogicalSwitchFromElan(String elanName) {
980 // Assuming logical switch name is same as elan name
981 String logicalSwitchName = elanName;
982 return logicalSwitchName;
986 * Gets the l2 gateway connection job key.
990 * @param logicalSwitchName
991 * the logical switch name
992 * @return the l2 gateway connection job key
994 public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
995 return logicalSwitchName;
998 public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
999 InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
1000 .builder(Interfaces.class).child(Interface.class, interfaceKey);
1001 return interfaceInstanceIdentifierBuilder.build();
1004 public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
1005 InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
1006 Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId,
1008 if (!interfaceOptional.isPresent()) {
1012 return interfaceOptional.get();
1016 * Delete l2 gateway device ucast local macs from elan.<br>
1017 * Deletes macs from internal ELAN nodes and also on rest of external l2
1018 * gateway devices which are part of the ELAN.
1020 * @param l2GatewayDevice
1021 * the l2 gateway device whose ucast local macs to be deleted
1025 * @return the listenable future
1027 public List<ListenableFuture<Void>> deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
1029 LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(),
1032 List<ListenableFuture<Void>> futures = new ArrayList<>();
1033 ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
1035 LOG.error("Could not find Elan by name: {}", elanName);
1039 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GatewayDevice);
1040 unInstallL2GwUcastMacFromElan(elan, l2GatewayDevice, localMacs);
1044 public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
1045 IpAddress tunnelIp) {
1046 AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
1047 builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
1048 builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
1049 builder.setIpAddress(tunnelIp);
1051 Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
1052 RpcResult<Void> rpcResult = result.get();
1053 if (rpcResult.isSuccessful()) {
1054 LOG.info("Created ITM tunnels for {}", hwvtepId);
1056 LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
1058 } catch (InterruptedException | ExecutionException e) {
1059 LOG.error("RPC to create ITM tunnels failed", e);
1063 public static String getNodeIdFromDpnId(BigInteger dpnId) {
1064 return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
1067 public void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
1068 List<PhysAddress> staticMacAddresses) {
1069 ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
1070 for (final L2GatewayDevice externalDevice : elanDevices.values()) {
1071 scheduleAddDpnMacsInExtDevice(elanName, dpId, staticMacAddresses, externalDevice);
1075 public void scheduleAddDpnMacsInExtDevice(final String elanName, BigInteger dpId,
1076 final List<PhysAddress> staticMacAddresses, final L2GatewayDevice externalDevice) {
1077 NodeId nodeId = new NodeId(externalDevice.getHwvtepNodeId());
1078 final IpAddress dpnTepIp = getSourceDpnTepIp(dpId, nodeId);
1079 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpId, nodeId);
1080 if (dpnTepIp == null) {
1081 LOG.error("could not install dpn mac in l2gw TEP IP not found for dpnId {} and nodeId {}", dpId, nodeId);
1084 TerminationPointKey tpKey = HwvtepSouthboundUtils.getTerminationPointKey(dpnTepIp.getIpv4Address().getValue());
1085 InstanceIdentifier<TerminationPoint> tpPath = HwvtepSouthboundUtils.createTerminationPointId(nodeId, tpKey);
1087 HwvtepTerminationPointListener.runJobAfterPhysicalLocatorIsAvialable(tpPath, () -> HwvtepUtils
1088 .installUcastMacs(broker, externalDevice.getHwvtepNodeId(), staticMacAddresses, elanName, dpnTepIp));
1091 public void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1092 TimerTask logicalSwitchDeleteTask = new TimerTask() {
1095 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId,
1097 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
1099 DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker, hwvtepNodeId, lsName);
1100 dataStoreJobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
1101 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1104 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1105 logicalSwitchDeletedTasks.put(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
1106 LogicalSwitchDeleteJobTimer.schedule(logicalSwitchDeleteTask, LOGICAL_SWITCH_DELETE_DELAY);
1109 public void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1110 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1111 TimerTask logicalSwitchDeleteTask = logicalSwitchDeletedTasks.get(nodeIdLogicalSwitchNamePair);
1112 if (logicalSwitchDeleteTask != null) {
1113 LOG.debug("Delete logical switch {} action on node {} cancelled", lsName, hwvtepNodeId);
1114 logicalSwitchDeleteTask.cancel();
1115 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);