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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Objects;
16 import java.util.Timer;
17 import java.util.TimerTask;
18 import java.util.concurrent.Callable;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ConcurrentMap;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import java.util.stream.Collectors;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
28 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
29 import org.opendaylight.netvirt.elan.l2gw.listeners.HwvtepPhysicalLocatorListener;
30 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
31 import org.opendaylight.netvirt.elan.utils.ElanConstants;
32 import org.opendaylight.netvirt.elan.utils.ElanUtils;
33 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
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.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
38 import org.opendaylight.genius.utils.SystemPropertyReader;
39 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
40 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
41 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
73 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
74 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
75 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
76 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.common.RpcResult;
79 import org.apache.commons.lang3.tuple.Pair;
80 import org.apache.commons.lang3.tuple.ImmutablePair;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
84 import com.google.common.base.Function;
85 import com.google.common.base.Optional;
86 import com.google.common.collect.Lists;
87 import com.google.common.util.concurrent.FutureCallback;
88 import com.google.common.util.concurrent.Futures;
89 import com.google.common.util.concurrent.ListenableFuture;
92 * It gathers a set of utility methods that handle ELAN configuration in external Devices (where external means
93 * "not-CSS". As of now: TORs).
95 * It makes use of HwvtepUtils class located under ovsdb/hwvtepsouthbound project for low-level mdsal operations
100 public class ElanL2GatewayUtils {
101 private static DataBroker broker;
102 private static ItmRpcService itmRpcService;
103 private static DataStoreJobCoordinator dataStoreJobCoordinator;
104 private static Timer LogicalSwitchDeleteJobTimer = new Timer();
105 private static final int LOGICAL_SWITCH_DELETE_DELAY = 120000;
106 private static ConcurrentMap<Pair<NodeId, String>, TimerTask> LogicalSwitchDeletedTasks =
107 new ConcurrentHashMap<Pair<NodeId, String>, TimerTask>();
109 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayUtils.class);
112 * Sets the data broker.
115 * the new data broker
117 public static void setDataBroker(DataBroker dataBroker) {
122 * Sets the itm rpc service.
125 * the new itm rpc service
127 public static void setItmRpcService(ItmRpcService itmRpc) {
128 itmRpcService = itmRpc;
132 * Sets DataStoreJobCoordinator
134 * @param dsJobCoordinator
135 * the new dataStoreJobCoordinator
137 public static void setDataStoreJobCoordinator(DataStoreJobCoordinator dsJobCoordinator) {
138 dataStoreJobCoordinator = dsJobCoordinator;
142 * Installs dpn macs in external device.
143 * first it checks if the physical locator towards this dpn tep is present or not
144 * if the physical locator is present go ahead and add the ucast macs
145 * otherwise update the mcast mac entry to include this dpn tep ip
146 * and schedule the job to put ucast macs once the physical locator is programmed in device
149 * @param lstElanInterfaceNames
150 * the lst Elan interface names
153 * @param externalNodeId
154 * the external node id
156 public static void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames,
157 BigInteger dpnId, NodeId externalNodeId) {
158 L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName,
159 externalNodeId.getValue());
160 if (elanL2GwDevice == null) {
161 LOG.debug("L2 gw device not found in elan cache for device name {}", externalNodeId);
164 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, externalNodeId);
165 if (dpnTepIp == null) {
166 LOG.warn("Could not install dpn macs in l2gw device , dpnTepIp not found dpn : {} , nodeid : {}",
167 dpnId, externalNodeId);
171 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
172 RemoteMcastMacs remoteMcastMac = readRemoteMcastMac(externalNodeId, logicalSwitchName,
173 LogicalDatastoreType.OPERATIONAL);
174 boolean phyLocAlreadyExists = checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(externalNodeId, remoteMcastMac,
176 LOG.debug("phyLocAlreadyExists = {} for locator [{}] in remote mcast entry for elan [{}], nodeId [{}]",
177 phyLocAlreadyExists, String.valueOf(dpnTepIp.getValue()), elanName, externalNodeId.getValue());
178 List<PhysAddress> staticMacs = null;
179 staticMacs = getElanDpnMacsFromInterfaces(lstElanInterfaceNames);
181 if (phyLocAlreadyExists) {
182 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
185 ElanL2GatewayMulticastUtils.scheduleMcastMacUpdateJob(elanName, elanL2GwDevice);
186 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
190 * gets the macs addresses for elan interfaces
192 * @param lstElanInterfaceNames
193 * the lst elan interface names
196 private static List<PhysAddress> getElanDpnMacsFromInterfaces(Set<String> lstElanInterfaceNames) {
197 List<PhysAddress> result = new ArrayList<>();
198 for (String interfaceName : lstElanInterfaceNames) {
199 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
200 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
201 for (MacEntry macEntry : elanInterfaceMac.getMacEntry()) {
202 result.add(macEntry.getMacAddress());
210 * Check if phy locator already exists in remote mcast entry.
214 * @param remoteMcastMac
215 * the remote mcast mac
216 * @param expectedPhyLocatorIp
217 * the expected phy locator ip
218 * @return true, if successful
220 public static boolean checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(NodeId nodeId,
221 RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
222 if (remoteMcastMac != null) {
223 HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
224 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
225 HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
226 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
227 if (remoteMcastMac.getLocatorSet() != null) {
228 for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
229 if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
230 LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
240 * Gets the remote mcast mac.
244 * @param logicalSwitchName
245 * the logical switch name
246 * @param datastoreType
248 * @return the remote mcast mac
250 public static RemoteMcastMacs readRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
251 LogicalDatastoreType datastoreType) {
252 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
253 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
254 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
255 new MacAddress(ElanConstants.UNKNOWN_DMAC));
256 RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
258 return remoteMcastMac;
262 * Removes the given MAC Addresses from all the External Devices belonging
263 * to the specified ELAN.
265 * @param elanInstance
267 * @param macAddresses
270 public static void removeMacsFromElanExternalDevices(ElanInstance elanInstance, List<PhysAddress> macAddresses) {
271 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
272 .getInvolvedL2GwDevices(elanInstance.getElanInstanceName());
273 for (L2GatewayDevice l2GatewayDevice : elanL2GwDevices.values()) {
274 removeRemoteUcastMacsFromExternalDevice(l2GatewayDevice.getHwvtepNodeId(),
275 elanInstance.getElanInstanceName(), macAddresses);
280 * Removes the given MAC Addresses from the specified External Device.
282 * @param deviceNodeId
284 * @param logicalSwitchName
285 * @param macAddresses
287 * @return the listenable future
289 private static ListenableFuture<Void> removeRemoteUcastMacsFromExternalDevice(String deviceNodeId,
290 String logicalSwitchName, List<PhysAddress> macAddresses) {
291 NodeId nodeId = new NodeId(deviceNodeId);
294 List<MacAddress> lstMac = Lists.transform(macAddresses, new Function<PhysAddress, MacAddress>() {
296 public MacAddress apply(PhysAddress physAddress) {
297 return (physAddress != null) ? new MacAddress(physAddress.getValue()) : null;
300 return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
303 public static ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
304 Optional<LogicalSwitches> lsOpc = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
305 (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
306 if (lsOpc.isPresent()) {
307 LogicalSwitches ls = lsOpc.get();
309 // Logical switch name is Elan name
310 String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
311 return ElanUtils.getElanInstanceByName(elanName);
313 String macAddress = localUcastMac.getMacEntryKey().getValue();
314 LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
321 * Install external device local macs in dpn.
325 * @param l2gwDeviceNodeId
326 * the l2gw device node id
330 public static void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan) {
331 L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
332 l2gwDeviceNodeId.getValue());
333 if (l2gwDevice == null) {
334 LOG.debug("L2 gw device not found in elan cache for device name {}", l2gwDeviceNodeId.getValue());
338 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan);
342 * Install dmac flows on dpn.
351 public static void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan) {
352 String elanName = elan.getElanInstanceName();
354 List<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
355 if (l2gwDeviceLocalMacs != null && !l2gwDeviceLocalMacs.isEmpty()) {
356 for (LocalUcastMacs localUcastMac : l2gwDeviceLocalMacs) {
357 //TODO batch these ops
358 ElanUtils.installDmacFlowsToExternalRemoteMac(dpnId, l2gwDevice.getHwvtepNodeId(), elan.getElanTag(),
359 elan.getVni(), localUcastMac.getMacEntryKey().getValue(), elanName);
361 LOG.debug("Installing L2gw device [{}] local macs [size: {}] in dpn [{}] for elan [{}]",
362 l2gwDevice.getHwvtepNodeId(), l2gwDeviceLocalMacs.size(), dpnId, elanName);
367 * Install elan l2gw devices local macs in dpn.
374 public static void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan) {
375 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
376 .getInvolvedL2GwDevices(elan.getElanInstanceName());
377 if (elanL2GwDevicesFromCache != null) {
378 for (L2GatewayDevice l2gwDevice : elanL2GwDevicesFromCache.values()) {
379 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan);
382 LOG.debug("No Elan l2 gateway devices in cache for [{}] ", elan.getElanInstanceName());
386 public static void installL2GwUcastMacInElan(final ElanInstance elan,
387 final L2GatewayDevice extL2GwDevice, final String macToBeAdded) {
388 final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
389 final String elanInstanceName = elan.getElanInstanceName();
391 // Retrieve all participating DPNs in this Elan. Populate this MAC in DMAC table.
392 // Looping through all DPNs in order to add/remove mac flows in their DMAC table
393 final List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInstanceName);
394 if (elanDpns != null && elanDpns.size() > 0) {
395 String jobKey = elan.getElanInstanceName() + ":" + macToBeAdded;
396 ElanClusterUtils.runOnlyInLeaderNode(jobKey,
397 "install l2gw macs in dmac table",
398 new Callable<List<ListenableFuture<Void>>>() {
400 public List<ListenableFuture<Void>> call() throws Exception {
401 List<ListenableFuture<Void>> fts = Lists.newArrayList();
402 if (doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
403 for (DpnInterfaces elanDpn : elanDpns) {
404 // TODO batch the below call
405 fts.addAll(ElanUtils.installDmacFlowsToExternalRemoteMac(elanDpn.getDpId(),
406 extDeviceNodeId, elan.getElanTag(), elan.getVni(), macToBeAdded,
410 LOG.trace("Skipping install of dmac flows for mac {} as it is not found in cache",
417 final IpAddress extL2GwDeviceTepIp = extL2GwDevice.getTunnelIp();
418 final List<PhysAddress> macList = new ArrayList<PhysAddress>();
419 macList.add(new PhysAddress(macToBeAdded));
421 String jobKey = "hwvtep:"+elan.getElanInstanceName() + ":" + macToBeAdded;
422 ElanClusterUtils.runOnlyInLeaderNode(jobKey,
423 "install remote ucast macs in l2gw device",
424 new Callable<List<ListenableFuture<Void>>>() {
426 public List<ListenableFuture<Void>> call() throws Exception {
427 List<ListenableFuture<Void>> fts = Lists.newArrayList();
428 if (!doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
430 "Skipping install of remote ucast macs {} in l2gw device as it is not found in cache",
434 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices =
435 ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanInstanceName);
436 for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
437 if (!otherDevice.getHwvtepNodeId().equals(extDeviceNodeId)
438 && !areMLAGDevices(extL2GwDevice, otherDevice)) {
439 final String hwvtepId = otherDevice.getHwvtepNodeId();
440 InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(
441 new NodeId(hwvtepId));
442 final String logicalSwitchName = elanInstanceName;
444 ListenableFuture<Void> ft = HwvtepUtils.installUcastMacs(
445 broker, hwvtepId, macList, logicalSwitchName, extL2GwDeviceTepIp);
446 //TODO batch the above call
447 Futures.addCallback(ft, new FutureCallback<Void>() {
449 public void onSuccess(Void noarg) {
450 LOG.trace("Successful in initiating ucast_remote_macs addition" +
451 "related to {} in {}", logicalSwitchName, hwvtepId);
455 public void onFailure(Throwable error) {
456 LOG.error(String.format("Failed adding ucast_remote_macs related to " +
457 "%s in %s", logicalSwitchName, hwvtepId), error);
468 * Does local ucast mac exists in cache.
470 * @param elanL2GwDevice
471 * the elan L2 Gw device
473 * the mac address to be verified
474 * @return true, if successful
476 private static boolean doesLocalUcastMacExistsInCache(L2GatewayDevice elanL2GwDevice, String macAddress) {
477 java.util.Optional<LocalUcastMacs> macExistsInCache = elanL2GwDevice.getUcastLocalMacs().stream()
478 .filter(mac -> mac.getMacEntryKey().getValue().equalsIgnoreCase(macAddress)).findFirst();
479 return macExistsInCache.isPresent();
483 * Un install l2 gw ucast mac from elan.
489 * @param macAddresses
492 public static void unInstallL2GwUcastMacFromElan(final ElanInstance elan, final L2GatewayDevice l2GwDevice,
493 final List<MacAddress> macAddresses) {
494 if (macAddresses == null || macAddresses.isEmpty()) {
497 final String elanName = elan.getElanInstanceName();
499 // Retrieve all participating DPNs in this Elan. Populate this MAC in
500 // DMAC table. Looping through all DPNs in order to add/remove mac flows
501 // in their DMAC table
502 for (final MacAddress mac : macAddresses) {
503 final List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanName);
504 if (elanDpns != null && !elanDpns.isEmpty()) {
505 String jobKey = elanName + ":" + mac.getValue();
506 ElanClusterUtils.runOnlyInLeaderNode(jobKey, "delete l2gw macs from dmac table",
507 new Callable<List<ListenableFuture<Void>>>() {
509 public List<ListenableFuture<Void>> call() {
510 List<ListenableFuture<Void>> fts = Lists.newArrayList();
511 for (DpnInterfaces elanDpn : elanDpns) {
512 BigInteger dpnId = elanDpn.getDpId();
513 // never batch deletes
514 fts.addAll(ElanUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
515 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
523 DeleteL2GwDeviceMacsFromElanJob job = new DeleteL2GwDeviceMacsFromElanJob(broker, elanName, l2GwDevice,
525 ElanClusterUtils.runOnlyInLeaderNode(job.getJobKey(), "delete remote ucast macs in l2gw devices", job);
529 * Delete elan l2 gateway devices ucast local macs from dpn.
536 public static void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
537 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
538 if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
539 LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
542 final ElanInstance elan = ElanUtils.getElanInstanceByName(elanName);
544 LOG.error("Could not find Elan by name: {}", elanName);
547 LOG.info("Deleting Elan [{}] L2GatewayDevices UcastLocalMacs from Dpn [{}]", elanName, dpnId);
549 final Long elanTag = elan.getElanTag();
550 for (final L2GatewayDevice l2GwDevice : elanL2GwDevices.values()) {
551 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GwDevice);
552 if (localMacs != null && !localMacs.isEmpty()) {
553 for (final MacAddress mac : localMacs) {
554 String jobKey = elanName + ":" + mac.getValue();
555 ElanClusterUtils.runOnlyInLeaderNode(jobKey, "delete l2gw macs from dmac table",
556 new Callable<List<ListenableFuture<Void>>>() {
558 public List<ListenableFuture<Void>> call() {
559 List<ListenableFuture<Void>> futures = Lists.newArrayList();
561 futures.addAll(ElanUtils.deleteDmacFlowsToExternalMac(elanTag, dpnId,
562 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
572 * Gets the l2 gw device local macs.
576 * @return the l2 gw device local macs
578 public static List<MacAddress> getL2GwDeviceLocalMacs(L2GatewayDevice l2gwDevice) {
579 List<MacAddress> macs = new ArrayList<>();
580 if (l2gwDevice == null) {
583 List<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
584 if (lstUcastLocalMacs != null && !lstUcastLocalMacs.isEmpty()) {
585 macs = Lists.transform(lstUcastLocalMacs, new Function<LocalUcastMacs, MacAddress>() {
587 public MacAddress apply(LocalUcastMacs localUcastMac) {
588 return (localUcastMac != null) ? localUcastMac.getMacEntryKey() : null;
596 * Delete elan macs from L2 gateway device.<br>
597 * This includes deleting ELAN mac table entries plus external device
598 * UcastLocalMacs which are part of the same ELAN.
600 * @param l2GatewayDevice
601 * the l2 gateway device
604 * @return the listenable future
606 public static ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(L2GatewayDevice l2GatewayDevice,
608 String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
609 String logicalSwitch = getLogicalSwitchFromElan(elanName);
611 List<MacAddress> lstElanMacs =
612 getRemoteUcastMacs(new NodeId(hwvtepNodeId), logicalSwitch, LogicalDatastoreType.CONFIGURATION);
613 ListenableFuture<Void> future =
614 HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(hwvtepNodeId), logicalSwitch, lstElanMacs);
616 Futures.addCallback(future, new FutureCallback<Void>() {
618 public void onSuccess(Void noarg) {
619 LOG.trace("Successful in batch deletion of elan [{}] macs from l2gw device [{}]", elanName,
624 public void onFailure(Throwable error) {
625 LOG.warn(String.format(
626 "Failed during batch delete of elan [%s] macs from l2gw device [%s]. Retrying with sequential deletes.",
627 elanName, hwvtepNodeId), error);
628 if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
629 for (MacAddress mac : lstElanMacs) {
630 HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
636 if (LOG.isDebugEnabled()) {
637 List<String> elanMacs = lstElanMacs.stream().map(mac -> mac.getValue()).collect(Collectors.toList());
638 LOG.debug("Deleting elan [{}] macs from node [{}]. Deleted macs = {}", elanName, hwvtepNodeId, elanMacs);
644 * Gets the remote ucast macs from hwvtep node filtering based on logical
647 * @param hwvtepNodeId the hwvtep node id
648 * @param logicalSwitch the logical switch
649 * @param datastoreType the datastore type
650 * @return the remote ucast macs
652 public static List<MacAddress> getRemoteUcastMacs(NodeId hwvtepNodeId, String logicalSwitch,
653 LogicalDatastoreType datastoreType) {
654 List<MacAddress> lstMacs = Collections.emptyList();
655 Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
656 if (hwvtepNode != null) {
657 List<RemoteUcastMacs> remoteUcastMacs =
658 hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class).getRemoteUcastMacs();
659 if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
660 // Filtering remoteUcastMacs based on the logical switch and
661 // forming a list of MacAddress
662 lstMacs = remoteUcastMacs.stream()
663 .filter(mac -> logicalSwitch.equals(mac.getLogicalSwitchRef().getValue()
664 .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue()))
665 .map(mac -> mac.getMacEntryKey()).collect(Collectors.toList());
672 * Install ELAN macs in L2 Gateway device.<br>
673 * This includes installing ELAN mac table entries plus external device
674 * UcastLocalMacs which are part of the same ELAN.
678 * @param l2GatewayDevice
679 * the l2 gateway device which has to be configured
680 * @return the listenable future
682 public static ListenableFuture<Void> installElanMacsInL2GatewayDevice(String elanName,
683 L2GatewayDevice l2GatewayDevice) {
684 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
685 NodeId hwVtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
687 List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName,
688 l2GatewayDevice, hwVtepNodeId, logicalSwitchName);
689 List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName,
690 l2GatewayDevice, hwVtepNodeId, logicalSwitchName);
692 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
693 lstRemoteUcastMacs.addAll(lstElanMacTableEntries);
695 ListenableFuture<Void> future = HwvtepUtils.addRemoteUcastMacs(broker, hwVtepNodeId, lstRemoteUcastMacs);
697 LOG.info("Added RemoteUcastMacs entries [{}] in config DS. NodeID: {}, LogicalSwitch: {}",
698 lstRemoteUcastMacs.size(), hwVtepNodeId.getValue(), logicalSwitchName);
703 * Gets the l2 gateway devices ucast local macs as remote ucast macs.
707 * @param l2GatewayDeviceToBeConfigured
708 * the l2 gateway device to be configured
709 * @param hwVtepNodeId
710 * the hw vtep node Id to be configured
711 * @param logicalSwitchName
712 * the logical switch name
713 * @return the l2 gateway devices macs as remote ucast macs
715 public static List<RemoteUcastMacs> getOtherDevicesMacs(String elanName,
716 L2GatewayDevice l2GatewayDeviceToBeConfigured,
717 NodeId hwVtepNodeId, String logicalSwitchName) {
718 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<RemoteUcastMacs>();
719 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
720 .getInvolvedL2GwDevices(elanName);
722 if (elanL2GwDevicesFromCache != null) {
723 for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
724 if (l2GatewayDeviceToBeConfigured.getHwvtepNodeId().equals(otherDevice.getHwvtepNodeId())) {
727 if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
728 List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
729 if (lstUcastLocalMacs != null) {
730 for (LocalUcastMacs localUcastMac : lstUcastLocalMacs) {
731 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
732 .createHwvtepPhysicalLocatorAugmentation(
733 String.valueOf(otherDevice.getTunnelIp().getValue()));
734 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
735 localUcastMac.getMacEntryKey().getValue(), localUcastMac.getIpaddr(),
736 logicalSwitchName, physLocatorAug);
737 lstRemoteUcastMacs.add(remoteUcastMac);
743 return lstRemoteUcastMacs;
749 * @param l2GatewayDevice
750 * the l2 gateway device
751 * @param otherL2GatewayDevice
752 * the other l2 gateway device
753 * @return true, if both the specified l2 gateway devices are part of same
756 public static boolean areMLAGDevices(L2GatewayDevice l2GatewayDevice, L2GatewayDevice otherL2GatewayDevice) {
757 // If tunnel IPs are same, then it is considered to be part of same MLAG
758 return Objects.equals(l2GatewayDevice.getTunnelIp(), otherL2GatewayDevice.getTunnelIp());
762 * Gets the elan mac table entries as remote ucast macs. <br>
763 * Note: ELAN MAC table only contains internal switches MAC's. It doesn't
764 * contain external device MAC's.
768 * @param l2GatewayDeviceToBeConfigured
769 * the l2 gateway device to be configured
770 * @param hwVtepNodeId
771 * the hw vtep node id
772 * @param logicalSwitchName
773 * the logical switch name
774 * @return the elan mac table entries as remote ucast macs
776 public static List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
777 L2GatewayDevice l2GatewayDeviceToBeConfigured,
778 NodeId hwVtepNodeId, String logicalSwitchName) {
779 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<RemoteUcastMacs>();
781 MacTable macTable = ElanUtils.getElanMacTable(elanName);
782 if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
783 LOG.trace("MacTable is empty for elan: {}", elanName);
784 return lstRemoteUcastMacs;
787 for (MacEntry macEntry : macTable.getMacEntry()) {
788 BigInteger dpnId = ElanUtils.getDpidFromInterface(macEntry.getInterface());
790 LOG.error("DPN ID not found for interface {}", macEntry.getInterface());
794 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, hwVtepNodeId);
795 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpnId, hwVtepNodeId.getValue());
796 if (dpnTepIp == null) {
797 LOG.error("TEP IP not found for dpnId {} and nodeId {}", dpnId, hwVtepNodeId.getValue());
800 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
801 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
802 // TODO: Query ARP cache to get IP address corresponding to the
804 IpAddress ipAddress = null;
805 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
806 macEntry.getMacAddress().getValue(), ipAddress, logicalSwitchName, physLocatorAug);
807 lstRemoteUcastMacs.add(remoteUcastMac);
809 return lstRemoteUcastMacs;
813 * Gets the external tunnel interface name.
819 * @return the external tunnel interface name
821 public static String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
822 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
823 String tunnelInterfaceName = null;
825 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
826 .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
827 .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
829 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
830 if (rpcResult.isSuccessful()) {
831 tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
832 LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
833 sourceNode, dstNode);
835 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}",
836 rpcResult.getErrors());
838 } catch (NullPointerException | InterruptedException | ExecutionException e) {
839 LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}: {} ",
840 sourceNode, dstNode, e);
842 return tunnelInterfaceName;
846 * Gets the source dpn tep ip.
850 * @param dstHwVtepNodeId
851 * the dst hw vtep node id
852 * @return the dpn tep ip
854 public static IpAddress getSourceDpnTepIp(BigInteger srcDpnId, NodeId dstHwVtepNodeId) {
855 IpAddress dpnTepIp = null;
856 String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(srcDpnId),
857 dstHwVtepNodeId.getValue());
858 if (tunnelInterfaceName != null) {
859 Interface tunnelInterface = getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
860 if (tunnelInterface != null) {
861 dpnTepIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
863 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
866 LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
873 * Update vlan bindings in l2 gateway device.
877 * @param logicalSwitchName
878 * the logical switch name
879 * @param hwVtepDevice
880 * the hardware device
881 * @param defaultVlanId
882 * the default vlan id
883 * @return the listenable future
885 public static ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String logicalSwitchName,
886 Devices hwVtepDevice, Integer defaultVlanId) {
887 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
888 String errMsg = "HwVtepDevice is null or interfaces are empty.";
890 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
893 WriteTransaction transaction = broker.newWriteOnlyTransaction();
894 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
896 List<VlanBindings> vlanBindings = new ArrayList<>();
897 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
898 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
899 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
902 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
903 // ID not specified at interface level.
904 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
906 HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
907 deviceInterface.getInterfaceName(), vlanBindings);
909 ListenableFuture<Void> future = transaction.submit();
910 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
916 * Delete vlan bindings from l2 gateway device.
920 * @param hwVtepDevice
922 * @param defaultVlanId
923 * the default vlan id
924 * @return the listenable future
926 public static ListenableFuture<Void> deleteVlanBindingsFromL2GatewayDevice(NodeId nodeId, Devices hwVtepDevice,
927 Integer defaultVlanId) {
928 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
929 String errMsg = "HwVtepDevice is null or interfaces are empty.";
931 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
933 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
935 WriteTransaction transaction = broker.newWriteOnlyTransaction();
936 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
938 String phyPortName = deviceInterface.getInterfaceName();
939 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
940 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
941 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
944 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
945 // ID not specified at interface level.
946 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
949 ListenableFuture<Void> future = transaction.submit();
951 LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
952 nodeId.getValue(), hwVtepDevice, defaultVlanId);
957 * Gets the elan name from logical switch name.
959 * @param logicalSwitchName
960 * the logical switch name
961 * @return the elan name from logical switch name
963 public static String getElanFromLogicalSwitch(String logicalSwitchName) {
964 // Assuming elan name is same as logical switch name
965 String elanName = logicalSwitchName;
970 * Gets the logical switch name from elan name.
974 * @return the logical switch from elan name
976 public static String getLogicalSwitchFromElan(String elanName) {
977 // Assuming logical switch name is same as elan name
978 String logicalSwitchName = elanName;
979 return logicalSwitchName;
983 * Gets the l2 gateway connection job key.
987 * @param logicalSwitchName
988 * the logical switch name
989 * @return the l2 gateway connection job key
991 public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
992 return logicalSwitchName;
995 public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
996 InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
997 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
998 return interfaceInstanceIdentifierBuilder.build();
1001 public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
1002 InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
1003 Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker);
1004 if (!interfaceOptional.isPresent()) {
1008 return interfaceOptional.get();
1012 * Delete l2 gateway device ucast local macs from elan.<br>
1013 * Deletes macs from internal ELAN nodes and also on rest of external l2
1014 * gateway devices which are part of the ELAN.
1016 * @param l2GatewayDevice
1017 * the l2 gateway device whose ucast local macs to be deleted
1021 * @return the listenable future
1023 public static List<ListenableFuture<Void>> deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
1025 LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(), elanName);
1027 List<ListenableFuture<Void>> futures = new ArrayList<>();
1028 ElanInstance elan = ElanUtils.getElanInstanceByName(elanName);
1030 LOG.error("Could not find Elan by name: {}", elanName);
1034 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GatewayDevice);
1035 unInstallL2GwUcastMacFromElan(elan, l2GatewayDevice, localMacs);
1039 public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
1040 IpAddress tunnelIp) {
1041 AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
1042 builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
1043 builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
1044 builder.setIpAddress(tunnelIp);
1046 Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
1047 RpcResult<Void> rpcResult = result.get();
1048 if (rpcResult.isSuccessful()) {
1049 LOG.info("Created ITM tunnels for {}", hwvtepId);
1051 LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
1053 } catch (InterruptedException | ExecutionException e) {
1054 LOG.error("RPC to create ITM tunnels failed", e);
1058 public static String getNodeIdFromDpnId(BigInteger dpnId) {
1059 return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
1062 public static void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
1063 List<PhysAddress> staticMacAddresses) {
1064 ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils
1065 .getInvolvedL2GwDevices(elanName);
1066 for (final L2GatewayDevice externalDevice : elanDevices.values()) {
1067 scheduleAddDpnMacsInExtDevice(elanName, dpId, staticMacAddresses, externalDevice);
1071 public static void scheduleAddDpnMacsInExtDevice(final String elanName, BigInteger dpId,
1072 final List<PhysAddress> staticMacAddresses,
1073 final L2GatewayDevice externalDevice) {
1074 NodeId nodeId = new NodeId(externalDevice.getHwvtepNodeId());
1075 final IpAddress dpnTepIp = ElanL2GatewayUtils.getSourceDpnTepIp(dpId, nodeId);
1076 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpId, nodeId);
1077 if (dpnTepIp == null) {
1078 LOG.error("could not install dpn mac in l2gw TEP IP not found for dpnId {} and nodeId {}", dpId, nodeId);
1081 TerminationPointKey tpKey = HwvtepSouthboundUtils.getTerminationPointKey(
1082 dpnTepIp.getIpv4Address().getValue());
1083 InstanceIdentifier<TerminationPoint> tpPath = HwvtepSouthboundUtils.createTerminationPointId
1086 HwvtepPhysicalLocatorListener.runJobAfterPhysicalLocatorIsAvialable(tpPath, new Runnable() {
1089 HwvtepUtils.installUcastMacs(broker,
1090 externalDevice.getHwvtepNodeId(), staticMacAddresses,
1091 elanName, dpnTepIp);
1096 public static void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1097 TimerTask logicalSwitchDeleteTask = new TimerTask() {
1100 Pair<NodeId, String> nodeIdLogicalSwitchNamePair =
1101 new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
1102 LogicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
1104 DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker, hwvtepNodeId, lsName);
1105 ElanL2GatewayUtils.dataStoreJobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
1106 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1109 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
1110 LogicalSwitchDeletedTasks.put(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
1111 LogicalSwitchDeleteJobTimer.schedule(logicalSwitchDeleteTask, LOGICAL_SWITCH_DELETE_DELAY);
1114 public static void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1115 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
1116 TimerTask logicalSwitchDeleteTask = LogicalSwitchDeletedTasks.get(nodeIdLogicalSwitchNamePair);
1117 if (logicalSwitchDeleteTask != null) {
1118 LOG.debug("Delete logical switch {} action on node {} cancelled", lsName, hwvtepNodeId);
1119 logicalSwitchDeleteTask.cancel();
1120 LogicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);