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 com.google.common.util.concurrent.MoreExecutors;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Locale;
23 import java.util.Objects;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentMap;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Future;
29 import java.util.concurrent.ScheduledFuture;
30 import java.util.concurrent.TimeUnit;
31 import java.util.function.Function;
32 import java.util.stream.Collectors;
33 import javax.annotation.Nonnull;
34 import javax.annotation.PreDestroy;
35 import javax.inject.Inject;
36 import javax.inject.Singleton;
38 import org.apache.commons.lang3.tuple.ImmutablePair;
39 import org.apache.commons.lang3.tuple.Pair;
40 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
41 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
44 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
45 import org.opendaylight.genius.mdsalutil.MDSALUtil;
46 import org.opendaylight.genius.utils.SystemPropertyReader;
47 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
48 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
49 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
50 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
51 import org.opendaylight.netvirt.elan.ElanException;
52 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
53 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
54 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
55 import org.opendaylight.netvirt.elan.utils.ElanConstants;
56 import org.opendaylight.netvirt.elan.utils.ElanDmacUtils;
57 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
58 import org.opendaylight.netvirt.elan.utils.ElanUtils;
59 import org.opendaylight.netvirt.elan.utils.Scheduler;
60 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
61 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepMacTableGenericAttributes;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
95 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
96 import org.opendaylight.yangtools.yang.common.RpcResult;
97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
101 * It gathers a set of utility methods that handle ELAN configuration in
102 * external Devices (where external means "not-CSS". As of now: TORs).
104 * <p>It makes use of HwvtepUtils class located under ovsdb/hwvtepsouthbound
105 * project for low-level mdsal operations
110 public class ElanL2GatewayUtils {
111 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayUtils.class);
112 private static final int DEFAULT_LOGICAL_SWITCH_DELETE_DELAY_SECS = 20;
114 private final DataBroker broker;
115 private final ElanDmacUtils elanDmacUtils;
116 private final ElanItmUtils elanItmUtils;
117 private final ElanClusterUtils elanClusterUtils;
118 private final OdlInterfaceRpcService interfaceManagerRpcService;
119 private final JobCoordinator jobCoordinator;
120 private final ElanUtils elanUtils;
122 private final ConcurrentMap<Pair<NodeId, String>, ScheduledFuture> logicalSwitchDeletedTasks
123 = new ConcurrentHashMap<>();
124 private final ConcurrentMap<Pair<NodeId, String>, DeleteLogicalSwitchJob> deleteJobs = new ConcurrentHashMap<>();
125 private final Scheduler scheduler;
126 private final ElanConfig elanConfig;
129 public ElanL2GatewayUtils(DataBroker broker, ElanDmacUtils elanDmacUtils, ElanItmUtils elanItmUtils,
130 ElanClusterUtils elanClusterUtils, OdlInterfaceRpcService interfaceManagerRpcService,
131 JobCoordinator jobCoordinator, ElanUtils elanUtils,
132 Scheduler scheduler, ElanConfig elanConfig) {
133 this.broker = broker;
134 this.elanDmacUtils = elanDmacUtils;
135 this.elanItmUtils = elanItmUtils;
136 this.elanClusterUtils = elanClusterUtils;
137 this.interfaceManagerRpcService = interfaceManagerRpcService;
138 this.jobCoordinator = jobCoordinator;
139 this.elanUtils = elanUtils;
140 this.scheduler = scheduler;
141 this.elanConfig = elanConfig;
145 public void close() {
148 public long getLogicalSwitchDeleteDelaySecs() {
149 return elanConfig.getL2gwLogicalSwitchDelaySecs() != null
150 ? elanConfig.getL2gwLogicalSwitchDelaySecs() : DEFAULT_LOGICAL_SWITCH_DELETE_DELAY_SECS;
154 * gets the macs addresses for elan interfaces.
156 * @param lstElanInterfaceNames
157 * the lst elan interface names
160 public List<PhysAddress> getElanDpnMacsFromInterfaces(Set<String> lstElanInterfaceNames) {
161 List<PhysAddress> result = new ArrayList<>();
162 for (String interfaceName : lstElanInterfaceNames) {
163 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(broker, interfaceName);
164 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
165 for (MacEntry macEntry : elanInterfaceMac.getMacEntry()) {
166 result.add(macEntry.getMacAddress());
174 * Check if phy locator already exists in remote mcast entry.
178 * @param remoteMcastMac
179 * the remote mcast mac
180 * @param expectedPhyLocatorIp
181 * the expected phy locator ip
182 * @return true, if successful
184 public static boolean checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(NodeId nodeId,
185 RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
186 if (remoteMcastMac != null) {
187 HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
188 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
189 HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
190 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
191 if (remoteMcastMac.getLocatorSet() != null) {
192 for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
193 if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
194 LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
204 * Gets the remote mcast mac.
208 * @param logicalSwitchName
209 * the logical switch name
210 * @param datastoreType
212 * @return the remote mcast mac
214 public RemoteMcastMacs readRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
215 LogicalDatastoreType datastoreType) {
216 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
217 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
218 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
219 new MacAddress(ElanConstants.UNKNOWN_DMAC));
220 RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
222 return remoteMcastMac;
226 * Removes the given MAC Addresses from all the External Devices belonging
227 * to the specified ELAN.
229 * @param elanInstance
231 * @param macAddresses
234 public void removeMacsFromElanExternalDevices(ElanInstance elanInstance, List<PhysAddress> macAddresses) {
235 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
236 .getInvolvedL2GwDevices(elanInstance.getElanInstanceName());
237 for (L2GatewayDevice l2GatewayDevice : elanL2GwDevices.values()) {
238 removeRemoteUcastMacsFromExternalDevice(l2GatewayDevice.getHwvtepNodeId(),
239 elanInstance.getElanInstanceName(), macAddresses);
244 * Removes the given MAC Addresses from the specified External Device.
246 * @param deviceNodeId
248 * @param macAddresses
250 * @return the listenable future
252 private ListenableFuture<Void> removeRemoteUcastMacsFromExternalDevice(String deviceNodeId,
253 String logicalSwitchName, List<PhysAddress> macAddresses) {
254 NodeId nodeId = new NodeId(deviceNodeId);
257 List<MacAddress> lstMac = macAddresses.stream().filter(Objects::nonNull).map(
258 physAddress -> new MacAddress(physAddress.getValue())).collect(Collectors.toList());
259 return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
262 public ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
263 Optional<LogicalSwitches> lsOpc = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
264 (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
265 if (lsOpc.isPresent()) {
266 LogicalSwitches ls = lsOpc.get();
268 // Logical switch name is Elan name
269 String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
270 return ElanUtils.getElanInstanceByName(broker, elanName);
272 String macAddress = localUcastMac.getMacEntryKey().getValue();
273 LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
280 * Install external device local macs in dpn.
284 * @param l2gwDeviceNodeId
285 * the l2gw device node id
288 * @param interfaceName
290 * @throws ElanException in case of issues creating the flow objects
292 public void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan,
293 String interfaceName) throws ElanException {
294 L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
295 l2gwDeviceNodeId.getValue());
296 if (l2gwDevice == null) {
297 LOG.debug("L2 gw device not found in elan cache for device name {}", l2gwDeviceNodeId.getValue());
301 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
305 * Install dmac flows on dpn.
313 * @param interfaceName
315 * @throws ElanException in case of issues creating the flow objects
317 public void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan,
318 String interfaceName) throws ElanException {
319 String elanName = elan.getElanInstanceName();
321 Collection<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
322 if (!l2gwDeviceLocalMacs.isEmpty()) {
323 for (LocalUcastMacs localUcastMac : l2gwDeviceLocalMacs) {
324 elanDmacUtils.installDmacFlowsToExternalRemoteMacInBatch(dpnId, l2gwDevice.getHwvtepNodeId(),
325 elan.getElanTag(), ElanUtils.getVxlanSegmentationId(elan),
326 localUcastMac.getMacEntryKey().getValue(), elanName, interfaceName);
328 LOG.debug("Installing L2gw device [{}] local macs [size: {}] in dpn [{}] for elan [{}]",
329 l2gwDevice.getHwvtepNodeId(), l2gwDeviceLocalMacs.size(), dpnId, elanName);
334 * Install elan l2gw devices local macs in dpn.
340 * @param interfaceName
342 * @throws ElanException in case of issues creating the flow objects
344 public void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan, String interfaceName)
345 throws ElanException {
346 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
347 .getInvolvedL2GwDevices(elan.getElanInstanceName());
348 if (elanL2GwDevicesFromCache != null) {
349 for (L2GatewayDevice l2gwDevice : elanL2GwDevicesFromCache.values()) {
350 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
353 LOG.debug("No Elan l2 gateway devices in cache for [{}] ", elan.getElanInstanceName());
357 public void installL2GwUcastMacInElan(final ElanInstance elan, final L2GatewayDevice extL2GwDevice,
358 final String macToBeAdded, final LocalUcastMacs localUcastMacs, String interfaceName) {
359 final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
360 final String elanInstanceName = elan.getElanInstanceName();
361 final List<DpnInterfaces> elanDpns = getElanDpns(elanInstanceName);
362 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
363 .getInvolvedL2GwDevices(elanInstanceName);
365 // Retrieve all participating DPNs in this Elan. Populate this MAC in
367 // Looping through all DPNs in order to add/remove mac flows in their
369 if (elanDpns.size() > 0 || elanL2GwDevices.values().size() > 0) {
370 String jobKey = elanInstanceName + ":" + macToBeAdded;
371 IpAddress extL2GwDeviceTepIp = extL2GwDevice.getTunnelIp();
372 List<PhysAddress> macList = Lists.newArrayList(new PhysAddress(macToBeAdded));
374 elanClusterUtils.runOnlyInOwnerNode(jobKey, "install l2gw macs in dmac table", () -> {
375 if (doesLocalUcastMacExistsInCache(extL2GwDevice, localUcastMacs)) {
376 List<ListenableFuture<Void>> futures = new ArrayList<>();
377 for (DpnInterfaces elanDpn : elanDpns) {
378 futures.addAll(elanDmacUtils.installDmacFlowsToExternalRemoteMacInBatch(elanDpn.getDpId(),
379 extDeviceNodeId, elan.getElanTag(), ElanUtils.getVxlanSegmentationId(elan),
380 macToBeAdded, elanInstanceName, interfaceName));
382 for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
383 if (!otherDevice.getHwvtepNodeId().equals(extDeviceNodeId)
384 && !areMLAGDevices(extL2GwDevice, otherDevice)) {
385 final String hwvtepId = otherDevice.getHwvtepNodeId();
386 final String logicalSwitchName = elanInstanceName;
387 futures.add(HwvtepUtils.installUcastMacs(
388 broker, hwvtepId, macList, logicalSwitchName, extL2GwDeviceTepIp));
393 LOG.trace("Skipping install of dmac flows for mac {} as it is not found in cache",
396 return Collections.emptyList();
402 * Does local ucast mac exists in cache.
404 * @param elanL2GwDevice
405 * the elan L2 Gw device
407 * the mac address to be verified
408 * @return true, if successful
410 private static boolean doesLocalUcastMacExistsInCache(L2GatewayDevice elanL2GwDevice, LocalUcastMacs macAddress) {
411 return elanL2GwDevice.containsUcastMac(macAddress);
415 * Uninstall l2gw macs from other l2gw devices in the elanName provided.
416 * @param elanName - Elan Name for which other l2gw devices will be scanned.
417 * @param l2GwDevice - l2gwDevice whose macs are required to be cleared from other devices.
418 * @param macAddresses - Mac address to be cleared.
420 public void unInstallL2GwUcastMacFromL2gwDevices(final String elanName,
421 final L2GatewayDevice l2GwDevice,
422 final Collection<MacAddress> macAddresses) {
423 if (macAddresses == null || macAddresses.isEmpty()) {
427 if (elanName == null) {
431 DeleteL2GwDeviceMacsFromElanJob job = new DeleteL2GwDeviceMacsFromElanJob(elanName, l2GwDevice,
433 elanClusterUtils.runOnlyInOwnerNode(job.getJobKey(), "delete remote ucast macs in l2gw devices", job);
437 * Uninstall l2gw macs from other DPNs in the elan instance provided.
438 * @param elan - Elan Instance for which other DPNs will be scanned.
439 * @param l2GwDevice - l2gwDevice whose macs are required to be cleared from other devices.
440 * @param macAddresses - Mac address to be cleared.
442 public void unInstallL2GwUcastMacFromElanDpns(final ElanInstance elan, final L2GatewayDevice l2GwDevice,
443 final Collection<MacAddress> macAddresses) {
444 if (macAddresses == null || macAddresses.isEmpty()) {
447 if (elan == null || elan.getElanInstanceName() == null) {
448 LOG.error("Could not delete l2gw ucast macs, Failed to find the elan for device {}",
449 l2GwDevice.getHwvtepNodeId());
453 final List<DpnInterfaces> elanDpns = getElanDpns(elan.getElanInstanceName());
455 // Retrieve all participating DPNs in this Elan. Populate this MAC in
456 // DMAC table. Looping through all DPNs in order to add/remove mac flows
457 // in their DMAC table
458 List<ListenableFuture<Void>> result = new ArrayList<>();
459 for (final MacAddress mac : macAddresses) {
460 elanClusterUtils.runOnlyInOwnerNode(elan.getElanInstanceName() + ":" + mac.getValue(),
461 "delete remote ucast macs in elan DPNs", () -> {
462 for (DpnInterfaces elanDpn : elanDpns) {
463 BigInteger dpnId = elanDpn.getDpId();
464 result.addAll(elanDmacUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
465 l2GwDevice.getHwvtepNodeId(), mac.getValue().toLowerCase(Locale.getDefault())));
473 * Delete elan l2 gateway devices ucast local macs from dpn.
479 * @throws ReadFailedException if a read fails throws ReadFailedException
481 public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId)
482 throws ReadFailedException {
483 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
484 if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
485 LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
488 final ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
490 LOG.error("Could not find Elan by name: {}", elanName);
493 LOG.info("Deleting Elan [{}] L2GatewayDevices UcastLocalMacs from Dpn [{}]", elanName, dpnId);
495 final Long elanTag = elan.getElanTag();
496 for (final L2GatewayDevice l2GwDevice : elanL2GwDevices.values()) {
497 getL2GwDeviceLocalMacsAndRunCallback(elan.getElanInstanceName(), l2GwDevice, (localMacs) -> {
498 for (MacAddress mac : localMacs) {
499 String jobKey = elanName + ":" + mac.getValue();
500 elanClusterUtils.runOnlyInOwnerNode(jobKey,
501 () -> elanDmacUtils.deleteDmacFlowsToExternalMac(elanTag, dpnId,
502 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
509 public void getL2GwDeviceLocalMacsAndRunCallback(String elanName, L2GatewayDevice l2gwDevice,
510 Function<Collection<MacAddress>, Void> function) {
511 if (l2gwDevice == null) {
514 Set<MacAddress> macs = new HashSet<>();
515 Collection<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
516 if (!lstUcastLocalMacs.isEmpty()) {
517 macs.addAll(lstUcastLocalMacs.stream().filter(Objects::nonNull)
518 .map(mac -> new MacAddress(mac.getMacEntryKey().getValue().toLowerCase()))
519 .collect(Collectors.toList()));
522 InstanceIdentifier<Node> nodeIid = HwvtepSouthboundUtils.createInstanceIdentifier(
523 new NodeId(l2gwDevice.getHwvtepNodeId()));
524 Futures.addCallback(broker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, nodeIid),
525 new FutureCallback<Optional<Node>>() {
527 public void onSuccess(Optional<Node> configNode) {
528 if (configNode != null && configNode.isPresent()) {
529 HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(
530 HwvtepGlobalAugmentation.class);
531 if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
532 macs.addAll(augmentation.getLocalUcastMacs().stream()
533 .filter(mac -> getLogicalSwitchName(mac).equals(elanName))
534 .map(mac -> mac.getMacEntryKey())
535 .collect(Collectors.toSet()));
537 function.apply(macs);
542 public void onFailure(Throwable throwable) {
543 LOG.error("Failed to read config topology node ", nodeIid);
545 }, MoreExecutors.directExecutor());
548 private String getLogicalSwitchName(LocalUcastMacs mac) {
549 return ((InstanceIdentifier<LogicalSwitches>)mac.getLogicalSwitchRef().getValue())
550 .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
554 * Delete elan macs from L2 gateway device.<br>
555 * This includes deleting ELAN mac table entries plus external device
556 * UcastLocalMacs which are part of the same ELAN.
558 * @param hwvtepNodeId
562 * @return the listenable future
564 public ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(String hwvtepNodeId, String elanName) {
565 String logicalSwitch = getLogicalSwitchFromElan(elanName);
567 List<MacAddress> lstElanMacs = getRemoteUcastMacs(new NodeId(hwvtepNodeId), logicalSwitch,
568 LogicalDatastoreType.CONFIGURATION);
569 ListenableFuture<Void> future = HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(hwvtepNodeId),
570 logicalSwitch, lstElanMacs);
572 Futures.addCallback(future, new FutureCallback<Void>() {
574 public void onSuccess(Void noarg) {
575 LOG.trace("Successful in batch deletion of elan [{}] macs from l2gw device [{}]", elanName,
580 public void onFailure(Throwable error) {
581 LOG.warn(String.format("Failed during batch delete of elan [%s] macs from l2gw device [%s]. "
582 + "Retrying with sequential deletes.", elanName, hwvtepNodeId), error);
583 if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
584 for (MacAddress mac : lstElanMacs) {
585 HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
589 }, MoreExecutors.directExecutor());
591 if (LOG.isDebugEnabled()) {
592 List<String> elanMacs = lstElanMacs.stream().map(MacAddress::getValue).collect(Collectors.toList());
593 LOG.debug("Deleting elan [{}] macs from node [{}]. Deleted macs = {}", elanName, hwvtepNodeId, elanMacs);
599 * Gets the remote ucast macs from hwvtep node filtering based on logical
602 * @param hwvtepNodeId
604 * @param logicalSwitch
606 * @param datastoreType
608 * @return the remote ucast macs
610 public List<MacAddress> getRemoteUcastMacs(NodeId hwvtepNodeId, String logicalSwitch,
611 LogicalDatastoreType datastoreType) {
612 List<MacAddress> lstMacs = Collections.emptyList();
613 Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
614 if (hwvtepNode != null) {
615 List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class)
616 .getRemoteUcastMacs();
617 if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
618 // Filtering remoteUcastMacs based on the logical switch and
619 // forming a list of MacAddress
620 lstMacs = remoteUcastMacs.stream()
621 .filter(mac -> logicalSwitch.equals(mac.getLogicalSwitchRef().getValue()
622 .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue()))
623 .map(HwvtepMacTableGenericAttributes::getMacEntryKey).collect(Collectors.toList());
630 * Install ELAN macs in L2 Gateway device.<br>
631 * This includes installing ELAN mac table entries plus external device
632 * UcastLocalMacs which are part of the same ELAN.
636 * @param l2GatewayDevice
637 * the l2 gateway device which has to be configured
638 * @return the listenable future
640 public ListenableFuture<Void> installElanMacsInL2GatewayDevice(String elanName,
641 L2GatewayDevice l2GatewayDevice) {
642 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
643 NodeId hwVtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
645 List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName, l2GatewayDevice, hwVtepNodeId,
647 List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName, l2GatewayDevice,
648 hwVtepNodeId, logicalSwitchName);
650 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
651 lstRemoteUcastMacs.addAll(lstElanMacTableEntries);
653 ListenableFuture<Void> future = HwvtepUtils.addRemoteUcastMacs(broker, hwVtepNodeId, lstRemoteUcastMacs);
655 LOG.info("Added RemoteUcastMacs entries [{}] in config DS. NodeID: {}, LogicalSwitch: {}",
656 lstRemoteUcastMacs.size(), hwVtepNodeId.getValue(), logicalSwitchName);
661 * Gets the l2 gateway devices ucast local macs as remote ucast macs.
665 * @param l2GatewayDeviceToBeConfigured
666 * the l2 gateway device to be configured
667 * @param hwVtepNodeId
668 * the hw vtep node Id to be configured
669 * @param logicalSwitchName
670 * the logical switch name
671 * @return the l2 gateway devices macs as remote ucast macs
673 public static List<RemoteUcastMacs> getOtherDevicesMacs(String elanName,
674 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
675 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
676 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
677 .getInvolvedL2GwDevices(elanName);
679 if (elanL2GwDevicesFromCache != null) {
680 for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
681 if (l2GatewayDeviceToBeConfigured.getHwvtepNodeId().equals(otherDevice.getHwvtepNodeId())) {
684 if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
685 for (LocalUcastMacs localUcastMac : otherDevice.getUcastLocalMacs()) {
686 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
687 .createHwvtepPhysicalLocatorAugmentation(
688 String.valueOf(otherDevice.getTunnelIp().getValue()));
689 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
690 localUcastMac.getMacEntryKey().getValue().toLowerCase(Locale.getDefault()),
691 localUcastMac.getIpaddr(), logicalSwitchName, physLocatorAug);
692 lstRemoteUcastMacs.add(remoteUcastMac);
697 return lstRemoteUcastMacs;
703 * @param l2GatewayDevice
704 * the l2 gateway device
705 * @param otherL2GatewayDevice
706 * the other l2 gateway device
707 * @return true, if both the specified l2 gateway devices are part of same
710 public static boolean areMLAGDevices(L2GatewayDevice l2GatewayDevice, L2GatewayDevice otherL2GatewayDevice) {
711 // If tunnel IPs are same, then it is considered to be part of same MLAG
712 return Objects.equals(l2GatewayDevice.getTunnelIp(), otherL2GatewayDevice.getTunnelIp());
716 * Gets the elan mac table entries as remote ucast macs. <br>
717 * Note: ELAN MAC table only contains internal switches MAC's. It doesn't
718 * contain external device MAC's.
722 * @param l2GatewayDeviceToBeConfigured
723 * the l2 gateway device to be configured
724 * @param hwVtepNodeId
725 * the hw vtep node id
726 * @param logicalSwitchName
727 * the logical switch name
728 * @return the elan mac table entries as remote ucast macs
730 public List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
731 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
732 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
734 MacTable macTable = ElanUtils.getElanMacTable(broker, elanName);
735 if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
736 LOG.trace("MacTable is empty for elan: {}", elanName);
737 return lstRemoteUcastMacs;
740 for (MacEntry macEntry : macTable.getMacEntry()) {
741 BigInteger dpnId = getDpidFromInterface(macEntry.getInterface());
743 LOG.error("DPN ID not found for interface {}", macEntry.getInterface());
747 IpAddress dpnTepIp = elanItmUtils.getSourceDpnTepIp(dpnId, hwVtepNodeId);
748 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpnId, hwVtepNodeId.getValue());
749 if (dpnTepIp == null) {
750 LOG.error("TEP IP not found for dpnId {} and nodeId {}", dpnId, hwVtepNodeId.getValue());
753 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
754 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
755 // TODO: Query ARP cache to get IP address corresponding to the
757 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
758 macEntry.getMacAddress().getValue().toLowerCase(Locale.getDefault()), null /*IpAddress*/,
759 logicalSwitchName, physLocatorAug);
760 lstRemoteUcastMacs.add(remoteUcastMac);
762 return lstRemoteUcastMacs;
766 * Gets the dpid from interface.
768 * @param interfaceName
770 * @return the dpid from interface
772 public BigInteger getDpidFromInterface(String interfaceName) {
773 BigInteger dpId = null;
774 Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService
775 .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
777 RpcResult<GetDpidFromInterfaceOutput> rpcResult = output.get();
778 if (rpcResult != null && rpcResult.isSuccessful()) {
779 dpId = rpcResult.getResult().getDpid();
781 } catch (InterruptedException | ExecutionException e) {
782 LOG.error("Failed to get the DPN ID for interface {}: {} ", interfaceName, e);
788 * Update vlan bindings in l2 gateway device.
792 * @param logicalSwitchName
793 * the logical switch name
794 * @param hwVtepDevice
795 * the hardware device
796 * @param defaultVlanId
797 * the default vlan id
798 * @return the listenable future
800 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String logicalSwitchName,
801 Devices hwVtepDevice, Integer defaultVlanId) {
802 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
803 String errMsg = "HwVtepDevice is null or interfaces are empty.";
805 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
808 WriteTransaction transaction = broker.newWriteOnlyTransaction();
809 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
810 .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
811 //Removed the check for checking terminationPoint present in OP or not
812 //for coniguring vlan bindings
813 //As we are not any more dependent on it , plugin takes care of this
814 // with port reconcilation.
815 List<VlanBindings> vlanBindings = new ArrayList<>();
816 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
817 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
818 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
821 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
822 // ID not specified at interface level.
823 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
825 HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
826 deviceInterface.getInterfaceName(), vlanBindings);
828 ListenableFuture<Void> future = transaction.submit();
829 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
835 * Update vlan bindings in l2 gateway device.
840 * the physical switch name
841 * @param interfaceName
842 * the interface in physical switch
843 * @param vlanBindings
844 * the vlan bindings to be configured
845 * @return the listenable future
847 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String psName,
848 String interfaceName, List<VlanBindings> vlanBindings) {
849 WriteTransaction transaction = broker.newWriteOnlyTransaction();
850 HwvtepUtils.mergeVlanBindings(transaction, nodeId, psName, interfaceName, vlanBindings);
851 ListenableFuture<Void> future = transaction.submit();
852 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
857 * Delete vlan bindings from l2 gateway device.
861 * @param hwVtepDevice
863 * @param defaultVlanId
864 * the default vlan id
865 * @return the listenable future
867 public ListenableFuture<Void> deleteVlanBindingsFromL2GatewayDevice(NodeId nodeId, Devices hwVtepDevice,
868 Integer defaultVlanId) {
869 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
870 String errMsg = "HwVtepDevice is null or interfaces are empty.";
872 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
874 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
876 WriteTransaction transaction = broker.newWriteOnlyTransaction();
877 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
878 .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
879 String phyPortName = deviceInterface.getInterfaceName();
880 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
881 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
882 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
885 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
886 // ID not specified at interface level.
887 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
890 ListenableFuture<Void> future = transaction.submit();
892 LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
893 nodeId.getValue(), hwVtepDevice, defaultVlanId);
898 * Gets the elan name from logical switch name.
900 * @param logicalSwitchName
901 * the logical switch name
902 * @return the elan name from logical switch name
904 public static String getElanFromLogicalSwitch(String logicalSwitchName) {
905 // Assuming elan name is same as logical switch name
906 String elanName = logicalSwitchName;
911 * Gets the logical switch name from elan name.
915 * @return the logical switch from elan name
917 public static String getLogicalSwitchFromElan(String elanName) {
918 // Assuming logical switch name is same as elan name
919 String logicalSwitchName = elanName;
920 return logicalSwitchName;
924 * Gets the l2 gateway connection job key.
928 * @param logicalSwitchName
929 * the logical switch name
930 * @return the l2 gateway connection job key
932 public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
933 return logicalSwitchName;
936 public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
937 InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
938 .builder(Interfaces.class).child(Interface.class, interfaceKey);
939 return interfaceInstanceIdentifierBuilder.build();
942 public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
943 InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
945 return SingleTransactionDataBroker
946 .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, interfaceId).orNull();
947 } catch (ReadFailedException e) {
948 // TODO remove this, and propagate ReadFailedException instead of re-throw RuntimeException
949 LOG.error("getInterfaceFromConfigDS({}) failed", interfaceKey, e);
950 throw new RuntimeException(e);
955 * Delete l2 gateway device ucast local macs from elan.<br>
956 * Deletes macs from internal ELAN nodes and also on rest of external l2
957 * gateway devices which are part of the ELAN.
959 * @param l2GatewayDevice
960 * the l2 gateway device whose ucast local macs to be deleted
964 * @throws ReadFailedException if a read fails
966 public void deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
967 String elanName) throws ReadFailedException {
968 LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(),
971 ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
973 LOG.error("Could not find Elan by name: {}", elanName);
977 Collection<MacAddress> localMacs = getL2GwDeviceLocalMacs(elanName, l2GatewayDevice);
978 unInstallL2GwUcastMacFromL2gwDevices(elanName, l2GatewayDevice, localMacs);
979 unInstallL2GwUcastMacFromElanDpns(elan, l2GatewayDevice, localMacs);
982 public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
983 IpAddress tunnelIp) {
984 AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
985 builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
986 builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
987 builder.setIpAddress(tunnelIp);
989 Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
990 RpcResult<Void> rpcResult = result.get();
991 if (rpcResult.isSuccessful()) {
992 LOG.info("Created ITM tunnels for {}", hwvtepId);
994 LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
996 } catch (InterruptedException | ExecutionException e) {
997 LOG.error("RPC to create ITM tunnels failed", e);
1001 public static String getNodeIdFromDpnId(BigInteger dpnId) {
1002 return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
1005 public void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
1006 List<PhysAddress> staticMacAddresses) {
1007 ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
1008 for (final L2GatewayDevice externalDevice : elanDevices.values()) {
1009 scheduleAddDpnMacsInExtDevice(elanName, dpId, staticMacAddresses, externalDevice);
1013 public void scheduleAddDpnMacsInExtDevice(final String elanName, BigInteger dpId,
1014 final List<PhysAddress> staticMacAddresses, final L2GatewayDevice externalDevice) {
1015 NodeId nodeId = new NodeId(externalDevice.getHwvtepNodeId());
1016 final IpAddress dpnTepIp = elanItmUtils.getSourceDpnTepIp(dpId, nodeId);
1017 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpId, nodeId);
1018 if (dpnTepIp == null) {
1019 LOG.error("could not install dpn mac in l2gw TEP IP not found for dpnId {} and nodeId {}", dpId, nodeId);
1023 //TODO: to be batched in genius
1024 HwvtepUtils.installUcastMacs(broker, externalDevice.getHwvtepNodeId(), staticMacAddresses, elanName, dpnTepIp);
1027 public void scheduleDeleteLogicalSwitch(NodeId hwvtepNodeId, String lsName) {
1028 scheduleDeleteLogicalSwitch(hwvtepNodeId, lsName, false);
1031 public void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName, final boolean clearUcast) {
1032 final Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1033 logicalSwitchDeletedTasks.computeIfAbsent(nodeIdLogicalSwitchNamePair, (key) -> {
1034 return scheduler.getScheduledExecutorService().schedule(() -> {
1035 DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker,
1036 ElanL2GatewayUtils.this, hwvtepNodeId, lsName, clearUcast);
1037 jobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
1038 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1039 deleteJobs.put(nodeIdLogicalSwitchNamePair, deleteLsJob);
1040 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
1041 }, getLogicalSwitchDeleteDelaySecs(), TimeUnit.SECONDS);
1045 public void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1046 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1047 ScheduledFuture logicalSwitchDeleteTask = logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
1048 if (logicalSwitchDeleteTask != null) {
1049 LOG.debug("Delete logical switch {} action on node {} cancelled", lsName, hwvtepNodeId);
1050 logicalSwitchDeleteTask.cancel(true);
1051 DeleteLogicalSwitchJob deleteLogicalSwitchJob = deleteJobs.remove(nodeIdLogicalSwitchNamePair);
1052 if (deleteLogicalSwitchJob != null) {
1053 deleteLogicalSwitchJob.cancel();
1059 public List<DpnInterfaces> getElanDpns(String elanName) {
1060 Set<DpnInterfaces> dpnInterfaces = ElanUtils.getElanInvolvedDPNsFromCache(elanName);
1061 if (dpnInterfaces == null) {
1062 return elanUtils.getElanDPNByName(elanName);
1064 return new ArrayList<>(dpnInterfaces);
1068 * Gets the l2 gw device local macs.
1073 * @return the l2 gw device local macs
1075 public Collection<MacAddress> getL2GwDeviceLocalMacs(String elanName, L2GatewayDevice l2gwDevice) {
1076 if (l2gwDevice == null) {
1077 return Collections.emptyList();
1079 Collection<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
1080 Set<MacAddress> macs = new HashSet<>();
1081 if (!lstUcastLocalMacs.isEmpty()) {
1082 macs.addAll(lstUcastLocalMacs.stream().filter(Objects::nonNull)
1083 .map(mac -> new MacAddress(mac.getMacEntryKey().getValue().toLowerCase()))
1084 .collect(Collectors.toList()));
1086 Optional<Node> configNode = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1087 HwvtepSouthboundUtils.createInstanceIdentifier(new NodeId(l2gwDevice.getHwvtepNodeId())));
1088 if (configNode.isPresent()) {
1089 HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(HwvtepGlobalAugmentation.class);
1090 if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
1091 macs.addAll(augmentation.getLocalUcastMacs().stream()
1092 .filter(mac -> getLogicalSwitchName(mac).equals(elanName))
1093 .map(mac -> mac.getMacEntryKey())
1094 .collect(Collectors.toSet()));